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