1 /**************************************************************************
2 * Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
4 * Author: The ALICE Off-line Project. *
5 * Contributors are mentioned in the code where appropriate. *
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 **************************************************************************/
16 ///////////////////////////////////////////////////////////////////////////
17 // AliITSUGeomTGeo is a simple interface class to TGeoManager //
18 // It is used in the simulation and reconstruction in order to //
19 // query the TGeo ITS geometry //
21 // author - cvetan.cheshkov@cern.ch //
23 // adapted to ITSupg 18/07/2012 - ruben.shahoyan@cern.ch //
25 // ATTENTION: In opposite to ols AliITSgeomTGeo, all indices start //
26 // from 0, not from 1!!! //
28 ///////////////////////////////////////////////////////////////////////////
32 #include <TGeoManager.h>
33 #include <TGeoPhysicalNode.h>
34 #include <TGeoShape.h>
40 #include "AliITSUGeomTGeo.h"
42 #include "AliAlignObj.h"
43 #include "AliITSsegmentation.h"
44 #include "AliITSUSegmentationPix.h"
45 using namespace TMath;
47 ClassImp(AliITSUGeomTGeo)
49 UInt_t AliITSUGeomTGeo::fgUIDShift = 16; // bit shift to go from mod.id to modUUID for TGeo
50 TString AliITSUGeomTGeo::fgITSVolName = "ITSV";
51 TString AliITSUGeomTGeo::fgITSLrName = "ITSULayer";
52 TString AliITSUGeomTGeo::fgITSStaveName = "ITSUStave";
53 TString AliITSUGeomTGeo::fgITSHalfStaveName = "ITSUHalfStave";
54 TString AliITSUGeomTGeo::fgITSModuleName = "ITSUModule";
55 TString AliITSUGeomTGeo::fgITSChipName = "ITSUChip";
56 TString AliITSUGeomTGeo::fgITSSensName = "ITSUSensor";
57 TString AliITSUGeomTGeo::fgITSWrapVolName = "ITSUWrapVol";
58 TString AliITSUGeomTGeo::fgITSChipTypeName[AliITSUGeomTGeo::kNChipTypes] = {"Pix"};
60 TString AliITSUGeomTGeo::fgITSsegmFileName = "itsSegmentations.root";
62 //______________________________________________________________________
63 AliITSUGeomTGeo::AliITSUGeomTGeo(Bool_t build, Bool_t loadSegm)
71 ,fNChipRowsPerModule(0)
72 ,fNChipsPerHalfStave(0)
82 for (int i=AliITSUAux::kMaxLayers;i--;) fLr2Wrapper[i] = -1;
83 if (build) BuildITS(loadSegm);
86 //______________________________________________________________________
87 AliITSUGeomTGeo::AliITSUGeomTGeo(const AliITSUGeomTGeo &src)
89 ,fVersion(src.fVersion)
90 ,fNLayers(src.fNLayers)
96 ,fNChipRowsPerModule(0)
97 ,fNChipsPerHalfStave(0)
108 fNStaves = new Int_t[fNLayers];
109 fNChipsPerModule = new Int_t[fNLayers];
110 fNChipRowsPerModule = new Int_t[fNLayers];
111 fLrChipType = new Int_t[fNLayers];
112 fLastChipIndex = new Int_t[fNLayers];
113 fNChipsPerHalfStave = new Int_t[fNLayers];
114 fNChipsPerStave = new Int_t[fNLayers];
115 fNChipsPerLayer = new Int_t[fNLayers];
117 for (int i=fNLayers;i--;) {
118 fNStaves[i] = src.fNStaves[i];
119 fNHalfStaves[i] = src.fNHalfStaves[i];
120 fNModules[i] = src.fNModules[i];
121 fNChipsPerModule[i] = src.fNChipsPerModule[i];
122 fNChipRowsPerModule[i] = src.fNChipRowsPerModule[i];
123 fNChipsPerHalfStave[i] = src.fNChipsPerHalfStave[i];
124 fNChipsPerStave[i] = src.fNChipsPerStave[i];
125 fNChipsPerLayer[i] = src.fNChipsPerLayer[i];
126 fLrChipType[i] = src.fLrChipType[i];
127 fLastChipIndex[i] = src.fLastChipIndex[i];
130 fMatSens = new TObjArray(fNChips);
131 fMatSens->SetOwner(kTRUE);
132 for (int i=0;i<fNChips;i++) {
133 const TGeoHMatrix* mat = (TGeoHMatrix*)src.fMatSens->At(i);
134 fMatSens->AddAt(new TGeoHMatrix(*mat),i);
138 fMatT2L = new TObjArray(fNChips);
139 fMatT2L->SetOwner(kTRUE);
140 for (int i=0;i<fNChips;i++) {
141 const TGeoHMatrix* mat =(TGeoHMatrix*) src.fMatT2L->At(i);
142 fMatT2L->AddAt(new TGeoHMatrix(*mat),i);
146 int sz = src.fSegm->GetEntriesFast();
147 fSegm = new TObjArray(sz);
148 fSegm->SetOwner(kTRUE);
149 for (int i=0;i<sz;i++) {
150 AliITSsegmentation* sg = (AliITSsegmentation*)src.fSegm->UncheckedAt(i);
152 fSegm->AddAt(sg->Clone(),i);
156 for (int i=AliITSUAux::kMaxLayers;i--;) fLr2Wrapper[i] = src.fLr2Wrapper[i];
159 //______________________________________________________________________
160 AliITSUGeomTGeo::~AliITSUGeomTGeo()
164 delete[] fNHalfStaves;
166 delete[] fLrChipType;
167 delete[] fNChipsPerModule;
168 delete[] fNChipRowsPerModule;
169 delete[] fNChipsPerHalfStave;
170 delete[] fNChipsPerStave;
171 delete[] fNChipsPerLayer;
172 delete[] fLastChipIndex;
179 //______________________________________________________________________
180 AliITSUGeomTGeo& AliITSUGeomTGeo::operator=(const AliITSUGeomTGeo &src)
185 delete[] fNHalfStaves;
187 delete[] fLrChipType;
188 delete[] fNChipsPerModule;
189 delete[] fNChipRowsPerModule;
190 delete[] fNChipsPerHalfStave;
191 delete[] fNChipsPerStave;
192 delete[] fNChipsPerLayer;
193 delete[] fLastChipIndex;
194 fNStaves = fNHalfStaves = fNModules = fLrChipType = fNChipsPerModule = fLastChipIndex = 0;
195 fVersion = src.fVersion;
196 fNLayers = src.fNLayers;
197 fNChips = src.fNChips;
200 fMatSens = new TObjArray(fNChips);
201 fMatSens->SetOwner(kTRUE);
202 for (int i=0;i<fNChips;i++) {
203 const TGeoHMatrix* mat = (TGeoHMatrix*) src.fMatSens->At(i);
204 fMatSens->AddAt(new TGeoHMatrix(*mat),i);
209 fMatT2L = new TObjArray(fNChips);
210 fMatT2L->SetOwner(kTRUE);
211 for (int i=0;i<fNChips;i++) {
212 const TGeoHMatrix* mat = (TGeoHMatrix*) src.fMatT2L->At(i);
213 fMatT2L->AddAt(new TGeoHMatrix(*mat),i);
217 int sz = src.fSegm->GetEntriesFast();
218 fSegm = new TObjArray(sz);
219 fSegm->SetOwner(kTRUE);
220 for (int i=0;i<sz;i++) {
221 AliITSsegmentation* sg = (AliITSsegmentation*)src.fSegm->UncheckedAt(i);
223 fSegm->AddAt(sg->Clone(),i);
228 fNStaves = new Int_t[fNLayers];
229 fNHalfStaves = new Int_t[fNLayers];
230 fNModules = new Int_t[fNLayers];
231 fNChipsPerModule = new Int_t[fNLayers];
232 fNChipRowsPerModule = new Int_t[fNLayers];
233 fNChipsPerHalfStave = new Int_t[fNLayers];
234 fNChipsPerStave = new Int_t[fNLayers];
235 fNChipsPerLayer = new Int_t[fNLayers];
236 fLrChipType = new Int_t[fNLayers];
237 fLastChipIndex = new Int_t[fNLayers];
238 for (int i=fNLayers;i--;) {
239 fNStaves[i] = src.fNStaves[i];
240 fNHalfStaves[i] = src.fNHalfStaves[i];
241 fNModules[i] = src.fNModules[i];
242 fNChipsPerModule[i] = src.fNChipsPerModule[i];
243 fNChipRowsPerModule[i] = src.fNChipRowsPerModule[i];
244 fNChipsPerHalfStave[i] = src.fNChipsPerHalfStave[i];
245 fNChipsPerStave[i] = src.fNChipsPerStave[i];
246 fNChipsPerLayer[i] = src.fNChipsPerLayer[i];
247 fLrChipType[i] = src.fLrChipType[i];
248 fLastChipIndex[i] = src.fLastChipIndex[i];
255 //______________________________________________________________________
256 Int_t AliITSUGeomTGeo::GetChipIndex(Int_t lay,Int_t sta,Int_t chipInStave) const
258 // This routine computes the chip index number from the layer,
259 // stave, and chip number in stave.
261 // Int_t lay The layer number. Starting from 0.
262 // Int_t sta The stave number. Starting from 0
263 // Int_t chipInStave The chip number in the stave. Starting from 0
265 return GetFirstChipIndex(lay) + fNChipsPerStave[lay]*sta + chipInStave;
268 //______________________________________________________________________
269 Int_t AliITSUGeomTGeo::GetChipIndex(Int_t lay,Int_t sta, Int_t substa, Int_t chipInSStave) const
271 // This routine computes the chip index number from the layer,
272 // stave, substave and chip number in substave.
274 // Int_t lay The layer number. Starting from 0.
275 // Int_t sta The stave number. Starting from 0
276 // Int_t substa The substave number. Starting from 0
277 // Int_t chipInSStave The chip number in the sub stave. Starting from 0
279 int n = GetFirstChipIndex(lay) + fNChipsPerStave[lay]*sta + chipInSStave;
280 if (fNHalfStaves[lay] && substa>0) n += fNChipsPerHalfStave[lay]*substa;
284 //______________________________________________________________________
285 Int_t AliITSUGeomTGeo::GetChipIndex(Int_t lay,Int_t sta, Int_t substa, Int_t md, Int_t chipInMod) const
287 // This routine computes the chip index number from the layer,
288 // stave, substave module and chip number in module.
290 // Int_t lay The layer number. Starting from 0.
291 // Int_t sta The stave number. Starting from 0
292 // Int_t substa The substave number. Starting from 0
293 // Int_t module The module number ...
294 // Int_t chipInSStave The chip number in the module. Starting from 0
296 int n = GetFirstChipIndex(lay) + fNChipsPerStave[lay]*sta + chipInMod;
297 if (fNHalfStaves[lay] && substa>0) n += fNChipsPerHalfStave[lay]*substa;
298 if (fNModules[lay] && md>0) n += fNChipsPerModule[lay]*md;
302 //______________________________________________________________________
303 Bool_t AliITSUGeomTGeo::GetLayer(Int_t index,Int_t &lay,Int_t &indexInLr) const
305 // This routine computes the layer number a
306 // given the chip index. The
308 // Int_t index The chip index number, starting from zero.
310 // Int_t indexInLr The chip index inside a layer, starting from zero.
311 // Int_t lay The layer number. Starting from 0.
313 lay = GetLayer(index);
314 indexInLr = index - GetFirstChipIndex(lay);
319 //______________________________________________________________________
320 Int_t AliITSUGeomTGeo::GetLayer(Int_t index) const
322 // Get chip layer, from 0
325 while(index>fLastChipIndex[lay]) lay++;
329 //______________________________________________________________________
330 Int_t AliITSUGeomTGeo::GetStave(Int_t index) const
332 // Get chip stave, from 0
335 while(index>fLastChipIndex[lay]) lay++;
336 index -= GetFirstChipIndex(lay);
337 return index/fNChipsPerStave[lay];
340 //______________________________________________________________________
341 Int_t AliITSUGeomTGeo::GetHalfStave(Int_t index) const
343 // Get chip substave id in stave, from 0
346 while(index>fLastChipIndex[lay]) lay++;
347 if (fNHalfStaves[lay]<0) return -1;
348 index -= GetFirstChipIndex(lay);
349 index %= fNChipsPerStave[lay];
350 return index/fNChipsPerHalfStave[lay];
353 //______________________________________________________________________
354 Int_t AliITSUGeomTGeo::GetModule(Int_t index) const
356 // Get chip module id in substave, from 0
359 while(index>fLastChipIndex[lay]) lay++;
360 if (fNModules[lay]<0) return 0;
361 index -= GetFirstChipIndex(lay);
362 index %= fNChipsPerStave[lay];
363 if (fNHalfStaves[lay]) index %= fNChipsPerHalfStave[lay];
364 return index/fNChipsPerModule[lay];
367 //______________________________________________________________________
368 Int_t AliITSUGeomTGeo::GetChipIdInLayer(Int_t index) const
370 // Get chip number within layer, from 0
373 while(index>fLastChipIndex[lay]) lay++;
374 index -= GetFirstChipIndex(lay);
378 //______________________________________________________________________
379 Int_t AliITSUGeomTGeo::GetChipIdInStave(Int_t index) const
381 // Get chip number within stave, from 0
384 while(index>fLastChipIndex[lay]) lay++;
385 index -= GetFirstChipIndex(lay);
386 return index%fNChipsPerStave[lay];
389 //______________________________________________________________________
390 Int_t AliITSUGeomTGeo::GetChipIdInHalfStave(Int_t index) const
392 // Get chip number within stave, from 0
395 while(index>fLastChipIndex[lay]) lay++;
396 index -= GetFirstChipIndex(lay);
397 return index%fNChipsPerHalfStave[lay];
400 //______________________________________________________________________
401 Int_t AliITSUGeomTGeo::GetChipIdInModule(Int_t index) const
403 // Get chip number within module, from 0
406 while(index>fLastChipIndex[lay]) lay++;
407 index -= GetFirstChipIndex(lay);
408 return index%fNChipsPerModule[lay];
411 //______________________________________________________________________
412 Bool_t AliITSUGeomTGeo::GetChipId(Int_t index,Int_t &lay,Int_t &sta,Int_t &hsta, Int_t &mod, Int_t &chip) const
415 // This routine computes the layer, stave, substave, module and chip number
416 // given the chip index number.
418 // Int_t index The chip index number, starting from zero.
420 // Int_t lay The layer number. Starting from 0
421 // Int_t sta The stave number. Starting from 0
422 // Int_t ssta The halfstave number. Starting from 0
423 // Int_t mod The module number. Starting from 0
424 // Int_t chip The detector number. Starting from 0
426 lay = GetLayer(index);
427 index -= GetFirstChipIndex(lay);
428 sta = index/fNChipsPerStave[lay];
429 index %= fNChipsPerStave[lay];
430 hsta = fNHalfStaves[lay]>0 ? index/fNChipsPerHalfStave[lay] : -1;
431 index %= fNChipsPerHalfStave[lay];
432 mod = fNModules[lay]>0 ? index/fNChipsPerModule[lay] : -1;
433 chip = index%fNChipsPerModule[lay];
438 //______________________________________________________________________
439 const char* AliITSUGeomTGeo::GetSymName(Int_t index) const
441 // Get the TGeoPNEntry symbolic name
442 // for a given chip identified by 'index'
445 if (!GetLayer(index,lay,index2)) return NULL;
446 // return AliGeomManager::SymName((AliGeomManager::ELayerID)((lay-1)+AliGeomManager::kSPD1),index2);
447 // RS: this is not optimal, but we cannod access directly AliGeomManager, since the latter has hardwired layers
448 // TGeoPNEntry* pne = gGeoManager->GetAlignableEntryByUID( AliGeomManager::LayerToVolUID(lay+1,index2) );
449 TGeoPNEntry* pne = gGeoManager->GetAlignableEntryByUID( ChipVolUID(index) );
451 AliError(Form("Failed to find alignable entry with index %d: (Lr%d Chip:%d) !",index,lay,index2));
454 return pne->GetName();
457 //______________________________________________________________________
458 const char* AliITSUGeomTGeo::ComposeSymNameITS()
460 // sym name of the layer
464 //______________________________________________________________________
465 const char* AliITSUGeomTGeo::ComposeSymNameLayer(Int_t lr)
467 // sym name of the layer
468 return Form("%s/%s%d",ComposeSymNameITS(),GetITSLayerPattern(),lr);
471 //______________________________________________________________________
472 const char* AliITSUGeomTGeo::ComposeSymNameStave(Int_t lr, Int_t stave)
474 // sym name of the stave at given layer
475 return Form("%s/%s%d",ComposeSymNameLayer(lr),GetITSStavePattern(),stave);
478 //______________________________________________________________________
479 const char* AliITSUGeomTGeo::ComposeSymNameHalfStave(Int_t lr, Int_t stave, Int_t substave)
481 // sym name of the stave at given layer
483 Form("%s/%s%d",ComposeSymNameStave(lr,stave),GetITSHalfStavePattern(),substave) :
484 ComposeSymNameStave(lr,stave);
487 //______________________________________________________________________
488 const char* AliITSUGeomTGeo::ComposeSymNameModule(Int_t lr, Int_t stave, Int_t substave, Int_t mod)
490 // sym name of the substave at given layer/stave
492 Form("%s/%s%d",ComposeSymNameHalfStave(lr,stave,substave),GetITSModulePattern(),mod) :
493 ComposeSymNameHalfStave(lr,stave,substave);
496 //______________________________________________________________________
497 const char* AliITSUGeomTGeo::ComposeSymNameChip(Int_t lr, Int_t sta, Int_t substave, Int_t mod, Int_t chip)
499 // sym name of the chip in the given layer/stave/substave/module
500 return Form("%s/%s%d",ComposeSymNameModule(lr,sta,substave,mod),GetITSChipPattern(),chip);
503 //______________________________________________________________________
504 TGeoHMatrix* AliITSUGeomTGeo::GetMatrix(Int_t index) const
506 // Get the transformation matrix for a given chip 'index'
507 // by quering the TGeoManager
508 static TGeoHMatrix matTmp;
509 TGeoPNEntry *pne = GetPNEntry(index);
510 if (!pne) return NULL;
512 TGeoPhysicalNode *pnode = pne->GetPhysicalNode();
513 if (pnode) return pnode->GetMatrix();
515 const char* path = pne->GetTitle();
516 gGeoManager->PushPath(); // Preserve the modeler state.
517 if (!gGeoManager->cd(path)) {
518 gGeoManager->PopPath();
519 AliError(Form("Volume path %s not valid!",path));
522 matTmp = *gGeoManager->GetCurrentMatrix();
523 gGeoManager->PopPath();
527 //______________________________________________________________________
528 Bool_t AliITSUGeomTGeo::GetTranslation(Int_t index, Double_t t[3]) const
530 // Get the translation vector for a given chip 'index'
531 // by quering the TGeoManager
532 TGeoHMatrix *m = GetMatrix(index);
533 if (!m) return kFALSE;
535 Double_t *trans = m->GetTranslation();
536 for (Int_t i = 0; i < 3; i++) t[i] = trans[i];
541 //______________________________________________________________________
542 Bool_t AliITSUGeomTGeo::GetRotation(Int_t index, Double_t r[9]) const
544 // Get the rotation matrix for a given chip 'index'
545 // by quering the TGeoManager
546 TGeoHMatrix *m = GetMatrix(index);
547 if (!m) return kFALSE;
549 Double_t *rot = m->GetRotationMatrix();
550 for (Int_t i = 0; i < 9; i++) r[i] = rot[i];
555 //______________________________________________________________________
556 Bool_t AliITSUGeomTGeo::GetOrigMatrix(Int_t index, TGeoHMatrix &m) const
558 // Get the original (ideal geometry) TGeo matrix for
559 // a given chip identified by 'index'.
560 // The method is slow, so it should be used
564 const char *symname = GetSymName(index);
565 if (!symname) return kFALSE;
567 return AliGeomManager::GetOrigGlobalMatrix(symname,m);
570 //______________________________________________________________________
571 Bool_t AliITSUGeomTGeo::GetOrigTranslation(Int_t index, Double_t t[3]) const
573 // Get the original translation vector (ideal geometry)
574 // for a given chip 'index' by quering the TGeoManager
576 if (!GetOrigMatrix(index,m)) return kFALSE;
578 Double_t *trans = m.GetTranslation();
579 for (Int_t i = 0; i < 3; i++) t[i] = trans[i];
584 //______________________________________________________________________
585 Bool_t AliITSUGeomTGeo::GetOrigRotation(Int_t index, Double_t r[9]) const
587 // Get the original rotation matrix (ideal geometry)
588 // for a given chip 'index' by quering the TGeoManager
590 if (!GetOrigMatrix(index,m)) return kFALSE;
592 Double_t *rot = m.GetRotationMatrix();
593 for (Int_t i = 0; i < 9; i++) r[i] = rot[i];
598 //______________________________________________________________________
599 TGeoHMatrix* AliITSUGeomTGeo::ExtractMatrixT2L(Int_t index) const
601 // Get the matrix which transforms from the tracking to local r.s.
602 // The method queries directly the TGeoPNEntry
603 TGeoPNEntry *pne = GetPNEntry(index);
604 if (!pne) return NULL;
606 TGeoHMatrix *m = (TGeoHMatrix*) pne->GetMatrix();
607 if (!m) AliError(Form("TGeoPNEntry (%s) contains no matrix !",pne->GetName()));
612 //______________________________________________________________________
613 Bool_t AliITSUGeomTGeo::GetTrackingMatrix(Int_t index, TGeoHMatrix &m)
615 // Get the matrix which transforms from the tracking r.s. to
617 // Returns kFALSE in case of error.
620 TGeoHMatrix *m1 = GetMatrix(index);
621 if (!m1) return kFALSE;
623 const TGeoHMatrix *m2 = GetMatrixT2L(index);
624 if (!m2) return kFALSE;
632 //______________________________________________________________________
633 TGeoHMatrix* AliITSUGeomTGeo::ExtractMatrixSens(Int_t index) const
635 // Get the transformation matrix of the SENSOR (not ncessary the same as the chip)
636 // for a given chip 'index' by quering the TGeoManager
637 Int_t lay,stav,sstav,mod,chipInMod;
638 GetChipId(index,lay,stav,sstav,mod,chipInMod);
639 int wrID = fLr2Wrapper[lay];
640 TString path = Form("/ALIC_1/%s_2/",AliITSUGeomTGeo::GetITSVolPattern());
641 if (wrID>=0) path += Form("%s%d_1/",GetITSWrapVolPattern(),wrID);
642 path += Form("%s%d_1/%s%d_%d/",AliITSUGeomTGeo::GetITSLayerPattern(),lay,AliITSUGeomTGeo::GetITSStavePattern(),lay,stav);
643 if (fNHalfStaves[lay]>0) path += Form("%s%d_%d/",AliITSUGeomTGeo::GetITSHalfStavePattern(),lay,sstav);
644 if (fNModules[lay]>0) path += Form("%s%d_%d/",AliITSUGeomTGeo::GetITSModulePattern(),lay,mod);
645 path += Form("%s%d_%d/%s%d_1",AliITSUGeomTGeo::GetITSChipPattern(),lay,chipInMod,AliITSUGeomTGeo::GetITSSensorPattern(),lay);
646 static TGeoHMatrix matTmp;
647 gGeoManager->PushPath();
648 if (!gGeoManager->cd(path.Data())) {
649 gGeoManager->PopPath();
650 AliError(Form("Error in cd-ing to %s",path.Data()));
652 } // end if !gGeoManager
653 matTmp = *gGeoManager->GetCurrentMatrix(); // matrix may change after cd
655 // printf("%d/%d/%d %s\n",lay,stav,detInSta,path.Data());
657 // Retstore the modeler state.
658 gGeoManager->PopPath();
663 //______________________________________________________________________
664 TGeoPNEntry* AliITSUGeomTGeo::GetPNEntry(Int_t index) const
666 // Get a pointer to the TGeoPNEntry of a chip
667 // identified by 'index'
668 // Returns NULL in case of invalid index,
669 // missing TGeoManager or invalid symbolic name
671 if (index >= fNChips) {
672 AliError(Form("Invalid ITS chip index: %d (0 -> %d) !",index,fNChips));
676 if (!gGeoManager || !gGeoManager->IsClosed()) {
677 AliError("Can't get the matrix! gGeoManager doesn't exist or it is still opened!");
680 TGeoPNEntry* pne = gGeoManager->GetAlignableEntryByUID( ChipVolUID(index) );
681 // TGeoPNEntry* pne = gGeoManager->GetAlignableEntry(GetSymName(index));
682 if (!pne) AliError(Form("The index %d does not correspond to a physical entry!",index));
687 //______________________________________________________________________
688 void AliITSUGeomTGeo::BuildITS(Bool_t loadSegm)
690 // exract upg ITS parameters from TGeo
691 if (fVersion!=kITSVNA) {AliWarning("Already built"); return; // already initialized}
692 if (!gGeoManager) AliFatal("Geometry is not loaded");
694 fNLayers = ExtractNumberOfLayers();
695 if (!fNLayers) return;
697 fNStaves = new Int_t[fNLayers];
698 fNHalfStaves = new Int_t[fNLayers];
699 fNModules = new Int_t[fNLayers];
700 fNChipsPerModule = new Int_t[fNLayers];
701 fNChipRowsPerModule = new Int_t[fNLayers];
702 fNChipsPerHalfStave = new Int_t[fNLayers];
703 fNChipsPerStave = new Int_t[fNLayers];
704 fNChipsPerLayer = new Int_t[fNLayers];
705 fLrChipType = new Int_t[fNLayers];
706 fLastChipIndex = new Int_t[fNLayers];
709 for (int i=0;i<fNLayers;i++) {
710 fLrChipType[i] = ExtractLayerChipType(i);
711 fNStaves[i] = ExtractNumberOfStaves(i);
712 fNHalfStaves[i] = ExtractNumberOfHalfStaves(i);
713 fNModules[i] = ExtractNumberOfModules(i);
714 fNChipsPerModule[i] = ExtractNChipsPerModule(i,fNChipRowsPerModule[i]);
715 fNChipsPerHalfStave[i]= fNChipsPerModule[i]*Max(1,fNModules[i]);
716 fNChipsPerStave[i] = fNChipsPerHalfStave[i]*Max(1,fNHalfStaves[i]);
717 fNChipsPerLayer[i] = fNChipsPerStave[i]*fNStaves[i];
718 fNChips += fNChipsPerLayer[i];
719 fLastChipIndex[i] = fNChips-1;
725 if (loadSegm) { // fetch segmentations
726 fSegm = new TObjArray();
727 AliITSUSegmentationPix::LoadSegmentations(fSegm,GetITSsegmentationFileName());
732 //______________________________________________________________________
733 Int_t AliITSUGeomTGeo::ExtractNumberOfLayers()
735 // Determines the number of layers in the Upgrade Geometry
737 Int_t numberOfLayers = 0;
739 TGeoVolume *itsV = gGeoManager->GetVolume(GetITSVolPattern());
740 if (!itsV) AliFatal(Form("ITS volume %s is not in the geometry",GetITSVolPattern()));
741 SetUIDShift(itsV->GetUniqueID());
743 // Loop on all ITSV nodes, count Layer volumes by checking names
744 // Build on the fly layer - wrapper correspondence
745 TObjArray* nodes = itsV->GetNodes();
746 Int_t nNodes = nodes->GetEntriesFast();
748 for (Int_t j=0; j<nNodes; j++) {
750 TGeoNode* nd = (TGeoNode*)nodes->At(j);
751 const char* name = nd->GetName();
752 if (strstr(name,GetITSLayerPattern())) {
754 if ( (lrID=ExtractVolumeCopy(name,AliITSUGeomTGeo::GetITSLayerPattern()))<0 ) {
755 AliFatal(Form("Failed to extract layer ID from the %s",name));
759 fLr2Wrapper[lrID] = -1; // not wrapped
761 else if (strstr(name,GetITSWrapVolPattern())) { // this is a wrapper volume, may cointain layers
763 if ( (wrID=ExtractVolumeCopy(name,AliITSUGeomTGeo::GetITSWrapVolPattern()))<0 ) {
764 AliFatal(Form("Failed to extract wrapper ID from the %s",name));
768 TObjArray* nodesW = nd->GetNodes();
769 int nNodesW = nodesW->GetEntriesFast();
770 for (Int_t jw=0; jw<nNodesW; jw++) {
771 TGeoNode* ndW = (TGeoNode*)nodesW->At(jw);
772 if (strstr(ndW->GetName(),GetITSLayerPattern())) {
773 if ( (lrID=ExtractVolumeCopy(ndW->GetName(),AliITSUGeomTGeo::GetITSLayerPattern()))<0 ) {
774 AliFatal(Form("Failed to extract layer ID from the %s",name));
778 fLr2Wrapper[lrID] = wrID;
784 return numberOfLayers;
787 //______________________________________________________________________
788 Int_t AliITSUGeomTGeo::ExtractNumberOfStaves(Int_t lay) const
790 // Determines the number of layers in the Upgrade Geometry
793 // lay: layer number, starting from 0
796 Int_t numberOfStaves = 0;
798 snprintf(laynam, 30, "%s%d",GetITSLayerPattern(),lay);
799 TGeoVolume* volLr = gGeoManager->GetVolume(laynam);
800 if (!volLr) AliFatal(Form("can't find %s volume",laynam));
802 // Loop on all layer nodes, count Stave volumes by checking names
803 Int_t nNodes = volLr->GetNodes()->GetEntries();
804 for (Int_t j=0; j<nNodes; j++) {
805 // AliInfo(Form("L%d %d of %d %s %s -> %d",lay,j,nNodes,volLr->GetNodes()->At(j)->GetName(),GetITSStavePattern(),numberOfStaves));
806 if (strstr(volLr->GetNodes()->At(j)->GetName(),GetITSStavePattern())) numberOfStaves++;
809 return numberOfStaves;
813 //______________________________________________________________________
814 Int_t AliITSUGeomTGeo::ExtractNumberOfHalfStaves(Int_t lay) const
816 // Determines the number of substaves in the stave of the layer
819 // lay: layer number, starting from 0
822 if (fgITSHalfStaveName.IsNull()) return 0; // for the setup w/o substave defined the stave and the substave is the same thing
825 snprintf(stavnam, 30, "%s%d", GetITSStavePattern(),lay);
826 TGeoVolume* volLd = gGeoManager->GetVolume(stavnam);
827 if (!volLd) AliFatal(Form("can't find %s volume",stavnam));
829 // Loop on all stave nodes, count Chip volumes by checking names
830 Int_t nNodes = volLd->GetNodes()->GetEntries();
831 for (Int_t j=0; j<nNodes; j++) if (strstr(volLd->GetNodes()->At(j)->GetName(),GetITSHalfStavePattern())) nSS++;
837 //______________________________________________________________________
838 Int_t AliITSUGeomTGeo::ExtractNumberOfModules(Int_t lay) const
840 // Determines the number of modules in substave in the stave of the layer
843 // lay: layer number, starting from 0
845 // for the setup w/o modules defined the module and the stave or the substave is the same thing
846 if (fgITSModuleName.IsNull()) return 0;
848 TGeoVolume* volLd = 0;
849 if (!fgITSHalfStaveName.IsNull()) {
850 snprintf(stavnam, 30, "%s%d", GetITSHalfStavePattern(),lay);
851 volLd = gGeoManager->GetVolume(stavnam);
853 if (!volLd) { // no substaves, check staves
854 snprintf(stavnam, 30, "%s%d", GetITSStavePattern(),lay);
855 volLd = gGeoManager->GetVolume(stavnam);
857 if (!volLd) return 0;
860 // Loop on all substave nodes, count module volumes by checking names
861 Int_t nNodes = volLd->GetNodes()->GetEntries();
862 for (Int_t j=0; j<nNodes; j++) if (strstr(volLd->GetNodes()->At(j)->GetName(),GetITSModulePattern())) nMod++;
868 //______________________________________________________________________
869 Int_t AliITSUGeomTGeo::ExtractNChipsPerModule(Int_t lay, int &nrow) const
871 // Determines the number of chips per module on the (sub)stave in the Upgrade Geometry
872 // Also extract the layout: span of module centers in Z and X
874 // lay: layer number from 0
876 Int_t numberOfChips = 0;
878 TGeoVolume* volLd = 0;
879 if (!fgITSModuleName.IsNull()) {
880 snprintf(stavnam, 30, "%s%d", GetITSModulePattern(),lay);
881 volLd = gGeoManager->GetVolume(stavnam);
883 if (!volLd) { // no modules on this layer, check substaves
884 if (!fgITSHalfStaveName.IsNull()) {
885 snprintf(stavnam, 30, "%s%d", GetITSHalfStavePattern(),lay);
886 volLd = gGeoManager->GetVolume(stavnam);
889 if (!volLd) { // no substaves on this layer, check staves
890 snprintf(stavnam, 30, "%s%d", GetITSStavePattern(),lay);
891 volLd = gGeoManager->GetVolume(stavnam);
893 if (!volLd) AliFatal(Form("can't find volume containing chips on layer %d",lay));
895 // Loop on all stave nodes, count Chip volumes by checking names
896 Int_t nNodes = volLd->GetNodes()->GetEntries();
898 double xmin=1e9,xmax=-1e9, zmin=1e9,zmax=-1e9;
899 double lab[3],loc[3]={0,0,0};
901 for (Int_t j=0; j<nNodes; j++) {
902 // AliInfo(Form("L%d %d of %d %s %s -> %d",lay,j,nNodes,volLd->GetNodes()->At(j)->GetName(),GetITSChipPattern(),numberOfChips));
903 TGeoNodeMatrix* node = (TGeoNodeMatrix*)volLd->GetNodes()->At(j);
904 if (!strstr(node->GetName(),GetITSChipPattern())) continue;
905 node->LocalToMaster(loc,lab);
906 if (lab[0]>xmax) xmax=lab[0];
907 if (lab[0]<xmin) xmin=lab[0];
908 if (lab[2]>zmax) zmax=lab[2];
909 if (lab[2]<zmin) zmin=lab[2];
914 TGeoShape* chShape = node->GetVolume()->GetShape();
915 TGeoBBox* bbox = dynamic_cast<TGeoBBox*>(chShape);
917 AliFatal(Form("Chip %s volume is of unprocessed shape %s",node->GetName(),chShape->IsA()->GetName()));
920 dx = 2*bbox->GetDX();
921 dz = 2*bbox->GetDZ();
926 double spanX = xmax-xmin;
927 double spanZ = zmax-zmin;
928 nrow = TMath::Nint(spanX/dx + 1);
929 int ncol = TMath::Nint(spanZ/dz + 1);
930 if (nrow*ncol != numberOfChips)
931 AliError(Form("Inconsistency between Nchips=%d and Nrow*Ncol=%d*%d->%d\n"
932 "Extracted chip dimensions (x,z): %.4f %.4f, Module Span: %.4f %.4f",
933 numberOfChips,nrow,ncol,nrow*ncol,
935 return numberOfChips;
939 //______________________________________________________________________
940 Int_t AliITSUGeomTGeo::ExtractLayerChipType(Int_t lay) const
942 // Determines the layer detector type the Upgrade Geometry
945 // lay: layer number from 0
949 // detector type id for the layer
952 snprintf(stavnam, 30, "%s%d", GetITSLayerPattern(),lay);
953 TGeoVolume* volLd = gGeoManager->GetVolume(stavnam);
954 if (!volLd) {AliFatal(Form("can't find %s volume",stavnam)); return -1;}
956 return volLd->GetUniqueID();
960 //______________________________________________________________________
961 UInt_t AliITSUGeomTGeo::ComposeChipTypeID(UInt_t segmId)
963 if (segmId>=kMaxSegmPerChipType) AliFatalClass(Form("Id=%d is >= max.allowed %d",segmId,kMaxSegmPerChipType));
964 return segmId + kChipTypePix*kMaxSegmPerChipType;
967 //______________________________________________________________________
968 void AliITSUGeomTGeo::Print(Option_t *) const
971 printf("Geometry version %d, NLayers:%d NChips:%d\n",fVersion,fNLayers,fNChips);
972 if (fVersion==kITSVNA) return;
973 for (int i=0;i<fNLayers;i++) {
974 printf("Lr%2d\tNStav:%2d\tNChips:%2d (%dx%-2d)\tNMod:%d\tNSubSt:%d\tNSt:%3d\tChipType:%3d\tChip#:%5d:%-5d\tWrapVol:%d\n",
975 i,fNStaves[i],fNChipsPerModule[i],fNChipRowsPerModule[i],
976 fNChipRowsPerModule[i] ? fNChipsPerModule[i]/fNChipRowsPerModule[i] : 0,
977 fNModules[i],fNHalfStaves[i],fNStaves[i],
978 fLrChipType[i],GetFirstChipIndex(i),GetLastChipIndex(i),fLr2Wrapper[i]);
982 //______________________________________________________________________
983 void AliITSUGeomTGeo::FetchMatrices()
985 // store pointer on often used matrices for faster access
986 if (!gGeoManager) AliFatal("Geometry is not loaded");
987 fMatSens = new TObjArray(fNChips);
988 fMatSens->SetOwner(kTRUE);
989 for (int i=0;i<fNChips;i++) fMatSens->AddAt(new TGeoHMatrix(*ExtractMatrixSens(i)),i);
993 //______________________________________________________________________
994 void AliITSUGeomTGeo::CreateT2LMatrices()
996 // create tracking to local (Sensor!) matrices
997 fMatT2L = new TObjArray(fNChips);
998 fMatT2L->SetOwner(kTRUE);
1000 double loc[3]={0,0,0},glo[3];
1002 for (int isn=0;isn<fNChips;isn++) {
1003 const TGeoHMatrix* matSens = GetMatrixSens(isn);
1004 if (!matSens) {AliFatal(Form("Failed to get matrix for sensor %d",isn)); return;}
1005 matSens->LocalToMaster(loc,glo);
1006 rotm = matSens->GetRotationMatrix();
1007 Double_t al = -ATan2(rotm[1],rotm[0]);
1008 double sn=Sin(al), cs=Cos(al), r=glo[0]*sn-glo[1]*cs, x=r*sn, y=-r*cs; // sensor plane PCA to origin
1009 TGeoHMatrix* t2l = new TGeoHMatrix();
1010 t2l->RotateZ(ATan2(y,x)*RadToDeg()); // rotate in direction of normal to the sensor plane
1013 t2l->MultiplyLeft(&matSens->Inverse());
1014 fMatT2L->AddAt(t2l,isn);
1016 const double *gtrans = matSens->GetTranslation();
1017 memcpy(&rotMatrix[0], matSens->GetRotationMatrix(), 9*sizeof(Double_t));
1018 Double_t al = -ATan2(rotMatrix[1],rotMatrix[0]);
1019 Double_t rSens = Sqrt(gtrans[0]*gtrans[0] + gtrans[1]*gtrans[1]);
1020 Double_t tanAl = ATan2(gtrans[1],gtrans[0]) - Pi()/2; //angle of tangent
1021 Double_t alTr = tanAl - al;
1023 // The X axis of tracking frame must always look outward
1025 matSens->LocalToMaster(loc,glo);
1026 double rPos = Sqrt(glo[0]*glo[0] + glo[1]*glo[1]);
1027 Bool_t rotOutward = rPos>rSens ? kFALSE : kTRUE;
1029 // Transformation matrix
1031 matLtoT.SetDx(-rSens*Sin(alTr)); // translation
1033 matLtoT.SetDz(gtrans[2]);
1035 rotMatrix[0]= 0; rotMatrix[1]= 1; rotMatrix[2]= 0; // + rotation
1036 rotMatrix[3]=-1; rotMatrix[4]= 0; rotMatrix[5]= 0;
1037 rotMatrix[6]= 0; rotMatrix[7]= 0; rotMatrix[8]= 1;
1040 rot.SetMatrix(rotMatrix);
1041 matLtoT.MultiplyLeft(&rot);
1042 if (rotOutward) matLtoT.RotateZ(180.);
1043 // Inverse transformation Matrix
1044 fMatT2L->AddAt(new TGeoHMatrix(matLtoT.Inverse()),isn);
1050 //______________________________________________________________________
1051 Int_t AliITSUGeomTGeo::ExtractVolumeCopy(const char* name, const char* prefix) const
1053 // extract Number following the prefix in the name string
1055 if (!nms.BeginsWith(prefix)) return -1;
1056 nms.Remove(0,strlen(prefix));
1057 if (!isdigit(nms.Data()[0])) return -1;