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