]> git.uio.no Git - u/mrichter/AliRoot.git/blob - STEER/AliGeomManager.cxx
Use bit 14 of TParticle to flag tracks that have been transported.
[u/mrichter/AliRoot.git] / STEER / AliGeomManager.cxx
1 /**************************************************************************
2  * Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
3  *                                                                        *
4  * Author: The ALICE Off-line Project.                                    *
5  * Contributors are mentioned in the code where appropriate.              *
6  *                                                                        *
7  * Permission to use, copy, modify and distribute this software and its   *
8  * documentation strictly for non-commercial purposes is hereby granted   *
9  * without fee, provided that the above copyright notice appears in all   *
10  * copies and that both the copyright notice and this permission notice   *
11  * appear in the supporting documentation. The authors make no claims     *
12  * about the suitability of this software for any purpose. It is          *
13  * provided "as is" without express or implied warranty.                  *
14  **************************************************************************/
15 //-------------------------------------------------------------------------
16 //   Implementation of AliGeomManager, the geometry manager class 
17 //   which interfaces to TGeo and the look-up table mapping unique
18 //   volume indices to symbolic volume names. For that it collects
19 //   several static methods.
20 //-------------------------------------------------------------------------
21
22 #include <TClass.h>
23 #include <TFile.h>
24 #include <TGeoManager.h>
25 #include <TObjString.h>
26 #include <TGeoPhysicalNode.h>
27 #include <TClonesArray.h>
28 #include <TGeoMatrix.h>
29 #include <TGeoPhysicalNode.h>
30 #include <TSystem.h>
31
32 #include "AliGeomManager.h"
33 #include "AliLog.h"
34 #include "AliAlignObj.h"
35 #include "AliAlignObjAngles.h"
36 #include "AliCDBManager.h"
37 #include "AliCDBStorage.h"
38 #include "AliCDBEntry.h"
39
40 ClassImp(AliGeomManager)
41   
42 Int_t AliGeomManager::fgLayerSize[kLastLayer - kFirstLayer] = {
43   80, 160,  // ITS SPD first and second layer
44   84, 176,  // ITS SDD first and second layer
45   748, 950, // ITS SSD first and second layer
46   36, 36,   // TPC inner and outer chambers
47   90, 90, 90, 90, 90, 90,  // 6 TRD chambers' layers
48   1638,     // TOF
49   5, 5,     // PHOS,CPV
50   7,        // HMPID ??
51   1         // MUON ??
52 };
53
54 const char* AliGeomManager::fgLayerName[kLastLayer - kFirstLayer] = {
55   "ITS inner pixels layer", "ITS outer pixels layer",
56   "ITS inner drifts layer", "ITS outer drifts layer",
57   "ITS inner strips layer", "ITS outer strips layer",
58   "TPC inner chambers layer", "TPC outer chambers layer",
59   "TRD chambers layer 1", "TRD chambers layer 2", "TRD chambers layer 3",
60   "TRD chambers layer 4", "TRD chambers layer 5", "TRD chambers layer 6",
61   "TOF layer",
62   "PHOS EMC layer","PHOS CPV layer",
63   "HMPID layer",
64   "?"
65 };
66
67 TString* AliGeomManager::fgSymName[kLastLayer - kFirstLayer] = {
68   0x0,0x0,
69   0x0,0x0,
70   0x0,0x0,
71   0x0,0x0,
72   0x0,0x0,0x0,
73   0x0,0x0,0x0,
74   0x0,
75   0x0,0x0,
76   0x0,
77   0x0
78 };
79
80 TGeoPNEntry** AliGeomManager::fgPNEntry[kLastLayer - kFirstLayer] = {
81   0x0,0x0,
82   0x0,0x0,
83   0x0,0x0,
84   0x0,0x0,
85   0x0,0x0,0x0,
86   0x0,0x0,0x0,
87   0x0,
88   0x0,0x0,
89   0x0,
90   0x0
91 };
92
93 TGeoHMatrix** AliGeomManager::fgOrigMatrix[kLastLayer - kFirstLayer] = {
94   0x0,0x0,
95   0x0,0x0,
96   0x0,0x0,
97   0x0,0x0,
98   0x0,0x0,0x0,
99   0x0,0x0,0x0,
100   0x0,
101   0x0,0x0,
102   0x0,
103   0x0
104 };
105
106 AliAlignObj** AliGeomManager::fgAlignObjs[kLastLayer - kFirstLayer] = {
107   0x0,0x0,
108   0x0,0x0,
109   0x0,0x0,
110   0x0,0x0,
111   0x0,0x0,0x0,
112   0x0,0x0,0x0,
113   0x0,
114   0x0,0x0,
115   0x0,
116   0x0
117 };
118
119 TGeoManager* AliGeomManager::fgGeometry = 0x0;
120
121 //_____________________________________________________________________________
122 void AliGeomManager::LoadGeometry(const char *geomFileName)
123 {
124   // initialization
125   // Load geometry either from a file
126   // or from the corresponding CDB entry
127
128   fgGeometry = NULL;
129   if (geomFileName && (!gSystem->AccessPathName(geomFileName))) { // gemotry.root exists
130     fgGeometry = TGeoManager::Import(geomFileName);
131     AliInfoClass("Using custom geometry.root file");
132   }
133
134   if (!fgGeometry) {
135     AliInfoClass("Using geometry from CDB");
136
137     AliCDBPath path("GRP","Geometry","Data");
138         
139     AliCDBEntry *entry=AliCDBManager::Instance()->Get(path.GetPath());
140     if(!entry) AliFatalClass("Couldn't load geometry data from CDB!");
141
142     entry->SetOwner(0);
143     fgGeometry = (TGeoManager*) entry->GetObject();
144     if (!fgGeometry) AliFatalClass("Couldn't find TGeoManager in the specified CDB entry!");
145   }
146
147   InitSymNamesLUT();
148   InitPNEntriesLUT();
149   InitOrigMatricesLUT();
150 }
151
152 //_____________________________________________________________________________
153 void AliGeomManager::SetGeometry(TGeoManager *geom)
154 {
155   // Load already active geometry
156   if (!geom) AliFatalClass("Pointer to the active geometry is 0x0!");
157
158   fgGeometry = geom;
159
160   InitSymNamesLUT();
161   InitPNEntriesLUT();
162   InitOrigMatricesLUT();
163 }
164
165 //_____________________________________________________________________________
166 AliGeomManager::AliGeomManager():
167   TObject()
168 {
169   // default constructor
170 }
171
172 //_____________________________________________________________________________
173 AliGeomManager::~AliGeomManager()
174 {
175   // dummy destructor
176 }
177
178 //_____________________________________________________________________________
179 Int_t AliGeomManager::LayerSize(Int_t layerId)
180 {
181   // Get the layer size for layer corresponding to layerId.
182   // Implemented only for ITS,TPC,TRD,TOF and HMPID
183   //
184   if (layerId < kFirstLayer || layerId >= kLastLayer) {
185     AliErrorClass(Form("Invalid layer index %d ! Layer range is (%d -> %d) !",layerId,kFirstLayer,kLastLayer));
186     return 0;
187   }
188   else {
189     return fgLayerSize[layerId - kFirstLayer];
190  }
191 }
192
193 //_____________________________________________________________________________
194 const char* AliGeomManager::LayerName(Int_t layerId)
195 {
196   // Get the layer name corresponding to layerId.
197   // Implemented only for ITS,TPC,TRD,TOF and HMPID
198   //
199   if (layerId < kFirstLayer || layerId >= kLastLayer) {
200     AliErrorClass(Form("Invalid layer index %d ! Layer range is (%d -> %d) !",layerId,kFirstLayer,kLastLayer));
201     return "Invalid Layer!";
202   }
203   else {
204     return fgLayerName[layerId - kFirstLayer];
205  }
206 }
207
208 //_____________________________________________________________________________
209 UShort_t AliGeomManager::LayerToVolUID(ELayerID layerId, Int_t modId)
210 {
211   // From detector (layer) name and module number (according to detector
212   // internal numbering) build the unique numerical identity of that volume
213   // inside ALICE
214   // fVolUID is 16 bits, first 5 reserved for layerID (32 possible values),
215   // remaining 11 for module ID inside det (2048 possible values).
216   // NO check for validity of given modId inside the layer for speed's sake.
217   //
218   return ((UShort_t(layerId) << 11) | UShort_t(modId));
219 }
220
221 //_____________________________________________________________________________
222 UShort_t AliGeomManager::LayerToVolUID(Int_t   layerId, Int_t modId)
223 {
224   // From detector (layer) name and module number (according to detector
225   // internal numbering) build the unique numerical identity of that volume
226   // inside ALICE
227   // fVolUID is 16 bits, first 5 reserved for layerID (32 possible values),
228   // remaining 11 for module ID inside det (2048 possible values).
229   // NO check for validity of given modId inside the layer for speed's sake.
230   //
231   return ((UShort_t(layerId) << 11) | UShort_t(modId));
232 }
233
234 //_____________________________________________________________________________
235 UShort_t AliGeomManager::LayerToVolUIDSafe(ELayerID layerId, Int_t modId)
236 {
237   // From detector (layer) name and module number (according to detector
238   // internal numbering) build the unique numerical identity of that volume
239   // inside ALICE
240   // fVolUID is 16 bits, first 5 reserved for layerID (32 possible values),
241   // remaining 11 for module ID inside det (2048 possible values).
242   // Check validity of given modId inside the layer.
243   //
244   if(modId < 0 || modId >= LayerSize(layerId)){
245     AliErrorClass(Form("Invalid volume id %d ! Range of valid ids for layer \"%s\" is [0, %d] !",modId,LayerName(layerId),LayerSize(layerId)-1));
246     return 0;
247   }
248   return ((UShort_t(layerId) << 11) | UShort_t(modId));
249 }
250
251 //_____________________________________________________________________________
252 UShort_t AliGeomManager::LayerToVolUIDSafe(Int_t layerId, Int_t modId)
253 {
254   // From detector (layer) name and module number (according to detector
255   // internal numbering) build the unique numerical identity of that volume
256   // inside ALICE
257   // fVolUID is 16 bits, first 5 reserved for layerID (32 possible values),
258   // remaining 11 for module ID inside det (2048 possible values).
259   // Check validity of given modId inside the layer.
260   //
261   if(modId < 0 || modId >= LayerSize(layerId)){
262     AliErrorClass(Form("Invalid volume id %d ! Range of valid ids for layer \"%s\" is [0, %d] !",modId,LayerName(layerId),LayerSize(layerId)-1));
263     return 0;
264   }
265   return ((UShort_t(layerId) << 11) | UShort_t(modId));
266 }
267
268 //_____________________________________________________________________________
269 AliGeomManager::ELayerID AliGeomManager::VolUIDToLayer(UShort_t voluid, Int_t &modId)
270 {
271   // From voluid, unique numerical identity of that volume inside ALICE,
272   // (voluid is 16 bits, first 5 reserved for layerID (32 possible values),
273   // remaining 11 for module ID inside det (2048 possible values)), return
274   // the identity of the layer to which that volume belongs and sets the
275   // argument modId to the identity of that volume internally to the layer.
276   // NO check for validity of given voluid for speed's sake.
277   //
278   modId = voluid & 0x7ff;
279
280   return VolUIDToLayer(voluid);
281 }
282
283 //_____________________________________________________________________________
284 AliGeomManager::ELayerID AliGeomManager::VolUIDToLayer(UShort_t voluid)
285 {
286   // From voluid, unique numerical identity of that volume inside ALICE,
287   // (voluid is 16 bits, first 5 reserved for layerID (32 possible values),
288   // remaining 11 for module ID inside det (2048 possible values)), return
289   // the identity of the layer to which that volume belongs
290   // NO check for validity of given voluid for speed's sake.
291   //
292   return ELayerID(voluid >> 11);
293 }
294
295 //_____________________________________________________________________________
296 AliGeomManager::ELayerID AliGeomManager::VolUIDToLayerSafe(UShort_t voluid, Int_t &modId)
297 {
298   // From voluid, unique numerical identity of that volume inside ALICE,
299   // (voluid is 16 bits, first 5 reserved for layerID (32 possible values),
300   // remaining 11 for module ID inside det (2048 possible values)), returns
301   // the identity of the layer to which that volume belongs and sets the
302   // argument modId to the identity of that volume internally to the layer.
303   // Checks the validity of the given voluid
304   //
305   ELayerID layId = VolUIDToLayerSafe(voluid);
306   if(layId){
307     Int_t mId = Int_t(voluid & 0x7ff);
308     if( mId>=0 && mId<LayerSize(layId)){
309       modId = mId;
310       return layId;
311     }
312   }
313
314   AliErrorClass(Form("Invalid unique volume id: %d !",voluid));
315   modId = -1;
316   return kInvalidLayer;
317
318 }
319
320 //_____________________________________________________________________________
321 AliGeomManager::ELayerID AliGeomManager::VolUIDToLayerSafe(UShort_t voluid)
322 {
323   // From voluid, unique numerical identity of that volume inside ALICE,
324   // (voluid is 16 bits, first 5 reserved for layerID (32 possible values),
325   // remaining 11 for module ID inside det (2048 possible values)), returns
326   // the identity of the layer to which that volume belongs
327   // Checks the validity of the given voluid
328   //
329   if( (voluid >> 11) < kLastLayer)  return ELayerID(voluid >> 11);
330
331   AliErrorClass(Form("Invalid layer id: %d !",(voluid >> 11)));
332   return kInvalidLayer;
333
334 }
335
336 //_____________________________________________________________________________
337 Bool_t AliGeomManager::GetFromGeometry(const char *symname, AliAlignObj &alobj)
338 {
339   // Get the alignment object which corresponds to the symbolic volume name
340   // symname (in case equal to the TGeo volume path)
341   // The method is extremely slow due to the searching by string,
342   // therefore it should be used with great care!!
343   // This method returns FALSE if the symname of the object was not
344   // valid neither to get a TGeoPEntry nor as a volume path, or if the path
345   // associated to the TGeoPNEntry was not valid.
346   //
347
348   // Reset the alignment object
349   alobj.SetPars(0,0,0,0,0,0);
350   alobj.SetSymName(symname);
351
352   if (!fgGeometry || !fgGeometry->IsClosed()) {
353     AliErrorClass("Can't get the alignment object! gGeoManager doesn't exist or it is still opened!");
354     return kFALSE;
355   }
356
357   if (!fgGeometry->GetListOfPhysicalNodes()) {
358     AliErrorClass("Can't get the alignment object! gGeoManager doesn't contain any aligned nodes!");
359     return kFALSE;
360   }
361
362   const char *path;
363   TGeoPNEntry* pne = fgGeometry->GetAlignableEntry(symname);
364   if(pne){
365     path = pne->GetTitle();
366   }else{
367     AliWarningClass(Form("The symbolic volume name %s does not correspond to a physical entry. Using it as a volume path!",symname));
368     path = symname;
369   }
370   TObjArray* nodesArr = fgGeometry->GetListOfPhysicalNodes();
371   TGeoPhysicalNode* node = NULL;
372   for (Int_t iNode = 0; iNode < nodesArr->GetEntriesFast(); iNode++) {
373     TGeoPhysicalNode* tempNode = (TGeoPhysicalNode*) nodesArr->UncheckedAt(iNode);
374     const char *nodePath = tempNode->GetName();
375     if (strcmp(path,nodePath) == 0) {
376       node = tempNode;
377       break;
378     }
379   }
380
381   if (!node) {
382     if (!fgGeometry->cd(path)) {
383       AliErrorClass(Form("%s not valid neither as symbolic volume name nor as volume path!",path));
384       return kFALSE;
385     }
386     else {
387       AliWarningClass(Form("Volume (%s) has not been misaligned!",path));
388       return kTRUE;
389     }
390   }
391
392   TGeoHMatrix align,gprime,g,ginv,l;
393   gprime = *node->GetMatrix();
394   l = *node->GetOriginalMatrix();
395   g = *node->GetMatrix(node->GetLevel()-1);
396   g *= l;
397   ginv = g.Inverse();
398   align = gprime * ginv;
399
400   return alobj.SetMatrix(align);
401 }
402
403
404 //_____________________________________________________________________________
405 void  AliGeomManager::InitAlignObjFromGeometry()
406 {
407  // Loop over all alignable volumes and extract
408  // the corresponding alignment objects from
409  // the TGeo geometry
410
411   if(fgAlignObjs[0]) return;
412   
413   for (Int_t iLayer = kFirstLayer; iLayer < AliGeomManager::kLastLayer; iLayer++) {
414     fgAlignObjs[iLayer-kFirstLayer] = new AliAlignObj*[LayerSize(iLayer)];
415     for (Int_t iModule = 0; iModule < LayerSize(iLayer); iModule++) {
416       UShort_t volid = LayerToVolUID(iLayer,iModule);
417       fgAlignObjs[iLayer-kFirstLayer][iModule] = new AliAlignObjAngles("",volid,0,0,0,0,0,0,kTRUE);
418       const char *symname = SymName(volid);
419       if (!GetFromGeometry(symname, *fgAlignObjs[iLayer-kFirstLayer][iModule]))
420         AliErrorClass(Form("Failed to extract the alignment object for the volume (ID=%d and path=%s) !",volid,symname));
421     }
422   }
423   
424 }
425
426 //_____________________________________________________________________________
427 AliAlignObj* AliGeomManager::GetAlignObj(UShort_t voluid) {
428   // Returns the alignment object for given volume ID
429   //
430   Int_t modId;
431   ELayerID layerId = VolUIDToLayer(voluid,modId);
432   return GetAlignObj(layerId,modId);
433 }
434
435 //_____________________________________________________________________________
436 AliAlignObj* AliGeomManager::GetAlignObj(ELayerID layerId, Int_t modId)
437 {
438   // Returns pointer to alignment object given its layer and module ID
439   //
440   if(modId<0 || modId>=fgLayerSize[layerId-kFirstLayer]){
441     AliWarningClass(Form("Module number %d not in the valid range (0->%d) !",modId,fgLayerSize[layerId-kFirstLayer]-1));
442     return NULL;
443   }
444   InitAlignObjFromGeometry();
445
446   return fgAlignObjs[layerId-kFirstLayer][modId];
447 }
448
449 //_____________________________________________________________________________
450 const char* AliGeomManager::SymName(UShort_t voluid) {
451   // Returns the symbolic volume name for given volume ID
452   //
453   Int_t modId;
454   ELayerID layerId = VolUIDToLayer(voluid,modId);
455   return SymName(layerId,modId);
456 }
457
458 //_____________________________________________________________________________
459 const char* AliGeomManager::SymName(ELayerID layerId, Int_t modId)
460 {
461   // Returns the symbolic volume name given for a given layer
462   // and module ID
463   //
464   if(modId<0 || modId>=fgLayerSize[layerId-kFirstLayer]){
465     AliWarningClass(Form("Module number %d not in the valid range (0->%d) !",modId,fgLayerSize[layerId-kFirstLayer]-1));
466     return NULL;
467   }
468   InitSymNamesLUT();
469
470   return fgSymName[layerId-kFirstLayer][modId].Data();
471 }
472
473 //_____________________________________________________________________________
474 void AliGeomManager::InitSymNamesLUT()
475 {
476   // Initialize the look-up table which associates the unique
477   // numerical identity of each alignable volume to the 
478   // corresponding symbolic volume name
479   // The LUTs are static; they are created at the creation of the
480   // AliGeomManager instance and recreated if the geometry has changed
481   //
482
483   if(fgSymName[0]) return;
484
485   for (Int_t iLayer = 0; iLayer < (kLastLayer - kFirstLayer); iLayer++){
486     if(!fgSymName[iLayer]) fgSymName[iLayer]=new TString[fgLayerSize[iLayer]];
487   }
488
489   TString symname;
490   Int_t modnum; // in the following, set it to 0 at the start of each layer
491
492   /*********************       ITS layers  ***********************/
493   TString strSPD = "ITS/SPD";
494   TString strSDD = "ITS/SDD";
495   TString strSSD = "ITS/SSD";
496   TString strStave = "/Stave";
497   TString strLadder = "/Ladder";
498   TString strSector = "/Sector";
499   TString strSensor = "/Sensor";
500   TString strEntryName1;
501   TString strEntryName2;
502
503
504   /*********************       SPD layer1  ***********************/
505   {
506     modnum = 0;
507
508     for(Int_t c1 = 1; c1<=10; c1++){
509       strEntryName1 = strSPD;
510       strEntryName1 += 0;
511       strEntryName1 += strSector;
512       strEntryName1 += (c1-1);
513       for(Int_t c2 =1; c2<=2; c2++){
514         strEntryName2 = strEntryName1;
515         strEntryName2 += strStave;
516         strEntryName2 += (c2-1);
517         for(Int_t c3 =1; c3<=4; c3++){
518           symname = strEntryName2;
519           symname += strLadder;
520           symname += (c3-1);
521           fgSymName[kSPD1-kFirstLayer][modnum] = symname.Data();
522           modnum++;
523         }
524       }
525     }
526   }
527   
528   /*********************       SPD layer2  ***********************/
529   {
530     modnum = 0;
531
532     for(Int_t c1 = 1; c1<=10; c1++){
533       strEntryName1 = strSPD;
534       strEntryName1 += 1;
535       strEntryName1 += strSector;
536       strEntryName1 += (c1-1);
537       for(Int_t c2 =1; c2<=4; c2++){
538         strEntryName2 = strEntryName1;
539         strEntryName2 += strStave;
540         strEntryName2 += (c2-1);
541         for(Int_t c3 =1; c3<=4; c3++){
542           symname = strEntryName2;
543           symname += strLadder;
544           symname += (c3-1);
545           fgSymName[kSPD2-kFirstLayer][modnum] = symname.Data();
546           modnum++;
547         }
548       }
549     }
550   }
551
552   /*********************       SDD layer1  ***********************/
553   {
554     modnum=0;
555
556     for(Int_t c1 = 1; c1<=14; c1++){
557       strEntryName1 = strSDD;
558       strEntryName1 += 2;
559       strEntryName1 +=strLadder;
560       strEntryName1 += (c1-1);
561       for(Int_t c2 =1; c2<=6; c2++){
562         symname = strEntryName1;
563         symname += strSensor;
564         symname += (c2-1);
565         fgSymName[kSDD1-kFirstLayer][modnum] = symname.Data();
566         modnum++;
567       }
568     }
569   }
570
571   /*********************       SDD layer2  ***********************/
572   {
573     modnum=0;
574
575     for(Int_t c1 = 1; c1<=22; c1++){
576       strEntryName1 = strSDD;
577       strEntryName1 += 3;
578       strEntryName1 +=strLadder;
579       strEntryName1 += (c1-1);
580       for(Int_t c2 = 1; c2<=8; c2++){
581         symname = strEntryName1;
582         symname += strSensor;
583         symname += (c2-1);
584         fgSymName[kSDD2-kFirstLayer][modnum] = symname.Data();
585         modnum++;
586       }
587     }
588   }
589
590   /*********************       SSD layer1  ***********************/
591   {
592     modnum=0;
593
594     for(Int_t c1 = 1; c1<=34; c1++){
595       strEntryName1 = strSSD;
596       strEntryName1 += 4;
597       strEntryName1 +=strLadder;
598       strEntryName1 += (c1-1);
599       for(Int_t c2 = 1; c2<=22; c2++){
600         symname = strEntryName1;
601         symname += strSensor;
602         symname += (c2-1);
603         fgSymName[kSSD1-kFirstLayer][modnum] = symname.Data();
604         modnum++;
605       }
606     }
607   }
608
609   /*********************       SSD layer2  ***********************/
610   {
611     modnum=0;
612
613     for(Int_t c1 = 1; c1<=38; c1++){
614       strEntryName1 = strSSD;
615       strEntryName1 += 5;
616       strEntryName1 +=strLadder;
617       strEntryName1 += (c1-1);
618       for(Int_t c2 = 1; c2<=25; c2++){
619         symname = strEntryName1;
620         symname += strSensor;
621         symname += (c2-1);
622         fgSymName[kSSD2-kFirstLayer][modnum] = symname.Data();
623         modnum++;
624       }
625     }
626   }
627
628
629   /***************    TPC inner and outer layers    ****************/
630   TString sAsector="TPC/EndcapA/Sector";
631   TString sCsector="TPC/EndcapC/Sector";
632   TString sInner="/InnerChamber";
633   TString sOuter="/OuterChamber";
634   
635   /***************    TPC inner chambers' layer    ****************/
636   {
637     modnum = 0;
638     
639     for(Int_t cnt=1; cnt<=18; cnt++){
640       symname = sAsector;
641       symname += cnt;
642       symname += sInner;
643       fgSymName[kTPC1-kFirstLayer][modnum] = symname.Data();
644       modnum++;
645     }
646     for(Int_t cnt=1; cnt<=18; cnt++){
647       symname = sCsector;
648       symname += cnt;
649       symname += sInner;
650       fgSymName[kTPC1-kFirstLayer][modnum] = symname.Data();
651       modnum++;
652     }
653   }
654
655   /***************    TPC outer chambers' layer    ****************/
656   {
657     modnum = 0;
658     
659     for(Int_t cnt=1; cnt<=18; cnt++){
660       symname = sAsector;
661       symname += cnt;
662       symname += sOuter;
663       fgSymName[kTPC2-kFirstLayer][modnum] = symname.Data();
664       modnum++;
665     }
666     for(Int_t cnt=1; cnt<=18; cnt++){
667       symname = sCsector;
668       symname += cnt;
669       symname += sOuter;
670       fgSymName[kTPC2-kFirstLayer][modnum] = symname.Data();
671       modnum++;
672     }
673   }    
674
675   /*********************       TOF layer   ***********************/
676   {
677     modnum=0;
678     
679     Int_t nstrA=15;
680     Int_t nstrB=19;
681     Int_t nstrC=19;
682     Int_t nSectors=18;
683     Int_t nStrips=nstrA+2*nstrB+2*nstrC;
684     
685     TString snSM  = "TOF/sm";
686     TString snSTRIP = "/strip";
687     
688     for (Int_t isect = 0; isect < nSectors; isect++) {
689       for (Int_t istr = 1; istr <= nStrips; istr++) {   
690         symname  = snSM;
691         symname += Form("%02d",isect);
692         symname += snSTRIP;
693         symname += Form("%02d",istr);
694         fgSymName[kTOF-kFirstLayer][modnum] = symname.Data();   
695         modnum++;
696       }
697     }
698   } 
699
700   /*********************      HMPID layer   ***********************/
701   {
702     TString str = "/HMPID/Chamber";
703
704     for (modnum=0; modnum < 7; modnum++) {
705       symname = str;
706       symname += modnum;
707       fgSymName[kHMPID-kFirstLayer][modnum] = symname.Data();
708     }
709   }
710
711   /*********************      TRD layers 1-6   *******************/
712   //!! 6 layers with index increasing in outwards direction
713   {
714     Int_t arTRDlayId[6] = {kTRD1, kTRD2, kTRD3, kTRD4, kTRD5, kTRD6};
715
716     TString snStr  = "TRD/sm";
717     TString snApp1 = "/st";
718     TString snApp2 = "/pl";
719     
720     for(Int_t layer=0; layer<6; layer++){
721       modnum=0;
722       for (Int_t isect = 0; isect < 18; isect++) {
723         for (Int_t icham = 0; icham < 5; icham++) {
724           symname  = snStr;
725           symname += Form("%02d",isect);
726           symname += snApp1;
727           symname += icham;
728           symname += snApp2;
729           symname += layer;
730           fgSymName[arTRDlayId[layer]-kFirstLayer][modnum] = symname.Data();
731           modnum++;
732         }
733       }
734     }
735   }
736
737   /*********************      PHOS EMC layer   ***********************/
738   {
739     TString str = "PHOS/Module";
740     modnum=0;
741
742     for (Int_t iModule=1; iModule <= 5; iModule++) {
743       symname = str;
744       symname += iModule;
745       modnum = iModule-1;
746       fgSymName[kPHOS1-kFirstLayer][modnum] = symname.Data();
747     }
748   }
749
750   /*********************      PHOS CPV layer   ***********************/
751   {
752     TString str = "PHOS/Module";
753     modnum=0;
754
755     for (Int_t iModule=1; iModule <= 5; iModule++) {
756       symname = str;
757       symname += iModule;
758       symname += "/CPV";
759       modnum = iModule-1;
760       fgSymName[kPHOS2-kFirstLayer][modnum] = symname.Data();
761     }
762   }
763
764
765 }
766
767 //_____________________________________________________________________________
768 void AliGeomManager::InitPNEntriesLUT()
769 {
770   // Initialize the look-up table which associates the unique
771   // numerical identity of each alignable volume to the
772   // corresponding TGeoPNEntry.
773   // The LUTs are static; they are created at the creation of the
774   // AliGeomManager instance and recreated if the geometry has changed
775   //
776   if (fgPNEntry[0]) return;
777
778   if(!fgGeometry) {
779     AliErrorClass("Impossible to initialize PNEntries LUT without an active geometry");
780     return;
781   }
782
783   for (Int_t iLayer = 0; iLayer < (kLastLayer - kFirstLayer); iLayer++){
784     fgPNEntry[iLayer] = new TGeoPNEntry*[fgLayerSize[iLayer]];
785     for(Int_t modnum=0; modnum<fgLayerSize[iLayer]; modnum++){
786       fgPNEntry[iLayer][modnum] = fgGeometry->GetAlignableEntry(fgSymName[iLayer][modnum]);
787     }
788   }
789 }
790
791 //_____________________________________________________________________________
792 void AliGeomManager::InitOrigMatricesLUT()
793 {
794   // Initialize the storage for the look-up table with the original global
795   // matrices for each alignable volume.
796   // The LUTs are static; the matrices are created on demand and recreated
797   // if the geometry has changed.
798   if (fgOrigMatrix[0]) return;
799
800   if (!fgGeometry || !fgGeometry->IsClosed()) {
801     AliErrorClass("Impossible to initialize orignal matrices LUT without an active geometry");
802     return;
803   }
804
805   for (Int_t iLayer = 0; iLayer < (kLastLayer - kFirstLayer); iLayer++){
806     fgOrigMatrix[iLayer] = new TGeoHMatrix*[fgLayerSize[iLayer]];
807     for(Int_t modnum=0; modnum<fgLayerSize[iLayer]; modnum++){
808       if (!fgPNEntry[iLayer][modnum]) continue;
809       TGeoHMatrix *m = GetOrigGlobalMatrix(fgPNEntry[iLayer][modnum]);
810       if (!m) continue;
811       fgOrigMatrix[iLayer][modnum] = new TGeoHMatrix(*m);
812     }
813   }
814
815 }
816
817 //______________________________________________________________________
818 TGeoHMatrix* AliGeomManager::GetMatrix(TGeoPNEntry* pne) 
819 {
820   // Get the transformation matrix for a given PNEntry
821   // by quering the TGeoManager
822
823   if (!fgGeometry || !fgGeometry->IsClosed()) {
824     AliErrorClass("Can't get the global matrix! gGeoManager doesn't exist or it is still opened!");
825     return NULL;
826   }
827   
828   TGeoPhysicalNode *pnode = pne->GetPhysicalNode();
829   if (pnode) return pnode->GetMatrix();
830
831   const char* path = pne->GetTitle();
832   if (!fgGeometry->cd(path)) {
833     AliErrorClass(Form("Volume path %s not valid!",path));
834     return NULL;
835   }
836   return fgGeometry->GetCurrentMatrix();
837 }
838
839 //______________________________________________________________________
840 TGeoHMatrix* AliGeomManager::GetMatrix(Int_t index) 
841 {
842   // Get the global transformation matrix for a given alignable volume
843   // identified by its unique ID 'index' by quering the TGeoManager
844
845   TGeoPNEntry *pne = GetPNEntry(index);
846   if (!pne) return NULL;
847
848   return GetMatrix(pne);
849 }
850
851 //______________________________________________________________________
852 TGeoHMatrix* AliGeomManager::GetMatrix(const char* symname) 
853 {
854   // Get the global transformation matrix for a given alignable volume
855   //  identified by its symbolic name 'symname' by quering the TGeoManager
856
857   if (!fgGeometry || !fgGeometry->IsClosed()) {
858     AliErrorClass("No active geometry or geometry not yet closed!");
859     return NULL;
860   }
861
862   TGeoPNEntry* pne = fgGeometry->GetAlignableEntry(symname);
863   if (!pne) return NULL;
864
865   return GetMatrix(pne);
866 }
867
868 //______________________________________________________________________
869 Bool_t AliGeomManager::GetTranslation(Int_t index, Double_t t[3]) 
870 {
871   // Get the translation vector for a given module 'index'
872   // by quering the TGeoManager
873
874   TGeoHMatrix *m = GetMatrix(index);
875   if (!m) return kFALSE;
876
877   Double_t *trans = m->GetTranslation();
878   for (Int_t i = 0; i < 3; i++) t[i] = trans[i];
879
880   return kTRUE;
881 }
882
883 //______________________________________________________________________
884 Bool_t AliGeomManager::GetRotation(Int_t index, Double_t r[9]) 
885 {
886   // Get the rotation matrix for a given module 'index'
887   // by quering the TGeoManager
888
889   TGeoHMatrix *m = GetMatrix(index);
890   if (!m) return kFALSE;
891
892   Double_t *rot = m->GetRotationMatrix();
893   for (Int_t i = 0; i < 9; i++) r[i] = rot[i];
894
895   return kTRUE;
896 }
897
898 //______________________________________________________________________
899 Bool_t AliGeomManager::GetOrigGlobalMatrix(const char* symname, TGeoHMatrix &m) 
900 {
901   // Get the global transformation matrix (ideal geometry) for a given alignable volume
902   //  identified by its symbolic name 'symname' by quering the TGeoManager
903   m.Clear();
904
905   if (!fgGeometry || !fgGeometry->IsClosed()) {
906     AliErrorClass("No active geometry or geometry not yet closed!");
907     return kFALSE;
908   }
909   if (!fgGeometry->GetListOfPhysicalNodes()) {
910     AliWarningClass("gGeoManager doesn't contain any aligned nodes!");
911     if (!fgGeometry->cd(symname)) {
912       AliErrorClass(Form("Volume path %s not valid!",symname));
913       return kFALSE;
914     }
915     else {
916       m = *fgGeometry->GetCurrentMatrix();
917       return kTRUE;
918     }
919   }
920
921   TGeoPNEntry* pne = fgGeometry->GetAlignableEntry(symname);
922   const char* path = NULL;
923   if(pne){
924     path = pne->GetTitle();
925   }else{
926     AliWarningClass(Form("The symbolic volume name %s does not correspond to a physical entry. Using it as a volume path!",symname));
927     path=symname;
928   }
929
930   return GetOrigGlobalMatrixFromPath(path,m);
931 }
932
933 //_____________________________________________________________________________
934 Bool_t AliGeomManager::GetOrigGlobalMatrixFromPath(const char *path, TGeoHMatrix &m)
935 {
936   // The method returns global matrix for the ideal detector geometry
937   // Symname identifies either the corresponding TGeoPNEntry or directly
938   // the volume path. The output global matrix is stored in 'm'.
939   // Returns kFALSE in case TGeo has not been initialized or the symname
940   // is invalid.
941   //
942   m.Clear();
943
944   if (!fgGeometry || !fgGeometry->IsClosed()) {
945     AliErrorClass("Can't get the original global matrix! gGeoManager doesn't exist or it is still opened!");
946     return kFALSE;
947   }
948
949   if (!fgGeometry->CheckPath(path)) {
950     AliErrorClass(Form("Volume path %s not valid!",path));
951     return kFALSE;
952   }
953
954   TIter next(fgGeometry->GetListOfPhysicalNodes());
955   fgGeometry->cd(path);
956
957   while(fgGeometry->GetLevel()){
958
959     TGeoPhysicalNode *physNode = NULL;
960     next.Reset();
961     TGeoNode *node = fgGeometry->GetCurrentNode();
962     while ((physNode=(TGeoPhysicalNode*)next())) 
963       if (physNode->GetNode() == node) break;
964
965     TGeoMatrix *lm = NULL;
966     if (physNode) {
967         lm = physNode->GetOriginalMatrix();
968         if (!lm) lm = node->GetMatrix();
969     } else
970       lm = node->GetMatrix();
971
972     m.MultiplyLeft(lm);
973
974     fgGeometry->CdUp();
975   }
976
977   return kTRUE;
978 }
979
980 //_____________________________________________________________________________
981 TGeoHMatrix* AliGeomManager::GetOrigGlobalMatrix(TGeoPNEntry* pne)
982 {
983   // The method returns global matrix for the ideal detector geometry
984   // using the corresponding TGeoPNEntry as an input.
985   // The method creates a new matrix, so it has to be used carefully in order
986   // to avoid memory leaks.
987   // In case of missing TGeoManager the method return NULL.
988
989   if (!fgGeometry || !fgGeometry->IsClosed()) {
990     AliErrorClass("Can't get the global matrix! gGeoManager doesn't exist or it is still opened!");
991     return NULL;
992   }
993
994   const char* path = pne->GetTitle();
995   static TGeoHMatrix m;
996   if (!GetOrigGlobalMatrixFromPath(path,m))
997     return NULL;
998
999   return &m;
1000 }
1001
1002 //______________________________________________________________________
1003 TGeoHMatrix* AliGeomManager::GetOrigGlobalMatrix(Int_t index)
1004 {
1005   // Get the original (ideal geometry) TGeo matrix for
1006   // a given module identified by 'index'.
1007   // In general the method is slow, so we use
1008   // LUT for fast access. The LUT is reset in case of
1009   // new geometry is loaded.
1010   Int_t modId;
1011   ELayerID layerId = VolUIDToLayer(index,modId);
1012
1013   if (fgOrigMatrix[layerId-kFirstLayer][modId])
1014     return fgOrigMatrix[layerId-kFirstLayer][modId];
1015   else {
1016     TGeoPNEntry *pne = GetPNEntry(index);
1017     if (!pne) return NULL;
1018     return GetOrigGlobalMatrix(pne);
1019   }
1020 }
1021
1022 //______________________________________________________________________
1023 Bool_t AliGeomManager::GetOrigTranslation(Int_t index, Double_t t[3]) 
1024 {
1025   // Get the original translation vector (ideal geometry)
1026   // for a given module 'index' by quering the TGeoManager
1027
1028   TGeoHMatrix *m = GetOrigGlobalMatrix(index);
1029   if (!m) return kFALSE;
1030
1031   Double_t *trans = m->GetTranslation();
1032   for (Int_t i = 0; i < 3; i++) t[i] = trans[i];
1033
1034   return kTRUE;
1035 }
1036
1037 //______________________________________________________________________
1038 Bool_t AliGeomManager::GetOrigRotation(Int_t index, Double_t r[9]) 
1039 {
1040   // Get the original rotation matrix (ideal geometry)
1041   // for a given module 'index' by quering the TGeoManager
1042
1043   TGeoHMatrix *m = GetOrigGlobalMatrix(index);
1044   if (!m) return kFALSE;
1045
1046   Double_t *rot = m->GetRotationMatrix();
1047   for (Int_t i = 0; i < 9; i++) r[i] = rot[i];
1048
1049   return kTRUE;
1050 }
1051
1052 //______________________________________________________________________
1053 const TGeoHMatrix* AliGeomManager::GetTracking2LocalMatrix(Int_t index)
1054 {
1055   // Get the matrix which transforms from the tracking to the local RS
1056   // The method queries directly the TGeoPNEntry
1057
1058   TGeoPNEntry *pne = GetPNEntry(index);
1059   if (!pne) return NULL;
1060
1061   const TGeoHMatrix *m = pne->GetMatrix();
1062   if (!m)
1063     AliErrorClass(Form("TGeoPNEntry (%s) contains no matrix !",pne->GetName()));
1064
1065   return m;
1066 }
1067
1068 //______________________________________________________________________
1069 Bool_t AliGeomManager::GetTrackingMatrix(Int_t index, TGeoHMatrix &m)
1070 {
1071   // Get the matrix which transforms from the tracking r.s. to
1072   // the global one.
1073   // Returns kFALSE in case of error.
1074
1075   m.Clear();
1076
1077   TGeoHMatrix *m1 = GetMatrix(index);
1078   if (!m1) return kFALSE;
1079
1080   const TGeoHMatrix *m2 = GetTracking2LocalMatrix(index);
1081   if (!m2) return kFALSE;
1082
1083   m = *m1;
1084   m.Multiply(m2);
1085
1086   return kTRUE;
1087 }
1088
1089 //_____________________________________________________________________________
1090 TGeoPNEntry* AliGeomManager::GetPNEntry(Int_t voluid) {
1091   // Returns the TGeoPNEntry for the given global volume ID "voluid"
1092   //
1093   Int_t modId;
1094   ELayerID layerId = VolUIDToLayer(voluid,modId);
1095   return GetPNEntry(layerId,modId);
1096 }
1097
1098 //_____________________________________________________________________________
1099 TGeoPNEntry* AliGeomManager::GetPNEntry(ELayerID layerId, Int_t modId)
1100 {
1101   // Returns the TGeoPNEntry for a given layer
1102   // and module ID
1103   //
1104
1105   if(modId<0 || modId>=fgLayerSize[layerId-kFirstLayer]){
1106     AliWarningClass(Form("Module number %d not in the valid range (0->%d) !",modId,fgLayerSize[layerId-kFirstLayer]-1));
1107     return NULL;
1108   }
1109
1110   return fgPNEntry[layerId-kFirstLayer][modId];
1111 }
1112
1113 //_____________________________________________________________________________
1114 Bool_t AliGeomManager::ApplyAlignObjsFromCDB(const char* AlignDetsList)
1115 {
1116   // Calls AddAlignObjsFromCDBSingleDet for the detectors appearing in
1117   // the list passed as argument (called by AliSimulation and
1118   // AliReconstruction)
1119   // Read the alignment objects from CDB.
1120   // Each detector is supposed to have the
1121   // alignment objects in DET/Align/Data CDB path.
1122   // All the detector objects are then collected,
1123   // sorted by geometry level (starting from ALIC) and
1124   // then applied to the TGeo geometry.
1125   // Finally an overlaps check is performed.
1126   //
1127  
1128   TObjArray alignObjArray;
1129   alignObjArray.Clear();        
1130   alignObjArray.SetOwner(0);
1131
1132   TString alObjsNotLoaded="";
1133   TString alObjsLoaded="";
1134
1135   TString AlignDetsString(AlignDetsList);
1136   TObjArray *detsarr = AlignDetsString.Tokenize(' ');
1137   TIter iter(detsarr);
1138   TObjString *str = 0;
1139   
1140   while((str = (TObjString*) iter.Next())){
1141     TString det(str->String());
1142     AliInfoClass(Form("Loading alignment objs for %s",det.Data()));
1143     if(!LoadAlignObjsFromCDBSingleDet(det.Data(),alignObjArray)){
1144       alObjsNotLoaded += det.Data();
1145       alObjsNotLoaded += " ";
1146     } else {
1147       alObjsLoaded += det.Data();
1148       alObjsLoaded += " ";
1149     }
1150   }
1151
1152   if(!alObjsLoaded.IsNull()) AliInfoClass(Form("Alignment objects loaded for: %s",
1153                                                alObjsLoaded.Data()));
1154   if(!alObjsNotLoaded.IsNull()) AliInfoClass(Form("Didn't/couldn't load alignment objects for: %s",
1155                                                   alObjsNotLoaded.Data()));
1156  
1157   return ApplyAlignObjsToGeom(alignObjArray);
1158 }
1159
1160 //_____________________________________________________________________________
1161 Bool_t AliGeomManager::LoadAlignObjsFromCDBSingleDet(const char* detName, TObjArray& alignObjArray)
1162 {
1163   // Adds the alignable objects found in the CDBEntry for the detector
1164   // passed as argument to the array of all alignment objects to be applyed
1165   // to geometry
1166   //
1167   // Fills array of single detector's alignable objects from CDB
1168   
1169   AliDebugClass(2, Form("Loading alignment objs for detector: %s",detName));
1170   
1171   AliCDBEntry *entry;
1172         
1173   AliCDBPath path(detName,"Align","Data");
1174         
1175   entry=AliCDBManager::Instance()->Get(path.GetPath());
1176   if(!entry){ 
1177         AliDebugClass(2,Form("Couldn't load alignment data for detector %s",detName));
1178         return kFALSE;
1179   }
1180   entry->SetOwner(1);
1181   TClonesArray *alignArray = (TClonesArray*) entry->GetObject();        
1182   alignArray->SetOwner(0);
1183   AliDebugClass(2,Form("Found %d alignment objects for %s",
1184                        alignArray->GetEntries(),detName));
1185
1186   AliAlignObj *alignObj=0;
1187   TIter iter(alignArray);
1188         
1189   // loop over align objects in detector
1190   while( ( alignObj=(AliAlignObj *) iter.Next() ) ){
1191         alignObjArray.Add(alignObj);
1192   }
1193   // delete entry --- Don't delete, it is cached!
1194         
1195   AliDebugClass(2, Form("fAlignObjArray entries: %d",alignObjArray.GetEntries() ));
1196   return kTRUE;
1197
1198 }
1199
1200 //_____________________________________________________________________________
1201 Bool_t AliGeomManager::ApplyAlignObjsToGeom(TObjArray& alignObjArray)
1202 {
1203   // Read collection of alignment objects (AliAlignObj derived) saved
1204   // in the TClonesArray alObjArray and apply them to gGeoManager
1205   //
1206   alignObjArray.Sort();
1207   Int_t nvols = alignObjArray.GetEntriesFast();
1208
1209   Bool_t flag = kTRUE;
1210
1211   for(Int_t j=0; j<nvols; j++)
1212     {
1213       AliAlignObj* alobj = (AliAlignObj*) alignObjArray.UncheckedAt(j);
1214       if (alobj->ApplyToGeometry() == kFALSE) flag = kFALSE;
1215     }
1216
1217   if (AliDebugLevelClass() >= 1) {
1218     fgGeometry->GetTopNode()->CheckOverlaps(1);
1219     TObjArray* ovexlist = fgGeometry->GetListOfOverlaps();
1220     if(ovexlist->GetEntriesFast()){  
1221       AliErrorClass("The application of alignment objects to the geometry caused huge overlaps/extrusions!");
1222    }
1223   }
1224
1225   // Update the TGeoPhysicalNodes
1226   fgGeometry->RefreshPhysicalNodes();
1227
1228   return flag;
1229
1230 }
1231
1232 //_____________________________________________________________________________
1233 Bool_t AliGeomManager::ApplyAlignObjsToGeom(const char* fileName, const char* clArrayName)
1234 {
1235   // read collection of alignment objects (AliAlignObj derived) saved
1236   // in the TClonesArray ClArrayName in the file fileName and apply
1237   // them to the geometry
1238   //
1239
1240   TFile* inFile = TFile::Open(fileName,"READ");
1241   if (!inFile || !inFile->IsOpen()) {
1242     AliErrorClass(Form("Could not open file %s !",fileName));
1243     return kFALSE;
1244   }
1245
1246   TClonesArray* alignObjArray = ((TClonesArray*) inFile->Get(clArrayName));
1247   inFile->Close();
1248   if (!alignObjArray) {
1249     AliErrorClass(Form("Could not get array (%s) from file (%s) !",clArrayName,fileName));
1250     return kFALSE;
1251   }
1252
1253   return ApplyAlignObjsToGeom(*alignObjArray);
1254
1255 }
1256
1257 //_____________________________________________________________________________
1258 Bool_t AliGeomManager::ApplyAlignObjsToGeom(AliCDBParam* param, AliCDBId& Id)
1259 {
1260   // read collection of alignment objects (AliAlignObj derived) saved
1261   // in the TClonesArray ClArrayName in the AliCDBEntry identified by
1262   // param (to get the AliCDBStorage) and Id; apply the alignment objects
1263   // to the geometry
1264   //
1265
1266   AliCDBStorage* storage = AliCDBManager::Instance()->GetStorage(param);
1267   AliCDBEntry* entry = storage->Get(Id);
1268   TClonesArray* alignObjArray = ((TClonesArray*) entry->GetObject());
1269
1270   return ApplyAlignObjsToGeom(*alignObjArray);
1271
1272 }
1273
1274 //_____________________________________________________________________________
1275 Bool_t AliGeomManager::ApplyAlignObjsToGeom(const char* uri, const char* path, Int_t runnum, Int_t version, Int_t sversion)
1276 {
1277   // read collection of alignment objects (AliAlignObj derived) saved
1278   // in the TClonesArray ClArrayName in the AliCDBEntry identified by
1279   // param (to get the AliCDBStorage) and Id; apply the alignment objects
1280   // to the geometry
1281   //
1282
1283   AliCDBParam* param = AliCDBManager::Instance()->CreateParameter(uri);
1284   AliCDBId id(path, runnum, runnum, version, sversion);
1285
1286   return ApplyAlignObjsToGeom(param, id);
1287
1288 }
1289
1290 //_____________________________________________________________________________
1291 Bool_t AliGeomManager::ApplyAlignObjsToGeom(const char* detName, Int_t runnum, Int_t version, Int_t sversion)
1292 {
1293   // read collection of alignment objects (AliAlignObj derived) saved
1294   // in the TClonesArray ClArrayName in the AliCDBEntry identified by
1295   // param (to get the AliCDBStorage) and Id; apply the alignment objects
1296   // to the geometry
1297   //
1298
1299   AliCDBPath path(detName,"Align","Data");
1300   AliCDBEntry* entry = AliCDBManager::Instance()->Get(path.GetPath(),runnum,version,sversion);
1301
1302   if(!entry) return kFALSE;
1303   TClonesArray* alignObjArray = ((TClonesArray*) entry->GetObject());
1304
1305   return ApplyAlignObjsToGeom(*alignObjArray);
1306 }