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