Coding conventions, clean-up and related changes
[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   // This method is used to transform all the track points
274   // from the input AliTrackPointArray
275   AliTrackPoint p;
276   for (Int_t i = 0; i < array.GetNPoints(); i++) {
277     array.GetPoint(p,i);
278     Transform(p);
279     array.AddPoint(i,&p);
280   }
281 }
282
283 //_____________________________________________________________________________
284 void AliAlignObj::Print(Option_t *) const
285 {
286   // Print the contents of the
287   // alignment object in angles and
288   // matrix representations
289   Double_t tr[3];
290   GetTranslation(tr);
291   Double_t angles[3];
292   GetAngles(angles);
293   TGeoHMatrix m;
294   GetMatrix(m);
295   const Double_t *rot = m.GetRotationMatrix();
296
297   printf("Volume=%s\n",GetVolPath());
298   if (GetVolUID() != 0) {
299     ELayerID layerId;
300     Int_t modId;
301     GetVolUID(layerId,modId);
302     printf("VolumeID=%d LayerID=%d ( %s ) ModuleID=%d\n", GetVolUID(),layerId,LayerName(layerId),modId);
303   }
304   printf("%12.8f%12.8f%12.8f    Tx = %12.8f    Psi   = %12.8f\n", rot[0], rot[1], rot[2], tr[0], angles[0]);
305   printf("%12.8f%12.8f%12.8f    Ty = %12.8f    Theta = %12.8f\n", rot[3], rot[4], rot[5], tr[1], angles[1]);
306   printf("%12.8f%12.8f%12.8f    Tz = %12.8f    Phi   = %12.8f\n", rot[6], rot[7], rot[8], tr[2], angles[2]);
307
308 }
309
310 //_____________________________________________________________________________
311 Int_t AliAlignObj::LayerSize(Int_t layerId)
312 {
313   // Get the corresponding layer size.
314   // Implemented only for ITS,TPC,TRD,TOF and RICH
315   if (layerId < kFirstLayer || layerId >= kLastLayer) {
316     AliErrorClass(Form("Invalid layer index %d ! Layer range is (%d -> %d) !",layerId,kFirstLayer,kLastLayer));
317     return 0;
318   }
319   else {
320     return fgLayerSize[layerId - kFirstLayer];
321  }
322 }
323
324 //_____________________________________________________________________________
325 const char* AliAlignObj::LayerName(Int_t layerId)
326 {
327   // Get the corresponding layer name.
328   // Implemented only for ITS,TPC,TRD,TOF and RICH
329   if (layerId < kFirstLayer || layerId >= kLastLayer) {
330     AliErrorClass(Form("Invalid layer index %d ! Layer range is (%d -> %d) !",layerId,kFirstLayer,kLastLayer));
331     return "Invalid Layer!";
332   }
333   else {
334     return fgLayerName[layerId - kFirstLayer];
335  }
336 }
337
338 //_____________________________________________________________________________
339 UShort_t AliAlignObj::LayerToVolUID(ELayerID layerId, Int_t modId)
340 {
341   // From detector (layer) name and module number (according to detector numbering)
342   // build fVolUID, unique numerical identity of that volume inside ALICE
343   // fVolUID is 16 bits, first 5 reserved for layerID (32 possible values),
344   // remaining 11 for module ID inside det (2048 possible values).
345   //
346   return ((UShort_t(layerId) << 11) | UShort_t(modId));
347 }
348
349 //_____________________________________________________________________________
350 UShort_t AliAlignObj::LayerToVolUID(Int_t   layerId, Int_t modId)
351 {
352   // From detector (layer) index and module number (according to detector numbering)
353   // build fVolUID, unique numerical identity of that volume inside ALICE
354   // fVolUID is 16 bits, first 5 reserved for layerID (32 possible values),
355   // remaining 11 for module ID inside det (2048 possible values).
356   //
357   return ((UShort_t(layerId) << 11) | UShort_t(modId));
358 }
359
360 //_____________________________________________________________________________
361 AliAlignObj::ELayerID AliAlignObj::VolUIDToLayer(UShort_t voluid, Int_t &modId)
362 {
363   // From detector (layer) name and module number (according to detector numbering)
364   // build fVolUID, unique numerical identity of that volume inside ALICE
365   // fVolUID is 16 bits, first 5 reserved for layerID (32 possible values),
366   // remaining 11 for module ID inside det (2048 possible values).
367   //
368   modId = voluid & 0x7ff;
369
370   return VolUIDToLayer(voluid);
371 }
372
373 //_____________________________________________________________________________
374 AliAlignObj::ELayerID AliAlignObj::VolUIDToLayer(UShort_t voluid)
375 {
376   // From detector (layer) name and module number (according to detector numbering)
377   // build fVolUID, unique numerical identity of that volume inside ALICE
378   // fVolUID is 16 bits, first 5 reserved for layerID (32 possible values),
379   // remaining 11 for module ID inside det (2048 possible values).
380   //
381   return ELayerID((voluid >> 11) & 0x1f);
382 }
383
384 //_____________________________________________________________________________
385 Bool_t AliAlignObj::SetLocalPars(Double_t x, Double_t y, Double_t z,
386                                  Double_t psi, Double_t theta, Double_t phi)
387 {
388   // Set the translations and angles by using parameters
389   // defined in the local (in TGeo means) coordinate system
390   // of the alignable volume. In case that the TGeo was
391   // initialized, returns false and the object parameters are
392   // not set.
393   if (!gGeoManager || !gGeoManager->IsClosed()) {
394     AliError("Can't set the alignment object parameters! gGeoManager doesn't exist or it is still opened!");
395     return kFALSE;
396   }
397
398   const char* volpath = GetVolPath();
399   TGeoPhysicalNode* node = (TGeoPhysicalNode*) gGeoManager->MakePhysicalNode(volpath);
400   if (!node) {
401     AliError(Form("Volume path %s not valid!",volpath));
402     return kFALSE;
403   }
404   if (node->IsAligned())
405     AliWarning(Form("Volume %s has been already misaligned!",volpath));
406
407   TGeoHMatrix m;
408   Double_t tr[3];
409   tr[0]=x; tr[1]=y; tr[2]=z;
410   m.SetTranslation(tr);
411   Double_t angles[3] = {psi, theta, phi};
412   Double_t rot[9];
413   AnglesToMatrix(angles,rot);
414   m.SetRotation(rot);
415
416   TGeoHMatrix align,gprime,gprimeinv;
417   gprime = *node->GetMatrix();
418   gprimeinv = gprime.Inverse();
419   m.Multiply(&gprimeinv);
420   m.MultiplyLeft(&gprime);
421
422   SetMatrix(m);
423
424   return kTRUE;
425 }
426
427 //_____________________________________________________________________________
428 Bool_t AliAlignObj::ApplyToGeometry()
429 {
430   // Apply the current alignment object
431   // to the TGeo geometry
432
433   if (!gGeoManager || !gGeoManager->IsClosed()) {
434     AliError("Can't apply the alignment object! gGeoManager doesn't exist or it is still opened!");
435     return kFALSE;
436   }
437   
438   const char* volpath = GetVolPath();
439
440   if (gGeoManager->GetListOfPhysicalNodes()->FindObject(volpath)) {
441     AliError(Form("Volume %s has been already misaligned!",volpath));
442     return kFALSE;
443   }
444
445   if (!gGeoManager->cd(volpath)) {
446     AliError(Form("Volume path %s not valid!",volpath));
447     return kFALSE;
448   }
449
450   TGeoPhysicalNode* node = (TGeoPhysicalNode*) gGeoManager->MakePhysicalNode(volpath);
451   if (!node) {
452     AliError(Form("Volume path %s not valid!",volpath));
453     return kFALSE;
454   }
455
456   TGeoHMatrix align,gprime;
457   gprime = *node->GetMatrix();
458   GetMatrix(align);
459   gprime.MultiplyLeft(&align);
460   TGeoHMatrix *ginv = new TGeoHMatrix;
461   TGeoHMatrix *g = node->GetMatrix(node->GetLevel()-1);
462   *ginv = g->Inverse();
463   *ginv *= gprime;
464   AliAlignObj::ELayerID layerId; // unique identity for volume in the alobj
465   Int_t modId; // unique identity for volume in the alobj
466   GetVolUID(layerId, modId);
467   AliDebug(2,Form("Aligning volume %s of detector layer %d with local ID %d",volpath,layerId,modId));
468   node->Align(ginv);
469
470   return kTRUE;
471 }
472
473 //_____________________________________________________________________________
474 Bool_t AliAlignObj::GetFromGeometry(const char *path, AliAlignObj &alobj)
475 {
476   // Get the alignment object which correspond
477   // to the TGeo volume defined by the 'path'.
478   // The method is extremely slow due to the
479   // searching by string. Therefore it should
480   // be used with great care!!
481
482   // Reset the alignment object
483   alobj.SetPars(0,0,0,0,0,0);
484   alobj.SetVolPath(path);
485
486   if (!gGeoManager || !gGeoManager->IsClosed()) {
487     AliErrorClass("Can't get the alignment object! gGeoManager doesn't exist or it is still opened!");
488     return kFALSE;
489   }
490
491   if (!gGeoManager->GetListOfPhysicalNodes()) {
492     AliErrorClass("Can't get the alignment object! gGeoManager doesn't contain any aligned nodes!");
493     return kFALSE;
494   }
495
496   TObjArray* nodesArr = gGeoManager->GetListOfPhysicalNodes();
497   TGeoPhysicalNode* node = NULL;
498   for (Int_t iNode = 0; iNode < nodesArr->GetEntriesFast(); iNode++) {
499     node = (TGeoPhysicalNode*) nodesArr->UncheckedAt(iNode);
500     const char *nodePath = node->GetName();
501     if (strcmp(path,nodePath) == 0) break;
502   }
503   if (!node) {
504     if (!gGeoManager->cd(path)) {
505       AliErrorClass(Form("Volume path %s not found!",path));
506       return kFALSE;
507     }
508     else {
509       AliWarningClass(Form("Volume (%s) has not been misaligned!",path));
510       return kTRUE;
511     }
512   }
513
514   TGeoHMatrix align,gprime,g,ginv,l;
515   gprime = *node->GetMatrix();
516   l = *node->GetOriginalMatrix();
517   g = *node->GetMatrix(node->GetLevel()-1);
518   g *= l;
519   ginv = g.Inverse();
520   align = gprime * ginv;
521   alobj.SetMatrix(align);
522
523   return kTRUE;
524 }
525
526 //_____________________________________________________________________________
527 void  AliAlignObj::InitAlignObjFromGeometry()
528 {
529   // Loop over all alignable volumes and extract
530   // the corresponding alignment objects from
531   // the TGeo geometry
532
533   if(fgAlignObjs[0]) return;
534   
535   InitVolPaths();
536
537   for (Int_t iLayer = kFirstLayer; iLayer < AliAlignObj::kLastLayer; iLayer++) {
538     fgAlignObjs[iLayer-kFirstLayer] = new AliAlignObj*[AliAlignObj::LayerSize(iLayer)];
539     for (Int_t iModule = 0; iModule < AliAlignObj::LayerSize(iLayer); iModule++) {
540       UShort_t volid = AliAlignObj::LayerToVolUID(iLayer,iModule);
541       fgAlignObjs[iLayer-kFirstLayer][iModule] = new AliAlignObjAngles("",volid,0,0,0,0,0,0);
542       const char *path = GetVolPath(volid);
543       if (!GetFromGeometry(path, *fgAlignObjs[iLayer-kFirstLayer][iModule]))
544         AliErrorClass(Form("Failed to extract the alignment object for the volume (ID=%d and path=%s) !",volid,path));
545     }
546   }
547   
548 }
549
550 //_____________________________________________________________________________
551 AliAlignObj* AliAlignObj::GetAlignObj(UShort_t voluid) {
552   // Returns the alignment object for given volume ID
553   Int_t modId;
554   ELayerID layerId = VolUIDToLayer(voluid,modId);
555   return GetAlignObj(layerId,modId);
556 }
557
558 //_____________________________________________________________________________
559 AliAlignObj* AliAlignObj::GetAlignObj(ELayerID layerId, Int_t modId)
560 {
561   // Returns pointer to alignment object givent its layer and module ID
562   if(modId<0 || modId>=fgLayerSize[layerId-kFirstLayer]){
563     AliWarningClass(Form("Module number %d not in the valid range (0->%d) !",modId,fgLayerSize[layerId-kFirstLayer]-1));
564     return NULL;
565   }
566   return fgAlignObjs[layerId-kFirstLayer][modId];
567 }
568
569 //_____________________________________________________________________________
570 const char* AliAlignObj::GetVolPath(UShort_t voluid) {
571   // Returns the volume path for given volume ID
572   Int_t modId;
573   ELayerID layerId = VolUIDToLayer(voluid,modId);
574   return GetVolPath(layerId,modId);
575 }
576
577 //_____________________________________________________________________________
578 const char* AliAlignObj::GetVolPath(ELayerID layerId, Int_t modId)
579 {
580   // Returns volume path to alignment object givent its layer and module ID
581   if(modId<0 || modId>=fgLayerSize[layerId-kFirstLayer]){
582     AliWarningClass(Form("Module number %d not in the valid range (0->%d) !",modId,fgLayerSize[layerId-kFirstLayer]-1));
583     return NULL;
584   }
585   return fgVolPath[layerId-kFirstLayer][modId].Data();
586 }
587
588 //_____________________________________________________________________________
589 void AliAlignObj::InitVolPaths()
590 {
591   // Initialize the LUTs which contain
592   // the TGeo volume paths for each
593   // alignable volume. The LUTs are
594   // static, so they are created during
595   // the creation of the first intance
596   // of AliAlignObj
597
598   if (fgVolPath[0]) return;
599
600   for (Int_t iLayer = 0; iLayer < (kLastLayer - kFirstLayer); iLayer++)
601     fgVolPath[iLayer] = new TString[fgLayerSize[iLayer]];
602
603   /*********************       SPD layer1  ***********************/
604   {
605     Int_t modnum = 0;
606     TString str0 = "ALIC_1/ITSV_1/ITSD_1/IT12_1/I12B_"; //".../I12A_"
607     TString str1 = "/I10B_";    //"/I10A_";
608     TString str2 = "/I107_";    //"/I103_"
609     //    TString str3 = "/I101_1/ITS1_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<=2; 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[kSPD1-kFirstLayer][modnum] = volpath2.Data();
625           modnum++;
626         }
627       }
628     }
629   }
630   
631   /*********************       SPD layer2  ***********************/
632   {
633     Int_t modnum = 0;
634     TString str0 = "ALIC_1/ITSV_1/ITSD_1/IT12_1/I12B_";  //".../I12A_"
635     TString str1 = "/I20B_";  //"/I20A"
636     TString str2 = "/I1D7_";  //"/I1D3"
637     //    TString str3 = "/I1D1_1/ITS2_1";
638     TString volpath, volpath1, volpath2;
639
640     for(Int_t c1 = 1; c1<=10; c1++){
641       volpath = str0;
642       volpath += c1;
643       volpath += str1;
644       for(Int_t c2 =1; c2<=4; c2++){
645         volpath1 = volpath;
646         volpath1 += c2;
647         volpath1 += str2;
648         for(Int_t c3 =1; c3<=4; c3++){
649           volpath2 = volpath1;
650           volpath2 += c3;
651           //      volpath2 += str3;
652           fgVolPath[kSPD2-kFirstLayer][modnum] = volpath2.Data();
653           modnum++;
654         }
655       }
656     }
657   }
658
659   /*********************       SDD layer1  ***********************/
660   {
661     Int_t modnum=0;
662     TString str0 = "ALIC_1/ITSV_1/ITSD_1/IT34_1/I004_";
663     TString str1 = "/I302_";
664     //    TString str2 = "/ITS3_1";
665     TString volpath, volpath1;
666
667     for(Int_t c1 = 1; c1<=14; c1++){
668       volpath = str0;
669       volpath += c1;
670       volpath += str1;
671       for(Int_t c2 =1; c2<=6; c2++){
672         volpath1 = volpath;
673         volpath1 += c2;
674         //      volpath1 += str2;
675         fgVolPath[kSDD1-kFirstLayer][modnum] = volpath1.Data();
676         modnum++;
677       }
678     }
679   }
680
681   /*********************       SDD layer2  ***********************/
682   {
683     Int_t modnum=0;
684     TString str0 = "ALIC_1/ITSV_1/ITSD_1/IT34_1/I005_";
685     TString str1 = "/I402_";
686     //    TString str2 = "/ITS4_1";
687     TString volpath, volpath1;
688
689     for(Int_t c1 = 1; c1<=22; c1++){
690       volpath = str0;
691       volpath += c1;
692       volpath += str1;
693       for(Int_t c2 = 1; c2<=8; c2++){
694         volpath1 = volpath;
695         volpath1 += c2;
696         //      volpath1 += str2;
697         fgVolPath[kSDD2-kFirstLayer][modnum] = volpath1.Data();
698         modnum++;
699       }
700     }
701   }
702
703   /*********************       SSD layer1  ***********************/
704   {
705     Int_t modnum=0;
706     TString str0 = "ALIC_1/ITSV_1/ITSD_1/IT56_1/I565_";
707     TString str1 = "/I562_";
708     //    TString str2 = "/ITS5_1";
709     TString volpath, volpath1;
710
711     for(Int_t c1 = 1; c1<=34; c1++){
712       volpath = str0;
713       volpath += c1;
714       volpath += str1;
715       for(Int_t c2 = 1; c2<=22; c2++){
716         volpath1 = volpath;
717         volpath1 += c2;
718         //      volpath1 += str2;
719         fgVolPath[kSSD1-kFirstLayer][modnum] = volpath1.Data();
720         modnum++;
721       }
722     }
723   }
724
725   /*********************       SSD layer1  ***********************/
726   {
727     Int_t modnum=0;
728     TString str0 = "ALIC_1/ITSV_1/ITSD_1/IT56_1/I569_";
729     TString str1 = "/I566_";
730     //    TString str2 = "/ITS6_1";
731     TString volpath, volpath1;
732
733     for(Int_t c1 = 1; c1<=38; c1++){
734       volpath = str0;
735       volpath += c1;
736       volpath += str1;
737       for(Int_t c2 = 1; c2<=25; c2++){
738         volpath1 = volpath;
739         volpath1 += c2;
740         //      volpath1 += str2;
741         fgVolPath[kSSD2-kFirstLayer][modnum] = volpath1.Data();
742         modnum++;
743       }
744     }
745   }
746
747   /***************    TPC inner chambers' layer    ****************/
748   {
749     Int_t modnum = 0;
750     TString str1 = "ALIC_1/TPC_M_1/TPC_Drift_1/TPC_ENDCAP_1/TPC_SECT_";
751     TString str2 = "ALIC_1/TPC_M_1/TPC_Drift_1/TPC_ENDCAP_2/TPC_SECT_";
752     TString strIn = "/TPC_IROC_1";
753     TString volpath;
754     
755     for(Int_t cnt=1; cnt<=18; cnt++){
756       volpath = str1;
757       volpath += cnt;
758       volpath += strIn;
759       fgVolPath[kTPC1-kFirstLayer][modnum] = volpath.Data();
760       modnum++;
761     }
762     for(Int_t cnt=1; cnt<=18; cnt++){
763       volpath = str2;
764       volpath += cnt;
765       volpath += strIn;
766       fgVolPath[kTPC1-kFirstLayer][modnum] = volpath.Data();
767       modnum++;
768     }
769   }
770
771   /***************    TPC outer chambers' layer    ****************/
772   {
773     Int_t modnum = 0;
774     TString str1 = "ALIC_1/TPC_M_1/TPC_Drift_1/TPC_ENDCAP_1/TPC_SECT_";
775     TString str2 = "ALIC_1/TPC_M_1/TPC_Drift_1/TPC_ENDCAP_2/TPC_SECT_";
776     TString strOut = "/TPC_OROC_1";
777     TString volpath;
778     
779     for(Int_t cnt=1; cnt<=18; cnt++){
780       volpath = str1;
781       volpath += cnt;
782       volpath += strOut;
783       fgVolPath[kTPC2-kFirstLayer][modnum] = volpath.Data();
784       modnum++;
785     }
786     for(Int_t cnt=1; cnt<=18; cnt++){
787       volpath = str2;
788       volpath += cnt;
789       volpath += strOut;
790       fgVolPath[kTPC2-kFirstLayer][modnum] = volpath.Data();
791       modnum++;
792     }
793   }    
794
795   /*********************       TOF layer   ***********************/
796   {
797     Int_t nstrA=15;
798     Int_t nstrB=19;
799     Int_t nstrC=19;
800     Int_t nsec=18;
801     Int_t nStripSec=nstrA+2*nstrB+2*nstrC;
802     Int_t nStrip=nStripSec*nsec;
803
804     for (Int_t modnum=0; modnum < nStrip; modnum++) {
805
806       Int_t sector = modnum/nStripSec;
807       Char_t  string1[100];
808       Char_t  string2[100];
809
810       Int_t icopy=-1;
811
812       if(sector<3){
813         icopy=sector+1;
814         sprintf(string1,"/ALIC_1/B077_1/B075_%i/BTO3_1/FTOA_0/FLTA_0",icopy);
815       }
816       else if(sector<11){
817         icopy=sector+3;
818         sprintf(string1,"/ALIC_1/B077_1/B071_%i/BTO1_1/FTOA_0/FLTA_0",icopy);
819       }
820       else if(sector==11 || sector==12){
821         icopy=sector-10;
822         sprintf(string1,"/ALIC_1/B077_1/B074_%i/BTO2_1/FTOA_0/FLTA_0",icopy);
823       }
824       else {
825         icopy=sector-12;
826         sprintf(string1,"/ALIC_1/B077_1/B071_%i/BTO1_1/FTOA_0/FLTA_0",icopy);
827       }
828       
829       Int_t strInSec=modnum%nStripSec;
830       icopy= strInSec;
831       icopy++;
832       sprintf(string2,"FSTR_%i",icopy);      
833       Char_t  path[100];
834       sprintf(path,"%s/%s",string1,string2); 
835       //      printf("%d  %s\n",modnum,path);
836       fgVolPath[kTOF-kFirstLayer][modnum] = path;
837     }
838   } 
839
840   /*********************      RICH layer   ***********************/
841   {
842     TString str = "ALIC_1/RICH_";
843     TString volpath;
844
845     for (Int_t modnum=0; modnum < 7; modnum++) {
846       volpath = str;
847       volpath += (modnum+1);
848       fgVolPath[kRICH-kFirstLayer][modnum] = volpath.Data();
849     }
850   }
851
852   /*********************      TRD layers 0-6   *******************/
853   {
854     TString strSM[18]={"ALIC_1/B077_1/B075_1/BTR3_1/UTR1_3/UTS1_1/UTI1_1/UT",
855                        "ALIC_1/B077_1/B075_2/BTR3_1/UTR1_3/UTS1_1/UTI1_1/UT",
856                        "ALIC_1/B077_1/B075_3/BTR3_1/UTR1_3/UTS1_1/UTI1_1/UT",
857                        "ALIC_1/B077_1/B071_6/BTR1_1/UTR1_1/UTS1_1/UTI1_1/UT",
858                        "ALIC_1/B077_1/B071_7/BTR1_1/UTR1_1/UTS1_1/UTI1_1/UT",
859                        "ALIC_1/B077_1/B071_8/BTR1_1/UTR1_1/UTS1_1/UTI1_1/UT",
860                        "ALIC_1/B077_1/B071_9/BTR1_1/UTR1_1/UTS1_1/UTI1_1/UT",
861                        "ALIC_1/B077_1/B071_10/BTR1_1/UTR1_1/UTS1_1/UTI1_1/UT",
862                        "ALIC_1/B077_1/B071_11/BTR1_1/UTR1_1/UTS1_1/UTI1_1/UT",
863                        "ALIC_1/B077_1/B071_12/BTR1_1/UTR1_1/UTS1_1/UTI1_1/UT",
864                        "ALIC_1/B077_1/B071_13/BTR1_1/UTR1_1/UTS1_1/UTI1_1/UT",
865                        "ALIC_1/B077_1/B074_1/BTR2_1/UTR1_2/UTS1_1/UTI1_1/UT",
866                        "ALIC_1/B077_1/B074_2/BTR2_1/UTR1_2/UTS1_1/UTI1_1/UT",
867                        "ALIC_1/B077_1/B071_1/BTR1_1/UTR1_1/UTS1_1/UTI1_1/UT",
868                        "ALIC_1/B077_1/B071_2/BTR1_1/UTR1_1/UTS1_1/UTI1_1/UT",
869                        "ALIC_1/B077_1/B071_3/BTR1_1/UTR1_1/UTS1_1/UTI1_1/UT",
870                        "ALIC_1/B077_1/B071_4/BTR1_1/UTR1_1/UTS1_1/UTI1_1/UT",
871                        "ALIC_1/B077_1/B071_5/BTR1_1/UTR1_1/UTS1_1/UTI1_1/UT"};
872     TString strPost = "_1";
873     TString zeroStr = "0";
874     TString volpath;
875
876     Int_t arTRDlayId[6] = {kTRD1, kTRD2, kTRD3, kTRD4, kTRD5, kTRD6};
877
878     for(Int_t layer=0; layer<6; layer++){
879       Int_t modnum=0;
880       for(Int_t sm = 0; sm < 18; sm++){
881         for(Int_t stacknum = 0; stacknum < 5; stacknum++){
882           Int_t chnum = layer + stacknum*6;
883           volpath = strSM[sm];
884           if(chnum<10) volpath += zeroStr;
885           volpath += chnum;
886           volpath += strPost;
887           fgVolPath[arTRDlayId[layer]-kFirstLayer][modnum] = volpath.Data();
888           modnum++;
889         }
890       }
891     }
892   }
893
894 }