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