1) Updated default numbers for the reports
[u/mrichter/AliRoot.git] / ITS / AliITSSurveyToAlign.cxx
1 /**************************************************************************
2  * Copyright(c) 2008-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 //   Class to convert survey tables in alignment objects
20 //   for SSD and SDD
21 //   origin: Marco Van Leeuwen (m.vanleeuwen1@uu.nl)
22 //           Panos.Christakoglou (Panos.Christakoglou@cern.ch)
23 //           Martin Poghosyan (Martin.Poghosyan@to.infn.it)
24 //////////////////////////////////////////////////////////////////////////
25
26 #include "Riostream.h"
27 #include "TFile.h"
28 #include "TSystem.h"
29 #include "TClonesArray.h"
30 #include "TGeoManager.h"
31 #include "TGeoMatrix.h"
32 #include "TGeoPhysicalNode.h"
33 #include "TMatrixD.h"
34 #include "TMath.h"
35
36 #include "AliITSSurveyToAlign.h"
37 #include "AliSurveyObj.h"
38 #include "AliSurveyPoint.h"
39 #include "AliAlignObjParams.h"
40 #include "AliGeomManager.h"
41
42 #include "AliLog.h"
43
44 #include "AliCDBManager.h"
45 #include "AliCDBEntry.h"
46 #include "AliCDBStorage.h"
47
48 #include "AliITSgeomTGeo.h"
49
50 ClassImp(AliITSSurveyToAlign)
51
52 const Double_t AliITSSurveyToAlign::fgkLocR[6][3]={{ 3.24,0.21905,-2.4},
53                                                    { 3.58,0.21905, 0. },
54                                                    { 3.24,0.21905,+2.4},
55                                                    {-3.24,0.21905,+2.4},
56                                                    {-3.58,0.21905, 0. },
57                                                    {-3.24,0.21905,-2.4}};
58
59 const Double_t AliITSSurveyToAlign::fgkLocL[6][3]={{-3.24,0.21905, 2.4},
60                                                    {-3.58,0.21905, 0. },
61                                                    {-3.24,0.21905,-2.4},
62                                                    { 3.24,0.21905,-2.4},
63                                                    { 3.58,0.21905, 0. },
64                                                    { 3.24,0.21905, 2.4}};
65
66
67 //________________________________________________________________________
68 AliITSSurveyToAlign::AliITSSurveyToAlign(Int_t run, Int_t repSDD, Int_t repVerSDD, Int_t repModSSD, Int_t repModVerSSD, Int_t repLaddSSD, Int_t repLaddVerSSD) :
69   //TObject(),
70   AliSurveyToAlignObjs(),
71   fRun(run),
72   fSDDrepNumber(repSDD),
73   fSDDrepVersion(repVerSDD),
74   fSSDModuleRepNumber(repModSSD),
75   fSSDModuleRepVersion(repModVerSSD),
76   fSSDLadderRepNumber(repLaddSSD),
77   fSSDLadderRepVersion(repLaddVerSSD)
78  {
79   //
80   //  default constructor
81   //  Arguments are report numbers for survey data. 
82   //  The defaults point to reports from detector construction
83   // 
84 }
85
86 //_________________________________________________________________________
87 AliITSSurveyToAlign::AliITSSurveyToAlign(const AliITSSurveyToAlign &align) :
88   //  TObject(),
89   AliSurveyToAlignObjs(align),
90   fRun(align.fRun),
91   fSDDrepNumber(align.fSDDrepNumber),
92   fSDDrepVersion(align.fSDDrepVersion),
93   fSSDModuleRepNumber(align.fSSDModuleRepNumber),
94   fSSDModuleRepVersion(align.fSSDModuleRepVersion),
95   fSSDLadderRepNumber(align.fSSDLadderRepNumber),
96   fSSDLadderRepVersion(align.fSSDLadderRepVersion)
97 {
98   //
99   //  copy constructor 
100   //
101 }
102
103 //__________________________________________________________________________
104 AliITSSurveyToAlign & AliITSSurveyToAlign::operator =(const AliITSSurveyToAlign& /* align */) {
105   //
106   // assignment operator - dummy
107   //
108
109   return (*this);
110 }
111
112 //__________________________________________________________________________
113 AliITSSurveyToAlign::~AliITSSurveyToAlign() {
114   //
115   // destructor
116   //
117 }
118
119 //______________________________________________________________________
120 void AliITSSurveyToAlign::Run() { 
121   //
122   // Runs the full chain
123   // User should call StoreAlignObjToFile or StoreAlignObjToCDB afterwards to 
124   // store output (not included here to leave the choice between the two)
125   //
126
127   // Load ideal geometry from the OCDB
128   AliCDBManager *cdb = AliCDBManager::Instance();
129   cdb->SetDefaultStorage("local://$ALICE_ROOT/OCDB");
130   cdb->SetRun(fRun);
131   AliGeomManager::LoadGeometry();
132
133   if(!CreateAlignObjs()) AliError("Construction of alignment objects from survey failed!");
134
135
136 //______________________________________________________________________
137 Bool_t AliITSSurveyToAlign::CreateAlignObjs() { 
138   // Fill the array of alignment objects with alignment objects
139   // from surveyfor all three subdetectors
140   //
141
142   //for SPD
143   CreateAlignObjDummySPD();
144
145   // for SDD
146   if(!LoadSurveyFromAlienFile("ITS", fSDDrepNumber, fSDDrepVersion)){
147       AliError("Loading of alignment objects from survey for SDD failed!");
148       return kFALSE;
149   }
150   CreateAlignObjSDD();
151
152   // for SSD ladders
153   if(!LoadSurveyFromAlienFile("ITS", fSSDLadderRepNumber, fSSDLadderRepVersion)){
154       AliError("Loading of alignment objects from survey for SSD ladders failed!");
155       return kFALSE;
156   }
157   CreateAlignObjSSDLadders();
158
159   // for SSD modules
160   if(!ApplyAlignObjSSDLadders()) return kFALSE; // needed to build correctly the objects for SSD modules
161   if(!LoadSurveyFromAlienFile("ITS", fSSDModuleRepNumber, fSSDModuleRepVersion)){
162       AliError("Loading of alignment objects from survey for SSD modules failed!");
163       return kFALSE;
164   }
165   CreateAlignObjSSDModules();
166
167   return kTRUE;
168 }
169
170 //______________________________________________________________________
171 void AliITSSurveyToAlign::CreateAlignObjDummySPD(){
172   // 
173   // Create alignObjs for SPD
174   //    For the moment, uses 0,0,0,0,0,0
175   //
176   for(Int_t imod = 0; imod < 240; imod++) {
177     Int_t ilayer = (imod < 80) ? AliGeomManager::kSPD1 : AliGeomManager::kSPD2;
178     Int_t imodule = (imod < 80) ? imod : imod - 80;
179
180     Int_t uid = AliGeomManager::LayerToVolUID(ilayer,imodule);
181     const Char_t *symname = AliGeomManager::SymName(uid);
182
183     new((*fAlignObjArray)[imod]) AliAlignObjParams(symname, uid, 0., 0., 0., 0., 0., 0., kTRUE);
184   }//module loop
185
186 }
187
188 //______________________________________________________________________
189 void AliITSSurveyToAlign::CreateAlignObjSDD(){
190   //
191   // Create alignment objects for SDD
192   // Called by Run()
193   //
194   Int_t uid = 0;
195   const char* symname = 0;
196   AliSurveyPoint* pt = 0;
197  
198   Int_t iModuleIndex=240;
199   Int_t iModule0=0;
200   Int_t iLadder0=0;
201   Int_t iLayer0=3;
202   Int_t nModules=0;
203
204   if (fSurveyPoints == 0 || fSurveyPoints->GetEntries() == 0) {
205     AliWarning("SDD survey data are not available, using zero values");
206     CreateAlignObjDummySDD();
207     return;
208   }
209
210   for(Int_t imod = 1; imod < fSurveyPoints->GetEntries(); imod++) {
211     pt = (AliSurveyPoint*) fSurveyPoints->At(imod);
212     if(!pt) continue;
213
214     Int_t iLayer, iLadder, iModule, iPoint;
215     ReadPointNameSDD(pt->GetName(),iLayer, iLadder, iModule, iPoint);
216
217     if(iModule==iModule0)
218     {
219       fSDDmeP[iPoint][0]=pt->GetX();
220       fSDDmeP[iPoint][1]=pt->GetY();
221       fSDDmeP[iPoint][2]=pt->GetZ();
222       fSDDmeP[iPoint][3]=pt->GetPrecisionX();
223       fSDDmeP[iPoint][4]=pt->GetPrecisionY();
224       fSDDmeP[iPoint][5]=pt->GetPrecisionZ();
225       fSDDisMe[iPoint]=kTRUE;
226
227       if(iLayer==3) uid = AliGeomManager::LayerToVolUID(iLayer0,iModuleIndex-240);
228       if(iLayer==4) uid = AliGeomManager::LayerToVolUID(iLayer0,iModuleIndex-324);
229       symname = AliGeomManager::SymName(uid);
230       GetIdPosSDD(uid,iLayer0, iModule0, iPoint);
231       nModules++;
232     }
233     //    cout << "Points red module " << imod << endl;
234     if((iModule!=iModule0)||(imod==(fSurveyPoints->GetEntries()-1)))
235     {
236       ConvertToRSofModulesAndRotSDD(iLayer0, iModule0);
237
238       Double_t tet = 0.;
239       Double_t psi =0.;
240       Double_t phi = 0.;
241       Double_t x0  = 0.;
242       Double_t y0  =0.;
243       Double_t z0  = 0.;
244
245       if(nModules==2) CalcShiftSDD(x0,y0,z0);
246       if(nModules>2)   CalcShiftRotSDD(tet, psi, phi, x0, y0, z0);
247       tet*=(180/TMath::Pi());
248       psi*=(180/TMath::Pi());
249       phi*=(180/TMath::Pi());
250
251 //    printf("%s  %d  %f  %f  %f  %f  %f  %f\n",symname, uid, x0/10., y0/10., z0/10., psi, tet, phi);
252 //      cout << "Allocate alignobjparams " << imod << endl;
253       new((*fAlignObjArray)[iModuleIndex]) AliAlignObjParams(symname, uid, x0/10., y0/10., z0/10., psi, tet, phi, kFALSE);
254
255       iModule0=iModule;
256       iLayer0=iLayer;
257       iLadder0=iLadder;
258       nModules=0;
259       iModuleIndex = AliITSgeomTGeo::GetModuleIndex(iLayer,iLadder+1,iModule+1);
260       for(Int_t i=0; i<6;i++) fSDDisMe[i]=kFALSE;
261       if(imod!=(fSurveyPoints->GetEntries()-1)) imod--;
262     }
263   }//module loop
264 }
265
266 //______________________________________________________________________
267 void AliITSSurveyToAlign::CreateAlignObjDummySDD(){
268   // 
269   // Create empty alignment objects
270   // Used when fSurveySDD == 0
271   //
272   for(Int_t imod = 0; imod < 260; imod++) {
273
274     Int_t ilayer = (imod < 84) ? AliGeomManager::kSDD1 : AliGeomManager::kSDD2;
275     Int_t imodule = (imod < 84) ? imod : imod - 84;
276
277     Int_t uid = AliGeomManager::LayerToVolUID(ilayer,imodule);
278     const Char_t *symname = AliGeomManager::SymName(uid);
279
280     new((*fAlignObjArray)[imod+240]) AliAlignObjParams(symname, uid, 0., 0., 0., 0., 0., 0., kTRUE);
281   }//module loop
282 }
283
284 //______________________________________________________________________
285 void AliITSSurveyToAlign::CreateAlignObjSSDModules(){
286   //
287   // Create alignment objects for SSD modules
288   // Objects for SSD ladders must be applied to geometry first
289   //
290   Double_t sx, sz;
291   const Float_t kMu2Cm = 1e-4;
292   const Float_t kSensLength = 7.464;
293   const Int_t kSSDMODULES = 1698;
294
295   if (fSurveyPoints == 0 || fSurveyPoints->GetEntries() == 0) {
296     AliWarning("SSD module survey data not available; using dummy values");
297     CreateAlignObjDummySSDModules();
298     return;
299   }
300
301   // First do module-by-module
302
303   for(Int_t imod = 500; imod < kSSDMODULES + 500; imod++) {
304     Int_t iLayer, iLadder, iLaddMod;
305     AliITSgeomTGeo::GetModuleId(imod,iLayer,iLadder,iLaddMod);  // returns 1-based numbers
306  
307     TString pname="ITS/SSD";
308     pname += iLayer-1;
309     pname += "/Ladder";
310     pname += iLadder-1;
311     pname += "/Sensor";
312     pname += iLaddMod-1;
313     AliSurveyPoint *pt1 = (AliSurveyPoint*) fSurveyPoints->FindObject(pname+"/Point0");
314     AliSurveyPoint *pt2 = (AliSurveyPoint*) fSurveyPoints->FindObject(pname+"/Point1");
315     if(!pt1 || !pt2) {
316       AliWarning(Form("No Survey points for iladd %d imod %d",iLadder,iLaddMod));
317       continue;
318     }
319
320     sx = 0.5*(pt1->GetX() + pt2->GetX()) * kMu2Cm;
321     sz = 0.5*(pt1->GetZ() + pt2->GetZ()) * kMu2Cm;
322
323     // Minus sign to change local coordinate convention 
324     Float_t theta = -(pt2->GetZ() - pt1->GetZ())*kMu2Cm/kSensLength;
325
326     theta *= 180./TMath::Pi();
327     Int_t iLayMod = imod - 500;
328     if (iLayer == 6)
329       iLayMod -= 748;
330     Int_t uid = AliGeomManager::LayerToVolUID(iLayer,iLayMod);
331
332     const Char_t *symname = AliGeomManager::SymName(uid);
333     if (pname.CompareTo(symname) != 0)
334       AliWarning(Form("Mapping mismatch survey point %s volume name %s",pname.Data(),symname));
335     /*
336     if (imod >= 676 && imod <= 697) {
337       cout << "ilayer " << iLayer << " imod " << imod 
338            << " uid " << uid << " name " << symname 
339            << " survey shift " << sx << " " << 0 << " " << sz << endl
340            << " theta " << theta << endl;
341     }
342     */
343     new((*fAlignObjArray)[imod]) AliAlignObjParams(symname, uid, sx, 0, sz, 0., theta, 0., kFALSE);
344   } //module loop
345 }
346
347 //______________________________________________________________________
348 Bool_t AliITSSurveyToAlign::ApplyAlignObjSSDLadders(){
349   //
350   //   Apply alignment objects for SSD ladders to geometry, needed to correctly
351   //   build alignment objects for SSD modules
352   // 
353   TClonesArray* tobeApplied = new TClonesArray("AliAlignObjParams",72);
354   Int_t ii=0;
355   for(Int_t jj=0; jj<fAlignObjArray->GetEntriesFast(); jj++)
356   {
357       AliAlignObjParams* ap = dynamic_cast<AliAlignObjParams*> (fAlignObjArray->UncheckedAt(jj));
358       if(ap) 
359       {
360           TString sName(ap->GetSymName());
361           if(sName.Contains("SSD") && sName.Contains("Ladder"))
362               (*tobeApplied)[ii++] = (AliAlignObjParams*) fAlignObjArray->UncheckedAt(jj);
363       }
364   }
365   AliInfo(Form(" %d alignment objects for SSD ladders applied to geometry.",tobeApplied->GetEntriesFast()));
366
367   return(AliGeomManager::ApplyAlignObjsToGeom(*tobeApplied));
368 }
369
370 //______________________________________________________________________
371 void AliITSSurveyToAlign::CreateAlignObjSSDLadders(){
372   //
373   //   Alignment objects from survey for SSD ladders (Torino data)
374   // 
375   const Float_t kLaddLen5 = 90.27;  // Layer 5: distance between mouting points
376   const Float_t kLaddLen6 = 102.0;  // Layer 6: distance between mouting points
377   const Float_t Z0 = 2.927;         // Distance between V mounting point and Zloc = 0
378                                     // = half ladder length - nom z-position of ladder from gGeoManager
379   const Float_t kMu2Cm = 1e-4;
380
381   TString ssdName = "ITS/SSD";
382
383   TObjArray *ladd_points = fSurveyPoints;  
384   if (ladd_points == 0 || ladd_points->GetEntries() == 0) {
385     AliWarning("No SSD Ladder alignment points found. Skipping");
386     return;
387   }
388   if (ladd_points->GetEntries()!= 2*(34+38)) {
389     AliWarning(Form("Unexpected number of survey points %d, should be 144",ladd_points->GetEntries())); 
390   }
391   Int_t iLadd = 0;
392   for (Int_t ilayer =  4; ilayer <=  5; ilayer ++) {
393     Int_t nLadder = 34; // layer 5
394     if (ilayer == 5)
395       nLadder = 38;     // layer 6
396
397     for (Int_t iLadder = 0; iLadder < nLadder; iLadder++) {
398       TString ladName = ssdName;
399       ladName += ilayer;
400       ladName += "/Ladder";
401       ladName += iLadder;
402
403       AliSurveyPoint *v_point =  (AliSurveyPoint*) ladd_points->FindObject(ladName+"/V");
404       AliSurveyPoint *q_point =  (AliSurveyPoint*) ladd_points->FindObject(ladName+"/Q");
405       if (v_point == 0) {
406         AliWarning(Form("Cannot find V side point for ladder %s",ladName.Data()));
407         continue;
408       }
409       if (q_point == 0) {
410         AliWarning(Form("Cannot find Q side point for ladder %s",ladName.Data()));
411         continue;
412       }
413
414       TString tmp_str;
415       tmp_str.Insert(0,v_point->GetName(),3);
416       Int_t ladder = tmp_str.Atoi();
417       tmp_str="";
418       tmp_str.Insert(0,q_point->GetName(),3);
419       if (tmp_str.Atoi() != ladder) 
420         AliError(Form("Survey data file error. Expect pairs of V,Q points. Got ladders %d %d",ladder,tmp_str.Atoi()));
421
422       // Note: file gives meas-nom in local offline coordinates, 
423       // ie. local z = - global z and local x = - global x (for ladder 508, i.e. top ladder)
424       Double_t dx_loc = v_point->GetX() * kMu2Cm;
425       Double_t dy_loc = v_point->GetY() * kMu2Cm;
426       Double_t dz_loc = v_point->GetZ() * kMu2Cm;
427
428       // rot around z-axis
429       Double_t phi = 0;  // Not measured
430       // rot around y-axis
431       Double_t theta = 0;
432       Double_t psi = 0;
433
434       // Note: local psi = -global psi, psi = atan(-(y(z1) - y(z0)) / (z1-z0))  
435       // local theta = global theta = atan(dx/dz) 
436       // V side is A side is large global z 
437       // Q side is C side is large local z
438
439       if (ladder >= 600) {
440         theta = TMath::ATan((q_point->GetX() - v_point->GetX())*kMu2Cm/kLaddLen6);
441         psi = TMath::ATan((v_point->GetY() - q_point->GetY())*kMu2Cm/kLaddLen6);
442       }
443       else {
444         theta = TMath::ATan((q_point->GetX() - v_point->GetX())*kMu2Cm/kLaddLen5);
445         psi = TMath::ATan((v_point->GetY() - q_point->GetY())*kMu2Cm/kLaddLen5);
446       } 
447
448       // Move along ladder to local Z = 0 point
449       dx_loc += Z0*theta;
450       dy_loc -= Z0*psi;
451
452       // Convert to degrees
453       theta *= 180./TMath::Pi();
454       psi *= 180./TMath::Pi();
455       AliDebug(1,Form("ladname %f %f %f %f %f %f ",dx_loc,dy_loc,dz_loc,psi,theta,phi));  
456       
457       new((*fAlignObjArray)[500+1698+iLadd]) AliAlignObjParams(ladName,0,dx_loc,dy_loc,dz_loc,psi,theta,phi,kFALSE);
458
459       iLadd++;
460     }  // Ladder loop
461   }  // Layer loop
462 }
463
464 //______________________________________________________________________
465 void AliITSSurveyToAlign::CreateAlignObjDummySSDModules(){
466   // 
467   // Create empty alignment objects
468   // Used when fSurveySSD == 0
469   //
470   for(Int_t imod = 0; imod < 1698; imod++) {
471     Int_t ilayer = (imod < 748) ? AliGeomManager::kSSD1 : AliGeomManager::kSSD2;
472     Int_t imodule = (imod < 748) ? imod : imod - 748;
473
474     Int_t uid = AliGeomManager::LayerToVolUID(ilayer,imodule);
475     const Char_t *symname = AliGeomManager::SymName(uid);
476
477     new((*fAlignObjArray)[500+imod]) AliAlignObjParams(symname, uid, 0., 0., 0., 0., 0., 0., kTRUE);
478   }//module loop
479 }
480
481
482 //______________________________________________________________________
483 void AliITSSurveyToAlign::GetIdPosSDD(Int_t uid, Int_t layer, Int_t module, Int_t iPoint)
484 {
485   // 
486   //    Utility function used by CreateAlignObjSDD
487   // 
488   TGeoHMatrix gMod = *AliGeomManager::GetMatrix(uid); //global matrix of sensor
489   TGeoPNEntry* pne = gGeoManager->GetAlignableEntryByUID(uid);
490   // TString ladderPath = AliGeomManager::SymName(uid);
491   TString ladderPath(pne->GetTitle());
492   if(ladderPath.EndsWith("/")) ladderPath.Remove(TString::kTrailing,'/');
493   ladderPath.Remove(ladderPath.Last('/'));
494   ladderPath.Remove(ladderPath.Last('/'));
495   gGeoManager->cd(ladderPath.Data());
496   TGeoHMatrix gLad = *gGeoManager->GetCurrentMatrix(); // global matrix of ladder
497   TGeoHMatrix rel = gMod; // to equal relative matrix ladder to sensor.
498   TGeoHMatrix invgLad = gLad.Inverse();
499   rel.MultiplyLeft(&invgLad);
500   TGeoRotation* rr = new TGeoRotation("rr",90,90,0,0,90,180);
501   TGeoCombiTrans* ct = 0;
502   if(layer==3) ct= new TGeoCombiTrans(25.,0.,0.,rr);
503   if(layer==4) ct= new TGeoCombiTrans(25.+7.5,0.,0.,rr);
504
505   rel.MultiplyLeft(ct);
506   
507   if((layer==3)&&(module<3)) rel.LocalToMaster(fgkLocR[iPoint],fSDDidP[iPoint]);
508   if((layer==3)&&(module>2)) rel.LocalToMaster(fgkLocL[iPoint],fSDDidP[iPoint]);
509   if((layer==4)&&(module<4)) rel.LocalToMaster(fgkLocR[iPoint],fSDDidP[iPoint]);
510   if((layer==4)&&(module>3)) rel.LocalToMaster(fgkLocL[iPoint],fSDDidP[iPoint]);
511
512   for(Int_t i=0; i<3; i++) fSDDidP[iPoint][i]*=10;
513
514 }
515
516 //______________________________________________________________________
517 void AliITSSurveyToAlign::ReadPointNameSDD(const char str[], Int_t &iLayer, Int_t &iLader, Int_t &iModul, Int_t &iPoint)
518 {
519   // 
520   //    Utility function used by CreateAlignObjSDD
521   // 
522   iLayer=-1;
523   iLader=-1;
524   iModul=-1;
525   iPoint=-1;
526
527   if(str[7]=='2') iLayer=3;
528   if(str[7]=='3') iLayer=4;
529
530   if(str[15]=='0') iLader=0;
531   if(str[15]=='1') iLader=1;
532   if(str[15]=='2') iLader=2;
533   if(str[15]=='3') iLader=3;
534   if(str[15]=='4') iLader=4;
535   if(str[15]=='5') iLader=5;
536   if(str[15]=='6') iLader=6;
537   if(str[15]=='7') iLader=7;
538   if(str[15]=='8') iLader=8;
539   if(str[15]=='9') iLader=9;
540
541   Int_t ord=0;
542   if(str[16]=='0') {iLader=10*iLader+0; ord=1;}
543   if(str[16]=='1') {iLader=10*iLader+1; ord=1;}
544   if(str[16]=='2') {iLader=10*iLader+2; ord=1;}
545   if(str[16]=='3') {iLader=10*iLader+3; ord=1;}
546   if(str[16]=='4') {iLader=10*iLader+4; ord=1;}
547   if(str[16]=='5') {iLader=10*iLader+5; ord=1;}
548   if(str[16]=='6') {iLader=10*iLader+6; ord=1;}
549   if(str[16]=='7') {iLader=10*iLader+7; ord=1;}
550   if(str[16]=='8') {iLader=10*iLader+8; ord=1;}
551   if(str[16]=='9') {iLader=10*iLader+9; ord=1;}
552
553   if(str[23+ord]=='0') iModul=0;
554   if(str[23+ord]=='1') iModul=1;
555   if(str[23+ord]=='2') iModul=2;
556   if(str[23+ord]=='3') iModul=3;
557   if(str[23+ord]=='4') iModul=4;
558   if(str[23+ord]=='5') iModul=5;
559   if(str[23+ord]=='6') iModul=6;
560   if(str[23+ord]=='7') iModul=7;
561   if(str[23+ord]=='8') iModul=8;
562   if(str[23+ord]=='9') iModul=9;
563
564   if((str[25+ord]=='R')&&(str[26+ord]=='D')) iPoint=0;
565   if((str[25+ord]=='R')&&(str[26+ord]=='C')) iPoint=1;
566   if((str[25+ord]=='R')&&(str[26+ord]=='U')) iPoint=2;
567   if((str[25+ord]=='L')&&(str[26+ord]=='U')) iPoint=3;
568   if((str[25+ord]=='L')&&(str[26+ord]=='C')) iPoint=4;
569   if((str[25+ord]=='L')&&(str[26+ord]=='D')) iPoint=5;
570   return;
571 }
572
573
574 //______________________________________________________________________
575 void AliITSSurveyToAlign::ConvertToRSofModulesAndRotSDD(Int_t Layer, Int_t Module)
576 {
577   // 
578   //    Utility function used by CreateAlignObjSDD
579   // 
580
581   Double_t YmId;
582   Double_t ZmId;
583
584   Double_t YmMe;
585   Double_t ZmMe;
586   Double_t YmMeE;
587   Double_t ZmMeE;
588
589   Double_t x0=fSDDidP[1][0];
590   Double_t z0=fSDDidP[1][2]-0.52;
591   for(Int_t i=0; i<6; i++)
592     {
593       fSDDidP[i][2]-=0.52;
594
595       if(!fSDDisMe[i]) continue; 
596
597       fSDDidP[i][0]-=x0;
598       fSDDidP[i][2]-=z0;
599       fSDDmeP[i][0]-=x0;
600       fSDDmeP[i][2]-=z0;
601                                 
602       YmId=fSDDidP[i][1];
603       ZmId=fSDDidP[i][2];
604                         
605       fSDDidP[i][2]=fSDDidP[i][0];
606       fSDDidP[i][0]=YmId;
607       fSDDidP[i][1]=ZmId;
608                         
609       YmMe=fSDDmeP[i][1];
610       ZmMe=fSDDmeP[i][2];
611                         
612       YmMeE=fSDDmeP[i][4];
613       ZmMeE=fSDDmeP[i][5];
614                         
615       fSDDmeP[i][2]=fSDDmeP[i][0];
616       fSDDmeP[i][0]=YmMe;
617       fSDDmeP[i][1]=ZmMe;
618       fSDDmeP[i][5]=fSDDmeP[i][3];
619       fSDDmeP[i][3]=YmMeE;
620       fSDDmeP[i][4]=ZmMeE;
621                         
622
623       if(((Layer==3)&&(Module>2))||((Layer==4)&&(Module>3)))
624         {
625           fSDDidP[i][0]*=(-1);
626           fSDDidP[i][2]*=(-1);
627           fSDDmeP[i][0]*=(-1);
628           fSDDmeP[i][2]*=(-1);
629         }
630     }   
631 }
632
633
634 //______________________________________________________________________
635 void AliITSSurveyToAlign::CalcShiftSDD(Double_t &x0,Double_t &y0,Double_t &z0)
636 {
637   Double_t Xid, Yid, Zid;
638   Double_t Xme, Yme, Zme, sX2, sY2, sZ2;
639   Double_t aX=0., bX=0.;
640   Double_t aY=0., bY=0.;
641   Double_t aZ=0., bZ=0.;
642   for(Int_t iP1=0; iP1<6; iP1++)
643     {
644       if(!fSDDisMe[iP1]) continue;
645       Xid=fSDDidP[iP1][0];
646       Yid=fSDDidP[iP1][1];
647       Zid=fSDDidP[iP1][2];
648       Xme=fSDDmeP[iP1][0];
649       Yme=fSDDmeP[iP1][1];
650       Zme=fSDDmeP[iP1][2];
651       sX2 =fSDDmeP[iP1][3]*fSDDmeP[iP1][3];
652       sY2 =fSDDmeP[iP1][4]*fSDDmeP[iP1][4];
653       sZ2 =fSDDmeP[iP1][5]*fSDDmeP[iP1][5];
654       aX+=(1./sX2);
655       bX+=((Xme-Xid)/sX2); 
656       aY+=(1./sY2);
657       bY+=((Yme-Yid)/sY2); 
658       aZ+=(1./sZ2);
659       bZ+=((Zme-Zid)/sZ2); 
660     }
661   Double_t x1 = bX/aX;
662   Double_t x2 = bY/aY;
663   Double_t x3 = bZ/aZ;
664   x0=x1;
665   y0=x2;
666   z0=x3;
667   return;
668 }
669
670
671 //______________________________________________________________________
672 void AliITSSurveyToAlign::CalcShiftRotSDD(Double_t &tet,Double_t &psi,Double_t &phi,Double_t &x0,Double_t &y0,Double_t &z0)
673 {
674   TMatrixD p1(6,6);
675   TMatrixD p2(6,6);
676   TMatrixD p3(6,6);
677   TMatrixD p4(6,6);
678   TMatrixD p5(6,6);
679   TMatrixD p6(6,6);
680   TMatrixD pC(6,6);
681
682   Double_t a11 =0.;
683   Double_t a12 =0.;
684   Double_t a13 =0.;
685   Double_t a14 =0.;
686   Double_t a15 =0.;
687   Double_t a16 =0.;
688
689   Double_t a21 =0.;
690   Double_t a22 =0.;
691   Double_t a23 =0.;
692   Double_t a24 =0.;
693   Double_t a25 =0.;
694   Double_t a26 =0.;
695
696   Double_t a31 =0.;
697   Double_t a32 =0.;
698   Double_t a33 =0.;
699   Double_t a34 =0.;
700   Double_t a35 =0.;
701   Double_t a36 =0.;
702
703   Double_t a41 =0.;
704   Double_t a42 =0.;
705   Double_t a43 =0.;
706   Double_t a44 =0.;
707   Double_t a45 =0.;
708   Double_t a46 =0.;
709
710   Double_t a51 =0.;
711   Double_t a52 =0.;
712   Double_t a53 =0.;
713   Double_t a54 =0.;
714   Double_t a55 =0.;
715   Double_t a56 =0.;
716
717   Double_t a61 =0.;
718   Double_t a62 =0.;
719   Double_t a63 =0.;
720   Double_t a64 =0.;
721   Double_t a65 =0.;
722   Double_t a66 =0.;
723
724   Double_t c1 =0.;
725   Double_t c2 =0.;
726   Double_t c3 =0.;
727   Double_t c4 =0.;
728   Double_t c5 =0.;
729   Double_t c6 =0.;
730
731   Double_t Xid, Yid, Zid;
732   Double_t Xme, Yme, Zme, sX2, sY2, sZ2;
733
734   for(Int_t iP1=0; iP1<=6; iP1++)
735     {
736       if(!fSDDisMe[iP1]) continue;
737
738       Xid= fSDDidP[iP1][0];
739       Yid= fSDDidP[iP1][1];
740       Zid= fSDDidP[iP1][2];
741
742       Xme= fSDDmeP[iP1][0];
743       Yme= fSDDmeP[iP1][1];
744       Zme= fSDDmeP[iP1][2];
745
746       sX2 = fSDDmeP[iP1][3]* fSDDmeP[iP1][3];
747       sY2 = fSDDmeP[iP1][4]* fSDDmeP[iP1][4];
748       sZ2 = fSDDmeP[iP1][5]* fSDDmeP[iP1][5];
749
750       a11+=(Zid*Zid/sX2+Xid*Xid/sZ2);
751       a12-=(Zid*Yid/sX2);
752       a13-=(Xid*Yid/sZ2);
753       a14-=(Zid/sX2);
754       a15 =0.;
755       a16+=(Xid/sZ2);
756       c1+=(Xid*(Zme-Zid)/sZ2-Zid*(Xme-Xid)/sX2); 
757
758       a21-=(Yid*Zid/sX2);
759       a22+=(Xid*Xid/sY2+Yid*Yid/sX2);
760       a23-=(Xid*Zid/sY2);
761       a24+=(Yid/sX2);
762       a25-=(Xid/sY2);
763       a26 =0.;
764       c2+=(Yid*(Xme-Xid)/sX2-Xid*(Yme-Yid)/sY2); 
765
766       a31-=(Yid*Xid/sZ2);
767       a32-=(Xid*Zid/sY2);
768       a33+=(Zid*Zid/sY2+Yid*Yid/sZ2);
769       a34 =0.;
770       a35+=(Zid/sY2);
771       a36-=(Yid/sZ2);
772       c3+=(Zid*(Yme-Yid)/sY2-Yid*(Zme-Zid)/sZ2); 
773
774       a41-=(Zid/sX2);
775       a42+=(Yid/sX2);
776       a43 =0.;
777       a44+=(1./sX2);
778       a45 =0.;
779       a46 =0.;
780       c4+=((Xme-Xid)/sX2); 
781
782       a51 =0.;
783       a52-=(Xid/sY2);
784       a53+=(Zid/sY2);
785       a54 =0.;
786       a55+=(1./sY2);
787       a56 =0.;
788       c5+=((Yme-Yid)/sY2); 
789
790       a61+=(Xid/sZ2);
791       a62 =0.;
792       a63-=(Yid/sZ2);
793       a64 =0.;
794       a65 =0.;
795       a66+=(1./sZ2);
796       c6+=((Zme-Zid)/sZ2); 
797     }
798
799   ///////////////////////////////////////////////////////////////
800
801   Double_t dataC[]={a11, a12, a13, a14, a15, a16, a21, a22, a23, a24, a25, a26,
802                     a31, a32, a33, a34, a35, a36, a41, a42, a43, a44, a45, a46,
803                     a51, a52, a53, a54, a55, a56, a61, a62, a63, a64, a65, a66};
804   Double_t data1[]={c1, a12, a13, a14, a15, a16, c2, a22, a23, a24, a25, a26,
805                     c3, a32, a33, a34, a35, a36, c4, a42, a43, a44, a45, a46,
806                     c5, a52, a53, a54, a55, a56, c6, a62, a63, a64, a65, a66};
807   Double_t data2[]={a11, c1, a13, a14, a15, a16, a21, c2, a23, a24, a25, a26,
808                     a31, c3, a33, a34, a35, a36, a41, c4, a43, a44, a45, a46,
809                     a51, c5, a53, a54, a55, a56, a61, c6, a63, a64, a65, a66};
810   Double_t data3[]={a11, a12, c1, a14, a15, a16, a21, a22, c2, a24, a25, a26,
811                     a31, a32, c3, a34, a35, a36, a41, a42, c4, a44, a45, a46,
812                     a51, a52, c5, a54, a55, a56, a61, a62, c6, a64, a65, a66};
813   Double_t data4[]={a11, a12, a13, c1, a15, a16, a21, a22, a23, c2, a25, a26,
814                     a31, a32, a33, c3, a35, a36, a41, a42, a43, c4, a45, a46,
815                     a51, a52, a53, c5, a55, a56, a61, a62, a63, c6, a65, a66};
816   Double_t data5[]={a11, a12, a13, a14, c1, a16, a21, a22, a23, a24, c2, a26,
817                     a31, a32, a33, a34, c3, a36, a41, a42, a43, a44, c4, a46,
818                     a51, a52, a53, a54, c5, a56, a61, a62, a63, a64, c6, a66};
819   Double_t data6[]={a11, a12, a13, a14, a15, c1, a21, a22, a23, a24, a25, c2,
820                     a31, a32, a33, a34, a35, c3, a41, a42, a43, a44, a45, c4,
821                     a51, a52, a53, a54, a55, c5, a61, a62, a63, a64, a65, c6};
822
823   p1.SetMatrixArray(data1);
824   p2.SetMatrixArray(data2);
825   p3.SetMatrixArray(data3);
826   p4.SetMatrixArray(data4);
827   p5.SetMatrixArray(data5);
828   p6.SetMatrixArray(data6);
829   pC.SetMatrixArray(dataC);
830
831   // cout << "calculating determinants" << endl;
832   Double_t det0=pC.Determinant();
833   Double_t x1 = p1.Determinant()/det0;
834   Double_t x2 = p2.Determinant()/det0;
835   Double_t x3 = p3.Determinant()/det0;
836   Double_t x4 = p4.Determinant()/det0;
837   Double_t x5 = p5.Determinant()/det0;
838   Double_t x6 = p6.Determinant()/det0;
839   //cout << "calculating determinants done" << endl;
840   if (x1 == 0) {
841     AliInfo("p1 singular ");
842     p1.Print();
843   }
844   if (x2 == 0) {
845     AliInfo("p2 singular ");
846     p2.Print();
847   }
848   if (x3 == 0) {
849     AliInfo("p3 singular ");
850     p3.Print();
851   }
852   if (x4 == 0) {
853     AliInfo("p4 singular ");
854     p4.Print();
855   }
856   if (x5 == 0) {
857     AliInfo("p5 singular ");
858     p5.Print();
859   }
860   if (x6 == 0) {
861     AliInfo("p6 singular ");
862     p6.Print();
863   }
864
865
866   tet=x1;
867   psi=x2;
868   phi=x3;
869   x0=x4;
870   y0=x5;
871   z0=x6;
872   return;
873 }
874
875