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