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