83ebbede468cfc310f3441fbddcff2d325b2c861
[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
438   if (gGeoManager->GetListOfPhysicalNodes()->FindObject(volpath)) {
439     AliError(Form("Volume %s has been already misaligned!",volpath));
440     return kFALSE;
441   }
442
443   if (!gGeoManager->cd(volpath)) {
444     AliError(Form("Volume path %s not valid!",volpath));
445     return kFALSE;
446   }
447
448   TGeoPhysicalNode* node = (TGeoPhysicalNode*) gGeoManager->MakePhysicalNode(volpath);
449   if (!node) {
450     AliError(Form("Volume path %s not valid!",volpath));
451     return kFALSE;
452   }
453
454   TGeoHMatrix align,gprime;
455   gprime = *node->GetMatrix();
456   GetMatrix(align);
457   gprime.MultiplyLeft(&align);
458   TGeoHMatrix *ginv = new TGeoHMatrix;
459   TGeoHMatrix *g = node->GetMatrix(node->GetLevel()-1);
460   *ginv = g->Inverse();
461   *ginv *= gprime;
462   AliAlignObj::ELayerID layerId; // unique identity for volume in the alobj
463   Int_t modId; // unique identity for volume in the alobj
464   GetVolUID(layerId, modId);
465   AliDebug(2,Form("Aligning volume %s of detector layer %d with local ID %d",volpath,layerId,modId));
466   node->Align(ginv);
467
468   return kTRUE;
469 }
470
471 //_____________________________________________________________________________
472 Bool_t AliAlignObj::GetFromGeometry(const char *path, AliAlignObj &alobj)
473 {
474   // Get the alignment object which correspond
475   // to the TGeo volume defined by the 'path'.
476   // The method is extremely slow due to the
477   // searching by string. Therefore it should
478   // be used with great care!!
479
480   // Reset the alignment object
481   alobj.SetPars(0,0,0,0,0,0);
482   alobj.SetVolPath(path);
483
484   if (!gGeoManager || !gGeoManager->IsClosed()) {
485     AliErrorClass("Can't get the alignment object! gGeoManager doesn't exist or it is still opened!");
486     return kFALSE;
487   }
488
489   if (!gGeoManager->GetListOfPhysicalNodes()) {
490     AliErrorClass("Can't get the alignment object! gGeoManager doesn't contain any aligned nodes!");
491     return kFALSE;
492   }
493
494   TObjArray* nodesArr = gGeoManager->GetListOfPhysicalNodes();
495   TGeoPhysicalNode* node = NULL;
496   for (Int_t iNode = 0; iNode < nodesArr->GetEntriesFast(); iNode++) {
497     node = (TGeoPhysicalNode*) nodesArr->UncheckedAt(iNode);
498     const char *nodePath = node->GetName();
499     if (strcmp(path,nodePath) == 0) break;
500   }
501   if (!node) {
502     if (!gGeoManager->cd(path)) {
503       AliErrorClass(Form("Volume path %s not found!",path));
504       return kFALSE;
505     }
506     else {
507       AliWarningClass(Form("Volume (%s) has not been misaligned!",path));
508       return kTRUE;
509     }
510   }
511
512   TGeoHMatrix align,gprime,g,ginv,l;
513   gprime = *node->GetMatrix();
514   l = *node->GetOriginalMatrix();
515   g = *node->GetMatrix(node->GetLevel()-1);
516   g *= l;
517   ginv = g.Inverse();
518   align = gprime * ginv;
519   alobj.SetMatrix(align);
520
521   return kTRUE;
522 }
523
524 //_____________________________________________________________________________
525 void  AliAlignObj::InitAlignObjFromGeometry()
526 {
527   // Loop over all alignable volumes and extract
528   // the corresponding alignment objects from
529   // the TGeo geometry
530
531   if(fgAlignObjs[0]) return;
532   
533   InitVolPaths();
534
535   for (Int_t iLayer = kFirstLayer; iLayer < AliAlignObj::kLastLayer; iLayer++) {
536     fgAlignObjs[iLayer-kFirstLayer] = new AliAlignObj*[AliAlignObj::LayerSize(iLayer)];
537     for (Int_t iModule = 0; iModule < AliAlignObj::LayerSize(iLayer); iModule++) {
538       UShort_t volid = AliAlignObj::LayerToVolUID(iLayer,iModule);
539       fgAlignObjs[iLayer-kFirstLayer][iModule] = new AliAlignObjAngles("",volid,0,0,0,0,0,0);
540       const char *path = GetVolPath(volid);
541       if (!GetFromGeometry(path, *fgAlignObjs[iLayer-kFirstLayer][iModule]))
542         AliErrorClass(Form("Failed to extract the alignment object for the volume (ID=%d and path=%s) !",volid,path));
543     }
544   }
545   
546 }
547
548 //_____________________________________________________________________________
549 AliAlignObj* AliAlignObj::GetAlignObj(ELayerID layerId, Int_t modId)
550 {
551   if(modId<0 || modId>=fgLayerSize[layerId-kFirstLayer]){
552     AliWarningClass(Form("Module number %d not in the valid range (0->%d) !",modId,fgLayerSize[layerId-kFirstLayer]-1));
553     return NULL;
554   }
555   return fgAlignObjs[layerId-kFirstLayer][modId];
556 }
557
558 //_____________________________________________________________________________
559 const char* AliAlignObj::GetVolPath(ELayerID layerId, Int_t modId)
560 {
561   if(modId<0 || modId>=fgLayerSize[layerId-kFirstLayer]){
562     AliWarningClass(Form("Module number %d not in the valid range (0->%d) !",modId,fgLayerSize[layerId-kFirstLayer]-1));
563     return NULL;
564   }
565   return fgVolPath[layerId-kFirstLayer][modId].Data();
566 }
567
568 //_____________________________________________________________________________
569 void AliAlignObj::InitVolPaths()
570 {
571   // Initialize the LUTs which contain
572   // the TGeo volume paths for each
573   // alignable volume. The LUTs are
574   // static, so they are created during
575   // the creation of the first intance
576   // of AliAlignObj
577
578   if (fgVolPath[0]) return;
579
580   for (Int_t iLayer = 0; iLayer < (kLastLayer - kFirstLayer); iLayer++)
581     fgVolPath[iLayer] = new TString[fgLayerSize[iLayer]];
582
583   /*********************       SPD layer1  ***********************/
584   {
585     Int_t modnum = 0;
586     TString str0 = "ALIC_1/ITSV_1/ITSD_1/IT12_1/I12B_"; //".../I12A_"
587     TString str1 = "/I10B_";    //"/I10A_";
588     TString str2 = "/I107_";    //"/I103_"
589     //    TString str3 = "/I101_1/ITS1_1";
590     TString volpath, volpath1, volpath2;
591
592     for(Int_t c1 = 1; c1<=10; c1++){
593       volpath = str0;
594       volpath += c1;
595       volpath += str1;
596       for(Int_t c2 =1; c2<=2; c2++){
597         volpath1 = volpath;
598         volpath1 += c2;
599         volpath1 += str2;
600         for(Int_t c3 =1; c3<=4; c3++){
601           volpath2 = volpath1;
602           volpath2 += c3;
603           //      volpath2 += str3;
604           fgVolPath[kSPD1-kFirstLayer][modnum] = volpath2.Data();
605           modnum++;
606         }
607       }
608     }
609   }
610   
611   /*********************       SPD layer2  ***********************/
612   {
613     Int_t modnum = 0;
614     TString str0 = "ALIC_1/ITSV_1/ITSD_1/IT12_1/I12B_";  //".../I12A_"
615     TString str1 = "/I20B_";  //"/I20A"
616     TString str2 = "/I1D7_";  //"/I1D3"
617     //    TString str3 = "/I1D1_1/ITS2_1";
618     TString volpath, volpath1, volpath2;
619
620     for(Int_t c1 = 1; c1<=10; c1++){
621       volpath = str0;
622       volpath += c1;
623       volpath += str1;
624       for(Int_t c2 =1; c2<=4; c2++){
625         volpath1 = volpath;
626         volpath1 += c2;
627         volpath1 += str2;
628         for(Int_t c3 =1; c3<=4; c3++){
629           volpath2 = volpath1;
630           volpath2 += c3;
631           //      volpath2 += str3;
632           fgVolPath[kSPD2-kFirstLayer][modnum] = volpath2.Data();
633           modnum++;
634         }
635       }
636     }
637   }
638
639   /*********************       SDD layer1  ***********************/
640   {
641     Int_t modnum=0;
642     TString str0 = "ALIC_1/ITSV_1/ITSD_1/IT34_1/I004_";
643     TString str1 = "/I302_";
644     //    TString str2 = "/ITS3_1";
645     TString volpath, volpath1;
646
647     for(Int_t c1 = 1; c1<=14; c1++){
648       volpath = str0;
649       volpath += c1;
650       volpath += str1;
651       for(Int_t c2 =1; c2<=6; c2++){
652         volpath1 = volpath;
653         volpath1 += c2;
654         //      volpath1 += str2;
655         fgVolPath[kSDD1-kFirstLayer][modnum] = volpath1.Data();
656         modnum++;
657       }
658     }
659   }
660
661   /*********************       SDD layer2  ***********************/
662   {
663     Int_t modnum=0;
664     TString str0 = "ALIC_1/ITSV_1/ITSD_1/IT34_1/I005_";
665     TString str1 = "/I402_";
666     //    TString str2 = "/ITS4_1";
667     TString volpath, volpath1;
668
669     for(Int_t c1 = 1; c1<=22; c1++){
670       volpath = str0;
671       volpath += c1;
672       volpath += str1;
673       for(Int_t c2 = 1; c2<=8; c2++){
674         volpath1 = volpath;
675         volpath1 += c2;
676         //      volpath1 += str2;
677         fgVolPath[kSDD2-kFirstLayer][modnum] = volpath1.Data();
678         modnum++;
679       }
680     }
681   }
682
683   /*********************       SSD layer1  ***********************/
684   {
685     Int_t modnum=0;
686     TString str0 = "ALIC_1/ITSV_1/ITSD_1/IT56_1/I565_";
687     TString str1 = "/I562_";
688     //    TString str2 = "/ITS5_1";
689     TString volpath, volpath1;
690
691     for(Int_t c1 = 1; c1<=34; c1++){
692       volpath = str0;
693       volpath += c1;
694       volpath += str1;
695       for(Int_t c2 = 1; c2<=22; c2++){
696         volpath1 = volpath;
697         volpath1 += c2;
698         //      volpath1 += str2;
699         fgVolPath[kSSD1-kFirstLayer][modnum] = volpath1.Data();
700         modnum++;
701       }
702     }
703   }
704
705   /*********************       SSD layer1  ***********************/
706   {
707     Int_t modnum=0;
708     TString str0 = "ALIC_1/ITSV_1/ITSD_1/IT56_1/I569_";
709     TString str1 = "/I566_";
710     //    TString str2 = "/ITS6_1";
711     TString volpath, volpath1;
712
713     for(Int_t c1 = 1; c1<=38; c1++){
714       volpath = str0;
715       volpath += c1;
716       volpath += str1;
717       for(Int_t c2 = 1; c2<=25; c2++){
718         volpath1 = volpath;
719         volpath1 += c2;
720         //      volpath1 += str2;
721         fgVolPath[kSSD2-kFirstLayer][modnum] = volpath1.Data();
722         modnum++;
723       }
724     }
725   }
726
727   /***************    TPC inner chambers' layer    ****************/
728   {
729     Int_t modnum = 0;
730     TString str1 = "ALIC_1/TPC_M_1/TPC_Drift_1/TPC_ENDCAP_1/TPC_SECT_";
731     TString str2 = "ALIC_1/TPC_M_1/TPC_Drift_1/TPC_ENDCAP_2/TPC_SECT_";
732     TString str_in = "/TPC_IROC_1";
733     TString volpath;
734     
735     for(Int_t cnt=1; cnt<=18; cnt++){
736       volpath = str1;
737       volpath += cnt;
738       volpath += str_in;
739       fgVolPath[kTPC1-kFirstLayer][modnum] = volpath.Data();
740       modnum++;
741     }
742     for(Int_t cnt=1; cnt<=18; cnt++){
743       volpath = str2;
744       volpath += cnt;
745       volpath += str_in;
746       fgVolPath[kTPC1-kFirstLayer][modnum] = volpath.Data();
747       modnum++;
748     }
749   }
750
751   /***************    TPC outer 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 str_out = "/TPC_OROC_1";
757     TString volpath;
758     
759     for(Int_t cnt=1; cnt<=18; cnt++){
760       volpath = str1;
761       volpath += cnt;
762       volpath += str_out;
763       fgVolPath[kTPC2-kFirstLayer][modnum] = volpath.Data();
764       modnum++;
765     }
766     for(Int_t cnt=1; cnt<=18; cnt++){
767       volpath = str2;
768       volpath += cnt;
769       volpath += str_out;
770       fgVolPath[kTPC2-kFirstLayer][modnum] = volpath.Data();
771       modnum++;
772     }
773   }    
774
775   /*********************       TOF layer   ***********************/
776   {
777     Int_t nstrA=15;
778     Int_t nstrB=19;
779     Int_t nstrC=19;
780     Int_t nsec=18;
781     Int_t nStripSec=nstrA+2*nstrB+2*nstrC;
782     Int_t nStrip=nStripSec*nsec;
783
784     for (Int_t modnum=0; modnum < nStrip; modnum++) {
785
786       Int_t sector = modnum/nStripSec;
787       Char_t  string1[100];
788       Char_t  string2[100];
789
790       Int_t icopy=-1;
791
792       if(sector<3){
793         icopy=sector+1;
794         sprintf(string1,"/ALIC_1/B077_1/B075_%i/BTO3_1/FTOA_0/FLTA_0",icopy);
795       }
796       else if(sector<11){
797         icopy=sector+3;
798         sprintf(string1,"/ALIC_1/B077_1/B071_%i/BTO1_1/FTOA_0/FLTA_0",icopy);
799       }
800       else if(sector==11 || sector==12){
801         icopy=sector-10;
802         sprintf(string1,"/ALIC_1/B077_1/B074_%i/BTO2_1/FTOA_0/FLTA_0",icopy);
803       }
804       else {
805         icopy=sector-12;
806         sprintf(string1,"/ALIC_1/B077_1/B071_%i/BTO1_1/FTOA_0/FLTA_0",icopy);
807       }
808       
809       Int_t strInSec=modnum%nStripSec;
810       icopy= strInSec;
811       icopy++;
812       sprintf(string2,"FSTR_%i",icopy);      
813       Char_t  path[100];
814       sprintf(path,"%s/%s",string1,string2); 
815       //      printf("%d  %s\n",modnum,path);
816       fgVolPath[kTOF-kFirstLayer][modnum] = path;
817     }
818   } 
819
820   /*********************      RICH layer   ***********************/
821   {
822     TString str = "ALIC_1/RICH_";
823     TString volpath;
824
825     for (Int_t modnum=0; modnum < 7; modnum++) {
826       volpath = str;
827       volpath += (modnum+1);
828       fgVolPath[kRICH-kFirstLayer][modnum] = volpath.Data();
829     }
830   }
831
832   /*********************      TRD layers 0-6   *******************/
833   {
834     TString strSM[18]={"ALIC_1/B077_1/B075_1/BTR3_1/UTR1_3/UTS1_1/UTI1_1/UT",
835                        "ALIC_1/B077_1/B075_2/BTR3_1/UTR1_3/UTS1_1/UTI1_1/UT",
836                        "ALIC_1/B077_1/B075_3/BTR3_1/UTR1_3/UTS1_1/UTI1_1/UT",
837                        "ALIC_1/B077_1/B071_6/BTR1_1/UTR1_1/UTS1_1/UTI1_1/UT",
838                        "ALIC_1/B077_1/B071_7/BTR1_1/UTR1_1/UTS1_1/UTI1_1/UT",
839                        "ALIC_1/B077_1/B071_8/BTR1_1/UTR1_1/UTS1_1/UTI1_1/UT",
840                        "ALIC_1/B077_1/B071_9/BTR1_1/UTR1_1/UTS1_1/UTI1_1/UT",
841                        "ALIC_1/B077_1/B071_10/BTR1_1/UTR1_1/UTS1_1/UTI1_1/UT",
842                        "ALIC_1/B077_1/B071_11/BTR1_1/UTR1_1/UTS1_1/UTI1_1/UT",
843                        "ALIC_1/B077_1/B071_12/BTR1_1/UTR1_1/UTS1_1/UTI1_1/UT",
844                        "ALIC_1/B077_1/B071_13/BTR1_1/UTR1_1/UTS1_1/UTI1_1/UT",
845                        "ALIC_1/B077_1/B074_1/BTR2_1/UTR1_2/UTS1_1/UTI1_1/UT",
846                        "ALIC_1/B077_1/B074_2/BTR2_1/UTR1_2/UTS1_1/UTI1_1/UT",
847                        "ALIC_1/B077_1/B071_1/BTR1_1/UTR1_1/UTS1_1/UTI1_1/UT",
848                        "ALIC_1/B077_1/B071_2/BTR1_1/UTR1_1/UTS1_1/UTI1_1/UT",
849                        "ALIC_1/B077_1/B071_3/BTR1_1/UTR1_1/UTS1_1/UTI1_1/UT",
850                        "ALIC_1/B077_1/B071_4/BTR1_1/UTR1_1/UTS1_1/UTI1_1/UT",
851                        "ALIC_1/B077_1/B071_5/BTR1_1/UTR1_1/UTS1_1/UTI1_1/UT"};
852     TString strPost = "_1";
853     TString zeroStr = "0";
854     TString volpath;
855
856     Int_t TRDlayId[6] = {kTRD1, kTRD2, kTRD3, kTRD4, kTRD5, kTRD6};
857
858     for(Int_t layer=0; layer<6; layer++){
859       Int_t modnum=0;
860       for(Int_t sm = 0; sm < 18; sm++){
861         for(Int_t stacknum = 0; stacknum < 5; stacknum++){
862           Int_t chnum = layer + stacknum*6;
863           volpath = strSM[sm];
864           if(chnum<10) volpath += zeroStr;
865           volpath += chnum;
866           volpath += strPost;
867           fgVolPath[TRDlayId[layer]-kFirstLayer][modnum] = volpath.Data();
868           modnum++;
869         }
870       }
871     }
872   }
873
874 }