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