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