]> git.uio.no Git - u/mrichter/AliRoot.git/blob - ITS/AliITSAlignMille2Module.cxx
Added in ITS upgrade -
[u/mrichter/AliRoot.git] / ITS / AliITSAlignMille2Module.cxx
1 /************************************************************************** \r
2  * Copyright(c) 2007-2009, ALICE Experiment at CERN, All rights reserved. * \r
3  *                                                                        * \r
4  * Author: The ALICE Off-line Project.                                    * \r
5  * Contributors are mentioned in the code where appropriate.              * \r
6  *                                                                        * \r
7  * Permission to use, copy, modify and distribute this software and its   * \r
8  * documentation strictly for non-commercial purposes is hereby granted   * \r
9  * without fee, provided that the above copyright notice appears in all   * \r
10  * copies and that both the copyright notice and this permission notice   * \r
11  * appear in the supporting documentation. The authors make no claims     * \r
12  * about the suitability of this software for any purpose. It is          * \r
13  * provided "as is" without express or implied warranty.                  * \r
14  **************************************************************************/ \r
15  \r
16 /* $Id$    */ \r
17 //----------------------------------------------------------------------------- \r
18 /// \class AliITSAlignMille2Module\r
19 /// Alignment class for the ALICE ITS detector \r
20 /// \r
21 /// This class is used by AliITSAlignMille to build custom supermodules    \r
22 /// made of ITS sensitive modules. These supermodules are then aligned\r
23 /// \r
24 /// Custom supermodules must have VolumeID > 14335\r
25 ///\r
26 /// \author M. Lunardon  \r
27 //----------------------------------------------------------------------------- \r
28  \r
29 #include <TGeoManager.h> \r
30 #include <TGeoMatrix.h> \r
31  \r
32 #include "AliITSAlignMille2Module.h" \r
33 #include "AliITSgeomTGeo.h" \r
34 #include "AliGeomManager.h" \r
35 #include "AliAlignObjParams.h" \r
36 #include "AliLog.h" \r
37 #include "AliITSAlignMille2.h"\r
38  \r
39 /// \cond CLASSIMP \r
40 ClassImp(AliITSAlignMille2Module) \r
41 /// \endcond \r
42 \r
43 #define CORHW_\r
44 \r
45 AliAlignObjParams AliITSAlignMille2Module::fgTempAlignObj;\r
46 const Float_t AliITSAlignMille2Module::fgkDummyConstraint = 1e-2;//1.E3;\r
47     \r
48 //-------------------------------------------------------------\r
49 AliITSAlignMille2Module::AliITSAlignMille2Module() : \r
50   TNamed(), \r
51   fNSensVol(0), \r
52   fIndex(-1),  \r
53   fDetType(-1),\r
54   fVolumeID(0),\r
55   fNParTot(0),\r
56   fNParFree(0),\r
57   fParOffs(0),\r
58   fNProcPoints(0),\r
59   fParVals(0),\r
60   fParErrs(0),\r
61   fParCstr(0),\r
62   fSensVolIndex(0),\r
63   fSensVolVolumeID(0),\r
64   fMatrix(NULL),\r
65   fSensVolMatrix(NULL),\r
66   fSensVolModifMatrix(NULL),\r
67   fParent(NULL),\r
68   fChildren(0)\r
69\r
70   /// void constructor  \r
71   fMatrix = new TGeoHMatrix; \r
72   fSensVolMatrix = new TGeoHMatrix; \r
73   fSensVolModifMatrix = new TGeoHMatrix; \r
74   fSensVolIndex.Set(1);\r
75   fSensVolVolumeID.Set(1);\r
76   fSigmaFactor[0]=fSigmaFactor[1]=fSigmaFactor[2]=1.0;\r
77\r
78 \r
79 //-------------------------------------------------------------\r
80 AliITSAlignMille2Module::AliITSAlignMille2Module(Int_t index, UShort_t volid, const char* symname,\r
81                                                  const TGeoHMatrix *m, Int_t nsv, const UShort_t *volidsv) : \r
82   TNamed(), \r
83   fNSensVol(0), \r
84   fIndex(-1),  \r
85   fDetType(-1),  \r
86   fVolumeID(0),\r
87   fNParTot(0),\r
88   fNParFree(0),\r
89   fParOffs(kMaxParGeom),\r
90   fNProcPoints(0),\r
91   fParVals(0),\r
92   fParErrs(0),\r
93   fParCstr(0),\r
94   fSensVolIndex(0),\r
95   fSensVolVolumeID(0),  \r
96   fMatrix(NULL),\r
97   fSensVolMatrix(NULL),\r
98   fSensVolModifMatrix(NULL),\r
99   fParent(NULL),\r
100   fChildren(0)\r
101\r
102   /// void constructor  \r
103   fMatrix = new TGeoHMatrix; \r
104   fSensVolMatrix = new TGeoHMatrix; \r
105   fSensVolModifMatrix = new TGeoHMatrix; \r
106   fSigmaFactor[0]=fSigmaFactor[1]=fSigmaFactor[2]=1.0;\r
107   for (int i=kMaxParGeom;i--;) fParOffs[i] = -1;\r
108   if (Set(index,volid,symname,m,nsv,volidsv)) {\r
109     AliInfo("Error in AliITSAlignMille2Module::Set() - initializing void supermodule...");\r
110   }\r
111   AssignDetType();\r
112\r
113 \r
114 //-------------------------------------------------------------\r
115 AliITSAlignMille2Module::AliITSAlignMille2Module(UShort_t volid) : \r
116   TNamed(), \r
117   fNSensVol(0), \r
118   fIndex(-1),    \r
119   fDetType(-1),\r
120   fVolumeID(0),\r
121   fNParTot(0),\r
122   fNParFree(0),\r
123   fParOffs(kMaxParGeom),\r
124   fNProcPoints(0),\r
125   fParVals(0),\r
126   fParErrs(0),\r
127   fParCstr(0),  \r
128   fSensVolIndex(0),\r
129   fSensVolVolumeID(0),\r
130   fMatrix(NULL),\r
131   fSensVolMatrix(NULL),\r
132   fSensVolModifMatrix(NULL),\r
133   fParent(NULL),\r
134   fChildren(0)\r
135\r
136   /// simple constructor building a supermodule from a single sensitive volume \r
137   fMatrix = new TGeoHMatrix; \r
138   fSensVolMatrix = new TGeoHMatrix; \r
139   fSensVolModifMatrix = new TGeoHMatrix;   \r
140   // temporary align object, just use the rotation...\r
141   fSensVolIndex.Set(1);\r
142   fSensVolVolumeID.Set(1);\r
143   fSigmaFactor[0]=fSigmaFactor[1]=fSigmaFactor[2]=1.0;\r
144   for (int i=kMaxParGeom;i--;) fParOffs[i] = -1;\r
145   //\r
146   fIndex = GetIndexFromVolumeID(volid);  \r
147   if (fIndex>=0 && gGeoManager) { // good sensitive module and geometry loaded\r
148     SetName(AliGeomManager::SymName(volid));\r
149     fVolumeID = volid;\r
150     AddSensitiveVolume(volid);\r
151     SetSensorsProvided(kTRUE);\r
152     if (SensVolMatrix(volid, fMatrix))\r
153        AliInfo("Matrix not defined");\r
154   }\r
155   else {\r
156     AliInfo("Wrong VolumeID or Geometry not loaded - initializing void supermodule...");\r
157   }\r
158   AssignDetType();\r
159\r
160 \r
161 \r
162 //_____________________________________________________________________________\r
163 AliITSAlignMille2Module::AliITSAlignMille2Module(const AliITSAlignMille2Module &m) :\r
164   TNamed(m),\r
165   fNSensVol(m.fNSensVol),\r
166   fIndex(m.fIndex),  \r
167   fDetType(m.fDetType),\r
168   fVolumeID(m.fVolumeID),\r
169   fNParTot(m.fNParTot),\r
170   fNParFree(m.fNParFree),\r
171   fParOffs(m.fNParTot),\r
172   fNProcPoints(0),\r
173   fParVals(0),\r
174   fParErrs(0),\r
175   fParCstr(0),  \r
176   fSensVolIndex(m.fSensVolIndex),\r
177   fSensVolVolumeID(m.fSensVolVolumeID),\r
178   fMatrix(new TGeoHMatrix(*m.GetMatrix())),\r
179   fSensVolMatrix(new TGeoHMatrix),\r
180   fSensVolModifMatrix(new TGeoHMatrix),\r
181   fParent(m.fParent),\r
182   fChildren(0)\r
183 {\r
184   // Copy constructor\r
185   fSensVolIndex = m.fSensVolIndex;\r
186   fSensVolVolumeID = m.fSensVolVolumeID;\r
187   for (int i=m.fNParTot;i--;) fParOffs[i] = m.fParOffs[i];\r
188   for (int i=3;i--;) fSigmaFactor[i] = m.fSigmaFactor[i];\r
189   if (fNParTot) {\r
190     fParVals = new Float_t[fNParTot];\r
191     fParErrs = new Float_t[fNParTot];\r
192     fParCstr = new Float_t[fNParTot];\r
193     for (int i=fNParTot;i--;) {\r
194       fParVals[i] = m.fParVals[i];\r
195       fParErrs[i] = m.fParErrs[i];\r
196       fParCstr[i] = m.fParCstr[i];\r
197     }\r
198   }\r
199 }\r
200 \r
201 //_____________________________________________________________________________\r
202 AliITSAlignMille2Module& AliITSAlignMille2Module::operator=(const AliITSAlignMille2Module &m)  \r
203 {\r
204   // operator =\r
205   //\r
206   if(this==&m) return *this;\r
207   ((TNamed *)this)->operator=(m);\r
208   //\r
209   fNSensVol=m.fNSensVol;\r
210   fIndex=m.fIndex;\r
211   fDetType = m.fDetType;\r
212   fVolumeID=m.fVolumeID;\r
213   fNParTot  = m.fNParTot;\r
214   fNParFree = m.fNParFree;\r
215   delete[] fParVals; fParVals = 0;\r
216   delete[] fParErrs; fParErrs = 0;\r
217   delete[] fParCstr; fParCstr = 0;\r
218   //\r
219   if (fNParTot) {\r
220     fParVals = new Float_t[fNParTot];\r
221     fParErrs = new Float_t[fNParTot];\r
222     fParCstr = new Float_t[fNParTot];\r
223     for (int i=m.GetNParTot();i--;) {\r
224       fParVals[i] = m.fParVals[i];\r
225       fParErrs[i] = m.fParErrs[i];\r
226       fParCstr[i] = m.fParCstr[i];\r
227     }\r
228   }\r
229   //\r
230   fParOffs.Set(fNParTot);\r
231   for (int i=0;i<fNParTot;i++) fParOffs[i] = m.fParOffs[i];\r
232   for (int i=3;i--;) fSigmaFactor[i] = m.fSigmaFactor[i];\r
233   if (fMatrix) delete fMatrix;\r
234   fMatrix=new TGeoHMatrix(*m.GetMatrix());\r
235   fSensVolIndex = m.fSensVolIndex;\r
236   fSensVolVolumeID = m.fSensVolVolumeID;\r
237   fParent = m.fParent;\r
238   fChildren.Clear();\r
239   for (int i=0;i<m.GetNChildren();i++) fChildren.Add(m.GetChild(i));\r
240   return *this;\r
241 }\r
242 \r
243 \r
244 //-------------------------------------------------------------\r
245 AliITSAlignMille2Module::~AliITSAlignMille2Module() { \r
246   /// Destructor \r
247   delete fMatrix; \r
248   delete fSensVolMatrix; \r
249   delete fSensVolModifMatrix; \r
250   delete[] fParVals;\r
251   delete[] fParErrs;\r
252   delete[] fParCstr;\r
253   fChildren.Clear();\r
254\r
255 \r
256 //-------------------------------------------------------------\r
257 Int_t AliITSAlignMille2Module::Set(Int_t index, UShort_t volid, const char* symname, \r
258                                    const TGeoHMatrix *m, Int_t nsv, const UShort_t *volidsv) \r
259 {\r
260   // initialize a custom supermodule\r
261   // index, volid, symname and matrix must be given\r
262   // if (volidsv) add nsv sensitive volumes to the supermodules\r
263   // return 0 if success\r
264 \r
265   if (index<2198) {\r
266     AliInfo("Index must be >= 2198");\r
267     return -1;\r
268   }\r
269   if (volid<14336) {\r
270     AliInfo("VolumeID must be >= 14336");\r
271     return -2;\r
272   }\r
273   \r
274   if (!symname) return -3;\r
275   for (Int_t i=0; i<2198; i++) {\r
276     if (!strcmp(symname,AliITSgeomTGeo::GetSymName(i))) {\r
277       AliInfo("Symname already used by a Sensitive Volume");\r
278       return -3;\r
279     }\r
280   }\r
281   \r
282   if (!m) return -4;\r
283 \r
284   // can initialize needed stuffs\r
285   fIndex = index;\r
286   fVolumeID = volid;\r
287   SetName(symname);\r
288   //\r
289   (*fMatrix) = (*m);\r
290   //\r
291   fSensVolIndex.Set(nsv);\r
292   fSensVolVolumeID.Set(nsv);\r
293   // add sensitive volumes\r
294   for (Int_t i=0; i<nsv; i++) AddSensitiveVolume(volidsv[i]);\r
295 \r
296   return 0;\r
297 }\r
298 \r
299 //-------------------------------------------------------------\r
300 void AliITSAlignMille2Module::SetFreeDOF(Int_t dof,Double_t cstr)\r
301 {\r
302   if (AliITSAlignMille2::IsZero(cstr)) fParCstr[dof] = 0;  // fixed parameter\r
303   else if (cstr>0)                     fParCstr[dof] = fgkDummyConstraint+1.; // the parameter is free and unconstrained\r
304   else                                 fParCstr[dof] = -cstr;                 // the parameter is free but constrained\r
305 }\r
306 \r
307 //-------------------------------------------------------------\r
308 Bool_t AliITSAlignMille2Module::IsSensor(UShort_t voluid) \r
309 {\r
310   // Does this volid correspond to sensor ?\r
311   AliGeomManager::ELayerID layId = AliGeomManager::VolUIDToLayerSafe(voluid);\r
312   if (layId>0 && layId<7) {\r
313     Int_t mId = Int_t(voluid & 0x7ff);\r
314     if( mId>=0 && mId<AliGeomManager::LayerSize(layId)) return kTRUE;\r
315   }\r
316   return kFALSE;\r
317 }\r
318 \r
319 //-------------------------------------------------------------\r
320 Int_t AliITSAlignMille2Module::GetIndexFromVolumeID(UShort_t voluid) {\r
321   /// index from volume ID\r
322   AliGeomManager::ELayerID lay = AliGeomManager::VolUIDToLayer(voluid);\r
323   if (lay<1|| lay>6) return -1;\r
324   Int_t idx=Int_t(voluid)-2048*lay;\r
325   if (idx>=AliGeomManager::LayerSize(lay)) return -1;\r
326   for (Int_t ilay=1; ilay<lay; ilay++) \r
327     idx += AliGeomManager::LayerSize(ilay);\r
328   return idx;\r
329 }\r
330 \r
331 //-------------------------------------------------------------\r
332 void AliITSAlignMille2Module::AddSensitiveVolume(UShort_t voluid)\r
333 {\r
334   /// add a sensitive volume to this supermodule\r
335   if (GetIndexFromVolumeID(voluid)<0) return; // bad volid\r
336   //\r
337   // in principle, the correct size of fSensVol... arrays was set outside but check anyway\r
338   if (fSensVolVolumeID.GetSize()<fNSensVol+1) {\r
339     fSensVolVolumeID.Set(fNSensVol+1);\r
340     fSensVolIndex.Set(fNSensVol+1);\r
341   }\r
342   //\r
343   fSensVolVolumeID[fNSensVol] = Short_t(voluid);\r
344   fSensVolIndex[fNSensVol] = GetIndexFromVolumeID(voluid);\r
345   fNSensVol++;\r
346 }\r
347 \r
348 //-------------------------------------------------------------\r
349 void AliITSAlignMille2Module::DelSensitiveVolume(Int_t at)\r
350 {\r
351   // Suppress sensor at position "at"\r
352   // in fact we are swapping with the last valid one \r
353   int lastValid = --fNSensVol;\r
354   int tmpv = fSensVolIndex[at];\r
355   fSensVolIndex[at] = fSensVolIndex[lastValid];\r
356   tmpv = fSensVolVolumeID[at];\r
357   fSensVolVolumeID[at] = fSensVolVolumeID[lastValid];\r
358   fSensVolVolumeID[lastValid] = tmpv;\r
359   //\r
360 }\r
361 \r
362 //-------------------------------------------------------------\r
363 Bool_t AliITSAlignMille2Module::IsIn(UShort_t voluid) const \r
364 {\r
365   /// check if voluid is defined\r
366   if (!voluid) return kFALSE; // only positive voluid are accepted\r
367   for (Int_t i=0; i<fNSensVol; i++) if (UShort_t(fSensVolVolumeID[i])==voluid) return kTRUE;\r
368   return kFALSE;\r
369 }\r
370 \r
371 //-------------------------------------------------------------\r
372 Bool_t AliITSAlignMille2Module::BelongsTo(AliITSAlignMille2Module* parent) const\r
373 {\r
374   /// check if parent contains the sensors of this volume\r
375   if (fNSensVol<1 || fNSensVol>=parent->GetNSensitiveVolumes()) return kFALSE;\r
376   return parent->IsIn( fSensVolVolumeID[0] );\r
377 }\r
378 \r
379 //-------------------------------------------------------------\r
380 TGeoHMatrix *AliITSAlignMille2Module::GetSensitiveVolumeModifiedMatrix(UShort_t voluid, Double_t *delta,Bool_t local)\r
381 {\r
382   // modify the original TGeoHMatrix of the sensitive module 'voluid' according\r
383   // with a delta transform. applied to the supermodule matrix\r
384   // return NULL if error\r
385 \r
386   if (!IsIn(voluid)) return NULL;\r
387   if (!gGeoManager)  return NULL;\r
388 \r
389   // prepare the TGeoHMatrix\r
390   Double_t tr[3],ang[3];\r
391   tr[0]=delta[0]; // in centimeter\r
392   tr[1]=delta[1]; \r
393   tr[2]=delta[2];\r
394   ang[0]=delta[3]; // psi   (X)  in deg\r
395   ang[1]=delta[4]; // theta (Y)\r
396   ang[2]=delta[5]; // phi   (Z)\r
397   //\r
398   fgTempAlignObj.SetRotation(ang[0],ang[1],ang[2]);\r
399   fgTempAlignObj.SetTranslation(tr[0],tr[1],tr[2]);\r
400   AliDebug(3,Form("Delta angles: psi=%f  theta=%f   phi=%f",ang[0],ang[1],ang[2]));\r
401   TGeoHMatrix hm;\r
402   fgTempAlignObj.GetMatrix(hm);\r
403   //printf("\n0: delta matrix\n");hm.Print();\r
404 \r
405   // 1) start setting fSensVolModif = fSensVol\r
406   if (SensVolMatrix(voluid, fSensVolModifMatrix)) return NULL;\r
407   //\r
408   if (local) {\r
409     // 2) set fSensVolModif = SensVolRel\r
410     fSensVolModifMatrix->MultiplyLeft( &fMatrix->Inverse() );\r
411     // 3) multiply left by delta\r
412     fSensVolModifMatrix->MultiplyLeft( &hm );\r
413     // 4) multiply left by fMatrix\r
414     fSensVolModifMatrix->MultiplyLeft( fMatrix );\r
415   }\r
416   else fSensVolModifMatrix->MultiplyLeft( &hm );\r
417   //\r
418   return fSensVolModifMatrix;\r
419 }\r
420 \r
421 //-------------------------------------------------------------\r
422 AliAlignObjParams *AliITSAlignMille2Module::GetSensitiveVolumeMisalignment(UShort_t voluid, Double_t *deltalocal)\r
423 {\r
424   // calculate misalignment of sens.vol. 'voluid' according with a displacement 'deltalocal'\r
425   // of the mother volume. The misalignment is returned as AliAlignObjParams object\r
426 \r
427   if (!IsIn(voluid)) return NULL;\r
428   if (!gGeoManager) return NULL;\r
429   \r
430   // prepare the TGeoHMatrix\r
431   Double_t tr[3],ang[3];\r
432   tr[0]=deltalocal[0]; // in centimeter\r
433   tr[1]=deltalocal[1]; \r
434   tr[2]=deltalocal[2];\r
435   ang[0]=deltalocal[3]; // psi   (X)  in deg\r
436   ang[1]=deltalocal[4]; // theta (Y)\r
437   ang[2]=deltalocal[5]; // phi   (Z)\r
438   //\r
439   fgTempAlignObj.SetRotation(ang[0],ang[1],ang[2]);\r
440   fgTempAlignObj.SetTranslation(tr[0],tr[1],tr[2]);\r
441   AliDebug(3,Form("Delta angles: psi=%f  theta=%f   phi=%f",ang[0],ang[1],ang[2]));\r
442   //\r
443   return GetSensitiveVolumeMisalignment(voluid,&fgTempAlignObj);\r
444 }\r
445 \r
446 //-------------------------------------------------------------\r
447 AliAlignObjParams *AliITSAlignMille2Module::GetSensitiveVolumeMisalignment(UShort_t voluid, AliAlignObjParams *a)\r
448 {\r
449   // return the misalignment of the sens. vol. 'voluid' corresponding with \r
450   // a misalignment 'a' in the mother volume\r
451   // return NULL if error\r
452 \r
453   // Gsv = Gg * Gg-1 * Gsv   -> Lsv,g = Gg-1 * Gsv\r
454   // G'sv = Gg * Dg * Lsv,g === Gsv * Dsv\r
455   // Gg * Dg * Gg-1 * Gsv = Gsv * Gsv-1 * Gg * Dg * Gg-1 * Gsv\r
456   //\r
457   // => Dsv = (Gsv-1 * Gg * Dg * Gg-1 * Gsv)\r
458   //\r
459 \r
460   if (!IsIn(voluid)) return NULL;\r
461   if (!gGeoManager) return NULL;\r
462 \r
463   //a->Print("");\r
464 \r
465   // prepare the Delta matrix Dg\r
466   TGeoHMatrix dg;\r
467   a->GetMatrix(dg);\r
468   //dg.Print();\r
469 \r
470   // 1) start setting fSensVolModif = Gsv\r
471   if (SensVolMatrix(voluid, fSensVolModifMatrix)) return NULL;\r
472   //printf("\n1: modif=orig del sensvol\n");fSensVolModifMatrix->Print();\r
473 \r
474   // 2) set fSensVolModif = Gg-1 * Gsv\r
475   fSensVolModifMatrix->MultiplyLeft( &fMatrix->Inverse() );\r
476   //printf("\n2: modif=relative del sensvol\n");fSensVolModifMatrix->Print();\r
477  \r
478   // 3) set fSensVolModif = Dg * Gg-1 * Gsv\r
479   fSensVolModifMatrix->MultiplyLeft( &dg );\r
480   //printf("\n3: modif= delta*relative\n");fSensVolModifMatrix->Print();\r
481   \r
482   // 4) set fSensVolModif = Gg * Dg * Gg-1 * Gsv\r
483   fSensVolModifMatrix->MultiplyLeft( fMatrix );\r
484   //printf("\n4: modif=quasi,manca il Gsv-1...\n");fSensVolModifMatrix->Print();\r
485 \r
486   // 5) set fSensVolModif = Gsv-1 * Gg * Dg * Gg-1 * Gsv\r
487   if (SensVolMatrix(voluid, &dg)) return NULL;\r
488   fSensVolModifMatrix->MultiplyLeft( &dg.Inverse() );\r
489   //printf("\n5: modif=finale\n");fSensVolModifMatrix->Print();\r
490   //\r
491   // >> RS\r
492  // 6) mo' fSensVolModif dovrebbe essere la Dsv(loc) t.c. G'sv = Gsv*Dsv(loc)\r
493   // per trasformarla in Dsv(loc rispetto al Gsv0, non modificato) dovrebbe essere:\r
494   // Dsv(loc) -> Dpre * Dsv(loc) * Dpre-1\r
495   //TGeoHMatrix dpre; // dpre = Gsv0-1*Gsv\r
496   //if (SensVolOrigGlobalMatrix(voluid, &dg)) return NULL;\r
497   //if (SensVolMatrix(voluid, &dpre)) return NULL;\r
498   //dpre.MultiplyLeft( &dg.Inverse() );\r
499   //fSensVolModifMatrix->Multiply( &dpre.Inverse() );\r
500   //fSensVolModifMatrix->MultiplyLeft( &dpre );\r
501   // direi che NON FUNZIONA!!!!  \r
502 \r
503   // << RS\r
504 \r
505   // reset align object (may not be needed...)\r
506   fgTempAlignObj.SetVolUID(0);\r
507   fgTempAlignObj.SetSymName("");\r
508   fgTempAlignObj.SetTranslation(0,0,0);\r
509   fgTempAlignObj.SetRotation(0,0,0);\r
510   //\r
511   // >> RS\r
512 #ifdef CORHW_\r
513   // correction for SPD y-shift\r
514   if (voluid>=2048 && voluid<4256) {\r
515     TGeoHMatrix deltay;\r
516     double dy[3]={0.,0.0081,0.};\r
517     deltay.SetTranslation(dy);\r
518     fSensVolModifMatrix->MultiplyLeft( &deltay );\r
519     fSensVolModifMatrix->Multiply( &deltay.Inverse() );\r
520   }\r
521 #endif\r
522   // << RS\r
523   if (!fgTempAlignObj.SetMatrix(*fSensVolModifMatrix)) return NULL;\r
524   fgTempAlignObj.SetVolUID(voluid);\r
525   fgTempAlignObj.SetSymName(AliGeomManager::SymName(voluid));\r
526   //\r
527   return &fgTempAlignObj;\r
528 }\r
529 \r
530 // >> RS\r
531 //-------------------------------------------------------------\r
532 AliAlignObjParams *AliITSAlignMille2Module::GetSensitiveVolumeTotalMisalignment(UShort_t voluid, Double_t *deltalocal)\r
533 {\r
534   // calculate misalignment of sens.vol. 'voluid' according with a displacement 'deltalocal'\r
535   // of the mother volume. The misalignment is returned as AliAlignObjParams object including\r
536   // the (evenctual) prealignment => no merging needed\r
537 \r
538   if (!IsIn(voluid)) return NULL;\r
539   if (!gGeoManager) return NULL;\r
540   \r
541   // prepare the TGeoHMatrix\r
542   Double_t tr[3],ang[3];\r
543   tr[0]=deltalocal[0]; // in centimeter\r
544   tr[1]=deltalocal[1]; \r
545   tr[2]=deltalocal[2];\r
546   ang[0]=deltalocal[3]; // psi   (X)  in deg\r
547   ang[1]=deltalocal[4]; // theta (Y)\r
548   ang[2]=deltalocal[5]; // phi   (Z)\r
549 \r
550   // reset align object (may not be needed...)\r
551   fgTempAlignObj.SetVolUID(0);\r
552   fgTempAlignObj.SetSymName("");\r
553   fgTempAlignObj.SetRotation(ang[0],ang[1],ang[2]);\r
554   fgTempAlignObj.SetTranslation(tr[0],tr[1],tr[2]);\r
555   AliDebug(3,Form("Delta angles: psi=%f  theta=%f   phi=%f",ang[0],ang[1],ang[2]));\r
556 \r
557   // Gsv = Gg * Gg-1 * Gsv   -> Lsv,g = Gg-1 * Gsv\r
558   // G'sv = Gg * Dg * Lsv,g === DGsv * Gsv \r
559   //\r
560   // => Dsv = (G0sv-1 * Gg * Dg * Gg-1 * GMsv)  //\r
561   //\r
562 \r
563   // prepare the Delta matrix Dg\r
564   TGeoHMatrix dg;\r
565   fgTempAlignObj.GetMatrix(dg);\r
566   //dg.Print();\r
567 \r
568   // 1) start setting fSensVolModif = Gsv\r
569   if (SensVolMatrix(voluid, fSensVolModifMatrix)) return NULL;\r
570   //printf("\n1: modif=orig del sensvol\n");fSensVolModifMatrix->Print();\r
571 \r
572   // 2) set fSensVolModif = Gg-1 * Gsv\r
573   fSensVolModifMatrix->MultiplyLeft( &fMatrix->Inverse() );\r
574   //printf("\n2: modif=relative del sensvol\n");fSensVolModifMatrix->Print();\r
575  \r
576   // 3) set fSensVolModif = Dg * Gg-1 * Gsv\r
577   fSensVolModifMatrix->MultiplyLeft( &dg );\r
578   //printf("\n3: modif= delta*relative\n");fSensVolModifMatrix->Print();\r
579   \r
580   // 4) set fSensVolModif = Gg * Dg * Gg-1 * Gsv\r
581   fSensVolModifMatrix->MultiplyLeft( fMatrix );\r
582   //printf("\n4: modif=quasi,manca il Gsv-1...\n");fSensVolModifMatrix->Print();\r
583 \r
584   // 5) set fSensVolModif = G0sv-1 * Gg * Dg * Gg-1 * Gsv\r
585   // qui usa l'orig anziche' la prealigned...\r
586   if (SensVolOrigGlobalMatrix(voluid, &dg)) return NULL;\r
587   fSensVolModifMatrix->MultiplyLeft( &dg.Inverse() );\r
588   //printf("\n5: modif=finale\n");fSensVolModifMatrix->Print();\r
589 \r
590   // reset align object (may not be needed...)\r
591   fgTempAlignObj.SetVolUID(0);\r
592   fgTempAlignObj.SetSymName("");\r
593   fgTempAlignObj.SetTranslation(0,0,0);\r
594   fgTempAlignObj.SetRotation(0,0,0);\r
595 \r
596 #ifdef CORHW_\r
597   // correction for SPD y-shift\r
598   if (voluid>=2048 && voluid<4256) {\r
599     TGeoHMatrix deltay;\r
600     double dy[3]={0.,0.0081,0.};\r
601     deltay.SetTranslation(dy);\r
602     fSensVolModifMatrix->MultiplyLeft( &deltay );\r
603     fSensVolModifMatrix->Multiply( &deltay.Inverse() );\r
604   }\r
605 #endif\r
606   if (!fgTempAlignObj.SetMatrix(*fSensVolModifMatrix)) return NULL;\r
607   fgTempAlignObj.SetVolUID(voluid);\r
608   fgTempAlignObj.SetSymName(AliGeomManager::SymName(voluid));\r
609 \r
610   \r
611   //fgTempAlignObj.Print("");\r
612 \r
613   return &fgTempAlignObj;\r
614 }\r
615 //-------------------------------------------------------------\r
616 \r
617 //-------------------------------------------------------------\r
618 AliAlignObjParams *AliITSAlignMille2Module::GetSensitiveVolumeGlobalMisalignment(UShort_t voluid, Double_t *deltalocal)\r
619 {\r
620   // calculate misalignment of sens.vol. 'voluid' according with a displacement 'deltalocal'\r
621   // of the mother volume. The misalignment is returned as AliAlignObjParams object\r
622 \r
623   if (!IsIn(voluid)) return NULL;\r
624   if (!gGeoManager) return NULL;\r
625   \r
626   // prepare the TGeoHMatrix\r
627   Double_t tr[3],ang[3];\r
628   tr[0]=deltalocal[0]; // in centimeter\r
629   tr[1]=deltalocal[1]; \r
630   tr[2]=deltalocal[2];\r
631   ang[0]=deltalocal[3]; // psi   (X)  in deg\r
632   ang[1]=deltalocal[4]; // theta (Y)\r
633   ang[2]=deltalocal[5]; // phi   (Z)\r
634 \r
635   // reset align object (may not be needed...)\r
636   fgTempAlignObj.SetTranslation(0,0,0);\r
637   fgTempAlignObj.SetRotation(0,0,0);\r
638 \r
639   fgTempAlignObj.SetRotation(ang[0],ang[1],ang[2]);\r
640   fgTempAlignObj.SetTranslation(tr[0],tr[1],tr[2]);\r
641   AliDebug(3,Form("Delta angles: psi=%f  theta=%f   phi=%f",ang[0],ang[1],ang[2]));\r
642 \r
643   // Gsv = Gg * Gg-1 * Gsv   -> Lsv,g = Gg-1 * Gsv\r
644   // G'sv = Gg * Dg * Lsv,g === DGsv * Gsv \r
645   //\r
646   // => DGsv = (Gg * Dg * Gg-1)\r
647   //\r
648 \r
649   // prepare the Delta matrix Dg\r
650   TGeoHMatrix dg;\r
651   fgTempAlignObj.GetMatrix(dg);\r
652   //dg.Print();\r
653 \r
654   dg.MultiplyLeft( fMatrix );\r
655   dg.Multiply( &fMatrix->Inverse() );\r
656 \r
657   // reset align object (may not be needed...)\r
658   fgTempAlignObj.SetTranslation(0,0,0);\r
659   fgTempAlignObj.SetRotation(0,0,0);\r
660 \r
661   fgTempAlignObj.SetVolUID(voluid);\r
662   fgTempAlignObj.SetSymName(AliGeomManager::SymName(voluid));\r
663 \r
664   if (!fgTempAlignObj.SetMatrix(dg)) return NULL;\r
665   \r
666   //fgTempAlignObj.Print("");\r
667 \r
668   return &fgTempAlignObj;\r
669 }\r
670 // << RS\r
671 \r
672 //-------------------------------------------------------------\r
673 TGeoHMatrix *AliITSAlignMille2Module::GetSensitiveVolumeMatrix(UShort_t voluid)\r
674 {\r
675   // return TGeoHMatrix of the sens.vol. 'voluid' in the current geometry\r
676   if (SensVolMatrix(voluid,fSensVolMatrix)) return NULL;\r
677   return fSensVolMatrix;\r
678 }\r
679 \r
680 //-------------------------------------------------------------\r
681 TGeoHMatrix *AliITSAlignMille2Module::GetSensitiveVolumeOrigGlobalMatrix(UShort_t voluid)\r
682 {\r
683   // return original ideal position (from AliGeomManager::GetOrigGlobalMatrix())\r
684   if (SensVolOrigGlobalMatrix(voluid,fSensVolMatrix)) return NULL;\r
685   return fSensVolMatrix;\r
686 }\r
687 //-------------------------------------------------------------\r
688 Int_t AliITSAlignMille2Module::SensVolMatrix(UShort_t volid, TGeoHMatrix *m) \r
689 {\r
690   // set matrix for sensitive modules (SPD corrected)\r
691   // return 0 if success\r
692   Double_t rot[9];\r
693   Int_t idx=GetIndexFromVolumeID(volid);\r
694   if (idx<0) return -1;\r
695   if (!AliITSgeomTGeo::GetRotation(idx,rot)) return -2;\r
696   m->SetRotation(rot);\r
697   Double_t oLoc[3]={0,0,0};\r
698   Double_t oGlo[3]={0,0,0};\r
699   if (!AliITSgeomTGeo::LocalToGlobal(idx,oLoc,oGlo)) return -3;\r
700   m->SetTranslation(oGlo);\r
701   return 0;\r
702 }\r
703 \r
704 //-------------------------------------------------------------\r
705 Int_t AliITSAlignMille2Module::SensVolOrigGlobalMatrix(UShort_t volid, TGeoHMatrix *m) \r
706 {\r
707   // set original global matrix for sensitive modules (SPD corrected)\r
708   // return 0 if success\r
709   Int_t idx=GetIndexFromVolumeID(volid);\r
710   if (idx<0) return -1;\r
711   TGeoHMatrix mo;\r
712   if (!AliGeomManager::GetOrigGlobalMatrix(AliGeomManager::SymName(volid),mo)) return -1;\r
713   (*m)=mo;\r
714   //\r
715 #ifdef CORHW_\r
716   // SPD y-shift by 81 mu\r
717   if (volid<5000) { \r
718     Double_t oLoc[3]={0.0,0.0081,0.0};\r
719     Double_t oGlo[3]={0,0,0};\r
720     m->LocalToMaster(oLoc,oGlo);\r
721     m->SetTranslation(oGlo);\r
722   }\r
723 #endif\r
724   return 0;\r
725 }\r
726 \r
727 //-------------------------------------------------------------\r
728 UShort_t AliITSAlignMille2Module::GetVolumeIDFromSymname(const Char_t *symname) {\r
729   /// volume ID from symname\r
730   if (!symname) return 0;\r
731 \r
732   for (UShort_t voluid=2000; voluid<13300; voluid++) {\r
733     Int_t modId;\r
734     AliGeomManager::ELayerID layerId = AliGeomManager::VolUIDToLayer(voluid,modId);\r
735     if (layerId>0 && layerId<7 && modId>=0 && modId<AliGeomManager::LayerSize(layerId)) {\r
736       if (!strcmp(symname,AliGeomManager::SymName(layerId,modId))) return voluid;\r
737     }\r
738   }\r
739 \r
740   return 0;\r
741 }\r
742 \r
743 //-------------------------------------------------------------\r
744 UShort_t AliITSAlignMille2Module::GetVolumeIDFromIndex(Int_t index) {\r
745   /// volume ID from index\r
746   if (index<0 || index>2197) return 0;\r
747   return GetVolumeIDFromSymname(AliITSgeomTGeo::GetSymName(index));\r
748 }\r
749 \r
750 //-------------------------------------------------------------\r
751 void AliITSAlignMille2Module::Print(Option_t*) const \r
752 {\r
753   //\r
754   const char* typeName[] = {"SPD","SDD","SSD"};\r
755   printf("*** ITS SuperModule for AliITSAlignMille ***\n");\r
756   printf("symname  : %s (type: %s)\n",GetName(),fDetType<0 ? "N/A":typeName[fDetType]);\r
757   printf("parent   : %s | %d children\n",fParent ? fParent->GetName() : "N/A",GetNChildren());\r
758   printf("volumeID : %4d  | index : %4d | Geom.Params are %s\n",fVolumeID,fIndex,\r
759          GeomParamsGlobal() ? "Global":"Local");\r
760   printf("Factors  : X=%.2f Y=%.2f Z=%.2f\n"\r
761          "DOF: %cTx:%5d| %cTy:%5d| %cTz:%5d| %cPsi:%5d| %cTheta:%5d| %cPhi:%5d|",\r
762          fSigmaFactor[0],fSigmaFactor[1],fSigmaFactor[2],\r
763          IsFreeDOF(kDOFTX) ? '+':'-',GetParOffset(kDOFTX),IsFreeDOF(kDOFTY) ? '+':'-',GetParOffset(kDOFTY),\r
764          IsFreeDOF(kDOFTZ) ? '+':'-',GetParOffset(kDOFTZ),IsFreeDOF(kDOFPS) ? '+':'-',GetParOffset(kDOFPS),\r
765          IsFreeDOF(kDOFTH) ? '+':'-',GetParOffset(kDOFTH),IsFreeDOF(kDOFPH) ? '+':'-',GetParOffset(kDOFPH));\r
766   if (IsSDD()) {\r
767     printf("%cT0:%5d| %cDVl:%5d| %cDVr:%5d|",IsFreeDOF(kDOFT0)?'+':'-',GetParOffset(kDOFT0),\r
768            IsFreeDOF(kDOFDVL)?'+':'-',GetParOffset(kDOFDVL),IsFreeDOF(kDOFDVR)?'+':'-',GetParOffset(kDOFDVR));\r
769     if (IsVDriftLRSame()) printf("(dVL=dVR)");\r
770   }\r
771   printf("\n");\r
772   fMatrix->Print();\r
773   printf("%4d Sensitive volumes | %6d Processed Points\n",fNSensVol,fNProcPoints);\r
774   for (Int_t i=0; i<fNSensVol; i++) printf("   voluid[%d] = %d\n",i,UShort_t(fSensVolVolumeID[i]));\r
775 }\r
776 \r
777 //-------------------------------------------------------------\r
778 Bool_t AliITSAlignMille2Module::IsAlignable() const\r
779 {\r
780   TGeoManager* geoManager = AliGeomManager::GetGeometry();\r
781   if (!geoManager) {\r
782     AliInfo("Couldn't initialize geometry");\r
783     return kFALSE;\r
784   }\r
785   return geoManager->GetAlignableEntry(GetName())!=0;\r
786 }\r
787 \r
788 //-------------------------------------------------------------\r
789 void AliITSAlignMille2Module::GetLocalMatrix(TGeoHMatrix &mat) const\r
790 {\r
791   // return the local matrix for transformation to its parent\r
792   mat = *fMatrix;\r
793   if (fParent) mat.MultiplyLeft( &fParent->GetMatrix()->Inverse() );\r
794 }\r
795 \r
796 //-------------------------------------------------------------\r
797 void AliITSAlignMille2Module::AssignDetType()\r
798 {\r
799   TString tp = GetName();\r
800   if      (tp.Contains("SPD",TString::kIgnoreCase)) fDetType = kSPD;\r
801   else if (tp.Contains("SDD",TString::kIgnoreCase)) fDetType = kSDD;\r
802   else if (tp.Contains("SSD",TString::kIgnoreCase)) fDetType = kSSD;\r
803   else fDetType = -1;\r
804   fNParTot = IsSDD() ? kMaxParTot:kMaxParGeom;\r
805   fNParFree = 0;\r
806   fParVals = new Float_t[fNParTot];\r
807   fParErrs = new Float_t[fNParTot];  \r
808   fParCstr = new Float_t[fNParTot];  \r
809   if (fParOffs.GetSize()<fNParTot) fParOffs.Set(fNParTot);\r
810   for (int i=fNParTot;i--;) {\r
811     fParVals[i] = fParErrs[i] = 0.; \r
812     fParCstr[i] = 0.;\r
813     fParOffs[i] = -1;\r
814   }\r
815 }\r
816 \r
817 //-------------------------------------------------------------\r
818 void AliITSAlignMille2Module::EvaluateDOF()\r
819 {\r
820   fNParFree = 0;\r
821   for (int i=fNParTot;i--;) if (IsFreeDOF(i)) fNParFree++;\r
822 }\r
823 \r
824 //-------------------------------------------------------------\r
825 void AliITSAlignMille2Module::GetSensVolGlobalParams(UShort_t volid,Double_t *t, Double_t *r)\r
826 {\r
827   // return global parameters of the sensor volid\r
828   for (int i=3;i--;) t[i] = r[i] = 0.;\r
829   if (SensVolMatrix(volid,fSensVolMatrix)) return;  \r
830   fgTempAlignObj.SetMatrix(*fSensVolMatrix);\r
831   fgTempAlignObj.GetPars(t,r);\r
832 }\r
833 \r
834 //-------------------------------------------------------------\r
835 void AliITSAlignMille2Module::GetSensVolLocalParams(UShort_t volid,Double_t *t, Double_t *r)\r
836 {\r
837   // return parameters of the sensor volid in the current module\r
838   for (int i=3;i--;) t[i] = r[i] = 0.;\r
839   if (SensVolMatrix(volid,fSensVolMatrix)) return;  \r
840   fSensVolMatrix->MultiplyLeft( &fMatrix->Inverse() );\r
841   fgTempAlignObj.SetMatrix(*fSensVolMatrix);\r
842   fgTempAlignObj.GetPars(t,r);\r
843 }\r
844 \r
845 //-------------------------------------------------------------\r
846 void AliITSAlignMille2Module::GetSensVolGlobalParams(UShort_t volid,Double_t* loct,Double_t* locr,Double_t *t, Double_t *r)\r
847 {\r
848   // return global parameters of the sensor volid modified by the localDelta params\r
849   for (int i=3;i--;) t[i] = r[i] = 0.;\r
850   if (SensVolMatrix(volid,fSensVolMatrix)) return;  \r
851   fgTempAlignObj.SetTranslation(loct[0],loct[1],loct[2]);\r
852   fgTempAlignObj.SetRotation(locr[0],locr[1],locr[2]);\r
853   //\r
854   fgTempAlignObj.GetMatrix(*fSensVolModifMatrix);      // obtain local delta\r
855   fSensVolModifMatrix->MultiplyLeft( fSensVolMatrix ); // obtain global delta\r
856   fgTempAlignObj.SetMatrix(*fSensVolModifMatrix);\r
857   fgTempAlignObj.GetPars(t,r);                         // obtain global params\r
858 }\r
859 \r
860 //-------------------------------------------------------------\r
861 void AliITSAlignMille2Module::GetSensVolLocalParams(UShort_t volid,Double_t* loct,Double_t* locr,Double_t *t, Double_t *r)\r
862 {\r
863   // return parameters of the sensor volid (modified by the localDelta params) in the current volume\r
864   for (int i=3;i--;) t[i] = r[i] = 0.;\r
865   if (SensVolMatrix(volid,fSensVolMatrix)) return;  \r
866   fgTempAlignObj.SetTranslation(loct[0],loct[1],loct[2]);\r
867   fgTempAlignObj.SetRotation(locr[0],locr[1],locr[2]);\r
868   //\r
869   fgTempAlignObj.GetMatrix(*fSensVolModifMatrix);      // obtain local delta\r
870   fSensVolModifMatrix->MultiplyLeft( fSensVolMatrix ); // obtain global delta\r
871   fSensVolModifMatrix->MultiplyLeft( &fMatrix->Inverse() ); // obtain delta in current volume\r
872   fgTempAlignObj.SetMatrix(*fSensVolModifMatrix);\r
873   fgTempAlignObj.GetPars(t,r);                         // obtain params\r
874 }\r
875 \r
876 //-------------------------------------------------------------\r
877 void AliITSAlignMille2Module::SetParVals(Double_t *vl,Int_t npar)\r
878 {\r
879   for (int i=TMath::Min(npar,(Int_t)fNParTot);i--;) fParVals[i] = vl[i];\r
880 }\r
881 \r
882 //-------------------------------------------------------------\r
883 void AliITSAlignMille2Module::GetGeomParamsGlo(Double_t *pars)\r
884 {\r
885   // recompute parameters from local to global frame\r
886   //\r
887   // is there anything to do?\r
888   if (GeomParamsGlobal()) {for (int i=kMaxParGeom;i--;) pars[i] = fParVals[i]; return;}\r
889   //\r
890   // IMPORTANT: It is assumed that the parents params are defined in a same way (local or global)\r
891   // as for the current module. Since in the mp2 the modules are stored from parents to children,\r
892   // it is safe to call this method in loop staring from the lowest level child, i.e. from the end\r
893   // of the modules array.\r
894   //\r
895   // DeltaGlobal = (ModifParents)*DeltaLocal*(ModifParents)^-1 \r
896   //\r
897   *fSensVolMatrix = *fMatrix;   // current global matrix\r
898   AliITSAlignMille2Module* parent = GetParent();\r
899   while (parent) {\r
900     if (parent->GeomParamsGlobal()) {\r
901       AliError("Cannot convert params to Global when the parents are already Global\n");\r
902       for (int i=kMaxParGeom;i--;) pars[i] = 0;\r
903       return;\r
904     }\r
905     fSensVolMatrix->MultiplyLeft( &parent->GetMatrix()->Inverse() ); // Local Matrix\r
906     Float_t *parpar = parent->GetParVals();\r
907     fgTempAlignObj.SetTranslation(parpar[0],parpar[1],parpar[2]);\r
908     fgTempAlignObj.SetRotation(parpar[3],parpar[4],parpar[5]);\r
909     fgTempAlignObj.GetMatrix(*fSensVolModifMatrix);\r
910     fSensVolMatrix->MultiplyLeft(fSensVolModifMatrix);\r
911     fSensVolMatrix->MultiplyLeft(parent->GetMatrix());  // global matrix after parents modifications\r
912     parent = parent->GetParent();\r
913   }\r
914   //\r
915   fgTempAlignObj.SetTranslation(fParVals[0],fParVals[1],fParVals[2]);\r
916   fgTempAlignObj.SetRotation(fParVals[3],fParVals[4],fParVals[5]);\r
917   fgTempAlignObj.GetMatrix(*fSensVolModifMatrix);  // local delta matrix\r
918   fSensVolModifMatrix->Multiply( &fSensVolMatrix->Inverse() );\r
919   fSensVolModifMatrix->MultiplyLeft( fSensVolMatrix );\r
920   fgTempAlignObj.SetMatrix( *fSensVolModifMatrix );  // global delta matrix\r
921   fgTempAlignObj.GetPars(pars,pars+3);\r
922   //\r
923 }\r
924 \r
925 //-------------------------------------------------------------\r
926 void AliITSAlignMille2Module::GetGeomParamsLoc(Double_t *pars)\r
927 {\r
928   // recompute parameters from global to local frame\r
929   //\r
930   // is there anything to do?\r
931   if (!GeomParamsGlobal()) {for (int i=kMaxParGeom;i--;) pars[i] = fParVals[i]; return;}\r
932   //\r
933   // IMPORTANT: It is assumed that the parents params are defined in a same way (local or global)\r
934   // as for the current module. Since in the mp2 the modules are stored from parents to children,\r
935   // it is safe to call this method in loop staring from the lowest level child, i.e. from the end\r
936   // of the modules array.\r
937   //\r
938   //  DeltaLocal = (DeltaParents*GlobalMat)^-1*DeltaGlobal*(DeltaParents*GlobalMat)\r
939   //\r
940   AliITSAlignMille2Module* parent = GetParent();\r
941   fgTempAlignObj.SetTranslation(0.,0.,0.);\r
942   fgTempAlignObj.SetRotation(0.,0.,0.);\r
943   fgTempAlignObj.GetMatrix(*fSensVolMatrix); // get no-shift matrix\r
944   //\r
945   while (parent) { // accumulate the product of parents global modifications\r
946     if (!parent->GeomParamsGlobal()) {\r
947       AliError("Cannot convert params to Local when the parents are already Local\n");\r
948       for (int i=kMaxParGeom;i--;) pars[i] = 0;\r
949       return;\r
950     }\r
951     Float_t *parpar = parent->GetParVals();\r
952     fgTempAlignObj.SetTranslation(parpar[0],parpar[1],parpar[2]);\r
953     fgTempAlignObj.SetRotation(parpar[3],parpar[4],parpar[5]);\r
954     fgTempAlignObj.GetMatrix(*fSensVolModifMatrix);\r
955     fSensVolMatrix->Multiply(fSensVolModifMatrix); \r
956     parent = parent->GetParent();\r
957   }\r
958   // global matrix after parents modifications\r
959   fSensVolMatrix->Multiply(fMatrix);\r
960   //\r
961   fgTempAlignObj.SetTranslation(fParVals[0],fParVals[1],fParVals[2]);\r
962   fgTempAlignObj.SetRotation(fParVals[3],fParVals[4],fParVals[5]);\r
963   fgTempAlignObj.GetMatrix(*fSensVolModifMatrix);  // global delta matrix\r
964   fSensVolModifMatrix->MultiplyLeft( &fSensVolMatrix->Inverse() );\r
965   fSensVolModifMatrix->Multiply( fSensVolMatrix );\r
966   fgTempAlignObj.SetMatrix( *fSensVolModifMatrix );  // local delta matrix\r
967   fgTempAlignObj.GetPars(pars,pars+3);\r
968   //\r
969 }\r
970 \r
971 \r
972 //-------------------------------------------------------------\r
973 void AliITSAlignMille2Module::CalcDerivDPosDPar(Int_t sensVol,const Double_t* pl, Double_t *deriv)\r
974 {\r
975   // calculate jacobian of the global position vs Parameters (dPos/dParam) \r
976   // for the point in the sensor sensVol\r
977   const double kDel = 0.01;\r
978   double pos0[3],pos1[3],pos2[3],pos3[3];\r
979   double delta[kMaxParGeom];\r
980   //\r
981   for (int ip=kMaxParGeom;ip--;) delta[ip] = 0;\r
982   //\r
983   for (int ip=kMaxParGeom;ip--;) {\r
984     //\r
985     delta[ip] -= kDel;\r
986     GetSensitiveVolumeModifiedMatrix(sensVol,delta,!GeomParamsGlobal())->LocalToMaster(pl,pos0);    \r
987     delta[ip] += kDel/2;\r
988     GetSensitiveVolumeModifiedMatrix(sensVol,delta,!GeomParamsGlobal())->LocalToMaster(pl,pos1);    \r
989     delta[ip] += kDel;\r
990     GetSensitiveVolumeModifiedMatrix(sensVol,delta,!GeomParamsGlobal())->LocalToMaster(pl,pos2);    \r
991     delta[ip] += kDel/2;\r
992     GetSensitiveVolumeModifiedMatrix(sensVol,delta,!GeomParamsGlobal())->LocalToMaster(pl,pos3);    \r
993     //\r
994     delta[ip] = 0;\r
995     double *curd = deriv + ip*3;\r
996     for (int i=3;i--;) curd[i] = (8.*(pos2[i]-pos1[i]) - (pos3[i]-pos0[i]))/6./kDel;\r
997   }\r
998   //\r
999 }\r
1000 \r
1001 //-------------------------------------------------------------\r
1002 void AliITSAlignMille2Module::CalcDerivGloLoc(Int_t idx,Double_t *deriv)\r
1003 {\r
1004   // calculate derivative of global params vs local param idx:  deriv[j] = dParGlo[j]/dParLoc[idx]\r
1005   Double_t lpar[kMaxParGeom];\r
1006   for (int i=kMaxParGeom;i--;) lpar[i] = 0.;\r
1007   //  using f(x+h),f(x-h),f(x+h/2),f(x-h2)...\r
1008   Double_t par1[kMaxParGeom]; // f(x-h)\r
1009   Double_t par2[kMaxParGeom]; // f(x-h/2)\r
1010   Double_t par3[kMaxParGeom]; // f(x+h/2)\r
1011   Double_t par4[kMaxParGeom]; // f(x+h)\r
1012   //\r
1013   const Double_t dpar = 1e-3;\r
1014   //\r
1015   // first values\r
1016   lpar[idx] -= dpar;\r
1017   GetGlobalParams(lpar,lpar+3, par1,par1+3);\r
1018   //\r
1019   // second values\r
1020   lpar[idx] += dpar/2;\r
1021   GetGlobalParams(lpar,lpar+3, par2,par2+3);\r
1022   //\r
1023   // third values\r
1024   lpar[idx] += dpar;\r
1025   GetGlobalParams(lpar,lpar+3, par3,par3+3);\r
1026   //\r
1027   // fourth values\r
1028   lpar[idx] += dpar/2;\r
1029   GetGlobalParams(lpar,lpar+3, par4,par4+3);\r
1030   //\r
1031   Double_t h2 = 1./(2.*dpar);\r
1032   for (int i=kMaxParGeom;i--;) {\r
1033     Double_t d0 = par4[i]-par1[i];\r
1034     Double_t d2 = 2.*(par3[i]-par2[i]);\r
1035     deriv[i] = h2*(4*d2 - d0)/3.;\r
1036     if (TMath::Abs(deriv[i]) < 1.0e-9) deriv[i] = 0.0;\r
1037   }\r
1038   //\r
1039 }\r
1040 \r
1041 //-------------------------------------------------------------\r
1042 void AliITSAlignMille2Module::CalcDerivLocGlo(Double_t *deriv)\r
1043 {\r
1044   // calculate derivative of local params vs global params:  deriv[i][j] = dParLoc[i]/dParGlo[j]\r
1045   Double_t gpar[kMaxParGeom];\r
1046   for (int i=kMaxParGeom;i--;) gpar[i] = 0.;\r
1047   //  using f(x+h),f(x-h),f(x+h/2),f(x-h2)...\r
1048   Double_t par1[kMaxParGeom]; // f(x-h)\r
1049   Double_t par2[kMaxParGeom]; // f(x-h/2)\r
1050   Double_t par3[kMaxParGeom]; // f(x+h/2)\r
1051   Double_t par4[kMaxParGeom]; // f(x+h)\r
1052   //\r
1053   const Double_t dpar = 1e-3;\r
1054   //\r
1055   for (int ig=kMaxParGeom;ig--;) {\r
1056     // first values\r
1057     gpar[ig] -= dpar;\r
1058     GetLocalParams(gpar,gpar+3, par1,par1+3);\r
1059     //\r
1060     // second values\r
1061     gpar[ig] += dpar/2;\r
1062     GetLocalParams(gpar,gpar+3, par2,par2+3);\r
1063     //\r
1064     // third values\r
1065     gpar[ig] += dpar;\r
1066     GetLocalParams(gpar,gpar+3, par3,par3+3);\r
1067     //\r
1068     // fourth values\r
1069     gpar[ig] += dpar/2;\r
1070     GetLocalParams(gpar,gpar+3, par4,par4+3);\r
1071     //\r
1072     Double_t h2 = 1./(2.*dpar);\r
1073     for (int i=kMaxParGeom;i--;) {\r
1074       Double_t d0 = par4[i]-par1[i];\r
1075       Double_t d2 = 2.*(par3[i]-par2[i]);\r
1076       int idig = i*kMaxParGeom + ig;\r
1077       deriv[idig] = h2*(4*d2 - d0)/3.;\r
1078       if (TMath::Abs(deriv[idig]) < 1.0e-9) deriv[idig] = 0.0;\r
1079     }\r
1080   }\r
1081   //\r
1082 }\r
1083 \r
1084 //________________________________________________________________________________________________________\r
1085 void AliITSAlignMille2Module::CalcDerivGloLoc(Int_t sensVol,Int_t paridx,Double_t* derivative)\r
1086 {\r
1087   /// calculate numerically the derivatives of global params vs local param paridx for sensor sensVol: dPglob/dPloc_paridx\r
1088   //\r
1089   Double_t lpar[kMaxParGeom];\r
1090   for (int i=kMaxParGeom;i--;) lpar[i] = 0.;\r
1091   //  using f(x+h),f(x-h),f(x+h/2),f(x-h2)...\r
1092   Double_t par1[kMaxParGeom]; // f(x-h)\r
1093   Double_t par2[kMaxParGeom]; // f(x-h/2)\r
1094   Double_t par3[kMaxParGeom]; // f(x+h/2)\r
1095   Double_t par4[kMaxParGeom]; // f(x+h)\r
1096   //\r
1097   const Double_t dpar = 1e-3;\r
1098   //\r
1099   // first values\r
1100   lpar[paridx] -= dpar;\r
1101   GetSensVolGlobalParams(sensVol,lpar,lpar+3, par1,par1+3);\r
1102   //\r
1103   // second values\r
1104   lpar[paridx] += dpar/2;\r
1105   GetSensVolGlobalParams(sensVol,lpar,lpar+3, par2,par2+3);\r
1106   //\r
1107   // third values\r
1108   lpar[paridx] += dpar;\r
1109   GetSensVolGlobalParams(sensVol,lpar,lpar+3, par3,par3+3);\r
1110   //\r
1111   // fourth values\r
1112   lpar[paridx] += dpar/2;\r
1113   GetSensVolGlobalParams(sensVol,lpar,lpar+3, par4,par4+3);\r
1114   //\r
1115   Double_t h2 = 1./(2.*dpar);\r
1116   for (int i=kMaxParGeom;i--;) {\r
1117     Double_t d0 = par4[i]-par1[i];\r
1118     Double_t d2 = 2.*(par3[i]-par2[i]);\r
1119     derivative[i] = h2*(4*d2 - d0)/3.;\r
1120     if (TMath::Abs(derivative[i]) < 1.0e-9) derivative[i] = 0.0;\r
1121   }\r
1122   //\r
1123 }\r
1124 \r
1125 //________________________________________________________________________________________________________\r
1126 void AliITSAlignMille2Module::CalcDerivCurLoc(Int_t sensVol,Int_t paridx,Double_t* derivative)  \r
1127 {\r
1128   /// calculate numerically the derivatives of sensor params in the current volume vs sensor local param paridx\r
1129   //\r
1130   Double_t lpar[kMaxParGeom];\r
1131   for (int i=kMaxParGeom;i--;) lpar[i] = 0.;\r
1132   //  using f(x+h),f(x-h),f(x+h/2),f(x-h2)...\r
1133   Double_t par1[kMaxParGeom]; // f(x-h)\r
1134   Double_t par2[kMaxParGeom]; // f(x-h/2)\r
1135   Double_t par3[kMaxParGeom]; // f(x+h/2)\r
1136   Double_t par4[kMaxParGeom]; // f(x+h)\r
1137   //\r
1138   const Double_t dpar = 1e-3;\r
1139   //\r
1140   // first values\r
1141   lpar[paridx] -= dpar;\r
1142   GetSensVolLocalParams(sensVol,lpar,lpar+3, par1,par1+3);\r
1143   //\r
1144   // second values\r
1145   lpar[paridx] += dpar/2;\r
1146   GetSensVolLocalParams(sensVol,lpar,lpar+3, par2,par2+3);\r
1147   //\r
1148   // third values\r
1149   lpar[paridx] += dpar;\r
1150   GetSensVolLocalParams(sensVol,lpar,lpar+3, par3,par3+3);\r
1151   //\r
1152   // fourth values\r
1153   lpar[paridx] += dpar/2;\r
1154   GetSensVolLocalParams(sensVol,lpar,lpar+3, par4,par4+3);\r
1155   //\r
1156   Double_t h2 = 1./(2.*dpar);\r
1157   for (int i=kMaxParGeom;i--;) {\r
1158     Double_t d0 = par4[i]-par1[i];\r
1159     Double_t d2 = 2.*(par3[i]-par2[i]);\r
1160     derivative[i] = h2*(4*d2 - d0)/3.;\r
1161     if (TMath::Abs(derivative[i]) < 1.0e-9) derivative[i] = 0.0;\r
1162   }\r
1163   //\r
1164 }\r
1165 \r
1166 \r
1167 //-------------------------------------------------------------\r
1168 void AliITSAlignMille2Module::GetGlobalParams(Double_t *t, Double_t *r)\r
1169 {\r
1170   // global parameters of the module\r
1171   fgTempAlignObj.SetMatrix( *fMatrix );\r
1172   fgTempAlignObj.GetPars(t,r);\r
1173 }\r
1174 \r
1175 //-------------------------------------------------------------\r
1176 void AliITSAlignMille2Module::GetGlobalParams(const Double_t* loct, const Double_t* locr, Double_t *t, Double_t *r)\r
1177 {\r
1178   // global parameters of the module after the modification by local loct,locr\r
1179   fgTempAlignObj.SetTranslation(loct[0],loct[1],loct[2]);\r
1180   fgTempAlignObj.SetRotation(locr[0],locr[1],locr[2]);\r
1181   fgTempAlignObj.GetMatrix(*fSensVolModifMatrix);  \r
1182   *fSensVolMatrix = *fMatrix;\r
1183   fSensVolMatrix->Multiply(fSensVolModifMatrix);\r
1184   fgTempAlignObj.SetMatrix(*fSensVolMatrix);\r
1185   fgTempAlignObj.GetPars(t,r);\r
1186 }\r
1187 \r
1188 //-------------------------------------------------------------\r
1189 void AliITSAlignMille2Module::GetLocalParams(const Double_t* glot, const Double_t* glor, Double_t *t, Double_t *r)\r
1190 {\r
1191   // obtain local delta parameters from global delta params\r
1192   fgTempAlignObj.SetTranslation(glot[0],glot[1],glot[2]);\r
1193   fgTempAlignObj.SetRotation(glor[0],glor[1],glor[2]);\r
1194   fgTempAlignObj.GetMatrix(*fSensVolMatrix);  \r
1195   fSensVolMatrix->Multiply( fMatrix );\r
1196   fSensVolMatrix->MultiplyLeft( &fMatrix->Inverse() );\r
1197   fgTempAlignObj.SetMatrix(*fSensVolMatrix);\r
1198   fgTempAlignObj.GetPars(t,r);\r
1199 }\r