]> git.uio.no Git - u/mrichter/AliRoot.git/blob - ITS/UPGRADE/AliITSUGeomTGeo.cxx
Add fine bin option and fix the pt weight option
[u/mrichter/AliRoot.git] / ITS / UPGRADE / AliITSUGeomTGeo.cxx
1 /**************************************************************************
2  * Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
3  *                                                                        *
4  * Author: The ALICE Off-line Project.                                    *
5  * Contributors are mentioned in the code where appropriate.              *
6  *                                                                        *
7  * Permission to use, copy, modify and distribute this software and its   *
8  * documentation strictly for non-commercial purposes is hereby granted   *
9  * without fee, provided that the above copyright notice appears in all   *
10  * copies and that both the copyright notice and this permission notice   *
11  * appear in the supporting documentation. The authors make no claims     *
12  * about the suitability of this software for any purpose. It is          *
13  * provided "as is" without express or implied warranty.                  *
14  **************************************************************************/
15
16 ///////////////////////////////////////////////////////////////////////////
17 //    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                                        //
20 //                                                                       //
21 //    author - cvetan.cheshkov@cern.ch                                   //
22 //    15/02/2007                                                         //
23 //    adapted to ITSupg 18/07/2012 - ruben.shahoyan@cern.ch              //
24 //                                                                       //
25 //    ATTENTION: In opposite to ols AliITSgeomTGeo, all indices start    //
26 //    from 0, not from 1!!!                                              //
27 //                                                                       //
28 ///////////////////////////////////////////////////////////////////////////
29
30 #include <TClass.h>
31 #include <TString.h>
32 #include <TGeoManager.h>
33 #include <TGeoPhysicalNode.h>
34 #include <TDatime.h>
35 #include <TMath.h>
36 #include <TSystem.h>
37
38 #include "AliITSUGeomTGeo.h"
39 #include "AliLog.h"
40 #include "AliAlignObj.h"
41 #include "AliITSsegmentation.h"
42 #include "AliITSUSegmentationPix.h"
43 using namespace TMath;
44
45 ClassImp(AliITSUGeomTGeo)
46
47
48 const char* AliITSUGeomTGeo::fgkITSVolName = "ITSV";
49 const char* AliITSUGeomTGeo::fgkITSLrName  = "ITSULayer";
50 const char* AliITSUGeomTGeo::fgkITSLadName = "ITSULadder";
51 const char* AliITSUGeomTGeo::fgkITSModName = "ITSUModule";
52 const char* AliITSUGeomTGeo::fgkITSSensName ="ITSUSensor";
53 const char* AliITSUGeomTGeo::fgkITSDetTypeName[AliITSUGeomTGeo::kNDetTypes] = {"Pix"};
54 //
55 TString     AliITSUGeomTGeo::fgITSsegmFileName = "itsSegmentations.root";
56
57 //______________________________________________________________________
58 AliITSUGeomTGeo::AliITSUGeomTGeo(Bool_t build, Bool_t loadSegm)
59   :fVersion(kITSVNA)
60   ,fNLayers(0)
61   ,fNModules(0)
62   ,fNLadders(0)
63   ,fLrDetType(0)
64   ,fNDetectors(0)
65   ,fLastModIndex(0)
66   ,fMatSens(0)
67   ,fMatT2L(0)
68   ,fSegm(0)
69 {
70   // default c-tor
71   if (build) BuildITS(loadSegm);
72 }
73
74 //______________________________________________________________________
75 AliITSUGeomTGeo::AliITSUGeomTGeo(const AliITSUGeomTGeo &src)
76   :TObject(src)
77   ,fVersion(src.fVersion)
78   ,fNLayers(src.fNLayers)
79   ,fNModules(src.fNModules)
80   ,fNLadders(0)
81   ,fLrDetType(0)
82   ,fNDetectors(0)
83   ,fLastModIndex(0)
84   ,fMatSens(0)
85   ,fMatT2L(0)
86   ,fSegm(0)
87 {
88   // copy c-tor
89   if (fNLayers) {
90     fNLadders   = new Int_t[fNLayers];
91     fNDetectors = new Int_t[fNLayers];
92     fLrDetType  = new Int_t[fNLayers];
93     fLastModIndex   = new Int_t[fNLayers];
94     for (int i=fNLayers;i--;) {
95       fNLadders[i] = src.fNLadders[i];
96       fNDetectors[i] = src.fNDetectors[i];
97       fLrDetType[i]  = src.fLrDetType[i];
98       fLastModIndex[i] = src.fLastModIndex[i];
99     }
100     if (src.fMatSens) {
101       fMatSens = new TObjArray(fNModules);
102       fMatSens->SetOwner(kTRUE);
103       for (int i=0;i<fNModules;i++) {
104         const TGeoHMatrix* mat = (TGeoHMatrix*)src.fMatSens->At(i);
105         fMatSens->AddAt(new TGeoHMatrix(*mat),i);
106       }
107     }
108     if (src.fMatT2L) {
109       fMatT2L = new TObjArray(fNModules);
110       fMatT2L->SetOwner(kTRUE);
111       for (int i=0;i<fNModules;i++) {
112         const TGeoHMatrix* mat =(TGeoHMatrix*) src.fMatT2L->At(i);
113         fMatT2L->AddAt(new TGeoHMatrix(*mat),i);
114       }
115     }
116     if (src.fSegm) {
117       int sz = src.fSegm->GetEntriesFast();
118       fSegm = new TObjArray(sz);
119       fSegm->SetOwner(kTRUE);
120       for (int i=0;i<sz;i++) {
121         AliITSsegmentation* sg = (AliITSsegmentation*)src.fSegm->UncheckedAt(i);
122         if (!sg) continue;
123         fSegm->AddAt(sg->Clone(),i);
124       }
125     }
126   }
127 }
128
129 //______________________________________________________________________
130 AliITSUGeomTGeo::~AliITSUGeomTGeo()
131 {
132   //d-tor
133   delete[] fNLadders;
134   delete[] fLrDetType;
135   delete[] fNDetectors;
136   delete[] fLastModIndex;
137   delete fMatT2L;
138   delete fMatSens;
139   delete fSegm;
140 }
141
142
143 //______________________________________________________________________
144 AliITSUGeomTGeo& AliITSUGeomTGeo::operator=(const AliITSUGeomTGeo &src)
145 {
146   // cp op.
147   if (this!=&src) {
148     delete[] fNLadders;
149     delete[] fLrDetType;
150     delete[] fNDetectors;
151     delete[] fLastModIndex;
152     fNLadders = fLrDetType = fNDetectors = fLastModIndex = 0;
153     fVersion = src.fVersion;
154     fNLayers = src.fNLayers;
155     fNModules = src.fNModules;
156     if (src.fMatSens) {
157       delete fMatSens; 
158       fMatSens = new TObjArray(fNModules);
159       fMatSens->SetOwner(kTRUE);
160       for (int i=0;i<fNModules;i++) {
161         const TGeoHMatrix* mat = (TGeoHMatrix*) src.fMatSens->At(i);
162         fMatSens->AddAt(new TGeoHMatrix(*mat),i);
163       }
164     }
165     if (src.fMatT2L) {
166       delete fMatT2L; 
167       fMatT2L = new TObjArray(fNModules);
168       fMatT2L->SetOwner(kTRUE);
169       for (int i=0;i<fNModules;i++) {
170         const TGeoHMatrix* mat = (TGeoHMatrix*) src.fMatT2L->At(i);
171         fMatT2L->AddAt(new TGeoHMatrix(*mat),i);
172       }
173     }
174     if (src.fSegm) {
175       int sz = src.fSegm->GetEntriesFast();
176       fSegm = new TObjArray(sz);
177       fSegm->SetOwner(kTRUE);
178       for (int i=0;i<sz;i++) {
179         AliITSsegmentation* sg = (AliITSsegmentation*)src.fSegm->UncheckedAt(i);
180         if (!sg) continue;
181         fSegm->AddAt(sg->Clone(),i);
182       }
183     }
184     //
185     if (fNLayers) {
186       fNLadders   = new Int_t[fNLayers];
187       fNDetectors = new Int_t[fNLayers];
188       fLrDetType  = new Int_t[fNLayers];
189       fLastModIndex   = new Int_t[fNLayers];
190       for (int i=fNLayers;i--;) {
191         fNLadders[i] = src.fNLadders[i];
192         fNDetectors[i] = src.fNDetectors[i];
193         fLrDetType[i]  = src.fLrDetType[i];
194         fLastModIndex[i] = src.fLastModIndex[i];
195       }
196     }    
197   }
198   return *this;
199 }
200
201 //______________________________________________________________________
202 Int_t AliITSUGeomTGeo::GetModuleIndex(Int_t lay,Int_t lad,Int_t det) const
203 {
204   // This routine computes the module index number from the layer,
205   // ladder, and detector numbers. The number of ladders and detectors
206   // per layer is set statically
207   // see above for details.
208   // Inputs:
209   //    Int_t lay  The layer number. Starting from 0.
210   //    Int_t lad  The ladder number. Starting from 0
211   //    Int_t det  The detector number in the ladder. Starting from 0
212   //
213   return GetFirstModIndex(lay) + fNDetectors[lay]*lad + det;
214 }
215
216 //______________________________________________________________________
217 Bool_t AliITSUGeomTGeo::GetLayer(Int_t index,Int_t &lay,Int_t &index2)  const
218 {
219   // This routine computes the layer number for a
220   // given the module index. The 
221   // Inputs:
222   //     Int_t index  The module index number, starting from zero.
223   // Outputs:
224   //     Int_t index2 The module index inside a layer, starting from zero.
225   //     Int_t lay    The layer number. Starting from 0.
226   //
227   lay = GetLayer(index);
228   index2 = index - GetFirstModIndex(lay);
229   return kTRUE;
230   //
231 }
232
233 //______________________________________________________________________
234 Int_t AliITSUGeomTGeo::GetLayer(Int_t index) const
235 {
236   // Get module layer, from 0
237   //
238   int lay = 0;
239   while(index>fLastModIndex[lay]) lay++;
240   return lay;
241 }
242
243 //______________________________________________________________________
244 Int_t AliITSUGeomTGeo::GetLadder(Int_t index) const
245 {
246   // Get module ladder, from 0
247   //
248   int lay = 0;
249   while(index>fLastModIndex[lay]) lay++;
250   index -= GetFirstModIndex(lay);
251   return index/fNDetectors[lay];
252 }
253
254 //______________________________________________________________________
255 Int_t AliITSUGeomTGeo::GetModIdInLayer(Int_t index) const
256 {
257   // Get module number within layer, from 0
258   //
259   int lay = 0;
260   while(index>fLastModIndex[lay]) lay++;
261   index -= GetFirstModIndex(lay);
262   return index;
263 }
264
265 //______________________________________________________________________
266 Int_t AliITSUGeomTGeo::GetModIdInLadder(Int_t index) const
267 {
268   // Get module number within ladder, from 0
269   //
270   int lay = 0;
271   while(index>fLastModIndex[lay]) lay++;
272   index -= GetFirstModIndex(lay);
273   return index%fNDetectors[lay];
274 }
275
276 //______________________________________________________________________
277 Bool_t AliITSUGeomTGeo::GetModuleId(Int_t index,Int_t &lay,Int_t &lad,Int_t &det)  const
278 {
279   // The method is taken from the old AliITSgeom class by Bjorn Nilsen
280   //
281   // This routine computes the layer, ladder and detector number 
282   // given the module index number. 
283   // Inputs:
284   //     Int_t index  The module index number, starting from zero.
285   // Outputs:
286   //     Int_t lay    The layer number. Starting from 0
287   //     Int_t lad    The ladder number. Starting from 0
288   //     Int_t det    The detector number. Starting from 0
289   //
290   lay  = GetLayer(index);
291   index -= GetFirstModIndex(lay);
292   lad  = index/fNDetectors[lay];
293   det  = index%fNDetectors[lay];
294   return kTRUE;
295 }
296
297 //______________________________________________________________________
298 const char* AliITSUGeomTGeo::GetSymName(Int_t index)  const
299 {
300   // Get the TGeoPNEntry symbolic name
301   // for a given module identified by 'index'
302   //
303   Int_t lay, index2;
304   if (!GetLayer(index,lay,index2)) return NULL;
305   // return AliGeomManager::SymName((AliGeomManager::ELayerID)((lay-1)+AliGeomManager::kSPD1),index2);
306   // RS: this is not optimal, but we cannod access directly AliGeomManager, since the latter has hardwired layers 
307   //  TGeoPNEntry* pne = gGeoManager->GetAlignableEntryByUID( AliGeomManager::LayerToVolUID(lay+1,index2) );
308   TGeoPNEntry* pne = gGeoManager->GetAlignableEntryByUID( ModuleVolUID(index) );
309   if (!pne) {
310     AliError(Form("Failed to find alignable entry with index %d: (Lr%d Mod:%d) !",index,lay,index2));
311     return NULL;
312   }
313   return pne->GetName();
314 }
315
316 //______________________________________________________________________
317 const char* AliITSUGeomTGeo::ComposeSymNameITS()
318 {
319   // sym name of the layer
320   return "ITS";
321 }
322
323 //______________________________________________________________________
324 const char* AliITSUGeomTGeo::ComposeSymNameLayer(Int_t lr)
325 {
326   // sym name of the layer
327   return Form("%s/%s%d",ComposeSymNameITS(),GetITSLayerPattern(),lr);
328 }
329
330 //______________________________________________________________________
331 const char* AliITSUGeomTGeo::ComposeSymNameLadder(Int_t lr, Int_t ladder)
332 {
333   // sym name of the ladder at given layer
334   return Form("%s/%s%d",ComposeSymNameLayer(lr),GetITSLadderPattern(),ladder);
335 }
336
337 //______________________________________________________________________
338 const char* AliITSUGeomTGeo::ComposeSymNameModule(Int_t lr, Int_t lad, int det)
339 {
340   // sym name of the module
341   return Form("%s/%s%d",ComposeSymNameLadder(lr,lad),GetITSModulePattern(),det);
342 }
343
344 //______________________________________________________________________
345 TGeoHMatrix* AliITSUGeomTGeo::GetMatrix(Int_t index)  const
346 {
347   // Get the transformation matrix for a given module 'index'
348   // by quering the TGeoManager
349   TGeoPNEntry *pne = GetPNEntry(index);
350   if (!pne) return NULL;
351
352   TGeoPhysicalNode *pnode = pne->GetPhysicalNode();
353   if (pnode) return pnode->GetMatrix();
354
355   const char* path = pne->GetTitle();
356   gGeoManager->PushPath(); // Preserve the modeler state.
357   if (!gGeoManager->cd(path)) {
358     gGeoManager->PopPath();
359     AliError(Form("Volume path %s not valid!",path));
360     return NULL;
361   }
362   TGeoHMatrix *mat = gGeoManager->GetCurrentMatrix();
363   gGeoManager->PopPath();
364   return mat;
365 }
366
367 //______________________________________________________________________
368 Bool_t AliITSUGeomTGeo::GetTranslation(Int_t index, Double_t t[3])  const
369 {
370   // Get the translation vector for a given module 'index'
371   // by quering the TGeoManager
372   TGeoHMatrix *m = GetMatrix(index);
373   if (!m) return kFALSE;
374
375   Double_t *trans = m->GetTranslation();
376   for (Int_t i = 0; i < 3; i++) t[i] = trans[i];
377
378   return kTRUE;
379 }
380
381 //______________________________________________________________________
382 Bool_t AliITSUGeomTGeo::GetRotation(Int_t index, Double_t r[9])  const
383 {
384   // Get the rotation matrix for a given module 'index'
385   // by quering the TGeoManager
386   TGeoHMatrix *m = GetMatrix(index);
387   if (!m) return kFALSE;
388
389   Double_t *rot = m->GetRotationMatrix();
390   for (Int_t i = 0; i < 9; i++) r[i] = rot[i];
391
392   return kTRUE;
393 }
394
395 //______________________________________________________________________
396 Bool_t AliITSUGeomTGeo::GetOrigMatrix(Int_t index, TGeoHMatrix &m) const
397 {
398   // Get the original (ideal geometry) TGeo matrix for
399   // a given module identified by 'index'.
400   // The method is slow, so it should be used
401   // with great care.
402   m.Clear();
403
404   const char *symname = GetSymName(index);
405   if (!symname) return kFALSE;
406
407   return AliGeomManager::GetOrigGlobalMatrix(symname,m);
408 }
409
410 //______________________________________________________________________
411 Bool_t AliITSUGeomTGeo::GetOrigTranslation(Int_t index, Double_t t[3])  const
412 {
413   // Get the original translation vector (ideal geometry)
414   // for a given module 'index' by quering the TGeoManager
415   TGeoHMatrix m;
416   if (!GetOrigMatrix(index,m)) return kFALSE;
417
418   Double_t *trans = m.GetTranslation();
419   for (Int_t i = 0; i < 3; i++) t[i] = trans[i];
420
421   return kTRUE;
422 }
423
424 //______________________________________________________________________
425 Bool_t AliITSUGeomTGeo::GetOrigRotation(Int_t index, Double_t r[9])  const
426 {
427   // Get the original rotation matrix (ideal geometry)
428   // for a given module 'index' by quering the TGeoManager
429   TGeoHMatrix m;
430   if (!GetOrigMatrix(index,m)) return kFALSE;
431
432   Double_t *rot = m.GetRotationMatrix();
433   for (Int_t i = 0; i < 9; i++) r[i] = rot[i];
434
435   return kTRUE;
436 }
437
438 //______________________________________________________________________
439 TGeoHMatrix* AliITSUGeomTGeo::ExtractMatrixT2L(Int_t index) const
440 {
441   // Get the matrix which transforms from the tracking to local r.s.
442   // The method queries directly the TGeoPNEntry
443   TGeoPNEntry *pne = GetPNEntry(index);
444   if (!pne) return NULL;
445
446   TGeoHMatrix *m = (TGeoHMatrix*) pne->GetMatrix();
447   if (!m) AliError(Form("TGeoPNEntry (%s) contains no matrix !",pne->GetName()));
448
449   return m;
450 }
451
452 //______________________________________________________________________
453 Bool_t AliITSUGeomTGeo::GetTrackingMatrix(Int_t index, TGeoHMatrix &m)
454 {
455   // Get the matrix which transforms from the tracking r.s. to
456   // the global one.
457   // Returns kFALSE in case of error.
458   m.Clear();
459
460   TGeoHMatrix *m1 = GetMatrix(index);
461   if (!m1) return kFALSE;
462
463   const TGeoHMatrix *m2 = GetMatrixT2L(index);
464   if (!m2) return kFALSE;
465
466   m = *m1;
467   m.Multiply(m2);
468
469   return kTRUE;
470 }
471
472 //______________________________________________________________________
473 TGeoHMatrix* AliITSUGeomTGeo::ExtractMatrixSens(Int_t index) const
474 {
475   // Get the transformation matrix of the SENSOR (not ncessary the same as the module) 
476   // for a given module 'index' by quering the TGeoManager
477   const TString kPathBase = Form("/ALIC_1/%s_2/",AliITSUGeomTGeo::GetITSVolPattern());
478   const TString kNames = Form("%%s%s%%d_1/%s%%d_%%d/%s%%d_%%d/%s%%d_%%d"
479                               ,AliITSUGeomTGeo::GetITSLayerPattern()
480                               ,AliITSUGeomTGeo::GetITSLadderPattern()
481                               ,AliITSUGeomTGeo::GetITSModulePattern()
482                               ,AliITSUGeomTGeo::GetITSSensorPattern());
483   TString path;
484   Int_t lay,ladd,detInLad;
485   GetModuleId(index,lay,ladd,detInLad);
486   //
487   path.Form(kNames.Data(),kPathBase.Data(),lay,lay,ladd,lay,detInLad,lay,1);
488   gGeoManager->PushPath();
489   if (!gGeoManager->cd(path.Data())) {
490     gGeoManager->PopPath();
491     AliError(Form("Error in cd-ing to %s",path.Data()));
492     return 0;
493   } // end if !gGeoManager
494   TGeoHMatrix* mat = gGeoManager->GetCurrentMatrix();
495   //RSS
496   //  printf("%d/%d/%d %s\n",lay,ladd,detInLad,path.Data());
497   //  mat->Print();
498   // Retstore the modeler state.
499   gGeoManager->PopPath();
500   return mat;
501 }
502
503
504 //______________________________________________________________________
505 TGeoPNEntry* AliITSUGeomTGeo::GetPNEntry(Int_t index) const
506 {
507   // Get a pointer to the TGeoPNEntry of a module
508   // identified by 'index'
509   // Returns NULL in case of invalid index,
510   // missing TGeoManager or invalid symbolic name
511   //
512   if (index >= fNModules) {
513     AliError(Form("Invalid ITS module index: %d (0 -> %d) !",index,fNModules));
514     return NULL;
515   }
516   
517   if (!gGeoManager || !gGeoManager->IsClosed()) {
518     AliError("Can't get the matrix! gGeoManager doesn't exist or it is still opened!");
519     return NULL;
520   }
521
522   TGeoPNEntry* pne = gGeoManager->GetAlignableEntry(GetSymName(index));
523   if (!pne) AliError(Form("The symbolic volume name %s does not correspond to a physical entry!",GetSymName(index)));
524   //
525   return pne;
526 }
527
528 //______________________________________________________________________
529 void AliITSUGeomTGeo::BuildITS(Bool_t loadSegm)
530 {
531   // exract upg ITS parameters from TGeo
532   if (fVersion!=kITSVNA) {AliWarning("Already built"); return; // already initialized}
533     if (!gGeoManager) AliFatal("Geometry is not loaded");
534   }
535   fNLayers    = ExtractNumberOfLayers();
536   if (!fNLayers) return;
537   //
538   fNLadders   = new Int_t[fNLayers];
539   fNDetectors = new Int_t[fNLayers];
540   fLrDetType  = new Int_t[fNLayers];
541   fLastModIndex   = new Int_t[fNLayers];
542   fNModules = 0;
543   for (int i=0;i<fNLayers;i++) {
544     fNLadders[i]   = ExtractNumberOfLadders(i);
545     fNDetectors[i] = ExtractNumberOfDetectors(i);
546     fLrDetType[i]  = ExtractLayerDetType(i);
547     fNModules     += fNLadders[i]*fNDetectors[i];
548     fLastModIndex[i]   = fNModules-1;
549   }
550   //
551   FetchMatrices();
552   fVersion = kITSVUpg;
553   //
554   if (loadSegm) {  // fetch segmentations
555     fSegm = new TObjArray();
556     AliITSUSegmentationPix::LoadSegmentations(fSegm,GetITSsegmentationFileName());
557   }
558   //
559 }
560
561 //______________________________________________________________________
562 Int_t AliITSUGeomTGeo::ExtractNumberOfLayers() const
563 {
564   // Determines the number of layers in the Upgrade Geometry
565   //
566   Int_t numberOfLayers = 0;
567   //
568   TGeoVolume *itsV = gGeoManager->GetVolume(fgkITSVolName);
569   if (!itsV) AliFatal(Form("ITS volume %s is not in the geometry",fgkITSVolName));
570   //
571   // Loop on all ITSV nodes, count Layer volumes by checking names
572   Int_t nNodes = itsV->GetNodes()->GetEntries();
573   for (Int_t j=0; j<nNodes; j++) if (strstr(itsV->GetNodes()->At(j)->GetName(),fgkITSLrName)) numberOfLayers++;
574   //  
575   return numberOfLayers;
576 }
577
578 //______________________________________________________________________
579 Int_t AliITSUGeomTGeo::ExtractNumberOfLadders(Int_t lay) const
580 {
581   // Determines the number of layers in the Upgrade Geometry
582   //
583   // Inputs:
584   //   lay: layer number, starting from 0
585   //
586   // MS
587   Int_t numberOfLadders = 0;
588   char laynam[30];
589   snprintf(laynam, 30, "%s%d",fgkITSLrName,lay);
590   TGeoVolume* volLr = gGeoManager->GetVolume(laynam);
591   if (!volLr) AliFatal(Form("can't find %s volume",laynam));
592   //
593   // Loop on all layer nodes, count Ladder volumes by checking names
594   Int_t nNodes = volLr->GetNodes()->GetEntries();
595   for (Int_t j=0; j<nNodes; j++) if (strstr(volLr->GetNodes()->At(j)->GetName(),fgkITSLadName)) numberOfLadders++;
596   //
597   return numberOfLadders;
598   //
599 }
600
601 //______________________________________________________________________
602 Int_t AliITSUGeomTGeo::ExtractNumberOfDetectors(Int_t lay)  const
603 {
604   // Determines the number of detectors per ladder in the Upgrade Geometry
605   //
606   // Inputs:
607   //   lay: layer number from 0
608   // MS
609   Int_t numberOfModules = 0;
610   char laddnam[30];
611   snprintf(laddnam, 30, "%s%d", fgkITSLadName,lay);
612   TGeoVolume* volLd = gGeoManager->GetVolume(laddnam);
613   if (!volLd) AliFatal(Form("can't find %s volume",laddnam));
614   //
615   // Loop on all ladder nodes, count Module volumes by checking names
616   Int_t nNodes = volLd->GetNodes()->GetEntries();
617   for (Int_t j=0; j<nNodes; j++) if (strstr(volLd->GetNodes()->At(j)->GetName(),fgkITSModName)) numberOfModules++;
618   //
619   return numberOfModules;
620   //
621 }
622
623 //______________________________________________________________________
624 Int_t AliITSUGeomTGeo::ExtractLayerDetType(Int_t lay)  const
625 {
626   // Determines the layer detector type the Upgrade Geometry
627   //
628   // Inputs:
629   //   lay: layer number from 0
630   // Outputs:
631   //   none
632   // Return:
633   //   detector type id for the layer
634   // MS
635   char laddnam[30];
636   snprintf(laddnam, 30, "%s%d", fgkITSLrName,lay);
637   TGeoVolume* volLd = gGeoManager->GetVolume(laddnam);
638   if (!volLd) {AliFatal(Form("can't find %s volume",laddnam)); return -1;}
639   //
640   return volLd->GetUniqueID();
641   //
642 }
643
644 //______________________________________________________________________
645 UInt_t AliITSUGeomTGeo::ComposeDetTypeID(UInt_t segmId)
646 {
647   if (segmId>=kMaxSegmPerDetType) AliFatalClass(Form("Id=%d is >= max.allowed %d",segmId,kMaxSegmPerDetType));
648   return segmId + kDetTypePix*kMaxSegmPerDetType;
649 }
650
651 //______________________________________________________________________
652 void AliITSUGeomTGeo::Print(Option_t *) const
653 {
654   // print
655   printf("Geometry version %d, NLayers:%d NModules:%d\n",fVersion,fNLayers,fNModules);
656   if (fVersion==kITSVNA) return;
657   for (int i=0;i<fNLayers;i++) {
658     printf("Lr%2d\tNLadd:%2d\tNDet:%2d\tDetType:%3d\tMod#:%4d:%4d\n",
659            i,fNLadders[i],fNDetectors[i],fLrDetType[i],GetFirstModIndex(i),GetLastModIndex(i));
660   }
661 }
662
663 //______________________________________________________________________
664 void AliITSUGeomTGeo::FetchMatrices()
665 {
666   // store pointer on often used matrices for faster access
667   if (!gGeoManager) AliFatal("Geometry is not loaded");
668   fMatSens = new TObjArray(fNModules);
669   fMatSens->SetOwner(kTRUE);
670   for (int i=0;i<fNModules;i++) fMatSens->AddAt(new TGeoHMatrix(*ExtractMatrixSens(i)),i);
671   CreateT2LMatrices();
672 }
673
674 //______________________________________________________________________
675 void AliITSUGeomTGeo::CreateT2LMatrices()
676 {
677   // create tracking to local (Sensor!) matrices
678   fMatT2L  = new TObjArray(fNModules);  
679   fMatT2L->SetOwner(kTRUE);
680   TGeoHMatrix matLtoT;
681   double loc[3]={0,0,0},glo[3];
682   const double *rotm;
683   for (int isn=0;isn<fNModules;isn++) {
684     const TGeoHMatrix* matSens = GetMatrixSens(isn);
685     if (!matSens) {AliFatal(Form("Failed to get matrix for sensor %d",isn)); return;}
686     matSens->LocalToMaster(loc,glo);
687     rotm = matSens->GetRotationMatrix();
688     Double_t al = -ATan2(rotm[1],rotm[0]);
689     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
690     TGeoHMatrix* t2l = new TGeoHMatrix();
691     t2l->RotateZ(ATan2(y,x)*RadToDeg()); // rotate in direction of normal to the sensor plane
692     t2l->SetDx(x);
693     t2l->SetDy(y);
694     t2l->MultiplyLeft(&matSens->Inverse());
695     fMatT2L->AddAt(t2l,isn);
696     /*
697     const double *gtrans = matSens->GetTranslation();
698     memcpy(&rotMatrix[0], matSens->GetRotationMatrix(), 9*sizeof(Double_t));
699     Double_t al = -ATan2(rotMatrix[1],rotMatrix[0]);
700     Double_t rSens = Sqrt(gtrans[0]*gtrans[0] + gtrans[1]*gtrans[1]);
701     Double_t tanAl = ATan2(gtrans[1],gtrans[0]) - Pi()/2; //angle of tangent
702     Double_t alTr = tanAl - al;
703     //
704     // The X axis of tracking frame must always look outward
705     loc[1] = rSens/2;
706     matSens->LocalToMaster(loc,glo);
707     double rPos = Sqrt(glo[0]*glo[0] + glo[1]*glo[1]);
708     Bool_t rotOutward = rPos>rSens ? kFALSE : kTRUE;
709     //
710     // Transformation matrix
711     matLtoT.Clear();
712     matLtoT.SetDx(-rSens*Sin(alTr)); // translation
713     matLtoT.SetDy(0.);
714     matLtoT.SetDz(gtrans[2]);
715     // Rotation matrix
716     rotMatrix[0]= 0;  rotMatrix[1]= 1;  rotMatrix[2]= 0; // + rotation
717     rotMatrix[3]=-1;  rotMatrix[4]= 0;  rotMatrix[5]= 0;
718     rotMatrix[6]= 0;  rotMatrix[7]= 0;  rotMatrix[8]= 1;
719     //
720     TGeoRotation rot;
721     rot.SetMatrix(rotMatrix);
722     matLtoT.MultiplyLeft(&rot);
723     if (rotOutward) matLtoT.RotateZ(180.);
724     // Inverse transformation Matrix
725     fMatT2L->AddAt(new TGeoHMatrix(matLtoT.Inverse()),isn);
726     */
727   }
728   //
729 }
730