+ }
+}
+
+//____________________________________________________________________
+Bool_t
+AliFMDDetector::HasAllTransforms(Char_t ring) const
+{
+ // Check if we got all transformations for a given ring. Return
+ // true in that case.
+ AliFMDRing* r = GetRing(ring);
+ if (!r) return kTRUE;
+ TObjArray* matricies = (r == fInner ? fInnerTransforms : fOuterTransforms);
+ if (!matricies) return kTRUE;
+ if (matricies->GetEntries() == r->GetNModules()) return kTRUE;
+ return kFALSE;
+}
+
+#define IS_NODE_THIS(name) \
+ (name[0] == 'F' && name[2] == 'M' && name[1] == Char_t(48+fId) && \
+ (name[3] == 'T' || name[3] == 'B'))
+#define IS_NODE_SENSOR(name) \
+ (name[0] == 'F' && (name[2] == 'B' || name[2] == 'F') && name[3] == 'H')
+//#define IS_NODE_SENSOR(name)
+// (name[0] == 'F' && name[2] == 'S' && name[3] == 'E')
+#define IS_NODE_HALF(name) \
+ (name[0] == 'F' && name[2] == 'M' && (name[3] == 'B' || name[3] == 'T'))
+#define HALF_FORMAT "FMD/FMD%d_%c"
+#define SENSOR_FORMAT "FMD/FMD%d_%c/FMD%c_%02d"
+
+//____________________________________________________________________
+void
+AliFMDDetector::InitTransformations()
+{
+ // Find all local<->global transformations for this detector.
+ if ((!fInner || (fInner && fInnerTransforms)) &&
+ (!fOuter || (fOuter && fOuterTransforms))) {
+ AliFMDDebug(5, ("Transforms for FMD%d already registered", fId));
+ return;
+ }
+ AliFMDDebug(5, ("Initializing transforms for FMD%d", fId));
+ if (!gGeoManager) {
+ AliFatal("No TGeoManager defined");
+ return;
+ }
+
+ // Implementation using alignable volume names.
+ // Make container of transforms
+ if (fInner && !fInnerTransforms)
+ fInnerTransforms = new TObjArray(fInner->GetNModules());
+ if (fOuter && !fOuterTransforms)
+ fOuterTransforms = new TObjArray(fOuter->GetNModules());
+
+ // Loop over bottom/top
+ for (size_t ihalf = 0; ihalf < 2; ihalf++) {
+ char half = (ihalf == 0 ? 'T' : 'B');
+ TString path(Form(HALF_FORMAT, fId, half));
+ TGeoPNEntry* entry = gGeoManager->GetAlignableEntry(path.Data());
+ if (!entry) {
+ AliError(Form("Alignable entry for half-detector \"%s\" not found!",
+ path.Data()));
+ continue;
+ }
+ TGeoPhysicalNode* pn = entry->GetPhysicalNode();
+ if (!pn) {
+ AliWarning(Form("Making physical volume for \"%s\"", path.Data()));
+ pn = gGeoManager->MakeAlignablePN(entry);
+ if (!pn) {
+ AliError(Form("No physical node for \"%s\"", path.Data()));
+ continue;
+ }
+ }
+ }
+
+ // Loop over rings
+ for (size_t iring = 0; iring < 2; iring++) {
+ char ring = (iring == 0 ? 'I' : 'O');
+ TObjArray* trans = 0;
+ AliFMDRing* r = 0;
+ switch (ring) {
+ case 'I': r = fInner; trans = fInnerTransforms; break;
+ case 'O': r = fOuter; trans = fOuterTransforms; break;
+ }
+ if (!r || !trans) continue;
+
+ Int_t nModules = r->GetNModules();
+ if (nModules <= 0) continue;
+
+ // Loop over bottom/top
+ for (size_t ihalf = 0; ihalf < 2; ihalf++) {
+ char half = (ihalf == 0 ? 'T' : 'B');
+ Int_t base = (half == 'T' ? 0 : nModules / 2);
+
+ // Loop over modules in this half ring
+ for (Int_t imod = 0; imod < nModules / 2; imod++) {
+ // Find physical node entry
+ TString path(Form(SENSOR_FORMAT, fId, half, ring, base+imod));
+ TGeoPNEntry* entry = gGeoManager->GetAlignableEntry(path.Data());
+ if (!entry) {
+ AliError(Form("Alignable entry for sensor \"%s\" not found!",
+ path.Data()));
+ continue;
+ }
+ TGeoPhysicalNode* pn = entry->GetPhysicalNode();
+ if (!pn) {
+ AliWarning(Form("Making physical volume for \"%s\"", path.Data()));
+ pn = gGeoManager->MakeAlignablePN(entry);
+ if (!pn) {
+ AliError(Form("No physical node for \"%s\"", path.Data()));
+ continue;
+ }
+ }
+
+ const TGeoMatrix* pm = pn->GetMatrix();
+ if (!pm) {
+ AliError(Form("No matrix for path \"%s\"", path.Data()));
+ continue;
+ }
+ // Get transformation matrix for this node, and store it.
+ TGeoMatrix* t = new TGeoHMatrix(*pm);
+ trans->AddAt(t, base+imod);
+ AliFMDDebug(5, ("Found matrix for path \"%s\": %p",path.Data(),pm));
+ }
+ }
+ }
+ if (HasAllTransforms('I') && HasAllTransforms('O')) return;
+
+ // Alternative implementation using TGeoIter.
+ TGeoVolume* topVolume = gGeoManager->GetTopVolume();
+ if (!topVolume) {
+ AliFatal("No top-level volume defined");
+ return;
+ }
+ // Make an iterator
+ TGeoIterator next(topVolume);
+ TGeoNode* node = 0;
+
+ // Find the node corresponding to this detector, and then find the
+ // sensor volumes
+ Bool_t thisNodeFound = kFALSE;
+ Bool_t allInners = HasAllTransforms('I');
+ Bool_t allOuters = HasAllTransforms('O');
+
+ while ((node = static_cast<TGeoNode*>(next()))
+ && !(allInners && allOuters)) {
+ // Get nodes names
+ const Char_t* name = node->GetName();
+ if (!name) continue;
+ AliFMDDebug(50, ("Got volume %s", name));
+ // Check if this node is this detector
+ // The base offset for numbers in the ASCII table is 48
+ if (IS_NODE_THIS(name)) {
+ AliFMDDebug(20, ("Found detector node '%s' for FMD%d", name, fId));
+ thisNodeFound = kTRUE;
+ }
+ // if the detector was found, then we're on that branch, and we
+ // check if this node represents a module in that branch.
+ if (thisNodeFound && IS_NODE_SENSOR(name)) {
+ AliFMDDebug(20, ("Found sensor node '%s' for FMD%d", name, fId));
+ // Get the ring Id.
+ Char_t ringid = name[1];
+
+ // Get the approprate ring
+ AliFMDRing* ring = GetRing(ringid);
+ if (!ring) continue;
+
+ // Check whether we have all the modules we need for this ring,
+ // and if so, go on to the next node.
+ Bool_t& done = (ring == fInner ? allInners : allOuters);
+ if ((done = HasAllTransforms(ringid))) {
+ AliFMDDebug(20, ("Already has all module transforms for ring %c",
+ ringid));
+ continue;
+ }
+
+ // Get the approprate container
+ TObjArray* matricies = (ringid == 'i' || ringid == 'I'
+ ? fInnerTransforms : fOuterTransforms);
+
+ // Get the copy (module) number, and check that it hasn't
+ // already been added to the container.
+ Int_t copy = node->GetNumber();
+ if (matricies->At(copy)) {
+ AliWarning(Form("Have a transformation for module %d in ring %c",
+ copy, ringid));
+ continue;
+ }
+
+ // Get the global transformation matrix, and store it.
+ TGeoMatrix* trans = new TGeoHMatrix(*(next.GetCurrentMatrix()));
+ matricies->AddAt(trans, copy);
+
+ }