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