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