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