Added two missing includes to allow macro compilation (thanks to Laurent for remarkin...
[u/mrichter/AliRoot.git] / ITS / AliITSMisAligner.cxx
1 /**************************************************************************
2  * Copyright(c) 2007-2010, 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 /* $Id$ */
17
18 //========================================================================
19 //
20 // This class is a helper, producing ITS aligmnent objects.
21 // It provides also some useful functions
22 // See the parameters of the misalignment at the end of this script.
23 //
24 // Main author: L. Gaudichet
25 // Contact: andrea.dainese@lnl.infn.it
26 //
27 //========================================================================
28
29 #include <TClonesArray.h>
30 #include <TMath.h>
31 #include <TClass.h>
32 #include <TGeoManager.h>
33 #include "AliLog.h"
34 #include "AliAlignObjParams.h"
35 #include "AliITSMisAligner.h"
36 #include "AliITSSurveyToAlign.h"
37 #include "AliMathBase.h"
38
39 ClassImp(AliITSMisAligner)
40   
41 const Int_t AliITSMisAligner::fgkNLadders[AliITSMisAligner::kNLayers] = {20,40,14,22,34,38};
42 const Int_t AliITSMisAligner::fgkNDetectors[AliITSMisAligner::kNLayers] = {4,4,6,8,22,25};
43
44 const Double_t kRadToDeg = 180./TMath::Pi();
45
46 //________________________________________________________________________
47 AliITSMisAligner::AliITSMisAligner():
48     AliMisAligner(),
49     fRnd(),
50     fInd(0),
51     fAlignObjArray(NULL),
52     fStrSPD("ITS/SPD"),
53     fStrSDD("ITS/SDD"),
54     fStrSSD("ITS/SSD"),
55     fStrStave("/Stave"),
56     fStrHalfStave("/HalfStave"),
57     fStrLadder("/Ladder"),
58     fStrSector("/Sector"),
59     fStrSensor("/Sensor"),
60     fUnifSPDSector(kFALSE),
61     fUnifSPDHS(kFALSE),
62     fUnifSDDLadder(kFALSE),
63     fUnifSSDLadder(kFALSE),
64     fUnifSPDLadder(kFALSE),
65     fUnifSDDModule(kFALSE),
66     fUnifSSDModule(kFALSE)
67 {
68     //
69     // defaul constructor
70     //
71     fRnd.SetSeed(38217945);
72     fAlignObjArray = new TClonesArray("AliAlignObjParams",4000);
73     for(Int_t ii=0; ii<6; ii++)
74     {
75         fWholeITS[ii]=0.;
76         fSPDSector[ii]=0.;
77         fSPDHB[ii]=0.;
78         fSPDBarrel[ii]=0.;
79         fSPDHS[ii]=0.;
80         fSPDLadder[ii]=0.;
81         fSDDLayer[ii]=0.;
82         fSDDBarrel[ii]=0.;
83         fSDDLadder[ii]=0.;
84         fSDDModule[ii]=0.;
85         fSSDBarrel[ii]=0.;
86         fSSDLayer[ii]=0.;
87         fSSDLadder[ii]=0.;
88         fSSDModule[ii]=0.;
89         fSPDLadderShiftT[ii]=0.;
90         fSPDLadderShiftB[ii]=0.;
91         fSDDLadderShift1[ii]=0.;
92         fSDDLadderShift2[ii]=0.;
93     }
94 }
95
96 //________________________________________________________________________
97 AliITSMisAligner::AliITSMisAligner(const AliITSMisAligner &mAligner):
98     AliMisAligner(),
99     fRnd(mAligner.fRnd),
100     fInd(0),
101     fAlignObjArray(mAligner.fAlignObjArray),
102     fStrSPD("ITS/SPD"),
103     fStrSDD("ITS/SDD"),
104     fStrSSD("ITS/SSD"),
105     fStrStave("/Stave"),
106     fStrHalfStave("/HalfStave"),
107     fStrLadder("/Ladder"),
108     fStrSector("/Sector"),
109     fStrSensor("/Sensor"),
110     fUnifSPDSector(kFALSE),
111     fUnifSPDHS(kFALSE),
112     fUnifSDDLadder(kFALSE),
113     fUnifSSDLadder(kFALSE),
114     fUnifSPDLadder(kFALSE),
115     fUnifSDDModule(kFALSE),
116     fUnifSSDModule(kFALSE)
117 {
118     //
119     // copy constructor
120     //
121
122   SetMisalType(mAligner.GetMisalType());
123 }
124
125 //________________________________________________________________________
126 AliITSMisAligner &AliITSMisAligner::operator= (const AliITSMisAligner &mAligner)
127 {
128     //
129     // assignment operator
130     //
131     fRnd = mAligner.fRnd;
132     fInd = 0;
133     fAlignObjArray = mAligner.fAlignObjArray;
134     fStrSPD = "ITS/SPD";
135     fStrSDD = "ITS/SDD";
136     fStrSSD = "ITS/SSD";
137     fStrStave = "/Stave";
138     fStrHalfStave = "/HalfStave";
139     fStrLadder = "/Ladder";
140     fStrSector = "/Sector";
141     fStrSensor = "/Sensor";
142     fUnifSPDSector = mAligner.fUnifSPDSector;
143     fUnifSPDHS = kFALSE;
144     fUnifSDDLadder = kFALSE;
145     fUnifSSDLadder = kFALSE;
146     fUnifSPDLadder = kFALSE;
147     fUnifSDDModule = kFALSE;
148     fUnifSSDModule = kFALSE;
149     return (*this);
150 }
151
152 //_______________________________________________________________________________________
153 TClonesArray* AliITSMisAligner::MakeAlObjsArray() {
154     // Make the array of alignment objects, depending on the misalignment scenario (Zero, Residual, Full)
155     //
156
157     // Setting default values for ideal, residual or full misalignment
158     SetWholeITSMisAlignment();
159     SetSPDMisAlignment();
160     SetSDDMisAlignment();
161     SetSSDMisAlignment(); 
162
163     // Get array of alignment objects from survey (based on which we build later the SSD objects)
164     AliITSSurveyToAlign* s2a = new AliITSSurveyToAlign();
165     s2a->Run();
166     TClonesArray* surveyArray = dynamic_cast<TClonesArray*> (s2a->GetAlignObjsArray());
167     if(!surveyArray){
168         Printf("SSD survey array was not build! Probably you missed to connect to alien");
169         return 0;
170     }else{
171         Printf("survey array contains %d entries", surveyArray->GetEntriesFast());
172     }
173
174     AddAlignObj("ITS",fWholeITS[0],fWholeITS[1],fWholeITS[2],fWholeITS[3],fWholeITS[4],fWholeITS[5],"fixed");
175
176     AddSectorAlignObj(1,5,fSPDSector[0],fSPDSector[1],fSPDSector[2],fSPDSector[3],fSPDSector[4],fSPDSector[5],
177             fSPDLadderShiftT[0],fSPDLadderShiftT[1],fSPDLadderShiftT[2],fSPDLadderShiftT[3],fSPDLadderShiftT[4],fSPDLadderShiftT[5],fUnifSPDSector);
178     AddSectorAlignObj(6,10,fSPDSector[0],fSPDSector[1],fSPDSector[2],fSPDSector[3],fSPDSector[4],fSPDSector[5],
179             fSPDLadderShiftB[0],fSPDLadderShiftB[1],fSPDLadderShiftB[2],fSPDLadderShiftB[3],fSPDLadderShiftB[4],fSPDLadderShiftB[5],fUnifSPDSector);
180
181     //=****************************************
182     // misalignment at the level of half-staves (SPD)/ladders (SDD,SSD) :
183     //=****************************************
184     AddAlignObj(0,-1,fSPDHS[0],fSPDHS[1],fSPDHS[2],fSPDHS[3],fSPDHS[4],fSPDHS[5],
185             0,0,0,0,0,0,fUnifSPDHS); // all SPD1 half-staves
186     AddAlignObj(1,-1,fSPDHS[0],fSPDHS[1],fSPDHS[2],fSPDHS[3],fSPDHS[4],fSPDHS[5],
187             0,0,0,0,0,0,fUnifSPDHS); // all SPD2 half-staves
188
189     AddAlignObj(2,-1,fSDDLadder[0],fSDDLadder[1],fSDDLadder[2],fSDDLadder[3],
190             fSDDLadder[4],fSDDLadder[5],fSDDLadderShift1[0],fSDDLadderShift1[1],fSDDLadderShift1[2],fSDDLadderShift1[3],fSDDLadderShift1[4],fSDDLadderShift1[5],fUnifSDDLadder); // all SDD1 ladders
191     AddAlignObj(3,-1,fSDDLadder[0],fSDDLadder[1],fSDDLadder[2],fSDDLadder[3],
192             fSDDLadder[4],fSDDLadder[5],fSDDLadderShift2[0],fSDDLadderShift2[1],fSDDLadderShift2[2],fSDDLadderShift2[3],fSDDLadderShift2[4],fSDDLadderShift2[5],fUnifSDDLadder); // all SDD2 ladders
193
194     // all SSD ladders as from survey, + shift and smearing in the "residual" and "full" case
195     for(Int_t ii=0; ii<surveyArray->GetEntriesFast(); ii++)
196     {
197         AliAlignObjParams* aop = dynamic_cast<AliAlignObjParams*> (surveyArray->UncheckedAt(ii));
198         TString sName(aop->GetSymName());
199
200         if(sName.Contains("SSD") && !sName.Contains("Sensor"))
201         {
202
203             if(!(TString(GetMisalType())=="ideal"))
204             {
205                 // First we shift all SSD ladders by the same quantity to reproduce a barrel shift
206                 ShiftAlignObj(*aop,fSSDBarrel[0],fSSDBarrel[1],fSSDBarrel[2],fSSDBarrel[3],fSSDBarrel[4],fSSDBarrel[5]);
207
208                 // Then we smear according to the sigmas given by the misalignment scenario
209                 if(sName.Contains("SSD4")){
210                     // we correct with the factor 1.13 for the fact that, in the inner SSD layer, z lever arm is 45.135cm instead of 51cm
211                     SmearAlignObj(*aop,fSSDLadder[0],fSSDLadder[1],fSSDLadder[2],fSSDLadder[3]*1.13,fSSDLadder[4]*1.13,fSSDLadder[5]);
212                 }else if(sName.Contains("SSD5")){
213                     SmearAlignObj(*aop,fSSDLadder[0],fSSDLadder[1],fSSDLadder[2],fSSDLadder[3],fSSDLadder[4],fSSDLadder[5]);
214                 }
215             }
216
217             new((*fAlignObjArray)[fInd++]) AliAlignObjParams(*aop);
218             aop->ApplyToGeometry(); // this we need to correctly build objects for SSD ladders below
219         }
220     }
221
222     //=****************************************
223     // misalignment at the level of ladders (SPD)/modules (SDD,SSD) :
224     //=****************************************
225     AddAlignObj(0,fSPDLadder[0],fSPDLadder[1],fSPDLadder[2],fSPDLadder[3],fSPDLadder[4],fSPDLadder[5],fUnifSPDLadder);// all SPD1 ladders
226     AddAlignObj(1,fSPDLadder[0],fSPDLadder[1],fSPDLadder[2],fSPDLadder[3],fSPDLadder[4],fSPDLadder[5],fUnifSPDLadder);// all SPD2 ladders
227
228     AddAlignObj(2,fSDDModule[0],fSDDModule[1],fSDDModule[2],fSDDModule[3],fSDDModule[4],fSDDModule[5],fUnifSDDModule);// all SDD1 modules
229     AddAlignObj(3,fSDDModule[0],fSDDModule[1],fSDDModule[2],fSDDModule[3],fSDDModule[4],fSDDModule[5],fUnifSDDModule);// all SDD2 modules
230
231     // all SSD modules
232     for(Int_t ii=0; ii<surveyArray->GetEntriesFast(); ii++)
233     {
234         AliAlignObjParams* aop = dynamic_cast<AliAlignObjParams*> (surveyArray->UncheckedAt(ii));
235         TString sName(aop->GetSymName());
236         if(sName.Contains("SSD") && sName.Contains("Sensor"))
237         {
238             if(!(TString(GetMisalType())=="ideal"))
239                 SmearAlignObj(*aop,fSSDModule[0],fSSDModule[1],fSSDModule[2],fSSDModule[3],fSSDModule[4],fSSDModule[5]);
240             new((*fAlignObjArray)[fInd++]) AliAlignObjParams(*aop);
241         }
242     }
243
244     return fAlignObjArray;
245 }
246
247 //_______________________________________________________________________________________
248 void AliITSMisAligner::ShiftAlignObj(AliAlignObjParams &alObj, Double_t dx, Double_t dy, Double_t dz, Double_t dpsi, Double_t dtheta, Double_t dphi)
249 {
250     // 
251     // Shift the parameters of the alignment object passed as first argument by the quantities defined by the arguments
252     //
253     Double_t shifts[3]; Double_t angles[3];
254     alObj.GetPars(shifts, angles);
255     alObj.SetPars(shifts[0]+dx, shifts[1]+dy, shifts[2]+dz, angles[0]+dpsi, angles[1]+dtheta, angles[2]+dphi);
256 }
257
258 //_______________________________________________________________________________________
259 void AliITSMisAligner::SmearAlignObj(AliAlignObjParams &alObj, Double_t sx, Double_t sy, Double_t sz, Double_t spsi, Double_t stheta, Double_t sphi)
260 {
261     // 
262     // Smear the parameters of the alignment object passed as first argument in the range defined by the subsequent arguments
263     //
264     Double_t shifts[3]; Double_t angles[3];
265     alObj.GetLocalPars(shifts, angles);
266     Double_t x = AliMathBase::TruncatedGaus(shifts[0], sx, 3.*sx);
267     Double_t y = AliMathBase::TruncatedGaus(shifts[1], sy, 3.*sy);
268     Double_t z = AliMathBase::TruncatedGaus(shifts[2], sz, 3.*sz);
269     Double_t psi = AliMathBase::TruncatedGaus(angles[0], spsi, 3.*spsi);
270     Double_t theta = AliMathBase::TruncatedGaus(angles[1], stheta, 3.*stheta);
271     Double_t phi = AliMathBase::TruncatedGaus(angles[2], sphi, 3.*sphi);
272     alObj.SetLocalPars(x, y, z, psi, theta, phi);
273 }
274
275 //_______________________________________________________________________________________
276 void AliITSMisAligner::SetWholeITSMisAlignment()
277 {
278     // Set misalignment for the whole ITS for the standar scenarios (zero, residual, full)
279     // To make custom misalignments set directly the misalignments at each level (methods "SetS?D*Pars")
280     //
281     if(TString(GetMisalType())=="ideal")
282     {
283         // overall ITS misalignment according to survey as reported by Werner Riegler (18/07/2008)
284         SetWholeITSPars(-0.12, -0.07, 0.29, 0., 0.03, 0.04);
285     }else if(TString(GetMisalType())=="residual"){
286         // overall ITS misalignment according to survey as reported by Werner Riegler (18/07/2008)
287         // no smearing added (would clash with vertex constraint)
288         SetWholeITSPars(-0.12, -0.07, 0.29, 0., 0.03, 0.04);
289     }else if(TString(GetMisalType())=="full"){
290         // overall ITS misalignment according to survey as reported by Werner Riegler (18/07/2008) plus smearing
291         Double_t sigmatrW = 0.01;
292         Double_t sigmarotW = 0.006;
293         SetWholeITSPars(AliMathBase::TruncatedGaus(-0.12,sigmatrW,3.*sigmatrW),
294                 AliMathBase::TruncatedGaus(-0.07,sigmatrW,3.*sigmatrW),
295                 AliMathBase::TruncatedGaus(0.29,sigmatrW,3.*sigmatrW),
296                 AliMathBase::TruncatedGaus(0.,sigmarotW,3.*sigmarotW),
297                 AliMathBase::TruncatedGaus(0.03,sigmarotW,3.*sigmarotW),
298                 AliMathBase::TruncatedGaus(0.04,sigmarotW,3.*sigmarotW));
299     }
300 }
301
302 //_______________________________________________________________________________________
303 void AliITSMisAligner::SetSPDMisAlignment()
304 {
305     // Set misalignment for SPD alignable volumes for the standar scenarios (zero, residual, full)
306     // To make custom misalignments set directly the misalignments at each level (methods "SetSPD*Pars")
307     //
308     if(TString(GetMisalType())=="ideal")
309     {
310         // misalignment for SPD at all levels equal to zero (identical transformations)
311         SetSPDBarrelSigmas(0., 0., 0., 0., 0., 0.); 
312         SetSPDHBSigmas(0., 0., 0., 0., 0., 0.); 
313         SetSPDSectorSigmas(0., 0., 0., 0., 0., 0.); 
314         SetSPDHSSigmas(0., 0., 0., 0., 0., 0.); 
315         SetSPDLadderSigmas(0., 0., 0., 0., 0., 0.); 
316     }else if(TString(GetMisalType())=="residual"){
317         // misalignment at the level of SPD barrel and half-barrels left to zero
318         SetSPDBarrelSigmas(0., 0., 0., 0., 0., 0.); 
319         SetSPDHBSigmas(0., 0., 0., 0., 0., 0.); 
320
321         // misalignment at the level of SPD sectors (source: A.Pepato)
322         SetSPDSectorSigmas( 0.0050/5., //  50 micron (~tangetial, i.e. rphi)
323                 0.0100/5., // 100 micron (~radial)
324                 0.0100/5., // 100 micron
325                 0.0100/30.*kRadToDeg/5., // so as to have 100 micron difference at the two extremes
326                 0.0100/30.*kRadToDeg/5., // so as to have 100 micron difference at the two extremes
327                 0.0050/1.5*kRadToDeg/5.); // so as to have 50 micron difference at the two extremes
328         fUnifSPDSector=kFALSE;
329
330         // misalignment at the level of half-staves (SPD) (source: S.Moretto)
331         SetSPDHSSigmas( 0.0100/4., // 100 micron
332                 0.0020/4., // 20 micron
333                 0.0020/4., // 20 micron
334                 0.0020/7.*kRadToDeg/4., // so as to have 20 micron difference at the two extremes
335                 0.0050/7.*kRadToDeg/4., // so as to have 50 micron difference at the two extremes
336                 0.0050/0.7*kRadToDeg/4.);// so as to have 50 micron difference at the two extremes
337         fUnifSPDHS=kFALSE;
338
339         // misalignment at the level of ladders (SPD) (source: R.Santoro)
340         SetSPDLadderSigmas( 0.0010/5., // 10 micron
341                 0.0050/5., // 50 micron
342                 0.0010/5., // 10 micron
343                 0.0001*kRadToDeg/5., // 0.1 mrad
344                 0.0001*kRadToDeg/5., // 0.1 mrad
345                 0.0001*kRadToDeg/5.);// 0.1 mrad
346         fUnifSPDLadder=kFALSE;
347
348     }else if(TString(GetMisalType())=="full"){
349         // misalignment at the level of SPD barrel (source: A.Pepato)
350         SetSPDBarrelSigmas( 0.1000, // 1 mm (very pessimistic)
351                 0.1000, // 1 mm (very pessimistic)
352                 0.1000, // 1 mm (very pessimistic)
353                 0.0500/30.*kRadToDeg, // so as to have 500 micron difference at the two extremes
354                 0.0500/30.*kRadToDeg, // so as to have 500 micron difference at the two extremes
355                 0.0500/7.*kRadToDeg); // so as to have 500 micron difference at the two extremes
356
357         // misalignment at the level of SPD half-barrels (source: A.Pepato)
358         SetSPDHBSigmas( 0.0200, // 200 micron
359                 0.0200, // 200 micron
360                 0.0200, // 200 micron
361                 0.0100/30.*kRadToDeg, // so as to have 100 micron difference at the two extremes
362                 0.0100/30.*kRadToDeg, // so as to have 100 micron difference at the two extremes
363                 0.0100/7.*kRadToDeg); // so as to have 100 micron difference at the two extremes
364
365         // misalignment at the level of SPD sectors (source: A.Pepato)
366         SetSPDSectorSigmas( 0.0050, //  50 micron (~tangetial, i.e. rphi)
367                 0.0100, // 100 micron (~radial)
368                 0.0100, // 100 micron
369                 0.0100/30.*kRadToDeg, // so as to have 100 micron difference at the two extremes
370                 0.0100/30.*kRadToDeg, // so as to have 100 micron difference at the two extremes
371                 0.0050/1.5*kRadToDeg); // so as to have 50 micron difference at the two extremes
372         fUnifSPDSector=kTRUE;
373
374         // misalignment at the level of half-staves (SPD) (source: S.Moretto)
375         SetSPDHSSigmas( 0.0100, // 100 micron // normal to plane
376                 0.0020, // 20 micron
377                 0.0020, // 20 micron
378                 0.0020/7.*kRadToDeg, // so as to have 20 micron difference at the two extremes
379                 0.0050/7.*kRadToDeg, // so as to have 50 micron difference at the two extremes
380                 0.0050/0.7*kRadToDeg); // so as to have 50 micron difference at the two extremes
381         fUnifSPDHS=kTRUE;
382
383         // misalignment at the level of ladders (SPD) (source: R.Santoro)
384         SetSPDLadderSigmas( 0.0010, // 10 micron
385                 0.0030, // 50 micron
386                 0.0010, // 10 micron
387                 0.0001*kRadToDeg, // 0.1 mrad
388                 0.0001*kRadToDeg, // 0.1 mrad
389                 0.0001*kRadToDeg); // 0.1 mrad
390         fUnifSPDLadder=kTRUE;
391
392
393         // misalignment at the level of SPD barrel, half-barrels, and at the level
394         // of SPD sectors
395         Double_t shBtop[6], shBbot[6]; //top and bottom barrel shifts
396         for(Int_t ii=0; ii<6; ii++){
397             shBtop[ii] = AliMathBase::TruncatedGaus(0.,fSPDBarrel[ii]/3,fSPDBarrel[ii]);
398             shBbot[ii] = shBtop[ii];
399         }
400
401         for(Int_t ii=0; ii<6; ii++){
402             shBtop[ii] += AliMathBase::TruncatedGaus(0.,fSPDHB[ii]/3,fSPDHB[ii]);
403             shBbot[ii] += AliMathBase::TruncatedGaus(0.,fSPDHB[ii]/3,fSPDHB[ii]);
404         }
405         SetSPDLadderShiftT(shBtop);
406         SetSPDLadderShiftB(shBbot);
407     }
408 }
409
410 //_______________________________________________________________________________________
411 void AliITSMisAligner::SetSDDMisAlignment() 
412 {
413     // Set misalignment for SDD alignable volumes for the standar scenarios (zero, residual, full)
414     // To make custom misalignments set directly the misalignments at each level (methods "SetSDD*Pars")
415     //
416     if(TString(GetMisalType())=="ideal")
417     {
418         // misalignment for SDD at all levels equal to zero
419         SetSDDLayerSigmas(0., 0., 0., 0., 0., 0.);
420         SetSDDBarrelSigmas(0., 0., 0., 0., 0., 0.);
421         SetSDDLadderSigmas(0., 0., 0., 0., 0., 0.);
422         SetSDDModuleSigmas(0., 0., 0., 0., 0., 0.);
423     }else if(TString(GetMisalType())=="residual"){
424         // misalignment at the level of SDD and SSD layers(source: B.Giraudo)
425         SetSDDLayerSigmas(0., 0., 0., 0., 0., 0.);
426         SetSDDBarrelSigmas(0., 0., 0., 0., 0., 0.);
427
428         // misalignment at the level of half-staves (SPD) (source: S.Moretto)
429         SetSDDLadderSigmas( 0.0005, // 5 micron
430                 0.0005, // 5 micron
431                 0.0005, // 5 micron
432                 0.00, //  ?
433                 0.00, //  ?
434                 0.00); //  ?
435         fUnifSDDLadder=kFALSE;
436
437         // misalignment at the level of SDD modules(source: L.Gaudichet)
438         SetSDDModuleSigmas( 0.0045/5., // 45 micron
439                 0.0045/5., // 45 micron
440                 0.0105/5., // 105 micron
441                 0.00, // ?
442                 0.00, //  ?
443                 0.00);//  ?
444         fUnifSDDModule=kFALSE;
445
446     }else if(TString(GetMisalType())=="full"){
447         // misalignment at the level of SDD layers(source: B.Giraudo)
448         SetSDDBarrelSigmas( 0.0020, // 20 micron
449                 0.0020, // 20 micron
450                 0.0020, // 20 micron
451                 0.0020/52.*kRadToDeg,  // so as to have 20 micron difference at the two extremes
452                 0.0020/52.*kRadToDeg,  // so as to have 20 micron difference at the two extremes
453                 0.0020/20.*kRadToDeg); // so as to have 20 micron difference at the two extremes
454
455         SetSDDLayerSigmas( 0.0010, // 10 micron
456                 0.0010, // 10 micron
457                 0.0010, // 10 micron
458                 0.0010/52.*kRadToDeg, // so as to have 10 micron difference at the two extremes
459                 0.0010/52.*kRadToDeg, // so as to have 10 micron difference at the two extremes
460                 0.0010/20.*kRadToDeg);  // so as to have 10 micron difference at the two extremes
461
462         // misalignment at the level of SDD ladders
463         SetSDDLadderSigmas( 0.0005, // 5 micron
464                 0.0005, // 5 micron
465                 0.0005, // 5 micron
466                 0.00, //  ?
467                 0.00, //  ?
468                 0.00);//  ?
469         fUnifSDDLadder=kTRUE;
470
471         // misalignment at the level of SDD modules (source: L.Gaudichet)
472         SetSDDModuleSigmas( 0.0045, // 45 micron
473                 0.0045, // 45 micron
474                 0.0105, // 105 micron
475                 0.00, // ?
476                 0.00, //  ?
477                 0.00);//  ?
478         fUnifSDDModule=kTRUE;
479     }
480
481     fSDDLadderShift1[0] = GetUnif(-fSDDBarrel[0],fSDDBarrel[0]);
482     fSDDLadderShift1[1] = GetUnif(-fSDDBarrel[1],fSDDBarrel[1]);
483     fSDDLadderShift1[2] = GetUnif(-fSDDBarrel[2],fSDDBarrel[2]);
484     fSDDLadderShift1[3] = GetUnif(-fSDDBarrel[3],fSDDBarrel[3]);
485     fSDDLadderShift1[4] = GetUnif(-fSDDBarrel[4],fSDDBarrel[4]);
486     fSDDLadderShift1[5] = GetUnif(-fSDDBarrel[5],fSDDBarrel[5]);
487
488     for(Int_t ii=0; ii<6; ii++)
489         fSDDLadderShift2[ii] = fSDDLadderShift1[ii];
490
491     //  layer SDD1
492     fSDDLadderShift1[0] += GetUnif(-fSDDLayer[0],fSDDLayer[0]);
493     fSDDLadderShift1[1] += GetUnif(-fSDDLayer[1],fSDDLayer[1]);
494     fSDDLadderShift1[2] += GetUnif(-fSDDLayer[2],fSDDLayer[2]);
495     fSDDLadderShift1[3] += GetUnif(-fSDDLayer[3],fSDDLayer[3]);
496     fSDDLadderShift1[4] += GetUnif(-fSDDLayer[4],fSDDLayer[4]);
497     fSDDLadderShift1[5] += GetUnif(-fSDDLayer[5],fSDDLayer[5]);
498
499     //  layer SDD2
500     fSDDLadderShift2[0] += GetUnif(-fSDDLayer[0],fSDDLayer[0]);
501     fSDDLadderShift2[1] += GetUnif(-fSDDLayer[1],fSDDLayer[1]);
502     fSDDLadderShift2[2] += GetUnif(-fSDDLayer[2],fSDDLayer[2]);
503     fSDDLadderShift2[3] += GetUnif(-fSDDLayer[3],fSDDLayer[3]);
504     fSDDLadderShift2[4] += GetUnif(-fSDDLayer[4],fSDDLayer[4]);
505     fSDDLadderShift2[5] += GetUnif(-fSDDLayer[5],fSDDLayer[5]);
506
507 }
508
509 //_______________________________________________________________________________________
510 void AliITSMisAligner::SetSSDMisAlignment() 
511 {
512     // Set misalignment for SSD alignable volumes for the standar scenarios (zero, residual, full)
513     // To make custom misalignments set directly the misalignments at each level (methods "SetSSD*Pars")
514     //
515     if(TString(GetMisalType())=="ideal"){
516
517         // zero misalignment at the level of SSD barrel
518         SetSSDBarrelPars(0.,0.,0.,0.,0.,0.);
519         // zero misalignment at the level of SSD ladders
520         SetSSDLadderSigmas(0.,0.,0.,0.,0.,0.);
521         // zero misalignment at the level of SSD modules
522         SetSSDModuleSigmas(0.,0.,0.,0.,0.,0.);
523
524     }else if(TString(GetMisalType())=="residual"){
525
526         // zero misalignment at the level of SSD barrel
527         SetSSDBarrelPars(0.,0.,0.,0.,0.,0.);
528         // misalignment at the level of SSD ladders (source: M. Van Leeuwen)
529         // values set so that overall maximum displacement (combined effect of shift and rotation
530         // of the ladder) for any point of the ladder cannot exceed 10um in x, 100 um in y, 50um in z
531         SetSSDLadderSigmas( 0.0005, // 5 microns
532                 0.0033, // 33 microns
533                 0.0050, // 50 microns
534                 0.000067*kRadToDeg, // 0.067 mrads
535                 0.00001*kRadToDeg, // 0.01 mrads
536                 0.001*kRadToDeg); // 1 mrad
537         fUnifSSDLadder=kTRUE;
538
539         // misalignment at the level of SSD modules (source: M. Van Leeuwen)
540         // values set so that overall maximum displacement (combined effect of shift and rotation
541         // of the ladder) for any point of the module cannot exceed 5um in x, 10 um in y, 5um in z
542         SetSSDModuleSigmas( 0.00025, // 2.5 microns
543                 0.00034, // 3.4 microns
544                 0.0005, // 5 microns
545                 0.00017*kRadToDeg, // 0.17 mrads
546                 0.000125*kRadToDeg, // 0.125 mrads
547                 0.0001*kRadToDeg); // 0.1 mrads
548         fUnifSSDModule=kTRUE;
549
550     }else if(TString(GetMisalType())=="full"){
551         // misalignment at the level of SSD layers (source: B. Giraudo)
552         SetSSDBarrelPars( GetUnif(-0.0020,0.0020), // 20 micron
553                 GetUnif(-0.0020,0.0020), // 20 micron
554                 GetUnif(-0.0020,0.0020), // 20 micron
555                 GetUnif(-0.0020/90.*kRadToDeg,0.0020), // so as to have 20 micron difference at the two extremes
556                 GetUnif(-0.0020/90.*kRadToDeg,0.0020), // so as to have 20 micron difference at the two extremes
557                 GetUnif(-0.0020/40.*kRadToDeg,0.0020));  // so as to have 20 micron difference at the two extremes
558
559         // misalignment at the level of SSD ladders (source: M. Van Leeuwen)
560         // values set so that overall maximum displacement (combined effect of shift and rotation
561         // of the ladder) for any point of the ladder cannot exceed 20um in x, 100 um in y, 50um in z
562         SetSSDLadderSigmas( 0.0010, // 10 microns
563                 0.0033, // 33 microns
564                 0.0050, // 50 microns
565                 0.000067*kRadToDeg, // 0.067 mrads
566                 0.00002*kRadToDeg, // 0.02 mrads
567                 0.001*kRadToDeg); // 1 mrad
568         fUnifSSDLadder=kTRUE;
569
570         // misalignment at the level of SSD modules (source: M. Van Leeuwen)
571         // values set so that overall maximum displacement (combined effect of shift and rotation
572         // of the ladder) for any point of the module cannot exceed 5um in x, 10 um in y, 5um in z
573         SetSSDModuleSigmas( 0.00025, // 2.5 microns
574                 0.00034, // 3.4 microns
575                 0.0005, // 5 microns
576                 0.00017*kRadToDeg, // 0.17 mrads
577                 0.000125*kRadToDeg, // 0.125 mrads
578                 0.0001*kRadToDeg); // 0.1 mrads
579         fUnifSSDModule=kTRUE;
580     }
581
582 }
583
584 //_______________________________________________________________________________________
585 AliCDBMetaData* AliITSMisAligner::GetCDBMetaData() const {
586     // Returns the AliCDBMetaData to be associated with AliCDBEntry which will contain
587     // the array of alignment objects for ITS misalignment
588     // Presently "responsible" and "comment" are filled.
589     //
590     AliCDBMetaData* md = new AliCDBMetaData();
591     md->SetResponsible("A. Dainese, M. Van Leeuwen, R. Grosso");
592
593     if(TString(GetMisalType())=="ideal")
594         md->SetComment(
595                 Form("Alignment objects for ITS ideal misalignment. It includes:"
596                     "\n                                 survey of whole ITS;"
597                     "\n                                 survey of SSD ladders and modules"));
598     if(TString(GetMisalType())=="residual")
599         md->SetComment(
600                 Form("Alignment objects for ITS residual misalignment. It includes:"
601                     "\n                                 survey of whole ITS;"
602                     "\n                                 survey of SSD ladders and modules"));
603     if(TString(GetMisalType())=="full")
604         md->SetComment(
605                 Form("Alignment objects for ITS full misalignment. It includes:"
606                     "\n                                 survey of whole ITS;"
607                     "\n                                 survey of SSD ladders and modules"));
608     return md;
609 }
610
611 //________________________________________________________________________
612 Bool_t AliITSMisAligner::AddAlignObj(char* name,Double_t dx,Double_t dy,Double_t dz,
613         Double_t dpsi,Double_t dtheta,Double_t dphi,const char* distrib) {
614     //
615     // misalignment by symname
616     //
617     Double_t vx=0.,vy=0.,vz=0.,vpsi=0.,vtheta=0.,vphi=0.;
618
619     TString sdistrib(distrib);
620
621     if(sdistrib==TString("gaussian")) {
622         vx = AliMathBase::TruncatedGaus(0.,dx/3.,dx); // mean, sigma, max absolute value 
623         vy = AliMathBase::TruncatedGaus(0.,dy/3.,dy);
624         vz = AliMathBase::TruncatedGaus(0.,dz/3.,dz);
625         vpsi   = AliMathBase::TruncatedGaus(0.,dpsi/3.,  dpsi );
626         vtheta = AliMathBase::TruncatedGaus(0.,dtheta/3.,dtheta);
627         vphi   = AliMathBase::TruncatedGaus(0.,dphi/3.,  dphi);
628     }else if(sdistrib==TString("uniform")){ 
629         vx = fRnd.Uniform(-dx,dx);
630         vy = fRnd.Uniform(-dy,dy);
631         vz = fRnd.Uniform(-dz,dz);
632         vpsi = fRnd.Uniform(-dpsi,dpsi);
633         vtheta = fRnd.Uniform(-dtheta,dtheta);
634         vphi = fRnd.Uniform(-dphi,dphi);
635     }else if(sdistrib==TString("fixed")){
636         vx=dx;
637         vy=dy;
638         vz=dz;
639         vpsi=dpsi;
640         vtheta=dtheta;
641         vphi=dphi;
642     }else{
643         AliFatal(Form("Invalid string \"%s\" specifying the misalignment type for the volume \"%s\""));
644     }
645
646     new((*fAlignObjArray)[fInd]) AliAlignObjParams(name,0,vx,vy,vz,vpsi,vtheta,vphi,kFALSE);
647
648     AliAlignObjParams* itsalobj = (AliAlignObjParams*) fAlignObjArray->UncheckedAt(fInd);
649     itsalobj->ApplyToGeometry();
650
651     fInd++;
652
653     return kTRUE;
654 }
655
656
657 //________________________________________________________________________
658 Bool_t AliITSMisAligner::AddAlignObj(Int_t lay,Double_t dx,Double_t dy,Double_t dz,
659         Double_t dpsi,Double_t dtheta,Double_t dphi,Bool_t unif) {
660     //
661     // misalignment at the level of sensitive alignable volumes (SPD ladders/ SDD,SSD modules)
662     // done for all ladders/modules of the given layer
663     //
664     lay+=1; // layers are numbered from 1 to 6 in AliGeomManager
665
666     printf("LAYER %d  MODULES %d\n",lay,AliGeomManager::LayerSize(lay));
667
668     for (Int_t iModule = 0; iModule < AliGeomManager::LayerSize(lay); iModule++) {
669
670         Double_t vx,vy,vz,vpsi,vtheta,vphi;
671
672         if(!unif) {
673             vx = AliMathBase::TruncatedGaus(0.,dx/3.,dx); // mean, sigma, max absolute value 
674             vy = AliMathBase::TruncatedGaus(0.,dy/3.,dy);
675             vz = AliMathBase::TruncatedGaus(0.,dz/3.,dz);
676             vpsi = AliMathBase::TruncatedGaus(0.,dpsi/3.,dpsi);
677             vtheta = AliMathBase::TruncatedGaus(0.,dtheta/3.,dtheta);
678             vphi = AliMathBase::TruncatedGaus(0.,dphi/3.,dphi);
679         } else {
680             vx = fRnd.Uniform(-dx,dx);
681             vy = fRnd.Uniform(-dy,dy);
682             vz = fRnd.Uniform(-dz,dz);
683             vpsi = fRnd.Uniform(-dpsi,dpsi);
684             vtheta = fRnd.Uniform(-dtheta,dtheta);
685             vphi = fRnd.Uniform(-dphi,dphi);
686         }
687
688         UShort_t volid = AliGeomManager::LayerToVolUID(lay,iModule);
689         const char *symname = AliGeomManager::SymName(volid);
690
691         new((*fAlignObjArray)[fInd]) AliAlignObjParams(symname,volid,vx,vy,vz,vpsi,vtheta,vphi,kFALSE);
692         fInd++; 
693     }
694
695     return kTRUE;
696 }
697
698 //________________________________________________________________________
699 Bool_t AliITSMisAligner::AddAlignObj(Int_t lay,Int_t ladd,Double_t dx,Double_t dy,Double_t dz,
700         Double_t dpsi,Double_t dtheta,Double_t dphi,
701         Double_t xShift,Double_t yShift,Double_t zShift,
702         Double_t psiShift,Double_t thetaShift,Double_t phiShift,
703         Bool_t unif) {
704     //
705     // misalignment at the level of half-staves/ladders (ladd=-1 means that all ladders are scanned)
706     //
707     Double_t vx,vy,vz,vpsi,vtheta,vphi;
708     Double_t tr[3],rot[3];  
709
710     Int_t laddMin = ladd;
711     Int_t laddMax = laddMin+1;
712     if (ladd<0) {
713         laddMin = 0;
714         laddMax = fgkNLadders[lay];
715     }
716
717     for (Int_t iLadd=laddMin; iLadd<laddMax; iLadd++) {
718
719         Int_t nHS = 1; 
720         if (lay<2) nHS = 2;
721         for (Int_t iHalfStave=0; iHalfStave<nHS; iHalfStave++) {
722
723             if(!unif) {
724                 vx = AliMathBase::TruncatedGaus(0.,dx/3.,dx); // mean, sigma, max absolute value 
725                 vy = AliMathBase::TruncatedGaus(0.,dy/3.,dy);
726                 vz = AliMathBase::TruncatedGaus(0.,dz/3.,dz);
727                 vpsi = AliMathBase::TruncatedGaus(0.,dpsi/3.,dpsi);
728                 vtheta = AliMathBase::TruncatedGaus(0.,dtheta/3.,dtheta);
729                 vphi = AliMathBase::TruncatedGaus(0.,dphi/3.,dphi);
730             } else {
731                 vx = fRnd.Uniform(-dx,dx);
732                 vy = fRnd.Uniform(-dy,dy);
733                 vz = fRnd.Uniform(-dz,dz);
734                 vpsi = fRnd.Uniform(-dpsi,dpsi);
735                 vtheta = fRnd.Uniform(-dtheta,dtheta);
736                 vphi = fRnd.Uniform(-dphi,dphi);
737             }
738
739             TString name(GetHalfStaveLadderSymbName(lay,iLadd,iHalfStave));
740
741             // first apply half-stave / ladder level misalignment
742             AliAlignObjParams aaop(name.Data(),0,vx,vy,vz,vpsi,vtheta,vphi,kFALSE); // set them as local
743             aaop.GetPars(tr,rot); // global
744
745             // then, apply layer-level misalignment (only for SDD and SSD)
746             if(lay>1) {
747                 tr[0] += xShift;
748                 tr[1] += yShift;
749                 tr[2] += zShift;
750                 rot[0] += psiShift;
751                 rot[1] += thetaShift;
752                 rot[2] += phiShift;
753             }
754             new((*fAlignObjArray)[fInd]) AliAlignObjParams(name.Data(),0,tr[0],tr[1],tr[2],rot[0],rot[1],rot[2],kTRUE); // set them as global
755
756             AliAlignObjParams* itsalobj = (AliAlignObjParams*) fAlignObjArray->UncheckedAt(fInd);
757             itsalobj->ApplyToGeometry();
758             fInd++;
759         }
760     }
761
762     return kTRUE;
763 }
764
765
766 //________________________________________________________________________
767 Bool_t AliITSMisAligner::AddSectorAlignObj(Int_t sectMin,Int_t sectMax,
768         Double_t dx,Double_t dy,Double_t dz,
769         Double_t dpsi,Double_t dtheta,Double_t dphi,
770         Double_t xShift,Double_t yShift,Double_t zShift,
771         Double_t psiShift,Double_t thetaShift,Double_t phiShift,Bool_t unif) {
772     //
773     // misalignment at the level of SPD sectors and half-barrels
774     // 
775
776     if ((sectMin<1) || (sectMax>10)) return kFALSE;
777     Double_t vx,vy,vz,vpsi,vtheta,vphi;
778     Double_t tr[3],rot[3];  
779
780     for (Int_t iSect = sectMin-1; iSect<sectMax; iSect++) {
781
782         // first, apply sector level misalignment    
783         if(!unif) {
784             vx = AliMathBase::TruncatedGaus(0.,dx/3.,dx); // mean, sigma, max absolute value 
785             vy = AliMathBase::TruncatedGaus(0.,dy/3.,dy);
786             vz = AliMathBase::TruncatedGaus(0.,dz/3.,dz);
787             vpsi = AliMathBase::TruncatedGaus(0.,dpsi/3.,dpsi);
788             vtheta = AliMathBase::TruncatedGaus(0.,dtheta/3.,dtheta);
789             vphi = AliMathBase::TruncatedGaus(0.,dphi/3.,dphi);
790         } else {
791             vx = fRnd.Uniform(-dx,dx);
792             vy = fRnd.Uniform(-dy,dy);
793             vz = fRnd.Uniform(-dz,dz);
794             vpsi = fRnd.Uniform(-dpsi,dpsi);
795             vtheta = fRnd.Uniform(-dtheta,dtheta);
796             vphi = fRnd.Uniform(-dphi,dphi);
797         }
798
799         TString name(GetSymbName(0));
800         name += fStrSector;
801         name += iSect;
802
803
804         AliAlignObjParams aaop(name.Data(),0,vx,vy,vz,vpsi,vtheta,vphi,kFALSE); // set them as local
805         aaop.GetPars(tr,rot); // global
806
807         // then, apply half-barrel level misalignment
808         tr[0] += xShift;
809         tr[1] += yShift;
810         tr[2] += zShift;
811         rot[0] += psiShift;
812         rot[1] += thetaShift;
813         rot[2] += phiShift;
814
815         new((*fAlignObjArray)[fInd]) AliAlignObjParams(name.Data(),0,tr[0],tr[1],tr[2],rot[0],rot[1],rot[2],kTRUE); // set them as global
816
817         AliAlignObjParams* itsalobj = (AliAlignObjParams*) fAlignObjArray->UncheckedAt(fInd);
818         itsalobj->ApplyToGeometry();
819         fInd++;
820     }
821     return kTRUE;
822 }
823
824 //________________________________________________________________________
825 const char* AliITSMisAligner::GetSymbName(Int_t layer) const {
826     //
827     // be careful : SPD0 and SPD1 are not physically separated 
828     //
829     TString name;
830     switch (layer) {
831         case 0:
832         case 1: name = fStrSPD; name += layer; break;
833         case 2:
834         case 3: name = fStrSDD; name += layer; break;
835         case 4:
836         case 5: name = fStrSSD; name += layer; break;
837         default: AliFatal("Wrong layer index");
838     }
839     return name.Data();
840 }
841
842 //________________________________________________________________________
843 const char* AliITSMisAligner::GetSymbName(Int_t layer, Int_t ladder, Int_t det) const {
844     //
845     // symname from layer, ladder, detector
846     //
847     TString symname(GetHalfStaveLadderSymbName(layer,ladder,det));
848     if(layer<=2){
849         symname+="Ladder";
850     }else if(layer<=6){
851         symname+="Sensor";
852     }else{
853         AliError("Invalid layer!");
854         return 0;
855     }
856     symname+=det;
857     return symname.Data();
858 }
859
860 //________________________________________________________________________
861 const char* AliITSMisAligner::GetSymbName(Int_t layer,Int_t ladd) const {
862     //
863     // Get logical names at the level of staves / ladders
864     //
865     TString name(GetSymbName(layer));
866     if (layer==0) { // SPD1
867
868         int sector = ladd/2;
869         name += fStrSector;
870         name += sector;
871         int stave = ladd-sector*2;
872         name += fStrStave;
873         name += stave;
874     }
875     else if (layer==1) { // SPD2
876
877         int sector = ladd/4;
878         name += fStrSector;
879         name += sector;
880         int stave = ladd-sector*4;
881         name += fStrStave;
882         name += stave;
883     }
884     else if (layer>=2 && layer<=5) { // SDD and SSD
885         name += fStrLadder;
886         name += ladd;
887     }
888     else {
889         AliFatal("Wrong layer index");
890     }
891     return name.Data();
892 }
893
894 //________________________________________________________________________
895 const char* AliITSMisAligner::GetHalfStaveLadderSymbName(Int_t layer,Int_t ladd,Int_t halfStave) const {
896     //
897     // Get logical names at the level of half-staves (SPD) or ladders (SDD and SSD)
898     //
899     TString name(GetSymbName(layer));
900     if (layer==0) { // SPD1
901
902         int sector = ladd/2;
903         name += fStrSector;
904         name += sector;
905         int stave = ladd-sector*2;
906         name += fStrStave;
907         name += stave;
908         name += fStrHalfStave;
909         name += halfStave;
910     }
911     else if (layer==1) { // SPD2
912
913         int sector = ladd/4;
914         name += fStrSector;
915         name += sector;
916         int stave = ladd-sector*4;
917         name += fStrStave;
918         name += stave;
919         name += fStrHalfStave;
920         name += halfStave;
921     }
922     else if (layer>=2 && layer<=5) { // SDD and SSD
923         name += fStrLadder;
924         name += ladd;
925     } 
926     else {
927         AliFatal("Wrong layer index");
928     }
929     return name.Data();
930 }
931
932 //________________________________________________________________________
933 const char* AliITSMisAligner::GetParentSymName(const char* symname) {
934     //
935     // symnane of parent volume
936     //
937     TString parent(symname);
938     // Give the symname of 
939     if(parent.BeginsWith('/')) parent.Remove(TString::kLeading,'/');
940     if(parent.EndsWith("/")) parent.Remove(TString::kTrailing,'/');
941
942     if(!parent.CountChar('/')) AliErrorClass("Not a valid symbolic name");
943
944     Int_t layer,level;
945     GetLayerAndLevel(symname,layer,level);
946     if(level==1) return "ITS";
947
948     parent.Remove(parent.Last('/'));
949
950     if((layer==0 || layer==1) && level==2){
951         parent.Remove(parent.Last('/'));
952         parent[7]='0';
953     }
954
955     return parent.Data(); 
956 }
957
958 //________________________________________________________________________
959 Bool_t AliITSMisAligner::GetLayerAndLevel(const char* symname, Int_t &layer, Int_t &level) {
960     //
961     // given the symbolic name set layer and level
962     //
963     const char* basename[6] = {"ITS/SPD0/Sector","ITS/SPD1/Sector","ITS/SDD2/Ladder","ITS/SDD3/Ladder","ITS/SSD4/Ladder","ITS/SSD5/Ladder"};
964     TString strSym(symname);
965     if(strSym=="ITS"){
966         level=0;
967         layer=-1;
968         return kTRUE;
969     }
970     Int_t i;
971     for(i=0; i<6; i++){
972         if(strSym.BeginsWith(basename[i])) break;
973     }
974
975     if(i>=6){
976         AliErrorClass(Form("%s is not a valid symbolic name for an ITS alignable volume",strSym.Data()));
977         return kFALSE;
978     }
979
980     layer=i;
981     //The part above could be replaced by just
982     // TString seventh = strSym[7];
983     // layer = seventh.Atoi();
984     // if we don't need to check the validity of the symname
985
986     level=1;
987     switch(layer){
988         case 0:
989         case 1:
990             if(strSym.Contains("Stave")) level=2;
991             if(strSym.Contains("Ladder")) level=3;
992             break;
993         case 2:
994         case 3:
995         case 4:
996         case 5:
997             if(strSym.Contains("Sensor")) level=2;
998     }
999
1000     return kTRUE;
1001 }
1002
1003 //________________________________________________________________________
1004 Int_t AliITSMisAligner::GetNSisters(const char* symname) {
1005     //
1006     // number of volumes on same level
1007     //
1008     Int_t layer,level;
1009     if(!GetLayerAndLevel(symname,layer,level)) return -1;
1010     if(level==0) return -1;
1011     if(level==1) return GetNLadders(layer);
1012     if(level==2) return GetNDetectors(layer);
1013     AliErrorClass(Form("Invalid layer and level"));
1014     return -1;
1015 }
1016
1017 //________________________________________________________________________
1018 Int_t AliITSMisAligner::GetNDaughters(const char* symname) {
1019     //
1020     // number of daughter volumes
1021     // 
1022     Int_t layer,level;
1023     if(!GetLayerAndLevel(symname,layer,level)) return -1;
1024     if(level==0) {
1025         Int_t nLadders = 0;
1026         for(Int_t lay=0; lay<6; lay++) nLadders += GetNLadders(lay);
1027         return nLadders;
1028     }
1029     if(level==1) return GetNDetectors(layer);
1030     if(level==2){
1031         AliWarningClass(Form("Volume %s is a sensitive volume and has no alignable dauthers",symname));
1032         return -1;
1033     }
1034     AliErrorClass(Form("Invalid layer and level"));
1035     return -1;
1036 }
1037
1038 /*
1039 //________________________________________________________________________
1040 TString AliITSMisAligner::GetSymbName(Int_t layer,Int_t ladd,Int_t mod) const {
1041
1042 // Get logical names at the level of SPD ladders / SDD and SSD modules
1043
1044 Int_t halfStave = mod/2;
1045 TString name = GetHalfStaveLadderSymbName(layer,ladd,halfStave);
1046
1047 if (layer<2) { // SPD
1048 name += fStrLadder;
1049 name += mod;
1050
1051 else if (layer>=2 && layer<=5) { // SDD and SSD
1052 name += fStrSensor;
1053 name += mod;
1054 }
1055 else {
1056 AliFatal("Wrong layer index");
1057 }
1058 return name;
1059 }
1060 */