]>
Commit | Line | Data |
---|---|---|
c18195b9 | 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 | //----------------------------------------------------------------- | |
befe2c08 | 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. | |
c18195b9 | 21 | //----------------------------------------------------------------- |
995ad051 | 22 | #include <TGeoManager.h> |
23 | #include <TGeoPhysicalNode.h> | |
24 | ||
c18195b9 | 25 | #include "AliAlignObj.h" |
03b18860 | 26 | #include "AliTrackPointArray.h" |
27 | #include "AliLog.h" | |
c5304981 | 28 | #include "AliAlignObjAngles.h" |
98937d93 | 29 | |
c18195b9 | 30 | ClassImp(AliAlignObj) |
31 | ||
98937d93 | 32 | Int_t AliAlignObj::fgLayerSize[kLastLayer - kFirstLayer] = { |
b760c02e | 33 | 80, 160, // ITS SPD first and second layer |
34 | 84, 176, // ITS SDD first and second layer | |
35 | 748, 950, // ITS SSD first and second layer | |
36 | 36, 36, // TPC inner and outer chambers | |
37 | 90, 90, 90, 90, 90, 90, // 6 TRD chambers' layers | |
da027ef2 | 38 | 1638, // TOF |
98937d93 | 39 | 1, 1, // PHOS ?? |
03b18860 | 40 | 7, // RICH ?? |
98937d93 | 41 | 1 // MUON ?? |
42 | }; | |
43 | ||
44 | const char* AliAlignObj::fgLayerName[kLastLayer - kFirstLayer] = { | |
45 | "ITS inner pixels layer", "ITS outer pixels layer", | |
46 | "ITS inner drifts layer", "ITS outer drifts layer", | |
47 | "ITS inner strips layer", "ITS outer strips layer", | |
48 | "TPC inner chambers layer", "TPC outer chambers layer", | |
49 | "TRD chambers layer 1", "TRD chambers layer 2", "TRD chambers layer 3", | |
50 | "TRD chambers layer 4", "TRD chambers layer 5", "TRD chambers layer 6", | |
51 | "TOF layer", | |
52 | "?","?", | |
03b18860 | 53 | "RICH layer", |
98937d93 | 54 | "?" |
55 | }; | |
56 | ||
7604a026 | 57 | TString* AliAlignObj::fgVolPath[kLastLayer - kFirstLayer] = { |
03b18860 | 58 | 0x0,0x0, |
59 | 0x0,0x0, | |
60 | 0x0,0x0, | |
61 | 0x0,0x0, | |
62 | 0x0,0x0,0x0, | |
63 | 0x0,0x0,0x0, | |
64 | 0x0, | |
65 | 0x0,0x0, | |
66 | 0x0, | |
67 | 0x0 | |
68 | }; | |
69 | ||
c5304981 | 70 | AliAlignObj** AliAlignObj::fgAlignObjs[kLastLayer - kFirstLayer] = { |
71 | 0x0,0x0, | |
72 | 0x0,0x0, | |
73 | 0x0,0x0, | |
74 | 0x0,0x0, | |
75 | 0x0,0x0,0x0, | |
76 | 0x0,0x0,0x0, | |
77 | 0x0, | |
78 | 0x0,0x0, | |
79 | 0x0, | |
80 | 0x0 | |
81 | }; | |
82 | ||
c18195b9 | 83 | //_____________________________________________________________________________ |
84 | AliAlignObj::AliAlignObj(): | |
fe12e09c | 85 | fVolPath(), |
c18195b9 | 86 | fVolUID(0) |
87 | { | |
03b18860 | 88 | // default constructor |
b760c02e | 89 | InitSymNames(); |
c18195b9 | 90 | } |
91 | ||
92 | //_____________________________________________________________________________ | |
b760c02e | 93 | AliAlignObj::AliAlignObj(const char* symname, UShort_t voluid) : |
fe12e09c | 94 | TObject(), |
b760c02e | 95 | fVolPath(symname), |
fe12e09c | 96 | fVolUID(voluid) |
d9cc42ed | 97 | { |
98 | // standard constructor | |
99 | // | |
d9cc42ed | 100 | } |
101 | ||
d9cc42ed | 102 | //_____________________________________________________________________________ |
c18195b9 | 103 | AliAlignObj::AliAlignObj(const AliAlignObj& theAlignObj) : |
fe12e09c | 104 | TObject(theAlignObj), |
b760c02e | 105 | fVolPath(theAlignObj.GetSymName()), |
fe12e09c | 106 | fVolUID(theAlignObj.GetVolUID()) |
c18195b9 | 107 | { |
108 | //copy constructor | |
c18195b9 | 109 | } |
110 | ||
111 | //_____________________________________________________________________________ | |
112 | AliAlignObj &AliAlignObj::operator =(const AliAlignObj& theAlignObj) | |
113 | { | |
114 | // assignment operator | |
115 | if(this==&theAlignObj) return *this; | |
b760c02e | 116 | fVolPath = theAlignObj.GetSymName(); |
c18195b9 | 117 | fVolUID = theAlignObj.GetVolUID(); |
118 | return *this; | |
119 | } | |
120 | ||
38b3a170 | 121 | //_____________________________________________________________________________ |
122 | AliAlignObj &AliAlignObj::operator*=(const AliAlignObj& theAlignObj) | |
123 | { | |
124 | // multiplication operator | |
125 | // The operator can be used to 'combine' | |
126 | // two alignment objects | |
127 | TGeoHMatrix m1; | |
128 | GetMatrix(m1); | |
129 | TGeoHMatrix m2; | |
130 | theAlignObj.GetMatrix(m2); | |
131 | m1.MultiplyLeft(&m2); | |
132 | SetMatrix(m1); | |
133 | return *this; | |
134 | } | |
135 | ||
c18195b9 | 136 | //_____________________________________________________________________________ |
137 | AliAlignObj::~AliAlignObj() | |
138 | { | |
139 | // dummy destructor | |
140 | } | |
141 | ||
befe2c08 | 142 | //_____________________________________________________________________________ |
143 | void AliAlignObj::SetVolUID(ELayerID detId, Int_t modId) | |
144 | { | |
145 | // From detector name and module number (according to detector numbering) | |
146 | // build fVolUID, unique numerical identity of that volume inside ALICE | |
147 | // fVolUID is 16 bits, first 5 reserved for detID (32 possible values), | |
148 | // remaining 11 for module ID inside det (2048 possible values). | |
149 | // | |
150 | fVolUID = LayerToVolUID(detId,modId); | |
151 | } | |
152 | ||
153 | //_____________________________________________________________________________ | |
154 | void AliAlignObj::GetVolUID(ELayerID &layerId, Int_t &modId) const | |
155 | { | |
156 | // From detector name and module number (according to detector numbering) | |
157 | // build fVolUID, unique numerical identity of that volume inside ALICE | |
158 | // fVolUID is 16 bits, first 5 reserved for detID (32 possible values), | |
159 | // remaining 11 for module ID inside det (2048 possible values). | |
160 | // | |
161 | layerId = VolUIDToLayer(fVolUID,modId); | |
162 | } | |
163 | ||
b760c02e | 164 | //_____________________________________________________________________________ |
165 | Bool_t AliAlignObj::GetPars(Double_t tr[], Double_t angles[]) const | |
166 | { | |
167 | GetTranslation(tr); | |
168 | return GetAngles(angles); | |
169 | } | |
170 | ||
4b94e753 | 171 | //_____________________________________________________________________________ |
172 | Int_t AliAlignObj::GetLevel() const | |
173 | { | |
174 | // Return the geometry level of | |
175 | // the alignable volume to which | |
176 | // the alignment object is associated | |
b760c02e | 177 | TString symname = fVolPath; |
178 | if(symname[0]!='/') symname.Prepend('/'); | |
179 | return symname.CountChar('/'); | |
4b94e753 | 180 | } |
181 | ||
182 | //_____________________________________________________________________________ | |
183 | Int_t AliAlignObj::Compare(const TObject *obj) const | |
184 | { | |
185 | // Compare the levels of two | |
186 | // alignment objects | |
187 | // Used in the sorting during | |
188 | // the application of alignment | |
189 | // objects to the geometry | |
190 | Int_t level = GetLevel(); | |
191 | Int_t level2 = ((AliAlignObj *)obj)->GetLevel(); | |
192 | if (level == level2) | |
193 | return 0; | |
194 | else | |
195 | return ((level > level2) ? 1 : -1); | |
196 | } | |
197 | ||
c18195b9 | 198 | //_____________________________________________________________________________ |
199 | void AliAlignObj::AnglesToMatrix(const Double_t *angles, Double_t *rot) const | |
200 | { | |
fdf65bb5 | 201 | // Calculates the rotation matrix using the |
202 | // Euler angles in "x y z" notation | |
c18195b9 | 203 | Double_t degrad = TMath::DegToRad(); |
204 | Double_t sinpsi = TMath::Sin(degrad*angles[0]); | |
205 | Double_t cospsi = TMath::Cos(degrad*angles[0]); | |
206 | Double_t sinthe = TMath::Sin(degrad*angles[1]); | |
207 | Double_t costhe = TMath::Cos(degrad*angles[1]); | |
208 | Double_t sinphi = TMath::Sin(degrad*angles[2]); | |
209 | Double_t cosphi = TMath::Cos(degrad*angles[2]); | |
210 | ||
211 | rot[0] = costhe*cosphi; | |
212 | rot[1] = -costhe*sinphi; | |
213 | rot[2] = sinthe; | |
214 | rot[3] = sinpsi*sinthe*cosphi + cospsi*sinphi; | |
215 | rot[4] = -sinpsi*sinthe*sinphi + cospsi*cosphi; | |
216 | rot[5] = -costhe*sinpsi; | |
217 | rot[6] = -cospsi*sinthe*cosphi + sinpsi*sinphi; | |
218 | rot[7] = cospsi*sinthe*sinphi + sinpsi*cosphi; | |
219 | rot[8] = costhe*cospsi; | |
220 | } | |
221 | ||
222 | //_____________________________________________________________________________ | |
223 | Bool_t AliAlignObj::MatrixToAngles(const Double_t *rot, Double_t *angles) const | |
224 | { | |
fdf65bb5 | 225 | // Calculates the Euler angles in "x y z" notation |
226 | // using the rotation matrix | |
b760c02e | 227 | // Returns false in case the rotation angles can not be |
228 | // extracted from the matrix | |
229 | if(TMath::Abs(rot[0])<1e-7 || TMath::Abs(rot[8])<1e-7) { | |
230 | AliError("Failed to extract roll-pitch-yall angles!"); | |
231 | return kFALSE; | |
232 | } | |
c18195b9 | 233 | Double_t raddeg = TMath::RadToDeg(); |
234 | angles[0]=raddeg*TMath::ATan2(-rot[5],rot[8]); | |
235 | angles[1]=raddeg*TMath::ASin(rot[2]); | |
236 | angles[2]=raddeg*TMath::ATan2(-rot[1],rot[0]); | |
237 | return kTRUE; | |
238 | } | |
239 | ||
03b18860 | 240 | //______________________________________________________________________________ |
241 | void AliAlignObj::Transform(AliTrackPoint &p) const | |
242 | { | |
243 | // The method transforms the space-point coordinates using the | |
244 | // transformation matrix provided by the AliAlignObj | |
245 | // The covariance matrix is not affected since we assume | |
246 | // that the transformations are sufficiently small | |
247 | ||
248 | if (fVolUID != p.GetVolumeID()) | |
249 | AliWarning(Form("Alignment object ID is not equal to the space-point ID (%d != %d)",fVolUID,p.GetVolumeID())); | |
250 | ||
251 | TGeoHMatrix m; | |
252 | GetMatrix(m); | |
253 | Double_t *rot = m.GetRotationMatrix(); | |
254 | Double_t *tr = m.GetTranslation(); | |
255 | ||
256 | Float_t xyzin[3],xyzout[3]; | |
257 | p.GetXYZ(xyzin); | |
258 | for (Int_t i = 0; i < 3; i++) | |
259 | xyzout[i] = tr[i]+ | |
260 | xyzin[0]*rot[3*i]+ | |
261 | xyzin[1]*rot[3*i+1]+ | |
262 | xyzin[2]*rot[3*i+2]; | |
263 | p.SetXYZ(xyzout); | |
264 | ||
265 | } | |
266 | ||
79e21da6 | 267 | //_____________________________________________________________________________ |
03b18860 | 268 | void AliAlignObj::Transform(AliTrackPointArray &array) const |
269 | { | |
e1e6896f | 270 | // This method is used to transform all the track points |
271 | // from the input AliTrackPointArray | |
03b18860 | 272 | AliTrackPoint p; |
273 | for (Int_t i = 0; i < array.GetNPoints(); i++) { | |
274 | array.GetPoint(p,i); | |
275 | Transform(p); | |
276 | array.AddPoint(i,&p); | |
277 | } | |
278 | } | |
279 | ||
c18195b9 | 280 | //_____________________________________________________________________________ |
281 | void AliAlignObj::Print(Option_t *) const | |
282 | { | |
283 | // Print the contents of the | |
284 | // alignment object in angles and | |
285 | // matrix representations | |
286 | Double_t tr[3]; | |
287 | GetTranslation(tr); | |
288 | Double_t angles[3]; | |
289 | GetAngles(angles); | |
290 | TGeoHMatrix m; | |
291 | GetMatrix(m); | |
292 | const Double_t *rot = m.GetRotationMatrix(); | |
c18195b9 | 293 | |
b760c02e | 294 | printf("Volume=%s\n",GetSymName()); |
c041444f | 295 | if (GetVolUID() != 0) { |
296 | ELayerID layerId; | |
297 | Int_t modId; | |
298 | GetVolUID(layerId,modId); | |
299 | printf("VolumeID=%d LayerID=%d ( %s ) ModuleID=%d\n", GetVolUID(),layerId,LayerName(layerId),modId); | |
300 | } | |
301 | printf("%12.8f%12.8f%12.8f Tx = %12.8f Psi = %12.8f\n", rot[0], rot[1], rot[2], tr[0], angles[0]); | |
302 | printf("%12.8f%12.8f%12.8f Ty = %12.8f Theta = %12.8f\n", rot[3], rot[4], rot[5], tr[1], angles[1]); | |
303 | printf("%12.8f%12.8f%12.8f Tz = %12.8f Phi = %12.8f\n", rot[6], rot[7], rot[8], tr[2], angles[2]); | |
304 | ||
305 | } | |
306 | ||
307 | //_____________________________________________________________________________ | |
308 | Int_t AliAlignObj::LayerSize(Int_t layerId) | |
309 | { | |
310 | // Get the corresponding layer size. | |
311 | // Implemented only for ITS,TPC,TRD,TOF and RICH | |
312 | if (layerId < kFirstLayer || layerId >= kLastLayer) { | |
313 | AliErrorClass(Form("Invalid layer index %d ! Layer range is (%d -> %d) !",layerId,kFirstLayer,kLastLayer)); | |
314 | return 0; | |
315 | } | |
316 | else { | |
317 | return fgLayerSize[layerId - kFirstLayer]; | |
318 | } | |
319 | } | |
320 | ||
321 | //_____________________________________________________________________________ | |
322 | const char* AliAlignObj::LayerName(Int_t layerId) | |
323 | { | |
324 | // Get the corresponding layer name. | |
325 | // Implemented only for ITS,TPC,TRD,TOF and RICH | |
326 | if (layerId < kFirstLayer || layerId >= kLastLayer) { | |
327 | AliErrorClass(Form("Invalid layer index %d ! Layer range is (%d -> %d) !",layerId,kFirstLayer,kLastLayer)); | |
328 | return "Invalid Layer!"; | |
329 | } | |
330 | else { | |
331 | return fgLayerName[layerId - kFirstLayer]; | |
332 | } | |
c18195b9 | 333 | } |
334 | ||
c18195b9 | 335 | //_____________________________________________________________________________ |
befe2c08 | 336 | UShort_t AliAlignObj::LayerToVolUID(ELayerID layerId, Int_t modId) |
c18195b9 | 337 | { |
befe2c08 | 338 | // From detector (layer) name and module number (according to detector numbering) |
339 | // build fVolUID, unique numerical identity of that volume inside ALICE | |
340 | // fVolUID is 16 bits, first 5 reserved for layerID (32 possible values), | |
341 | // remaining 11 for module ID inside det (2048 possible values). | |
c18195b9 | 342 | // |
befe2c08 | 343 | return ((UShort_t(layerId) << 11) | UShort_t(modId)); |
c18195b9 | 344 | } |
345 | ||
46ae650f | 346 | //_____________________________________________________________________________ |
347 | UShort_t AliAlignObj::LayerToVolUID(Int_t layerId, Int_t modId) | |
348 | { | |
349 | // From detector (layer) index and module number (according to detector numbering) | |
350 | // build fVolUID, unique numerical identity of that volume inside ALICE | |
351 | // fVolUID is 16 bits, first 5 reserved for layerID (32 possible values), | |
352 | // remaining 11 for module ID inside det (2048 possible values). | |
353 | // | |
354 | return ((UShort_t(layerId) << 11) | UShort_t(modId)); | |
355 | } | |
356 | ||
c18195b9 | 357 | //_____________________________________________________________________________ |
befe2c08 | 358 | AliAlignObj::ELayerID AliAlignObj::VolUIDToLayer(UShort_t voluid, Int_t &modId) |
c18195b9 | 359 | { |
befe2c08 | 360 | // From detector (layer) name and module number (according to detector numbering) |
361 | // build fVolUID, unique numerical identity of that volume inside ALICE | |
362 | // fVolUID is 16 bits, first 5 reserved for layerID (32 possible values), | |
363 | // remaining 11 for module ID inside det (2048 possible values). | |
364 | // | |
365 | modId = voluid & 0x7ff; | |
c18195b9 | 366 | |
befe2c08 | 367 | return VolUIDToLayer(voluid); |
c18195b9 | 368 | } |
369 | ||
370 | //_____________________________________________________________________________ | |
befe2c08 | 371 | AliAlignObj::ELayerID AliAlignObj::VolUIDToLayer(UShort_t voluid) |
c18195b9 | 372 | { |
befe2c08 | 373 | // From detector (layer) name and module number (according to detector numbering) |
374 | // build fVolUID, unique numerical identity of that volume inside ALICE | |
375 | // fVolUID is 16 bits, first 5 reserved for layerID (32 possible values), | |
376 | // remaining 11 for module ID inside det (2048 possible values). | |
377 | // | |
378 | return ELayerID((voluid >> 11) & 0x1f); | |
c18195b9 | 379 | } |
03b18860 | 380 | |
b760c02e | 381 | //_____________________________________________________________________________ |
382 | void AliAlignObj::SetPars(Double_t x, Double_t y, Double_t z, | |
383 | Double_t psi, Double_t theta, Double_t phi) | |
384 | { | |
385 | // Set rotation matrix and translation | |
386 | // using 3 angles and 3 translations | |
387 | SetTranslation(x,y,z); | |
388 | SetRotation(psi,theta,phi); | |
389 | } | |
390 | ||
1bfe7ffc | 391 | //_____________________________________________________________________________ |
392 | Bool_t AliAlignObj::SetLocalPars(Double_t x, Double_t y, Double_t z, | |
393 | Double_t psi, Double_t theta, Double_t phi) | |
394 | { | |
395 | // Set the translations and angles by using parameters | |
396 | // defined in the local (in TGeo means) coordinate system | |
397 | // of the alignable volume. In case that the TGeo was | |
398 | // initialized, returns false and the object parameters are | |
399 | // not set. | |
b760c02e | 400 | TGeoHMatrix m; |
401 | Double_t tr[3] = {x, y, z}; | |
402 | m.SetTranslation(tr); | |
403 | Double_t angles[3] = {psi, theta, phi}; | |
404 | Double_t rot[9]; | |
405 | AnglesToMatrix(angles,rot); | |
406 | m.SetRotation(rot); | |
407 | ||
408 | return SetLocalMatrix(m); | |
409 | ||
410 | } | |
411 | ||
412 | //_____________________________________________________________________________ | |
413 | Bool_t AliAlignObj::SetLocalMatrix(const TGeoMatrix& m) | |
414 | { | |
415 | // Set the translations and angles by using TGeo matrix | |
416 | // defined in the local (in TGeo means) coordinate system | |
417 | // of the alignable volume. In case that the TGeo was | |
418 | // initialized, returns false and the object parameters are | |
419 | // not set. | |
420 | ||
1bfe7ffc | 421 | if (!gGeoManager || !gGeoManager->IsClosed()) { |
422 | AliError("Can't set the alignment object parameters! gGeoManager doesn't exist or it is still opened!"); | |
423 | return kFALSE; | |
424 | } | |
425 | ||
b760c02e | 426 | const char* symname = GetSymName(); |
427 | TGeoPhysicalNode* node; | |
428 | TGeoPNEntry* pne = gGeoManager->GetAlignableEntry(symname); | |
429 | if(pne){ | |
430 | node = gGeoManager->MakeAlignablePN(pne); | |
431 | }else{ | |
432 | AliWarning(Form("The symbolic volume name %s does not correspond to a physical entry. Using it as volume path!",symname)); | |
433 | node = (TGeoPhysicalNode*) gGeoManager->MakePhysicalNode(symname); | |
434 | } | |
435 | ||
1bfe7ffc | 436 | if (!node) { |
b760c02e | 437 | AliError(Form("Volume name or path %s not valid!",symname)); |
1bfe7ffc | 438 | return kFALSE; |
439 | } | |
440 | if (node->IsAligned()) | |
b760c02e | 441 | AliWarning(Form("Volume %s has been already misaligned!",symname)); |
1bfe7ffc | 442 | |
b760c02e | 443 | TGeoHMatrix m1; |
444 | const Double_t *tr = m.GetTranslation(); | |
445 | m1.SetTranslation(tr); | |
446 | const Double_t* rot = m.GetRotationMatrix(); | |
447 | m1.SetRotation(rot); | |
1bfe7ffc | 448 | |
449 | TGeoHMatrix align,gprime,gprimeinv; | |
450 | gprime = *node->GetMatrix(); | |
451 | gprimeinv = gprime.Inverse(); | |
b760c02e | 452 | m1.Multiply(&gprimeinv); |
453 | m1.MultiplyLeft(&gprime); | |
1bfe7ffc | 454 | |
b760c02e | 455 | return SetMatrix(m1); |
456 | } | |
1bfe7ffc | 457 | |
b760c02e | 458 | //_____________________________________________________________________________ |
459 | Bool_t AliAlignObj::SetMatrix(const TGeoMatrix& m) | |
460 | { | |
461 | // Set rotation matrix and translation | |
462 | // using TGeoMatrix | |
463 | SetTranslation(m); | |
464 | return SetRotation(m); | |
1bfe7ffc | 465 | } |
466 | ||
995ad051 | 467 | //_____________________________________________________________________________ |
468 | Bool_t AliAlignObj::ApplyToGeometry() | |
469 | { | |
470 | // Apply the current alignment object | |
471 | // to the TGeo geometry | |
472 | ||
473 | if (!gGeoManager || !gGeoManager->IsClosed()) { | |
474 | AliError("Can't apply the alignment object! gGeoManager doesn't exist or it is still opened!"); | |
475 | return kFALSE; | |
476 | } | |
477 | ||
b760c02e | 478 | const char* symname = GetSymName(); |
479 | const char* path; | |
480 | TGeoPhysicalNode* node; | |
481 | TGeoPNEntry* pne = gGeoManager->GetAlignableEntry(symname); | |
482 | if(pne){ | |
483 | node = gGeoManager->MakeAlignablePN(pne); | |
484 | if(!node) return kFALSE; | |
485 | path = pne->GetTitle(); | |
486 | }else{ | |
487 | AliWarning(Form("The symbolic volume name %s does not correspond to a physical entry. Using it as a volume path!",symname)); | |
488 | path=symname; | |
489 | if (gGeoManager->GetListOfPhysicalNodes()->FindObject(path)) { | |
490 | AliError(Form("Volume %s has already been misaligned!",path)); | |
491 | return kFALSE; | |
492 | } | |
493 | if (!gGeoManager->cd(path)) { | |
494 | AliError(Form("Volume path %s not valid!",path)); | |
495 | return kFALSE; | |
496 | } | |
497 | node = (TGeoPhysicalNode*) gGeoManager->MakePhysicalNode(path); | |
995ad051 | 498 | } |
48cac49d | 499 | |
48cac49d | 500 | if (!node) { |
b760c02e | 501 | AliError(Form("Volume path %s not valid!",path)); |
995ad051 | 502 | return kFALSE; |
503 | } | |
504 | ||
505 | TGeoHMatrix align,gprime; | |
506 | gprime = *node->GetMatrix(); | |
507 | GetMatrix(align); | |
508 | gprime.MultiplyLeft(&align); | |
509 | TGeoHMatrix *ginv = new TGeoHMatrix; | |
510 | TGeoHMatrix *g = node->GetMatrix(node->GetLevel()-1); | |
511 | *ginv = g->Inverse(); | |
512 | *ginv *= gprime; | |
b760c02e | 513 | AliAlignObj::ELayerID layerId; // unique identity for layer in the alobj |
514 | Int_t modId; // unique identity for volume inside layer in the alobj | |
995ad051 | 515 | GetVolUID(layerId, modId); |
b760c02e | 516 | AliDebug(2,Form("Aligning volume %s of detector layer %d with local ID %d",symname,layerId,modId)); |
995ad051 | 517 | node->Align(ginv); |
518 | ||
519 | return kTRUE; | |
520 | } | |
521 | ||
522 | //_____________________________________________________________________________ | |
b760c02e | 523 | Bool_t AliAlignObj::GetFromGeometry(const char *symname, AliAlignObj &alobj) |
995ad051 | 524 | { |
b760c02e | 525 | // Get the alignment object which corresponds to the symbolic volume name |
526 | // symname (in case equal to the TGeo volume path) | |
527 | // The method is extremely slow due to the searching by string. | |
528 | // Therefore it should be used with great care!! | |
529 | // | |
995ad051 | 530 | |
531 | // Reset the alignment object | |
532 | alobj.SetPars(0,0,0,0,0,0); | |
b760c02e | 533 | alobj.SetSymName(symname); |
995ad051 | 534 | |
535 | if (!gGeoManager || !gGeoManager->IsClosed()) { | |
536 | AliErrorClass("Can't get the alignment object! gGeoManager doesn't exist or it is still opened!"); | |
537 | return kFALSE; | |
538 | } | |
539 | ||
540 | if (!gGeoManager->GetListOfPhysicalNodes()) { | |
541 | AliErrorClass("Can't get the alignment object! gGeoManager doesn't contain any aligned nodes!"); | |
542 | return kFALSE; | |
543 | } | |
544 | ||
b760c02e | 545 | const char *path; |
546 | TGeoPNEntry* pne = gGeoManager->GetAlignableEntry(symname); | |
547 | if(pne){ | |
548 | path = pne->GetTitle(); | |
549 | }else{ | |
550 | AliWarningClass(Form("The symbolic volume name %s does not correspond to a physical entry. Using it as a volume path!",symname)); | |
551 | path = symname; | |
552 | } | |
995ad051 | 553 | TObjArray* nodesArr = gGeoManager->GetListOfPhysicalNodes(); |
554 | TGeoPhysicalNode* node = NULL; | |
555 | for (Int_t iNode = 0; iNode < nodesArr->GetEntriesFast(); iNode++) { | |
b760c02e | 556 | TGeoPhysicalNode* tempNode = (TGeoPhysicalNode*) nodesArr->UncheckedAt(iNode); |
557 | const char *nodePath = tempNode->GetName(); | |
558 | if (strcmp(symname,nodePath) == 0) { | |
559 | node = tempNode; | |
560 | break; | |
561 | } | |
995ad051 | 562 | } |
b760c02e | 563 | |
995ad051 | 564 | if (!node) { |
b760c02e | 565 | if (!gGeoManager->cd(symname)) { |
566 | AliErrorClass(Form("%s not valid neither as symbolic volume name nor as volume path!",symname)); | |
e1c4b551 | 567 | return kFALSE; |
568 | } | |
569 | else { | |
b760c02e | 570 | AliWarningClass(Form("Volume (%s) has not been misaligned!",symname)); |
e1c4b551 | 571 | return kTRUE; |
572 | } | |
995ad051 | 573 | } |
574 | ||
575 | TGeoHMatrix align,gprime,g,ginv,l; | |
576 | gprime = *node->GetMatrix(); | |
577 | l = *node->GetOriginalMatrix(); | |
578 | g = *node->GetMatrix(node->GetLevel()-1); | |
579 | g *= l; | |
580 | ginv = g.Inverse(); | |
581 | align = gprime * ginv; | |
995ad051 | 582 | |
b760c02e | 583 | return alobj.SetMatrix(align); |
995ad051 | 584 | } |
585 | ||
79e21da6 | 586 | //_____________________________________________________________________________ |
c5304981 | 587 | void AliAlignObj::InitAlignObjFromGeometry() |
588 | { | |
589 | // Loop over all alignable volumes and extract | |
590 | // the corresponding alignment objects from | |
591 | // the TGeo geometry | |
25b4e81e | 592 | |
593 | if(fgAlignObjs[0]) return; | |
c5304981 | 594 | |
b760c02e | 595 | InitSymNames(); |
c5304981 | 596 | |
c041444f | 597 | for (Int_t iLayer = kFirstLayer; iLayer < AliAlignObj::kLastLayer; iLayer++) { |
598 | fgAlignObjs[iLayer-kFirstLayer] = new AliAlignObj*[AliAlignObj::LayerSize(iLayer)]; | |
c5304981 | 599 | for (Int_t iModule = 0; iModule < AliAlignObj::LayerSize(iLayer); iModule++) { |
c041444f | 600 | UShort_t volid = AliAlignObj::LayerToVolUID(iLayer,iModule); |
b760c02e | 601 | fgAlignObjs[iLayer-kFirstLayer][iModule] = new AliAlignObjAngles("",volid,0,0,0,0,0,0,kTRUE); |
602 | const char *symname = SymName(volid); | |
603 | if (!GetFromGeometry(symname, *fgAlignObjs[iLayer-kFirstLayer][iModule])) | |
604 | AliErrorClass(Form("Failed to extract the alignment object for the volume (ID=%d and path=%s) !",volid,symname)); | |
c5304981 | 605 | } |
606 | } | |
607 | ||
608 | } | |
609 | ||
e1e6896f | 610 | //_____________________________________________________________________________ |
611 | AliAlignObj* AliAlignObj::GetAlignObj(UShort_t voluid) { | |
612 | // Returns the alignment object for given volume ID | |
613 | Int_t modId; | |
614 | ELayerID layerId = VolUIDToLayer(voluid,modId); | |
615 | return GetAlignObj(layerId,modId); | |
616 | } | |
617 | ||
c5304981 | 618 | //_____________________________________________________________________________ |
619 | AliAlignObj* AliAlignObj::GetAlignObj(ELayerID layerId, Int_t modId) | |
620 | { | |
e1e6896f | 621 | // Returns pointer to alignment object givent its layer and module ID |
c5304981 | 622 | if(modId<0 || modId>=fgLayerSize[layerId-kFirstLayer]){ |
623 | AliWarningClass(Form("Module number %d not in the valid range (0->%d) !",modId,fgLayerSize[layerId-kFirstLayer]-1)); | |
624 | return NULL; | |
625 | } | |
b760c02e | 626 | InitAlignObjFromGeometry(); |
627 | ||
c5304981 | 628 | return fgAlignObjs[layerId-kFirstLayer][modId]; |
629 | } | |
630 | ||
e1e6896f | 631 | //_____________________________________________________________________________ |
b760c02e | 632 | const char* AliAlignObj::SymName(UShort_t voluid) { |
e1e6896f | 633 | // Returns the volume path for given volume ID |
634 | Int_t modId; | |
635 | ELayerID layerId = VolUIDToLayer(voluid,modId); | |
b760c02e | 636 | return SymName(layerId,modId); |
e1e6896f | 637 | } |
638 | ||
e7570944 | 639 | //_____________________________________________________________________________ |
b760c02e | 640 | const char* AliAlignObj::SymName(ELayerID layerId, Int_t modId) |
e7570944 | 641 | { |
e1e6896f | 642 | // Returns volume path to alignment object givent its layer and module ID |
e7570944 | 643 | if(modId<0 || modId>=fgLayerSize[layerId-kFirstLayer]){ |
644 | AliWarningClass(Form("Module number %d not in the valid range (0->%d) !",modId,fgLayerSize[layerId-kFirstLayer]-1)); | |
645 | return NULL; | |
646 | } | |
b760c02e | 647 | InitSymNames(); |
648 | ||
e7570944 | 649 | return fgVolPath[layerId-kFirstLayer][modId].Data(); |
650 | } | |
651 | ||
03b18860 | 652 | //_____________________________________________________________________________ |
b760c02e | 653 | void AliAlignObj::InitSymNames() |
03b18860 | 654 | { |
655 | // Initialize the LUTs which contain | |
656 | // the TGeo volume paths for each | |
657 | // alignable volume. The LUTs are | |
658 | // static, so they are created during | |
659 | // the creation of the first intance | |
660 | // of AliAlignObj | |
661 | ||
662 | if (fgVolPath[0]) return; | |
663 | ||
664 | for (Int_t iLayer = 0; iLayer < (kLastLayer - kFirstLayer); iLayer++) | |
7604a026 | 665 | fgVolPath[iLayer] = new TString[fgLayerSize[iLayer]]; |
03b18860 | 666 | |
667 | /********************* SPD layer1 ***********************/ | |
668 | { | |
669 | Int_t modnum = 0; | |
670 | TString str0 = "ALIC_1/ITSV_1/ITSD_1/IT12_1/I12B_"; //".../I12A_" | |
671 | TString str1 = "/I10B_"; //"/I10A_"; | |
672 | TString str2 = "/I107_"; //"/I103_" | |
995ad051 | 673 | // TString str3 = "/I101_1/ITS1_1"; |
b760c02e | 674 | TString symname, symname1, symname2; |
03b18860 | 675 | |
676 | for(Int_t c1 = 1; c1<=10; c1++){ | |
b760c02e | 677 | symname = str0; |
678 | symname += c1; | |
679 | symname += str1; | |
03b18860 | 680 | for(Int_t c2 =1; c2<=2; c2++){ |
b760c02e | 681 | symname1 = symname; |
682 | symname1 += c2; | |
683 | symname1 += str2; | |
03b18860 | 684 | for(Int_t c3 =1; c3<=4; c3++){ |
b760c02e | 685 | symname2 = symname1; |
686 | symname2 += c3; | |
687 | // symname2 += str3; | |
688 | fgVolPath[kSPD1-kFirstLayer][modnum] = symname2.Data(); | |
03b18860 | 689 | modnum++; |
690 | } | |
691 | } | |
692 | } | |
693 | } | |
694 | ||
695 | /********************* SPD layer2 ***********************/ | |
696 | { | |
697 | Int_t modnum = 0; | |
698 | TString str0 = "ALIC_1/ITSV_1/ITSD_1/IT12_1/I12B_"; //".../I12A_" | |
699 | TString str1 = "/I20B_"; //"/I20A" | |
700 | TString str2 = "/I1D7_"; //"/I1D3" | |
995ad051 | 701 | // TString str3 = "/I1D1_1/ITS2_1"; |
b760c02e | 702 | TString symname, symname1, symname2; |
03b18860 | 703 | |
704 | for(Int_t c1 = 1; c1<=10; c1++){ | |
b760c02e | 705 | symname = str0; |
706 | symname += c1; | |
707 | symname += str1; | |
03b18860 | 708 | for(Int_t c2 =1; c2<=4; c2++){ |
b760c02e | 709 | symname1 = symname; |
710 | symname1 += c2; | |
711 | symname1 += str2; | |
03b18860 | 712 | for(Int_t c3 =1; c3<=4; c3++){ |
b760c02e | 713 | symname2 = symname1; |
714 | symname2 += c3; | |
715 | // symname2 += str3; | |
716 | fgVolPath[kSPD2-kFirstLayer][modnum] = symname2.Data(); | |
03b18860 | 717 | modnum++; |
718 | } | |
719 | } | |
720 | } | |
721 | } | |
722 | ||
723 | /********************* SDD layer1 ***********************/ | |
724 | { | |
725 | Int_t modnum=0; | |
726 | TString str0 = "ALIC_1/ITSV_1/ITSD_1/IT34_1/I004_"; | |
727 | TString str1 = "/I302_"; | |
995ad051 | 728 | // TString str2 = "/ITS3_1"; |
b760c02e | 729 | TString symname, symname1; |
03b18860 | 730 | |
731 | for(Int_t c1 = 1; c1<=14; c1++){ | |
b760c02e | 732 | symname = str0; |
733 | symname += c1; | |
734 | symname += str1; | |
03b18860 | 735 | for(Int_t c2 =1; c2<=6; c2++){ |
b760c02e | 736 | symname1 = symname; |
737 | symname1 += c2; | |
738 | // symname1 += str2; | |
739 | fgVolPath[kSDD1-kFirstLayer][modnum] = symname1.Data(); | |
03b18860 | 740 | modnum++; |
741 | } | |
742 | } | |
743 | } | |
744 | ||
745 | /********************* SDD layer2 ***********************/ | |
746 | { | |
747 | Int_t modnum=0; | |
748 | TString str0 = "ALIC_1/ITSV_1/ITSD_1/IT34_1/I005_"; | |
749 | TString str1 = "/I402_"; | |
995ad051 | 750 | // TString str2 = "/ITS4_1"; |
b760c02e | 751 | TString symname, symname1; |
03b18860 | 752 | |
753 | for(Int_t c1 = 1; c1<=22; c1++){ | |
b760c02e | 754 | symname = str0; |
755 | symname += c1; | |
756 | symname += str1; | |
03b18860 | 757 | for(Int_t c2 = 1; c2<=8; c2++){ |
b760c02e | 758 | symname1 = symname; |
759 | symname1 += c2; | |
760 | // symname1 += str2; | |
761 | fgVolPath[kSDD2-kFirstLayer][modnum] = symname1.Data(); | |
03b18860 | 762 | modnum++; |
763 | } | |
764 | } | |
765 | } | |
766 | ||
767 | /********************* SSD layer1 ***********************/ | |
768 | { | |
769 | Int_t modnum=0; | |
770 | TString str0 = "ALIC_1/ITSV_1/ITSD_1/IT56_1/I565_"; | |
771 | TString str1 = "/I562_"; | |
995ad051 | 772 | // TString str2 = "/ITS5_1"; |
b760c02e | 773 | TString symname, symname1; |
03b18860 | 774 | |
775 | for(Int_t c1 = 1; c1<=34; c1++){ | |
b760c02e | 776 | symname = str0; |
777 | symname += c1; | |
778 | symname += str1; | |
03b18860 | 779 | for(Int_t c2 = 1; c2<=22; c2++){ |
b760c02e | 780 | symname1 = symname; |
781 | symname1 += c2; | |
782 | // symname1 += str2; | |
783 | fgVolPath[kSSD1-kFirstLayer][modnum] = symname1.Data(); | |
03b18860 | 784 | modnum++; |
785 | } | |
786 | } | |
787 | } | |
788 | ||
789 | /********************* SSD layer1 ***********************/ | |
790 | { | |
791 | Int_t modnum=0; | |
792 | TString str0 = "ALIC_1/ITSV_1/ITSD_1/IT56_1/I569_"; | |
793 | TString str1 = "/I566_"; | |
995ad051 | 794 | // TString str2 = "/ITS6_1"; |
b760c02e | 795 | TString symname, symname1; |
03b18860 | 796 | |
797 | for(Int_t c1 = 1; c1<=38; c1++){ | |
b760c02e | 798 | symname = str0; |
799 | symname += c1; | |
800 | symname += str1; | |
03b18860 | 801 | for(Int_t c2 = 1; c2<=25; c2++){ |
b760c02e | 802 | symname1 = symname; |
803 | symname1 += c2; | |
804 | // symname1 += str2; | |
805 | fgVolPath[kSSD2-kFirstLayer][modnum] = symname1.Data(); | |
03b18860 | 806 | modnum++; |
807 | } | |
808 | } | |
809 | } | |
810 | ||
e7570944 | 811 | /*************** TPC inner chambers' layer ****************/ |
812 | { | |
813 | Int_t modnum = 0; | |
814 | TString str1 = "ALIC_1/TPC_M_1/TPC_Drift_1/TPC_ENDCAP_1/TPC_SECT_"; | |
815 | TString str2 = "ALIC_1/TPC_M_1/TPC_Drift_1/TPC_ENDCAP_2/TPC_SECT_"; | |
e1e6896f | 816 | TString strIn = "/TPC_IROC_1"; |
b760c02e | 817 | TString symname; |
e7570944 | 818 | |
819 | for(Int_t cnt=1; cnt<=18; cnt++){ | |
b760c02e | 820 | symname = str1; |
821 | symname += cnt; | |
822 | symname += strIn; | |
823 | fgVolPath[kTPC1-kFirstLayer][modnum] = symname.Data(); | |
e7570944 | 824 | modnum++; |
825 | } | |
826 | for(Int_t cnt=1; cnt<=18; cnt++){ | |
b760c02e | 827 | symname = str2; |
828 | symname += cnt; | |
829 | symname += strIn; | |
830 | fgVolPath[kTPC1-kFirstLayer][modnum] = symname.Data(); | |
e7570944 | 831 | modnum++; |
832 | } | |
833 | } | |
834 | ||
835 | /*************** TPC outer chambers' layer ****************/ | |
836 | { | |
837 | Int_t modnum = 0; | |
838 | TString str1 = "ALIC_1/TPC_M_1/TPC_Drift_1/TPC_ENDCAP_1/TPC_SECT_"; | |
839 | TString str2 = "ALIC_1/TPC_M_1/TPC_Drift_1/TPC_ENDCAP_2/TPC_SECT_"; | |
e1e6896f | 840 | TString strOut = "/TPC_OROC_1"; |
b760c02e | 841 | TString symname; |
e7570944 | 842 | |
843 | for(Int_t cnt=1; cnt<=18; cnt++){ | |
b760c02e | 844 | symname = str1; |
845 | symname += cnt; | |
846 | symname += strOut; | |
847 | fgVolPath[kTPC2-kFirstLayer][modnum] = symname.Data(); | |
e7570944 | 848 | modnum++; |
849 | } | |
850 | for(Int_t cnt=1; cnt<=18; cnt++){ | |
b760c02e | 851 | symname = str2; |
852 | symname += cnt; | |
853 | symname += strOut; | |
854 | fgVolPath[kTPC2-kFirstLayer][modnum] = symname.Data(); | |
e7570944 | 855 | modnum++; |
856 | } | |
857 | } | |
858 | ||
9abb5d7b | 859 | /********************* TOF layer ***********************/ |
860 | { | |
861 | Int_t nstrA=15; | |
862 | Int_t nstrB=19; | |
da027ef2 | 863 | Int_t nstrC=19; |
864 | Int_t nsec=18; | |
9abb5d7b | 865 | Int_t nStripSec=nstrA+2*nstrB+2*nstrC; |
da027ef2 | 866 | Int_t nStrip=nStripSec*nsec; |
9abb5d7b | 867 | |
da027ef2 | 868 | for (Int_t modnum=0; modnum < nStrip; modnum++) { |
9abb5d7b | 869 | |
870 | Int_t sector = modnum/nStripSec; | |
9abb5d7b | 871 | Char_t string1[100]; |
872 | Char_t string2[100]; | |
9abb5d7b | 873 | Int_t icopy=-1; |
de0b6220 | 874 | icopy=sector; |
875 | ||
876 | // Old 6h convention | |
877 | // if(sector<13){ | |
878 | // icopy=sector+5;} | |
879 | // else{ icopy=sector-13;} | |
38b3a170 | 880 | |
06e24a91 | 881 | sprintf(string1,"/ALIC_1/B077_1/BSEGMO%i_1/BTOF%i_1/FTOA_0/FLTA_0",sector,sector); |
da027ef2 | 882 | |
9abb5d7b | 883 | Int_t strInSec=modnum%nStripSec; |
da027ef2 | 884 | icopy= strInSec; |
885 | icopy++; | |
886 | sprintf(string2,"FSTR_%i",icopy); | |
9abb5d7b | 887 | Char_t path[100]; |
888 | sprintf(path,"%s/%s",string1,string2); | |
889 | // printf("%d %s\n",modnum,path); | |
890 | fgVolPath[kTOF-kFirstLayer][modnum] = path; | |
891 | } | |
892 | } | |
c8874495 | 893 | |
894 | /********************* RICH layer ***********************/ | |
895 | { | |
896 | TString str = "ALIC_1/RICH_"; | |
b760c02e | 897 | TString symname; |
c8874495 | 898 | |
899 | for (Int_t modnum=0; modnum < 7; modnum++) { | |
b760c02e | 900 | symname = str; |
901 | symname += (modnum+1); | |
902 | fgVolPath[kRICH-kFirstLayer][modnum] = symname.Data(); | |
c8874495 | 903 | } |
904 | } | |
274fcc1a | 905 | |
906 | /********************* TRD layers 0-6 *******************/ | |
907 | { | |
de0b6220 | 908 | TString strSM[18]={"ALIC_1/B077_1/BSEGMO0_1/BTRD0_1/UTR1_1/UTS1_1/UTI1_1/UT", |
909 | "ALIC_1/B077_1/BSEGMO1_1/BTRD1_1/UTR1_1/UTS1_1/UTI1_1/UT", | |
910 | "ALIC_1/B077_1/BSEGMO2_1/BTRD2_1/UTR1_1/UTS1_1/UTI1_1/UT", | |
911 | "ALIC_1/B077_1/BSEGMO3_1/BTRD3_1/UTR1_1/UTS1_1/UTI1_1/UT", | |
912 | "ALIC_1/B077_1/BSEGMO4_1/BTRD4_1/UTR1_1/UTS1_1/UTI1_1/UT", | |
913 | "ALIC_1/B077_1/BSEGMO5_1/BTRD5_1/UTR1_1/UTS1_1/UTI1_1/UT", | |
9ce7d00f | 914 | "ALIC_1/B077_1/BSEGMO6_1/BTRD6_1/UTR1_1/UTS1_1/UTI1_1/UT", |
915 | "ALIC_1/B077_1/BSEGMO7_1/BTRD7_1/UTR1_1/UTS1_1/UTI1_1/UT", | |
916 | "ALIC_1/B077_1/BSEGMO8_1/BTRD8_1/UTR1_1/UTS1_1/UTI1_1/UT", | |
917 | "ALIC_1/B077_1/BSEGMO9_1/BTRD9_1/UTR1_1/UTS1_1/UTI1_1/UT", | |
918 | "ALIC_1/B077_1/BSEGMO10_1/BTRD10_1/UTR1_1/UTS1_1/UTI1_1/UT", | |
919 | "ALIC_1/B077_1/BSEGMO11_1/BTRD11_1/UTR1_1/UTS1_1/UTI1_1/UT", | |
920 | "ALIC_1/B077_1/BSEGMO12_1/BTRD12_1/UTR1_1/UTS1_1/UTI1_1/UT", | |
921 | "ALIC_1/B077_1/BSEGMO13_1/BTRD13_1/UTR1_1/UTS1_1/UTI1_1/UT", | |
922 | "ALIC_1/B077_1/BSEGMO14_1/BTRD14_1/UTR1_1/UTS1_1/UTI1_1/UT", | |
923 | "ALIC_1/B077_1/BSEGMO15_1/BTRD15_1/UTR1_1/UTS1_1/UTI1_1/UT", | |
924 | "ALIC_1/B077_1/BSEGMO16_1/BTRD16_1/UTR1_1/UTS1_1/UTI1_1/UT", | |
de0b6220 | 925 | "ALIC_1/B077_1/BSEGMO17_1/BTRD17_1/UTR1_1/UTS1_1/UTI1_1/UT"}; |
274fcc1a | 926 | TString strPost = "_1"; |
a1a23a88 | 927 | TString zeroStr = "0"; |
b760c02e | 928 | TString symname; |
a1a23a88 | 929 | |
e1e6896f | 930 | Int_t arTRDlayId[6] = {kTRD1, kTRD2, kTRD3, kTRD4, kTRD5, kTRD6}; |
274fcc1a | 931 | |
a1a23a88 | 932 | for(Int_t layer=0; layer<6; layer++){ |
933 | Int_t modnum=0; | |
934 | for(Int_t sm = 0; sm < 18; sm++){ | |
935 | for(Int_t stacknum = 0; stacknum < 5; stacknum++){ | |
936 | Int_t chnum = layer + stacknum*6; | |
b760c02e | 937 | symname = strSM[sm]; |
938 | if(chnum<10) symname += zeroStr; | |
939 | symname += chnum; | |
940 | symname += strPost; | |
941 | fgVolPath[arTRDlayId[layer]-kFirstLayer][modnum] = symname.Data(); | |
274fcc1a | 942 | modnum++; |
943 | } | |
944 | } | |
945 | } | |
946 | } | |
947 | ||
03b18860 | 948 | } |