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();
749 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())) numberOfLayers++;
753 else if (strstr(name,GetITSWrapVolPattern())) { // this is a wrapper volume, may cointain layers
754 TObjArray* nodesW = nd->GetNodes();
755 int nNodesW = nodesW->GetEntriesFast();
756 for (Int_t jw=0; jw<nNodesW; jw++) {
757 TGeoNode* ndW = (TGeoNode*)nodesW->At(jw);
758 if (strstr(ndW->GetName(),GetITSLayerPattern())) fLr2Wrapper[numberOfLayers++] = nWrp;
764 return numberOfLayers;
767 //______________________________________________________________________
768 Int_t AliITSUGeomTGeo::ExtractNumberOfStaves(Int_t lay) const
770 // Determines the number of layers in the Upgrade Geometry
773 // lay: layer number, starting from 0
776 Int_t numberOfStaves = 0;
778 snprintf(laynam, 30, "%s%d",GetITSLayerPattern(),lay);
779 TGeoVolume* volLr = gGeoManager->GetVolume(laynam);
780 if (!volLr) AliFatal(Form("can't find %s volume",laynam));
782 // Loop on all layer nodes, count Stave volumes by checking names
783 Int_t nNodes = volLr->GetNodes()->GetEntries();
784 for (Int_t j=0; j<nNodes; j++) {
785 // AliInfo(Form("L%d %d of %d %s %s -> %d",lay,j,nNodes,volLr->GetNodes()->At(j)->GetName(),GetITSStavePattern(),numberOfStaves));
786 if (strstr(volLr->GetNodes()->At(j)->GetName(),GetITSStavePattern())) numberOfStaves++;
789 return numberOfStaves;
793 //______________________________________________________________________
794 Int_t AliITSUGeomTGeo::ExtractNumberOfHalfStaves(Int_t lay) const
796 // Determines the number of substaves in the stave of the layer
799 // lay: layer number, starting from 0
802 if (fgITSHalfStaveName.IsNull()) return 0; // for the setup w/o substave defined the stave and the substave is the same thing
805 snprintf(stavnam, 30, "%s%d", GetITSStavePattern(),lay);
806 TGeoVolume* volLd = gGeoManager->GetVolume(stavnam);
807 if (!volLd) AliFatal(Form("can't find %s volume",stavnam));
809 // Loop on all stave nodes, count Chip volumes by checking names
810 Int_t nNodes = volLd->GetNodes()->GetEntries();
811 for (Int_t j=0; j<nNodes; j++) if (strstr(volLd->GetNodes()->At(j)->GetName(),GetITSHalfStavePattern())) nSS++;
817 //______________________________________________________________________
818 Int_t AliITSUGeomTGeo::ExtractNumberOfModules(Int_t lay) const
820 // Determines the number of modules in substave in the stave of the layer
823 // lay: layer number, starting from 0
825 // for the setup w/o modules defined the module and the stave or the substave is the same thing
826 if (fgITSModuleName.IsNull()) return 0;
828 TGeoVolume* volLd = 0;
829 if (!fgITSHalfStaveName.IsNull()) {
830 snprintf(stavnam, 30, "%s%d", GetITSHalfStavePattern(),lay);
831 volLd = gGeoManager->GetVolume(stavnam);
833 if (!volLd) { // no substaves, check staves
834 snprintf(stavnam, 30, "%s%d", GetITSStavePattern(),lay);
835 volLd = gGeoManager->GetVolume(stavnam);
837 if (!volLd) return 0;
840 // Loop on all substave nodes, count module volumes by checking names
841 Int_t nNodes = volLd->GetNodes()->GetEntries();
842 for (Int_t j=0; j<nNodes; j++) if (strstr(volLd->GetNodes()->At(j)->GetName(),GetITSModulePattern())) nMod++;
848 //______________________________________________________________________
849 Int_t AliITSUGeomTGeo::ExtractNChipsPerModule(Int_t lay, int &nrow) const
851 // Determines the number of chips per module on the (sub)stave in the Upgrade Geometry
852 // Also extract the layout: span of module centers in Z and X
854 // lay: layer number from 0
856 Int_t numberOfChips = 0;
858 TGeoVolume* volLd = 0;
859 if (!fgITSModuleName.IsNull()) {
860 snprintf(stavnam, 30, "%s%d", GetITSModulePattern(),lay);
861 volLd = gGeoManager->GetVolume(stavnam);
863 if (!volLd) { // no modules on this layer, check substaves
864 if (!fgITSHalfStaveName.IsNull()) {
865 snprintf(stavnam, 30, "%s%d", GetITSHalfStavePattern(),lay);
866 volLd = gGeoManager->GetVolume(stavnam);
869 if (!volLd) { // no substaves on this layer, check staves
870 snprintf(stavnam, 30, "%s%d", GetITSStavePattern(),lay);
871 volLd = gGeoManager->GetVolume(stavnam);
873 if (!volLd) AliFatal(Form("can't find volume containing chips on layer %d",lay));
875 // Loop on all stave nodes, count Chip volumes by checking names
876 Int_t nNodes = volLd->GetNodes()->GetEntries();
878 double xmin=1e9,xmax=-1e9, zmin=1e9,zmax=-1e9;
879 double lab[3],loc[3]={0,0,0};
881 for (Int_t j=0; j<nNodes; j++) {
882 // AliInfo(Form("L%d %d of %d %s %s -> %d",lay,j,nNodes,volLd->GetNodes()->At(j)->GetName(),GetITSChipPattern(),numberOfChips));
883 TGeoNodeMatrix* node = (TGeoNodeMatrix*)volLd->GetNodes()->At(j);
884 if (!strstr(node->GetName(),GetITSChipPattern())) continue;
885 node->LocalToMaster(loc,lab);
886 if (lab[0]>xmax) xmax=lab[0];
887 if (lab[0]<xmin) xmin=lab[0];
888 if (lab[2]>zmax) zmax=lab[2];
889 if (lab[2]<zmin) zmin=lab[2];
894 TGeoShape* chShape = node->GetVolume()->GetShape();
895 TGeoBBox* bbox = dynamic_cast<TGeoBBox*>(chShape);
897 AliFatal(Form("Chip %s volume is of unprocessed shape %s",node->GetName(),chShape->IsA()->GetName()));
900 dx = 2*bbox->GetDX();
901 dz = 2*bbox->GetDZ();
906 double spanX = xmax-xmin;
907 double spanZ = zmax-zmin;
908 nrow = TMath::Nint(spanX/dx + 1);
909 int ncol = TMath::Nint(spanZ/dz + 1);
910 if (nrow*ncol != numberOfChips)
911 AliError(Form("Inconsistency between Nchips=%d and Nrow*Ncol=%d*%d->%d\n"
912 "Extracted chip dimensions (x,z): %.4f %.4f, Module Span: %.4f %.4f",
913 numberOfChips,nrow,ncol,nrow*ncol,
915 return numberOfChips;
919 //______________________________________________________________________
920 Int_t AliITSUGeomTGeo::ExtractLayerChipType(Int_t lay) const
922 // Determines the layer detector type the Upgrade Geometry
925 // lay: layer number from 0
929 // detector type id for the layer
932 snprintf(stavnam, 30, "%s%d", GetITSLayerPattern(),lay);
933 TGeoVolume* volLd = gGeoManager->GetVolume(stavnam);
934 if (!volLd) {AliFatal(Form("can't find %s volume",stavnam)); return -1;}
936 return volLd->GetUniqueID();
940 //______________________________________________________________________
941 UInt_t AliITSUGeomTGeo::ComposeChipTypeID(UInt_t segmId)
943 if (segmId>=kMaxSegmPerChipType) AliFatalClass(Form("Id=%d is >= max.allowed %d",segmId,kMaxSegmPerChipType));
944 return segmId + kChipTypePix*kMaxSegmPerChipType;
947 //______________________________________________________________________
948 void AliITSUGeomTGeo::Print(Option_t *) const
951 printf("Geometry version %d, NLayers:%d NChips:%d\n",fVersion,fNLayers,fNChips);
952 if (fVersion==kITSVNA) return;
953 for (int i=0;i<fNLayers;i++) {
954 printf("Lr%2d\tNStav:%2d\tNChips:%2d (%dx%-2d)\tNMod:%d\tNSubSt:%d\tNSt:%3d\tChipType:%3d\tChip#:%5d:%-5d\tWrapVol:%d\n",
955 i,fNStaves[i],fNChipsPerModule[i],fNChipRowsPerModule[i],
956 fNChipRowsPerModule[i] ? fNChipsPerModule[i]/fNChipRowsPerModule[i] : 0,
957 fNModules[i],fNHalfStaves[i],fNStaves[i],
958 fLrChipType[i],GetFirstChipIndex(i),GetLastChipIndex(i),fLr2Wrapper[i]);
962 //______________________________________________________________________
963 void AliITSUGeomTGeo::FetchMatrices()
965 // store pointer on often used matrices for faster access
966 if (!gGeoManager) AliFatal("Geometry is not loaded");
967 fMatSens = new TObjArray(fNChips);
968 fMatSens->SetOwner(kTRUE);
969 for (int i=0;i<fNChips;i++) fMatSens->AddAt(new TGeoHMatrix(*ExtractMatrixSens(i)),i);
973 //______________________________________________________________________
974 void AliITSUGeomTGeo::CreateT2LMatrices()
976 // create tracking to local (Sensor!) matrices
977 fMatT2L = new TObjArray(fNChips);
978 fMatT2L->SetOwner(kTRUE);
980 double loc[3]={0,0,0},glo[3];
982 for (int isn=0;isn<fNChips;isn++) {
983 const TGeoHMatrix* matSens = GetMatrixSens(isn);
984 if (!matSens) {AliFatal(Form("Failed to get matrix for sensor %d",isn)); return;}
985 matSens->LocalToMaster(loc,glo);
986 rotm = matSens->GetRotationMatrix();
987 Double_t al = -ATan2(rotm[1],rotm[0]);
988 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
989 TGeoHMatrix* t2l = new TGeoHMatrix();
990 t2l->RotateZ(ATan2(y,x)*RadToDeg()); // rotate in direction of normal to the sensor plane
993 t2l->MultiplyLeft(&matSens->Inverse());
994 fMatT2L->AddAt(t2l,isn);
996 const double *gtrans = matSens->GetTranslation();
997 memcpy(&rotMatrix[0], matSens->GetRotationMatrix(), 9*sizeof(Double_t));
998 Double_t al = -ATan2(rotMatrix[1],rotMatrix[0]);
999 Double_t rSens = Sqrt(gtrans[0]*gtrans[0] + gtrans[1]*gtrans[1]);
1000 Double_t tanAl = ATan2(gtrans[1],gtrans[0]) - Pi()/2; //angle of tangent
1001 Double_t alTr = tanAl - al;
1003 // The X axis of tracking frame must always look outward
1005 matSens->LocalToMaster(loc,glo);
1006 double rPos = Sqrt(glo[0]*glo[0] + glo[1]*glo[1]);
1007 Bool_t rotOutward = rPos>rSens ? kFALSE : kTRUE;
1009 // Transformation matrix
1011 matLtoT.SetDx(-rSens*Sin(alTr)); // translation
1013 matLtoT.SetDz(gtrans[2]);
1015 rotMatrix[0]= 0; rotMatrix[1]= 1; rotMatrix[2]= 0; // + rotation
1016 rotMatrix[3]=-1; rotMatrix[4]= 0; rotMatrix[5]= 0;
1017 rotMatrix[6]= 0; rotMatrix[7]= 0; rotMatrix[8]= 1;
1020 rot.SetMatrix(rotMatrix);
1021 matLtoT.MultiplyLeft(&rot);
1022 if (rotOutward) matLtoT.RotateZ(180.);
1023 // Inverse transformation Matrix
1024 fMatT2L->AddAt(new TGeoHMatrix(matLtoT.Inverse()),isn);