]> git.uio.no Git - u/mrichter/AliRoot.git/blob - ITS/AliITSAlignMille2Module.cxx
remove obselete clean QA macros command
[u/mrichter/AliRoot.git] / ITS / AliITSAlignMille2Module.cxx
1 /************************************************************************** 
2  * Copyright(c) 2007-2009, ALICE Experiment at CERN, All rights reserved. * 
3  *                                                                        * 
4  * Author: The ALICE Off-line Project.                                    * 
5  * Contributors are mentioned in the code where appropriate.              * 
6  *                                                                        * 
7  * Permission to use, copy, modify and distribute this software and its   * 
8  * documentation strictly for non-commercial purposes is hereby granted   * 
9  * without fee, provided that the above copyright notice appears in all   * 
10  * copies and that both the copyright notice and this permission notice   * 
11  * appear in the supporting documentation. The authors make no claims     * 
12  * about the suitability of this software for any purpose. It is          * 
13  * provided "as is" without express or implied warranty.                  * 
14  **************************************************************************/ 
15  
16 /* $Id$    */ 
17 //----------------------------------------------------------------------------- 
18 /// class AliITSAlignMille2Module
19 /// Alignment class for the ALICE ITS detector 
20 /// 
21 /// This class is used by AliITSAlignMille to build custom supermodules    
22 /// made of ITS sensitive modules. These supermodules are then aligned
23 /// 
24 /// Custom supermodules must have VolumeID > 14335
25 ///
26 /// \author M. Lunardon  
27 //----------------------------------------------------------------------------- 
28  
29 #include <TGeoManager.h> 
30 #include <TGeoMatrix.h> 
31  
32 #include "AliITSAlignMille2Module.h" 
33 #include "AliITSgeomTGeo.h" 
34 #include "AliGeomManager.h" 
35 #include "AliAlignObjParams.h" 
36 #include "AliLog.h" 
37 #include "AliITSAlignMille2.h"
38  
39 /// \cond CLASSIMP 
40 ClassImp(AliITSAlignMille2Module) 
41 /// \endcond 
42
43 #define CORHW_
44
45 AliAlignObjParams AliITSAlignMille2Module::fgTempAlignObj;
46     
47 //-------------------------------------------------------------
48 AliITSAlignMille2Module::AliITSAlignMille2Module() : 
49   TNamed(), 
50   fNSensVol(0), 
51   fIndex(-1),  
52   fVolumeID(0),
53   fNProcPoints(0),
54   fSensVolIndex(0),
55   fSensVolVolumeID(0),
56   fMatrix(NULL),
57   fSensVolMatrix(NULL),
58   fSensVolModifMatrix(NULL),
59   fParent(NULL)
60
61   /// void constructor  
62   fMatrix = new TGeoHMatrix; 
63   fSensVolMatrix = new TGeoHMatrix; 
64   fSensVolModifMatrix = new TGeoHMatrix; 
65   fSensVolIndex.Set(1);
66   fSensVolVolumeID.Set(1);
67   fSigmaFactor[0]=fSigmaFactor[1]=fSigmaFactor[2]=1.0;
68
69
70 //-------------------------------------------------------------
71 AliITSAlignMille2Module::AliITSAlignMille2Module(Int_t index,UShort_t volid,char* symname,TGeoHMatrix *m,Int_t nsv,UShort_t *volidsv) : 
72   TNamed(), 
73   fNSensVol(0), 
74   fIndex(-1),  
75   fVolumeID(0),
76   fNProcPoints(0),
77   fSensVolIndex(0),
78   fSensVolVolumeID(0),  
79   fMatrix(NULL),
80   fSensVolMatrix(NULL),
81   fSensVolModifMatrix(NULL),
82   fParent(NULL)
83
84   /// void constructor  
85   fMatrix = new TGeoHMatrix; 
86   fSensVolMatrix = new TGeoHMatrix; 
87   fSensVolModifMatrix = new TGeoHMatrix; 
88   fSigmaFactor[0]=fSigmaFactor[1]=fSigmaFactor[2]=1.0;
89   if (Set(index,volid,symname,m,nsv,volidsv)) {
90     AliInfo("Error in AliITSAlignMille2Module::Set() - initializing void supermodule...");
91   }
92
93
94 //-------------------------------------------------------------
95 AliITSAlignMille2Module::AliITSAlignMille2Module(UShort_t volid) : 
96   TNamed(), 
97   fNSensVol(0), 
98   fIndex(-1),  
99   fVolumeID(0),
100   fNProcPoints(0),
101   fSensVolIndex(0),
102   fSensVolVolumeID(0),
103   fMatrix(NULL),
104   fSensVolMatrix(NULL),
105   fSensVolModifMatrix(NULL),
106   fParent(NULL)
107
108   /// simple constructor building a supermodule from a single sensitive volume 
109   fMatrix = new TGeoHMatrix; 
110   fSensVolMatrix = new TGeoHMatrix; 
111   fSensVolModifMatrix = new TGeoHMatrix;   
112   // temporary align object, just use the rotation...
113   fSensVolIndex.Set(1);
114   fSensVolVolumeID.Set(1);
115   fSigmaFactor[0]=fSigmaFactor[1]=fSigmaFactor[2]=1.0;
116   //
117   fIndex = GetIndexFromVolumeID(volid);  
118   if (fIndex>=0 && gGeoManager) { // good sensitive module and geometry loaded
119     SetName(AliGeomManager::SymName(volid));
120     fVolumeID = volid;
121     AddSensitiveVolume(volid);
122     if (SensVolMatrix(volid, fMatrix))
123        AliInfo("Matrix not defined");
124   }
125   else {
126     AliInfo("Wrong VolumeID or Geometry not loaded - initializing void supermodule...");
127   }
128
129
130
131 //_____________________________________________________________________________
132 AliITSAlignMille2Module::AliITSAlignMille2Module(const AliITSAlignMille2Module &m) :
133   TNamed(m),
134   fNSensVol(m.fNSensVol),
135   fIndex(m.fIndex),
136   fVolumeID(m.fVolumeID),
137   fNProcPoints(0),
138   fSensVolIndex(m.fSensVolIndex),
139   fSensVolVolumeID(m.fSensVolVolumeID),
140   fMatrix(new TGeoHMatrix(*m.GetMatrix())),
141   fSensVolMatrix(new TGeoHMatrix),
142   fSensVolModifMatrix(new TGeoHMatrix),
143   fParent(m.fParent)
144 {
145   // Copy constructor
146   fSensVolIndex = m.fSensVolIndex;
147   fSensVolVolumeID = m.fSensVolVolumeID;
148   for (int i=3;i--;) fSigmaFactor[i] = m.fSigmaFactor[i];
149 }
150
151 //_____________________________________________________________________________
152 AliITSAlignMille2Module& AliITSAlignMille2Module::operator=(const AliITSAlignMille2Module &m)  
153 {
154   // operator =
155   //
156   if(this==&m) return *this;
157   ((TNamed *)this)->operator=(m);
158   //
159   fNSensVol=m.fNSensVol;
160   fIndex=m.fIndex;
161   fVolumeID=m.fVolumeID;
162   for (int i=3;i--;) fSigmaFactor[i] = m.fSigmaFactor[i];
163   if (fMatrix) delete fMatrix;
164   fMatrix=new TGeoHMatrix(*m.GetMatrix());
165   fSensVolIndex = m.fSensVolIndex;
166   fSensVolVolumeID = m.fSensVolVolumeID;
167   fParent = m.fParent;
168   return *this;
169 }
170
171
172 //-------------------------------------------------------------
173 AliITSAlignMille2Module::~AliITSAlignMille2Module() { 
174   /// Destructor 
175   delete fMatrix; 
176   delete fSensVolMatrix; 
177   delete fSensVolModifMatrix; 
178
179
180 //-------------------------------------------------------------
181 Int_t AliITSAlignMille2Module::Set(Int_t index, UShort_t volid, char* symname, TGeoHMatrix *m, Int_t nsv, UShort_t *volidsv) 
182 {
183   // initialize a custom supermodule
184   // index, volid, symname and matrix must be given
185   // if (volidsv) add nsv sensitive volumes to the supermodules
186   // return 0 if success
187
188   if (index<2198) {
189     AliInfo("Index must be >= 2198");
190     return -1;
191   }
192   if (volid<14336) {
193     AliInfo("VolumeID must be >= 14336");
194     return -2;
195   }
196   
197   if (!symname) return -3;
198   for (Int_t i=0; i<2198; i++) {
199     if (!strcmp(symname,AliITSgeomTGeo::GetSymName(i))) {
200       AliInfo("Symname already used by a Sensitive Volume");
201       return -3;
202     }
203   }
204   
205   if (!m) return -4;
206
207   // can initialize needed stuffs
208   fIndex = index;
209   fVolumeID = volid;
210   SetName(symname);
211   //
212   (*fMatrix) = (*m);
213   //
214   fSensVolIndex.Set(nsv);
215   fSensVolVolumeID.Set(nsv);
216   // add sensitive volumes
217   for (Int_t i=0; i<nsv; i++) AddSensitiveVolume(volidsv[i]);
218
219   return 0;
220 }
221
222 //-------------------------------------------------------------
223 Int_t AliITSAlignMille2Module::GetIndexFromVolumeID(UShort_t voluid) {
224   /// index from volume ID
225   AliGeomManager::ELayerID lay = AliGeomManager::VolUIDToLayer(voluid);
226   if (lay<1|| lay>6) return -1;
227   Int_t idx=Int_t(voluid)-2048*lay;
228   if (idx>=AliGeomManager::LayerSize(lay)) return -1;
229   for (Int_t ilay=1; ilay<lay; ilay++) 
230     idx += AliGeomManager::LayerSize(ilay);
231   return idx;
232 }
233
234 //-------------------------------------------------------------
235 void AliITSAlignMille2Module::AddSensitiveVolume(UShort_t voluid)
236 {
237   /// add a sensitive volume to this supermodule
238   if (GetIndexFromVolumeID(voluid)<0) return; // bad volid
239   //
240   // in principle, the correct size of fSensVol... arrays was set outside but check anyway
241   if (fSensVolVolumeID.GetSize()<fNSensVol) {
242     fSensVolVolumeID.Set(fNSensVol+1);
243     fSensVolIndex.Set(fNSensVol+1);
244   }
245   //
246   fSensVolVolumeID[fNSensVol] = Short_t(voluid);
247   fSensVolIndex[fNSensVol] = GetIndexFromVolumeID(voluid);
248   fNSensVol++;
249 }
250
251 //-------------------------------------------------------------
252 void AliITSAlignMille2Module::DelSensitiveVolume(Int_t at)
253 {
254   // Suppress sensor at position "at"
255   // in fact we are swapping with the last valid one 
256   int lastValid = --fNSensVol;
257   int tmpv = fSensVolIndex[at];
258   fSensVolIndex[at] = fSensVolIndex[lastValid];
259   tmpv = fSensVolVolumeID[at];
260   fSensVolVolumeID[at] = fSensVolVolumeID[lastValid];
261   fSensVolVolumeID[lastValid] = tmpv;
262   //
263 }
264
265 //-------------------------------------------------------------
266 Bool_t AliITSAlignMille2Module::IsIn(UShort_t voluid) const 
267 {
268   /// check if voluid is defined
269   if (!voluid) return kFALSE; // only positive voluid are accepted
270   for (Int_t i=0; i<fNSensVol; i++) if (UShort_t(fSensVolVolumeID[i])==voluid) return kTRUE;
271   return kFALSE;
272 }
273
274 //-------------------------------------------------------------
275 Bool_t AliITSAlignMille2Module::BelongsTo(AliITSAlignMille2Module* parent) const
276 {
277   /// check if parent contains the sensors of this volume
278   if (fNSensVol<1 || fNSensVol>=parent->GetNSensitiveVolumes()) return kFALSE;
279   return parent->IsIn( fSensVolVolumeID[0] );
280 }
281
282 //-------------------------------------------------------------
283 TGeoHMatrix *AliITSAlignMille2Module::GetSensitiveVolumeModifiedMatrix(UShort_t voluid, Double_t *delta,Bool_t local)
284 {
285   // modify the original TGeoHMatrix of the sensitive module 'voluid' according
286   // with a delta transform. applied to the supermodule matrix
287   // return NULL if error
288
289   if (!IsIn(voluid)) return NULL;
290   if (!gGeoManager)  return NULL;
291
292   // prepare the TGeoHMatrix
293   Double_t tr[3],ang[3];
294   tr[0]=delta[0]; // in centimeter
295   tr[1]=delta[1]; 
296   tr[2]=delta[2];
297   ang[0]=delta[3]; // psi   (X)  in deg
298   ang[1]=delta[4]; // theta (Y)
299   ang[2]=delta[5]; // phi   (Z)
300   //
301   fgTempAlignObj.SetRotation(ang[0],ang[1],ang[2]);
302   fgTempAlignObj.SetTranslation(tr[0],tr[1],tr[2]);
303   AliDebug(3,Form("Delta angles: psi=%f  theta=%f   phi=%f",ang[0],ang[1],ang[2]));
304   TGeoHMatrix hm;
305   fgTempAlignObj.GetMatrix(hm);
306   //printf("\n0: delta matrix\n");hm.Print();
307
308   // 1) start setting fSensVolModif = fSensVol
309   if (SensVolMatrix(voluid, fSensVolModifMatrix)) return NULL;
310   //
311   if (local) {
312     // 2) set fSensVolModif = SensVolRel
313     fSensVolModifMatrix->MultiplyLeft( &fMatrix->Inverse() );
314     // 3) multiply left by delta
315     fSensVolModifMatrix->MultiplyLeft( &hm );
316     // 4) multiply left by fMatrix
317     fSensVolModifMatrix->MultiplyLeft( fMatrix );
318   }
319   else fSensVolModifMatrix->MultiplyLeft( &hm );
320   //
321   return fSensVolModifMatrix;
322 }
323
324 //-------------------------------------------------------------
325 AliAlignObjParams *AliITSAlignMille2Module::GetSensitiveVolumeMisalignment(UShort_t voluid, Double_t *deltalocal)
326 {
327   // calculate misalignment of sens.vol. 'voluid' according with a displacement 'deltalocal'
328   // of the mother volume. The misalignment is returned as AliAlignObjParams object
329
330   if (!IsIn(voluid)) return NULL;
331   if (!gGeoManager) return NULL;
332   
333   // prepare the TGeoHMatrix
334   Double_t tr[3],ang[3];
335   tr[0]=deltalocal[0]; // in centimeter
336   tr[1]=deltalocal[1]; 
337   tr[2]=deltalocal[2];
338   ang[0]=deltalocal[3]; // psi   (X)  in deg
339   ang[1]=deltalocal[4]; // theta (Y)
340   ang[2]=deltalocal[5]; // phi   (Z)
341   //
342   fgTempAlignObj.SetRotation(ang[0],ang[1],ang[2]);
343   fgTempAlignObj.SetTranslation(tr[0],tr[1],tr[2]);
344   AliDebug(3,Form("Delta angles: psi=%f  theta=%f   phi=%f",ang[0],ang[1],ang[2]));
345   //
346   return GetSensitiveVolumeMisalignment(voluid,&fgTempAlignObj);
347 }
348
349 //-------------------------------------------------------------
350 AliAlignObjParams *AliITSAlignMille2Module::GetSensitiveVolumeMisalignment(UShort_t voluid, AliAlignObjParams *a)
351 {
352   // return the misalignment of the sens. vol. 'voluid' corresponding with 
353   // a misalignment 'a' in the mother volume
354   // return NULL if error
355
356   // Gsv = Gg * Gg-1 * Gsv   -> Lsv,g = Gg-1 * Gsv
357   // G'sv = Gg * Dg * Lsv,g === Gsv * Dsv
358   // Gg * Dg * Gg-1 * Gsv = Gsv * Gsv-1 * Gg * Dg * Gg-1 * Gsv
359   //
360   // => Dsv = (Gsv-1 * Gg * Dg * Gg-1 * Gsv)
361   //
362
363   if (!IsIn(voluid)) return NULL;
364   if (!gGeoManager) return NULL;
365
366   //a->Print("");
367
368   // prepare the Delta matrix Dg
369   TGeoHMatrix dg;
370   a->GetMatrix(dg);
371   //dg.Print();
372
373   // 1) start setting fSensVolModif = Gsv
374   if (SensVolMatrix(voluid, fSensVolModifMatrix)) return NULL;
375   //printf("\n1: modif=orig del sensvol\n");fSensVolModifMatrix->Print();
376
377   // 2) set fSensVolModif = Gg-1 * Gsv
378   fSensVolModifMatrix->MultiplyLeft( &fMatrix->Inverse() );
379   //printf("\n2: modif=relative del sensvol\n");fSensVolModifMatrix->Print();
380  
381   // 3) set fSensVolModif = Dg * Gg-1 * Gsv
382   fSensVolModifMatrix->MultiplyLeft( &dg );
383   //printf("\n3: modif= delta*relative\n");fSensVolModifMatrix->Print();
384   
385   // 4) set fSensVolModif = Gg * Dg * Gg-1 * Gsv
386   fSensVolModifMatrix->MultiplyLeft( fMatrix );
387   //printf("\n4: modif=quasi,manca il Gsv-1...\n");fSensVolModifMatrix->Print();
388
389   // 5) set fSensVolModif = Gsv-1 * Gg * Dg * Gg-1 * Gsv
390   if (SensVolMatrix(voluid, &dg)) return NULL;
391   fSensVolModifMatrix->MultiplyLeft( &dg.Inverse() );
392   //printf("\n5: modif=finale\n");fSensVolModifMatrix->Print();
393   //
394   // >> RS
395  // 6) mo' fSensVolModif dovrebbe essere la Dsv(loc) t.c. G'sv = Gsv*Dsv(loc)
396   // per trasformarla in Dsv(loc rispetto al Gsv0, non modificato) dovrebbe essere:
397   // Dsv(loc) -> Dpre * Dsv(loc) * Dpre-1
398   //TGeoHMatrix dpre; // dpre = Gsv0-1*Gsv
399   //if (SensVolOrigGlobalMatrix(voluid, &dg)) return NULL;
400   //if (SensVolMatrix(voluid, &dpre)) return NULL;
401   //dpre.MultiplyLeft( &dg.Inverse() );
402   //fSensVolModifMatrix->Multiply( &dpre.Inverse() );
403   //fSensVolModifMatrix->MultiplyLeft( &dpre );
404   // direi che NON FUNZIONA!!!!  
405
406   // << RS
407
408   // reset align object (may not be needed...)
409   fgTempAlignObj.SetVolUID(0);
410   fgTempAlignObj.SetSymName("");
411   fgTempAlignObj.SetTranslation(0,0,0);
412   fgTempAlignObj.SetRotation(0,0,0);
413   //
414   // >> RS
415 #ifdef CORHW_
416   // correction for SPD y-shift
417   if (voluid>=2048 && voluid<4256) {
418     TGeoHMatrix deltay;
419     double dy[3]={0.,0.0081,0.};
420     deltay.SetTranslation(dy);
421     fSensVolModifMatrix->MultiplyLeft( &deltay );
422     fSensVolModifMatrix->Multiply( &deltay.Inverse() );
423   }
424 #endif
425   // << RS
426   if (!fgTempAlignObj.SetMatrix(*fSensVolModifMatrix)) return NULL;
427   fgTempAlignObj.SetVolUID(voluid);
428   fgTempAlignObj.SetSymName(AliGeomManager::SymName(voluid));
429   //
430   return &fgTempAlignObj;
431 }
432
433 // >> RS
434 //-------------------------------------------------------------
435 AliAlignObjParams *AliITSAlignMille2Module::GetSensitiveVolumeTotalMisalignment(UShort_t voluid, Double_t *deltalocal)
436 {
437   // calculate misalignment of sens.vol. 'voluid' according with a displacement 'deltalocal'
438   // of the mother volume. The misalignment is returned as AliAlignObjParams object including
439   // the (evenctual) prealignment => no merging needed
440
441   if (!IsIn(voluid)) return NULL;
442   if (!gGeoManager) return NULL;
443   
444   // prepare the TGeoHMatrix
445   Double_t tr[3],ang[3];
446   tr[0]=deltalocal[0]; // in centimeter
447   tr[1]=deltalocal[1]; 
448   tr[2]=deltalocal[2];
449   ang[0]=deltalocal[3]; // psi   (X)  in deg
450   ang[1]=deltalocal[4]; // theta (Y)
451   ang[2]=deltalocal[5]; // phi   (Z)
452
453   // reset align object (may not be needed...)
454   fgTempAlignObj.SetVolUID(0);
455   fgTempAlignObj.SetSymName("");
456   fgTempAlignObj.SetRotation(ang[0],ang[1],ang[2]);
457   fgTempAlignObj.SetTranslation(tr[0],tr[1],tr[2]);
458   AliDebug(3,Form("Delta angles: psi=%f  theta=%f   phi=%f",ang[0],ang[1],ang[2]));
459
460   // Gsv = Gg * Gg-1 * Gsv   -> Lsv,g = Gg-1 * Gsv
461   // G'sv = Gg * Dg * Lsv,g === DGsv * Gsv 
462   //
463   // => Dsv = (G0sv-1 * Gg * Dg * Gg-1 * GMsv)  //
464   //
465
466   // prepare the Delta matrix Dg
467   TGeoHMatrix dg;
468   fgTempAlignObj.GetMatrix(dg);
469   //dg.Print();
470
471   // 1) start setting fSensVolModif = Gsv
472   if (SensVolMatrix(voluid, fSensVolModifMatrix)) return NULL;
473   //printf("\n1: modif=orig del sensvol\n");fSensVolModifMatrix->Print();
474
475   // 2) set fSensVolModif = Gg-1 * Gsv
476   fSensVolModifMatrix->MultiplyLeft( &fMatrix->Inverse() );
477   //printf("\n2: modif=relative del sensvol\n");fSensVolModifMatrix->Print();
478  
479   // 3) set fSensVolModif = Dg * Gg-1 * Gsv
480   fSensVolModifMatrix->MultiplyLeft( &dg );
481   //printf("\n3: modif= delta*relative\n");fSensVolModifMatrix->Print();
482   
483   // 4) set fSensVolModif = Gg * Dg * Gg-1 * Gsv
484   fSensVolModifMatrix->MultiplyLeft( fMatrix );
485   //printf("\n4: modif=quasi,manca il Gsv-1...\n");fSensVolModifMatrix->Print();
486
487   // 5) set fSensVolModif = G0sv-1 * Gg * Dg * Gg-1 * Gsv
488   // qui usa l'orig anziche' la prealigned...
489   if (SensVolOrigGlobalMatrix(voluid, &dg)) return NULL;
490   fSensVolModifMatrix->MultiplyLeft( &dg.Inverse() );
491   //printf("\n5: modif=finale\n");fSensVolModifMatrix->Print();
492
493   // reset align object (may not be needed...)
494   fgTempAlignObj.SetVolUID(0);
495   fgTempAlignObj.SetSymName("");
496   fgTempAlignObj.SetTranslation(0,0,0);
497   fgTempAlignObj.SetRotation(0,0,0);
498
499 #ifdef CORHW_
500   // correction for SPD y-shift
501   if (voluid>=2048 && voluid<4256) {
502     TGeoHMatrix deltay;
503     double dy[3]={0.,0.0081,0.};
504     deltay.SetTranslation(dy);
505     fSensVolModifMatrix->MultiplyLeft( &deltay );
506     fSensVolModifMatrix->Multiply( &deltay.Inverse() );
507   }
508 #endif
509   if (!fgTempAlignObj.SetMatrix(*fSensVolModifMatrix)) return NULL;
510   fgTempAlignObj.SetVolUID(voluid);
511   fgTempAlignObj.SetSymName(AliGeomManager::SymName(voluid));
512
513   
514   //fgTempAlignObj.Print("");
515
516   return &fgTempAlignObj;
517 }
518 //-------------------------------------------------------------
519
520 //-------------------------------------------------------------
521 AliAlignObjParams *AliITSAlignMille2Module::GetSensitiveVolumeGlobalMisalignment(UShort_t voluid, Double_t *deltalocal)
522 {
523   // calculate misalignment of sens.vol. 'voluid' according with a displacement 'deltalocal'
524   // of the mother volume. The misalignment is returned as AliAlignObjParams object
525
526   if (!IsIn(voluid)) return NULL;
527   if (!gGeoManager) return NULL;
528   
529   // prepare the TGeoHMatrix
530   Double_t tr[3],ang[3];
531   tr[0]=deltalocal[0]; // in centimeter
532   tr[1]=deltalocal[1]; 
533   tr[2]=deltalocal[2];
534   ang[0]=deltalocal[3]; // psi   (X)  in deg
535   ang[1]=deltalocal[4]; // theta (Y)
536   ang[2]=deltalocal[5]; // phi   (Z)
537
538   // reset align object (may not be needed...)
539   fgTempAlignObj.SetTranslation(0,0,0);
540   fgTempAlignObj.SetRotation(0,0,0);
541
542   fgTempAlignObj.SetRotation(ang[0],ang[1],ang[2]);
543   fgTempAlignObj.SetTranslation(tr[0],tr[1],tr[2]);
544   AliDebug(3,Form("Delta angles: psi=%f  theta=%f   phi=%f",ang[0],ang[1],ang[2]));
545
546   // Gsv = Gg * Gg-1 * Gsv   -> Lsv,g = Gg-1 * Gsv
547   // G'sv = Gg * Dg * Lsv,g === DGsv * Gsv 
548   //
549   // => DGsv = (Gg * Dg * Gg-1)
550   //
551
552   // prepare the Delta matrix Dg
553   TGeoHMatrix dg;
554   fgTempAlignObj.GetMatrix(dg);
555   //dg.Print();
556
557   dg.MultiplyLeft( fMatrix );
558   dg.Multiply( &fMatrix->Inverse() );
559
560   // reset align object (may not be needed...)
561   fgTempAlignObj.SetTranslation(0,0,0);
562   fgTempAlignObj.SetRotation(0,0,0);
563
564   fgTempAlignObj.SetVolUID(voluid);
565   fgTempAlignObj.SetSymName(AliGeomManager::SymName(voluid));
566
567   if (!fgTempAlignObj.SetMatrix(dg)) return NULL;
568   
569   //fgTempAlignObj.Print("");
570
571   return &fgTempAlignObj;
572 }
573 // << RS
574
575 //-------------------------------------------------------------
576 TGeoHMatrix *AliITSAlignMille2Module::GetSensitiveVolumeMatrix(UShort_t voluid)
577 {
578   // return TGeoHMatrix of the sens.vol. 'voluid' in the current geometry
579   if (SensVolMatrix(voluid,fSensVolMatrix)) return NULL;
580   return fSensVolMatrix;
581 }
582
583 //-------------------------------------------------------------
584 TGeoHMatrix *AliITSAlignMille2Module::GetSensitiveVolumeOrigGlobalMatrix(UShort_t voluid)
585 {
586   // return original ideal position (from AliGeomManager::GetOrigGlobalMatrix())
587   if (SensVolOrigGlobalMatrix(voluid,fSensVolMatrix)) return NULL;
588   return fSensVolMatrix;
589 }
590 //-------------------------------------------------------------
591 Int_t AliITSAlignMille2Module::SensVolMatrix(UShort_t volid, TGeoHMatrix *m) 
592 {
593   // set matrix for sensitive modules (SPD corrected)
594   // return 0 if success
595   Double_t rot[9];
596   Int_t idx=GetIndexFromVolumeID(volid);
597   if (idx<0) return -1;
598   if (!AliITSgeomTGeo::GetRotation(idx,rot)) return -2;
599   m->SetRotation(rot);
600   Double_t oLoc[3]={0,0,0};
601   Double_t oGlo[3]={0,0,0};
602   if (!AliITSgeomTGeo::LocalToGlobal(idx,oLoc,oGlo)) return -3;
603   m->SetTranslation(oGlo);
604   return 0;
605 }
606
607 //-------------------------------------------------------------
608 Int_t AliITSAlignMille2Module::SensVolOrigGlobalMatrix(UShort_t volid, TGeoHMatrix *m) 
609 {
610   // set original global matrix for sensitive modules (SPD corrected)
611   // return 0 if success
612   Int_t idx=GetIndexFromVolumeID(volid);
613   if (idx<0) return -1;
614   TGeoHMatrix mo;
615   if (!AliGeomManager::GetOrigGlobalMatrix(AliGeomManager::SymName(volid),mo)) (*m)=mo;
616
617 #ifdef CORHW_
618   // SPD y-shift by 81 mu
619   if (volid<5000) { 
620     Double_t oLoc[3]={0.0,0.0081,0.0};
621     Double_t oGlo[3]={0,0,0};
622     m->LocalToMaster(oLoc,oGlo);
623     m->SetTranslation(oGlo);
624   }
625 #endif
626   return 0;
627 }
628
629 //-------------------------------------------------------------
630 UShort_t AliITSAlignMille2Module::GetVolumeIDFromSymname(const Char_t *symname) {
631   /// volume ID from symname
632   if (!symname) return 0;
633
634   for (UShort_t voluid=2000; voluid<13300; voluid++) {
635     Int_t modId;
636     AliGeomManager::ELayerID layerId = AliGeomManager::VolUIDToLayer(voluid,modId);
637     if (layerId>0 && layerId<7 && modId>=0 && modId<AliGeomManager::LayerSize(layerId)) {
638       if (!strcmp(symname,AliGeomManager::SymName(layerId,modId))) return voluid;
639     }
640   }
641
642   return 0;
643 }
644
645 //-------------------------------------------------------------
646 UShort_t AliITSAlignMille2Module::GetVolumeIDFromIndex(Int_t index) {
647   /// volume ID from index
648   if (index<0 || index>2197) return 0;
649   return GetVolumeIDFromSymname(AliITSgeomTGeo::GetSymName(index));
650 }
651
652 //-------------------------------------------------------------
653 void AliITSAlignMille2Module::Print(Option_t*) const 
654 {
655   ///
656   printf("*** ITS SuperModule for AliITSAlignMille ***\n");
657   printf("symname  : %s\n",GetName());
658   printf("parent   : %s\n",fParent ? fParent->GetName() : "N/A");
659   printf("volumeID : %4d  | index : %4d\n",fVolumeID,fIndex);
660   printf("Factors  : X=%.2f Y=%.2f Z=%.2f | DOF: Tx:%d Ty:%d Tz:%d Phi:%d Theta:%d Psi:%d\n",
661          fSigmaFactor[0],fSigmaFactor[1],fSigmaFactor[2],
662          IsFreeDOF(AliITSAlignMille2::kDOFTX),IsFreeDOF(AliITSAlignMille2::kDOFTY),
663          IsFreeDOF(AliITSAlignMille2::kDOFTZ),IsFreeDOF(AliITSAlignMille2::kDOFPH),
664          IsFreeDOF(AliITSAlignMille2::kDOFTH),IsFreeDOF(AliITSAlignMille2::kDOFPS));
665   fMatrix->Print();
666   printf("%4d Sensitive volumes | %6d Processed Points\n",fNSensVol,fNProcPoints);
667   for (Int_t i=0; i<fNSensVol; i++) printf("   voluid[%d] = %d\n",i,UShort_t(fSensVolVolumeID[i]));
668 }
669
670 //-------------------------------------------------------------
671 Bool_t AliITSAlignMille2Module::IsAlignable() const
672 {
673   TGeoManager* geoManager = AliGeomManager::GetGeometry();
674   if (!geoManager) {
675     AliInfo("Couldn't initialize geometry");
676     return kFALSE;
677   }
678   return geoManager->GetAlignableEntry(GetName())!=0;
679 }
680
681 //-------------------------------------------------------------
682 void AliITSAlignMille2Module::GetLocalMatrix(TGeoHMatrix &mat) const
683 {
684   // return the local matrix for transformation to its parent
685   mat = *fMatrix;
686   if (fParent) mat.MultiplyLeft( &fParent->GetMatrix()->Inverse() );
687 }