ee4f0db96e87c186fbd1556fd1699a06f4ef388b
[u/mrichter/AliRoot.git] / STEER / AliAlignObj.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 //-----------------------------------------------------------------
17 //   Implementation of the alignment object class through the abstract
18 //  class AliAlignObj. From it two derived concrete representation of
19 //  alignment object class (AliAlignObjAngles, AliAlignObjMatrix) are
20 //  derived in separate files.
21 //-----------------------------------------------------------------
22 /*****************************************************************************
23  * AliAlignObjAngles: derived alignment class storing alignment information  *
24  *   for a single volume in form of three doubles for the translation        *
25  *   and three doubles for the rotation expressed with the euler angles      *
26  *   in the xyz-convention (http://mathworld.wolfram.com/EulerAngles.html),  *
27  *   also known as roll, pitch, yaw. PLEASE NOTE THE ANGLES SIGNS ARE        *
28  *   INVERSE WITH RESPECT TO THIS REFERENCE!!! In this way the representation*
29  *   is fully consistent with the TGeo Rotation methods.                     *
30  *****************************************************************************/
31
32 #include <TGeoManager.h>
33 #include <TGeoPhysicalNode.h>
34
35 #include "AliAlignObj.h"
36 #include "AliTrackPointArray.h"
37 #include "AliLog.h"
38 #include "AliAlignObjAngles.h"
39  
40 ClassImp(AliAlignObj)
41
42 Int_t AliAlignObj::fgLayerSize[kLastLayer - kFirstLayer] = {
43   80, 160,  // ITS SPD
44   84, 176,  // ITS SDD
45   748, 950, // ITS SSD
46   36, 36,   // TPC
47   90, 90, 90, 90, 90, 90,  // TRD
48   1638,     // TOF
49   1, 1,     // PHOS ??
50   7,        // RICH ??
51   1         // MUON ??
52 };
53
54 const char* AliAlignObj::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   "?","?",
63   "RICH layer",
64   "?"
65 };
66
67 TString* AliAlignObj::fgVolPath[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 AliAlignObj** AliAlignObj::fgAlignObjs[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 //_____________________________________________________________________________
94 AliAlignObj::AliAlignObj():
95   fVolPath(),
96   fVolUID(0)
97 {
98   // default constructor
99   InitVolPaths();
100 }
101
102 //_____________________________________________________________________________
103 AliAlignObj::AliAlignObj(const char* volpath, UShort_t voluid) :
104   TObject(),
105   fVolPath(volpath),
106   fVolUID(voluid)
107 {
108   // standard constructor
109   //
110 }
111
112 AliAlignObj::AliAlignObj(const char* volpath, ELayerID detId, Int_t volId) :
113   TObject(),
114   fVolPath(volpath),
115   fVolUID(0)
116 {
117   // standard constructor
118   // 
119   SetVolUID(detId,volId); 
120 }
121
122 //_____________________________________________________________________________
123 AliAlignObj::AliAlignObj(const AliAlignObj& theAlignObj) :
124   TObject(theAlignObj),
125   fVolPath(theAlignObj.GetVolPath()),
126   fVolUID(theAlignObj.GetVolUID())
127 {
128   //copy constructor
129 }
130
131 //_____________________________________________________________________________
132 AliAlignObj &AliAlignObj::operator =(const AliAlignObj& theAlignObj)
133 {
134   // assignment operator
135   if(this==&theAlignObj) return *this;
136   fVolPath = theAlignObj.GetVolPath();
137   fVolUID = theAlignObj.GetVolUID();
138   return *this;
139 }
140
141 //_____________________________________________________________________________
142 AliAlignObj &AliAlignObj::operator*=(const AliAlignObj& theAlignObj)
143 {
144   // multiplication operator
145   // The operator can be used to 'combine'
146   // two alignment objects
147   TGeoHMatrix m1;
148   GetMatrix(m1);
149   TGeoHMatrix m2;
150   theAlignObj.GetMatrix(m2);
151   m1.MultiplyLeft(&m2);
152   SetMatrix(m1);
153   return *this;
154 }
155
156 //_____________________________________________________________________________
157 AliAlignObj::~AliAlignObj()
158 {
159   // dummy destructor
160 }
161
162 //_____________________________________________________________________________
163 void AliAlignObj::SetVolUID(ELayerID detId, Int_t modId)
164 {
165   // From detector name and module number (according to detector numbering)
166   // build fVolUID, unique numerical identity of that volume inside ALICE
167   // fVolUID is 16 bits, first 5 reserved for detID (32 possible values),
168   // remaining 11 for module ID inside det (2048 possible values).
169   //
170   fVolUID = LayerToVolUID(detId,modId);
171 }
172
173 //_____________________________________________________________________________
174 void AliAlignObj::GetVolUID(ELayerID &layerId, Int_t &modId) const
175 {
176   // From detector name and module number (according to detector numbering)
177   // build fVolUID, unique numerical identity of that volume inside ALICE
178   // fVolUID is 16 bits, first 5 reserved for detID (32 possible values),
179   // remaining 11 for module ID inside det (2048 possible values).
180   //
181   layerId = VolUIDToLayer(fVolUID,modId);
182 }
183
184 //_____________________________________________________________________________
185 Int_t AliAlignObj::GetLevel() const
186 {
187   // Return the geometry level of
188   // the alignable volume to which
189   // the alignment object is associated
190   TString volpath = fVolPath;
191   return (volpath.CountChar('/')+1);
192 }
193
194 //_____________________________________________________________________________
195 Int_t AliAlignObj::Compare(const TObject *obj) const
196 {
197   // Compare the levels of two
198   // alignment objects
199   // Used in the sorting during
200   // the application of alignment
201   // objects to the geometry
202   Int_t level = GetLevel();
203   Int_t level2 = ((AliAlignObj *)obj)->GetLevel();
204   if (level == level2)
205     return 0;
206   else
207     return ((level > level2) ? 1 : -1);
208 }
209
210 //_____________________________________________________________________________
211 void AliAlignObj::AnglesToMatrix(const Double_t *angles, Double_t *rot) const
212 {
213   // Calculates the rotation matrix using the 
214   // Euler angles in "x y z" notation
215   Double_t degrad = TMath::DegToRad();
216   Double_t sinpsi = TMath::Sin(degrad*angles[0]);
217   Double_t cospsi = TMath::Cos(degrad*angles[0]);
218   Double_t sinthe = TMath::Sin(degrad*angles[1]);
219   Double_t costhe = TMath::Cos(degrad*angles[1]);
220   Double_t sinphi = TMath::Sin(degrad*angles[2]);
221   Double_t cosphi = TMath::Cos(degrad*angles[2]);
222
223   rot[0] =  costhe*cosphi;
224   rot[1] = -costhe*sinphi;
225   rot[2] =  sinthe;
226   rot[3] =  sinpsi*sinthe*cosphi + cospsi*sinphi;
227   rot[4] = -sinpsi*sinthe*sinphi + cospsi*cosphi;
228   rot[5] = -costhe*sinpsi;
229   rot[6] = -cospsi*sinthe*cosphi + sinpsi*sinphi;
230   rot[7] =  cospsi*sinthe*sinphi + sinpsi*cosphi;
231   rot[8] =  costhe*cospsi;
232 }
233
234 //_____________________________________________________________________________
235 Bool_t AliAlignObj::MatrixToAngles(const Double_t *rot, Double_t *angles) const
236 {
237   // Calculates the Euler angles in "x y z" notation
238   // using the rotation matrix
239   if(TMath::Abs(rot[0])<1e-7 || TMath::Abs(rot[8])<1e-7) return kFALSE;
240   Double_t raddeg = TMath::RadToDeg();
241   angles[0]=raddeg*TMath::ATan2(-rot[5],rot[8]);
242   angles[1]=raddeg*TMath::ASin(rot[2]);
243   angles[2]=raddeg*TMath::ATan2(-rot[1],rot[0]);
244   return kTRUE;
245 }
246
247 //______________________________________________________________________________
248 void AliAlignObj::Transform(AliTrackPoint &p) const
249 {
250   // The method transforms the space-point coordinates using the
251   // transformation matrix provided by the AliAlignObj
252   // The covariance matrix is not affected since we assume
253   // that the transformations are sufficiently small
254
255   if (fVolUID != p.GetVolumeID())
256     AliWarning(Form("Alignment object ID is not equal to the space-point ID (%d != %d)",fVolUID,p.GetVolumeID())); 
257
258   TGeoHMatrix m;
259   GetMatrix(m);
260   Double_t *rot = m.GetRotationMatrix();
261   Double_t *tr  = m.GetTranslation();
262
263   Float_t xyzin[3],xyzout[3];
264   p.GetXYZ(xyzin);
265   for (Int_t i = 0; i < 3; i++)
266     xyzout[i] = tr[i]+
267                 xyzin[0]*rot[3*i]+
268                 xyzin[1]*rot[3*i+1]+
269                 xyzin[2]*rot[3*i+2];
270   p.SetXYZ(xyzout);
271   
272 }
273
274 //_____________________________________________________________________________
275 void AliAlignObj::Transform(AliTrackPointArray &array) const
276 {
277   // This method is used to transform all the track points
278   // from the input AliTrackPointArray
279   AliTrackPoint p;
280   for (Int_t i = 0; i < array.GetNPoints(); i++) {
281     array.GetPoint(p,i);
282     Transform(p);
283     array.AddPoint(i,&p);
284   }
285 }
286
287 //_____________________________________________________________________________
288 void AliAlignObj::Print(Option_t *) const
289 {
290   // Print the contents of the
291   // alignment object in angles and
292   // matrix representations
293   Double_t tr[3];
294   GetTranslation(tr);
295   Double_t angles[3];
296   GetAngles(angles);
297   TGeoHMatrix m;
298   GetMatrix(m);
299   const Double_t *rot = m.GetRotationMatrix();
300
301   printf("Volume=%s\n",GetVolPath());
302   if (GetVolUID() != 0) {
303     ELayerID layerId;
304     Int_t modId;
305     GetVolUID(layerId,modId);
306     printf("VolumeID=%d LayerID=%d ( %s ) ModuleID=%d\n", GetVolUID(),layerId,LayerName(layerId),modId);
307   }
308   printf("%12.8f%12.8f%12.8f    Tx = %12.8f    Psi   = %12.8f\n", rot[0], rot[1], rot[2], tr[0], angles[0]);
309   printf("%12.8f%12.8f%12.8f    Ty = %12.8f    Theta = %12.8f\n", rot[3], rot[4], rot[5], tr[1], angles[1]);
310   printf("%12.8f%12.8f%12.8f    Tz = %12.8f    Phi   = %12.8f\n", rot[6], rot[7], rot[8], tr[2], angles[2]);
311
312 }
313
314 //_____________________________________________________________________________
315 Int_t AliAlignObj::LayerSize(Int_t layerId)
316 {
317   // Get the corresponding layer size.
318   // Implemented only for ITS,TPC,TRD,TOF and RICH
319   if (layerId < kFirstLayer || layerId >= kLastLayer) {
320     AliErrorClass(Form("Invalid layer index %d ! Layer range is (%d -> %d) !",layerId,kFirstLayer,kLastLayer));
321     return 0;
322   }
323   else {
324     return fgLayerSize[layerId - kFirstLayer];
325  }
326 }
327
328 //_____________________________________________________________________________
329 const char* AliAlignObj::LayerName(Int_t layerId)
330 {
331   // Get the corresponding layer name.
332   // Implemented only for ITS,TPC,TRD,TOF and RICH
333   if (layerId < kFirstLayer || layerId >= kLastLayer) {
334     AliErrorClass(Form("Invalid layer index %d ! Layer range is (%d -> %d) !",layerId,kFirstLayer,kLastLayer));
335     return "Invalid Layer!";
336   }
337   else {
338     return fgLayerName[layerId - kFirstLayer];
339  }
340 }
341
342 //_____________________________________________________________________________
343 UShort_t AliAlignObj::LayerToVolUID(ELayerID layerId, Int_t modId)
344 {
345   // From detector (layer) name and module number (according to detector numbering)
346   // build fVolUID, unique numerical identity of that volume inside ALICE
347   // fVolUID is 16 bits, first 5 reserved for layerID (32 possible values),
348   // remaining 11 for module ID inside det (2048 possible values).
349   //
350   return ((UShort_t(layerId) << 11) | UShort_t(modId));
351 }
352
353 //_____________________________________________________________________________
354 UShort_t AliAlignObj::LayerToVolUID(Int_t   layerId, Int_t modId)
355 {
356   // From detector (layer) index and module number (according to detector numbering)
357   // build fVolUID, unique numerical identity of that volume inside ALICE
358   // fVolUID is 16 bits, first 5 reserved for layerID (32 possible values),
359   // remaining 11 for module ID inside det (2048 possible values).
360   //
361   return ((UShort_t(layerId) << 11) | UShort_t(modId));
362 }
363
364 //_____________________________________________________________________________
365 AliAlignObj::ELayerID AliAlignObj::VolUIDToLayer(UShort_t voluid, Int_t &modId)
366 {
367   // From detector (layer) name and module number (according to detector numbering)
368   // build fVolUID, unique numerical identity of that volume inside ALICE
369   // fVolUID is 16 bits, first 5 reserved for layerID (32 possible values),
370   // remaining 11 for module ID inside det (2048 possible values).
371   //
372   modId = voluid & 0x7ff;
373
374   return VolUIDToLayer(voluid);
375 }
376
377 //_____________________________________________________________________________
378 AliAlignObj::ELayerID AliAlignObj::VolUIDToLayer(UShort_t voluid)
379 {
380   // From detector (layer) name and module number (according to detector numbering)
381   // build fVolUID, unique numerical identity of that volume inside ALICE
382   // fVolUID is 16 bits, first 5 reserved for layerID (32 possible values),
383   // remaining 11 for module ID inside det (2048 possible values).
384   //
385   return ELayerID((voluid >> 11) & 0x1f);
386 }
387
388 //_____________________________________________________________________________
389 Bool_t AliAlignObj::SetLocalPars(Double_t x, Double_t y, Double_t z,
390                                  Double_t psi, Double_t theta, Double_t phi)
391 {
392   // Set the translations and angles by using parameters
393   // defined in the local (in TGeo means) coordinate system
394   // of the alignable volume. In case that the TGeo was
395   // initialized, returns false and the object parameters are
396   // not set.
397   if (!gGeoManager || !gGeoManager->IsClosed()) {
398     AliError("Can't set the alignment object parameters! gGeoManager doesn't exist or it is still opened!");
399     return kFALSE;
400   }
401
402   const char* volpath = GetVolPath();
403   TGeoPhysicalNode* node = (TGeoPhysicalNode*) gGeoManager->MakePhysicalNode(volpath);
404   if (!node) {
405     AliError(Form("Volume path %s not valid!",volpath));
406     return kFALSE;
407   }
408   if (node->IsAligned())
409     AliWarning(Form("Volume %s has been already misaligned!",volpath));
410
411   TGeoHMatrix m;
412   Double_t tr[3];
413   tr[0]=x; tr[1]=y; tr[2]=z;
414   m.SetTranslation(tr);
415   Double_t angles[3] = {psi, theta, phi};
416   Double_t rot[9];
417   AnglesToMatrix(angles,rot);
418   m.SetRotation(rot);
419
420   TGeoHMatrix align,gprime,gprimeinv;
421   gprime = *node->GetMatrix();
422   gprimeinv = gprime.Inverse();
423   m.Multiply(&gprimeinv);
424   m.MultiplyLeft(&gprime);
425
426   SetMatrix(m);
427
428   return kTRUE;
429 }
430
431 //_____________________________________________________________________________
432 Bool_t AliAlignObj::ApplyToGeometry()
433 {
434   // Apply the current alignment object
435   // to the TGeo geometry
436
437   if (!gGeoManager || !gGeoManager->IsClosed()) {
438     AliError("Can't apply the alignment object! gGeoManager doesn't exist or it is still opened!");
439     return kFALSE;
440   }
441   
442   const char* volpath = GetVolPath();
443
444   if (gGeoManager->GetListOfPhysicalNodes()->FindObject(volpath)) {
445     AliError(Form("Volume %s has been already misaligned!",volpath));
446     return kFALSE;
447   }
448
449   if (!gGeoManager->cd(volpath)) {
450     AliError(Form("Volume path %s not valid!",volpath));
451     return kFALSE;
452   }
453
454   TGeoPhysicalNode* node = (TGeoPhysicalNode*) gGeoManager->MakePhysicalNode(volpath);
455   if (!node) {
456     AliError(Form("Volume path %s not valid!",volpath));
457     return kFALSE;
458   }
459
460   TGeoHMatrix align,gprime;
461   gprime = *node->GetMatrix();
462   GetMatrix(align);
463   gprime.MultiplyLeft(&align);
464   TGeoHMatrix *ginv = new TGeoHMatrix;
465   TGeoHMatrix *g = node->GetMatrix(node->GetLevel()-1);
466   *ginv = g->Inverse();
467   *ginv *= gprime;
468   AliAlignObj::ELayerID layerId; // unique identity for volume in the alobj
469   Int_t modId; // unique identity for volume in the alobj
470   GetVolUID(layerId, modId);
471   AliDebug(2,Form("Aligning volume %s of detector layer %d with local ID %d",volpath,layerId,modId));
472   node->Align(ginv);
473
474   return kTRUE;
475 }
476
477 //_____________________________________________________________________________
478 Bool_t AliAlignObj::GetFromGeometry(const char *path, AliAlignObj &alobj)
479 {
480   // Get the alignment object which correspond
481   // to the TGeo volume defined by the 'path'.
482   // The method is extremely slow due to the
483   // searching by string. Therefore it should
484   // be used with great care!!
485
486   // Reset the alignment object
487   alobj.SetPars(0,0,0,0,0,0);
488   alobj.SetVolPath(path);
489
490   if (!gGeoManager || !gGeoManager->IsClosed()) {
491     AliErrorClass("Can't get the alignment object! gGeoManager doesn't exist or it is still opened!");
492     return kFALSE;
493   }
494
495   if (!gGeoManager->GetListOfPhysicalNodes()) {
496     AliErrorClass("Can't get the alignment object! gGeoManager doesn't contain any aligned nodes!");
497     return kFALSE;
498   }
499
500   TObjArray* nodesArr = gGeoManager->GetListOfPhysicalNodes();
501   TGeoPhysicalNode* node = NULL;
502   for (Int_t iNode = 0; iNode < nodesArr->GetEntriesFast(); iNode++) {
503     node = (TGeoPhysicalNode*) nodesArr->UncheckedAt(iNode);
504     const char *nodePath = node->GetName();
505     if (strcmp(path,nodePath) == 0) break;
506   }
507   if (!node) {
508     if (!gGeoManager->cd(path)) {
509       AliErrorClass(Form("Volume path %s not found!",path));
510       return kFALSE;
511     }
512     else {
513       AliWarningClass(Form("Volume (%s) has not been misaligned!",path));
514       return kTRUE;
515     }
516   }
517
518   TGeoHMatrix align,gprime,g,ginv,l;
519   gprime = *node->GetMatrix();
520   l = *node->GetOriginalMatrix();
521   g = *node->GetMatrix(node->GetLevel()-1);
522   g *= l;
523   ginv = g.Inverse();
524   align = gprime * ginv;
525   alobj.SetMatrix(align);
526
527   return kTRUE;
528 }
529
530 //_____________________________________________________________________________
531 void  AliAlignObj::InitAlignObjFromGeometry()
532 {
533   // Loop over all alignable volumes and extract
534   // the corresponding alignment objects from
535   // the TGeo geometry
536
537   if(fgAlignObjs[0]) return;
538   
539   InitVolPaths();
540
541   for (Int_t iLayer = kFirstLayer; iLayer < AliAlignObj::kLastLayer; iLayer++) {
542     fgAlignObjs[iLayer-kFirstLayer] = new AliAlignObj*[AliAlignObj::LayerSize(iLayer)];
543     for (Int_t iModule = 0; iModule < AliAlignObj::LayerSize(iLayer); iModule++) {
544       UShort_t volid = AliAlignObj::LayerToVolUID(iLayer,iModule);
545       fgAlignObjs[iLayer-kFirstLayer][iModule] = new AliAlignObjAngles("",volid,0,0,0,0,0,0);
546       const char *path = GetVolPath(volid);
547       if (!GetFromGeometry(path, *fgAlignObjs[iLayer-kFirstLayer][iModule]))
548         AliErrorClass(Form("Failed to extract the alignment object for the volume (ID=%d and path=%s) !",volid,path));
549     }
550   }
551   
552 }
553
554 //_____________________________________________________________________________
555 AliAlignObj* AliAlignObj::GetAlignObj(UShort_t voluid) {
556   // Returns the alignment object for given volume ID
557   Int_t modId;
558   ELayerID layerId = VolUIDToLayer(voluid,modId);
559   return GetAlignObj(layerId,modId);
560 }
561
562 //_____________________________________________________________________________
563 AliAlignObj* AliAlignObj::GetAlignObj(ELayerID layerId, Int_t modId)
564 {
565   // Returns pointer to alignment object givent its layer and module ID
566   if(modId<0 || modId>=fgLayerSize[layerId-kFirstLayer]){
567     AliWarningClass(Form("Module number %d not in the valid range (0->%d) !",modId,fgLayerSize[layerId-kFirstLayer]-1));
568     return NULL;
569   }
570   return fgAlignObjs[layerId-kFirstLayer][modId];
571 }
572
573 //_____________________________________________________________________________
574 const char* AliAlignObj::GetVolPath(UShort_t voluid) {
575   // Returns the volume path for given volume ID
576   Int_t modId;
577   ELayerID layerId = VolUIDToLayer(voluid,modId);
578   return GetVolPath(layerId,modId);
579 }
580
581 //_____________________________________________________________________________
582 const char* AliAlignObj::GetVolPath(ELayerID layerId, Int_t modId)
583 {
584   // Returns volume path to alignment object givent its layer and module ID
585   if(modId<0 || modId>=fgLayerSize[layerId-kFirstLayer]){
586     AliWarningClass(Form("Module number %d not in the valid range (0->%d) !",modId,fgLayerSize[layerId-kFirstLayer]-1));
587     return NULL;
588   }
589   return fgVolPath[layerId-kFirstLayer][modId].Data();
590 }
591
592 //_____________________________________________________________________________
593 void AliAlignObj::InitVolPaths()
594 {
595   // Initialize the LUTs which contain
596   // the TGeo volume paths for each
597   // alignable volume. The LUTs are
598   // static, so they are created during
599   // the creation of the first intance
600   // of AliAlignObj
601
602   if (fgVolPath[0]) return;
603
604   for (Int_t iLayer = 0; iLayer < (kLastLayer - kFirstLayer); iLayer++)
605     fgVolPath[iLayer] = new TString[fgLayerSize[iLayer]];
606
607   /*********************       SPD layer1  ***********************/
608   {
609     Int_t modnum = 0;
610     TString str0 = "ALIC_1/ITSV_1/ITSD_1/IT12_1/I12B_"; //".../I12A_"
611     TString str1 = "/I10B_";    //"/I10A_";
612     TString str2 = "/I107_";    //"/I103_"
613     //    TString str3 = "/I101_1/ITS1_1";
614     TString volpath, volpath1, volpath2;
615
616     for(Int_t c1 = 1; c1<=10; c1++){
617       volpath = str0;
618       volpath += c1;
619       volpath += str1;
620       for(Int_t c2 =1; c2<=2; c2++){
621         volpath1 = volpath;
622         volpath1 += c2;
623         volpath1 += str2;
624         for(Int_t c3 =1; c3<=4; c3++){
625           volpath2 = volpath1;
626           volpath2 += c3;
627           //      volpath2 += str3;
628           fgVolPath[kSPD1-kFirstLayer][modnum] = volpath2.Data();
629           modnum++;
630         }
631       }
632     }
633   }
634   
635   /*********************       SPD layer2  ***********************/
636   {
637     Int_t modnum = 0;
638     TString str0 = "ALIC_1/ITSV_1/ITSD_1/IT12_1/I12B_";  //".../I12A_"
639     TString str1 = "/I20B_";  //"/I20A"
640     TString str2 = "/I1D7_";  //"/I1D3"
641     //    TString str3 = "/I1D1_1/ITS2_1";
642     TString volpath, volpath1, volpath2;
643
644     for(Int_t c1 = 1; c1<=10; c1++){
645       volpath = str0;
646       volpath += c1;
647       volpath += str1;
648       for(Int_t c2 =1; c2<=4; c2++){
649         volpath1 = volpath;
650         volpath1 += c2;
651         volpath1 += str2;
652         for(Int_t c3 =1; c3<=4; c3++){
653           volpath2 = volpath1;
654           volpath2 += c3;
655           //      volpath2 += str3;
656           fgVolPath[kSPD2-kFirstLayer][modnum] = volpath2.Data();
657           modnum++;
658         }
659       }
660     }
661   }
662
663   /*********************       SDD layer1  ***********************/
664   {
665     Int_t modnum=0;
666     TString str0 = "ALIC_1/ITSV_1/ITSD_1/IT34_1/I004_";
667     TString str1 = "/I302_";
668     //    TString str2 = "/ITS3_1";
669     TString volpath, volpath1;
670
671     for(Int_t c1 = 1; c1<=14; c1++){
672       volpath = str0;
673       volpath += c1;
674       volpath += str1;
675       for(Int_t c2 =1; c2<=6; c2++){
676         volpath1 = volpath;
677         volpath1 += c2;
678         //      volpath1 += str2;
679         fgVolPath[kSDD1-kFirstLayer][modnum] = volpath1.Data();
680         modnum++;
681       }
682     }
683   }
684
685   /*********************       SDD layer2  ***********************/
686   {
687     Int_t modnum=0;
688     TString str0 = "ALIC_1/ITSV_1/ITSD_1/IT34_1/I005_";
689     TString str1 = "/I402_";
690     //    TString str2 = "/ITS4_1";
691     TString volpath, volpath1;
692
693     for(Int_t c1 = 1; c1<=22; c1++){
694       volpath = str0;
695       volpath += c1;
696       volpath += str1;
697       for(Int_t c2 = 1; c2<=8; c2++){
698         volpath1 = volpath;
699         volpath1 += c2;
700         //      volpath1 += str2;
701         fgVolPath[kSDD2-kFirstLayer][modnum] = volpath1.Data();
702         modnum++;
703       }
704     }
705   }
706
707   /*********************       SSD layer1  ***********************/
708   {
709     Int_t modnum=0;
710     TString str0 = "ALIC_1/ITSV_1/ITSD_1/IT56_1/I565_";
711     TString str1 = "/I562_";
712     //    TString str2 = "/ITS5_1";
713     TString volpath, volpath1;
714
715     for(Int_t c1 = 1; c1<=34; c1++){
716       volpath = str0;
717       volpath += c1;
718       volpath += str1;
719       for(Int_t c2 = 1; c2<=22; c2++){
720         volpath1 = volpath;
721         volpath1 += c2;
722         //      volpath1 += str2;
723         fgVolPath[kSSD1-kFirstLayer][modnum] = volpath1.Data();
724         modnum++;
725       }
726     }
727   }
728
729   /*********************       SSD layer1  ***********************/
730   {
731     Int_t modnum=0;
732     TString str0 = "ALIC_1/ITSV_1/ITSD_1/IT56_1/I569_";
733     TString str1 = "/I566_";
734     //    TString str2 = "/ITS6_1";
735     TString volpath, volpath1;
736
737     for(Int_t c1 = 1; c1<=38; c1++){
738       volpath = str0;
739       volpath += c1;
740       volpath += str1;
741       for(Int_t c2 = 1; c2<=25; c2++){
742         volpath1 = volpath;
743         volpath1 += c2;
744         //      volpath1 += str2;
745         fgVolPath[kSSD2-kFirstLayer][modnum] = volpath1.Data();
746         modnum++;
747       }
748     }
749   }
750
751   /***************    TPC inner chambers' layer    ****************/
752   {
753     Int_t modnum = 0;
754     TString str1 = "ALIC_1/TPC_M_1/TPC_Drift_1/TPC_ENDCAP_1/TPC_SECT_";
755     TString str2 = "ALIC_1/TPC_M_1/TPC_Drift_1/TPC_ENDCAP_2/TPC_SECT_";
756     TString strIn = "/TPC_IROC_1";
757     TString volpath;
758     
759     for(Int_t cnt=1; cnt<=18; cnt++){
760       volpath = str1;
761       volpath += cnt;
762       volpath += strIn;
763       fgVolPath[kTPC1-kFirstLayer][modnum] = volpath.Data();
764       modnum++;
765     }
766     for(Int_t cnt=1; cnt<=18; cnt++){
767       volpath = str2;
768       volpath += cnt;
769       volpath += strIn;
770       fgVolPath[kTPC1-kFirstLayer][modnum] = volpath.Data();
771       modnum++;
772     }
773   }
774
775   /***************    TPC outer chambers' layer    ****************/
776   {
777     Int_t modnum = 0;
778     TString str1 = "ALIC_1/TPC_M_1/TPC_Drift_1/TPC_ENDCAP_1/TPC_SECT_";
779     TString str2 = "ALIC_1/TPC_M_1/TPC_Drift_1/TPC_ENDCAP_2/TPC_SECT_";
780     TString strOut = "/TPC_OROC_1";
781     TString volpath;
782     
783     for(Int_t cnt=1; cnt<=18; cnt++){
784       volpath = str1;
785       volpath += cnt;
786       volpath += strOut;
787       fgVolPath[kTPC2-kFirstLayer][modnum] = volpath.Data();
788       modnum++;
789     }
790     for(Int_t cnt=1; cnt<=18; cnt++){
791       volpath = str2;
792       volpath += cnt;
793       volpath += strOut;
794       fgVolPath[kTPC2-kFirstLayer][modnum] = volpath.Data();
795       modnum++;
796     }
797   }    
798
799   /*********************       TOF layer   ***********************/
800   {
801     Int_t nstrA=15;
802     Int_t nstrB=19;
803     Int_t nstrC=19;
804     Int_t nsec=18;
805     Int_t nStripSec=nstrA+2*nstrB+2*nstrC;
806     Int_t nStrip=nStripSec*nsec;
807
808     for (Int_t modnum=0; modnum < nStrip; modnum++) {
809
810       Int_t sector = modnum/nStripSec;
811       Char_t  string1[100];
812       Char_t  string2[100];
813       Int_t icopy=-1;
814       icopy=sector; 
815
816       // Old 6h convention
817       // if(sector<13){
818       //        icopy=sector+5;}  
819       // else{ icopy=sector-13;}
820
821       sprintf(string1,"/ALIC_1/B077_1/BSEGMO%i_1/BTOF%i_1/FTOA_0/FLTA_0",sector,sector);
822       
823       Int_t strInSec=modnum%nStripSec;
824       icopy= strInSec;
825       icopy++;
826       sprintf(string2,"FSTR_%i",icopy);      
827       Char_t  path[100];
828       sprintf(path,"%s/%s",string1,string2); 
829       //      printf("%d  %s\n",modnum,path);
830       fgVolPath[kTOF-kFirstLayer][modnum] = path;
831     }
832   } 
833
834   /*********************      RICH layer   ***********************/
835   {
836     TString str = "ALIC_1/RICH_";
837     TString volpath;
838
839     for (Int_t modnum=0; modnum < 7; modnum++) {
840       volpath = str;
841       volpath += (modnum+1);
842       fgVolPath[kRICH-kFirstLayer][modnum] = volpath.Data();
843     }
844   }
845
846   /*********************      TRD layers 0-6   *******************/
847   {
848     TString strSM[18]={"ALIC_1/B077_1/BSEGMO0_1/BTRD0_1/UTR1_1/UTS1_1/UTI1_1/UT",
849                        "ALIC_1/B077_1/BSEGMO1_1/BTRD1_1/UTR1_1/UTS1_1/UTI1_1/UT",
850                        "ALIC_1/B077_1/BSEGMO2_1/BTRD2_1/UTR1_1/UTS1_1/UTI1_1/UT",
851                        "ALIC_1/B077_1/BSEGMO3_1/BTRD3_1/UTR1_1/UTS1_1/UTI1_1/UT",
852                        "ALIC_1/B077_1/BSEGMO4_1/BTRD4_1/UTR1_1/UTS1_1/UTI1_1/UT",
853                        "ALIC_1/B077_1/BSEGMO5_1/BTRD5_1/UTR1_1/UTS1_1/UTI1_1/UT",
854                        "ALIC_1/B077_1/BSEGMO6_1/BTRD6_1/UTR1_1/UTS1_1/UTI1_1/UT",
855                        "ALIC_1/B077_1/BSEGMO7_1/BTRD7_1/UTR1_1/UTS1_1/UTI1_1/UT",
856                        "ALIC_1/B077_1/BSEGMO8_1/BTRD8_1/UTR1_1/UTS1_1/UTI1_1/UT",
857                        "ALIC_1/B077_1/BSEGMO9_1/BTRD9_1/UTR1_1/UTS1_1/UTI1_1/UT",
858                        "ALIC_1/B077_1/BSEGMO10_1/BTRD10_1/UTR1_1/UTS1_1/UTI1_1/UT",
859                        "ALIC_1/B077_1/BSEGMO11_1/BTRD11_1/UTR1_1/UTS1_1/UTI1_1/UT",
860                        "ALIC_1/B077_1/BSEGMO12_1/BTRD12_1/UTR1_1/UTS1_1/UTI1_1/UT",
861                        "ALIC_1/B077_1/BSEGMO13_1/BTRD13_1/UTR1_1/UTS1_1/UTI1_1/UT",
862                        "ALIC_1/B077_1/BSEGMO14_1/BTRD14_1/UTR1_1/UTS1_1/UTI1_1/UT",
863                        "ALIC_1/B077_1/BSEGMO15_1/BTRD15_1/UTR1_1/UTS1_1/UTI1_1/UT",
864                        "ALIC_1/B077_1/BSEGMO16_1/BTRD16_1/UTR1_1/UTS1_1/UTI1_1/UT",
865                        "ALIC_1/B077_1/BSEGMO17_1/BTRD17_1/UTR1_1/UTS1_1/UTI1_1/UT"};
866     TString strPost = "_1";
867     TString zeroStr = "0";
868     TString volpath;
869
870     Int_t arTRDlayId[6] = {kTRD1, kTRD2, kTRD3, kTRD4, kTRD5, kTRD6};
871
872     for(Int_t layer=0; layer<6; layer++){
873       Int_t modnum=0;
874       for(Int_t sm = 0; sm < 18; sm++){
875         for(Int_t stacknum = 0; stacknum < 5; stacknum++){
876           Int_t chnum = layer + stacknum*6;
877           volpath = strSM[sm];
878           if(chnum<10) volpath += zeroStr;
879           volpath += chnum;
880           volpath += strPost;
881           fgVolPath[arTRDlayId[layer]-kFirstLayer][modnum] = volpath.Data();
882           modnum++;
883         }
884       }
885     }
886   }
887
888 }