]> git.uio.no Git - u/mrichter/AliRoot.git/blobdiff - ITS/AliITSAlignMille2Module.cxx
Fixes for Coverity warnings
[u/mrichter/AliRoot.git] / ITS / AliITSAlignMille2Module.cxx
index 81ce6b52f0b34bf5c1441154320c1077a4e8efb2..5d967c64b959534e8804453200887948718075fc 100644 (file)
-/************************************************************************** 
- * Copyright(c) 2007-2009, ALICE Experiment at CERN, All rights reserved. * 
- *                                                                        * 
- * Author: The ALICE Off-line Project.                                    * 
- * Contributors are mentioned in the code where appropriate.              * 
- *                                                                        * 
- * Permission to use, copy, modify and distribute this software and its   * 
- * documentation strictly for non-commercial purposes is hereby granted   * 
- * without fee, provided that the above copyright notice appears in all   * 
- * copies and that both the copyright notice and this permission notice   * 
- * appear in the supporting documentation. The authors make no claims     * 
- * about the suitability of this software for any purpose. It is          * 
- * provided "as is" without express or implied warranty.                  * 
- **************************************************************************/ 
-/* $Id$    */ 
-//----------------------------------------------------------------------------- 
-/// class AliITSAlignMille2Module
-/// Alignment class for the ALICE ITS detector 
-/// 
-/// This class is used by AliITSAlignMille to build custom supermodules    
-/// made of ITS sensitive modules. These supermodules are then aligned
-/// 
-/// Custom supermodules must have VolumeID > 14335
-///
-/// \author M. Lunardon  
-//----------------------------------------------------------------------------- 
-#include <TGeoManager.h> 
-#include <TGeoMatrix.h> 
-#include "AliITSAlignMille2Module.h" 
-#include "AliITSgeomTGeo.h" 
-#include "AliGeomManager.h" 
-#include "AliAlignObjParams.h" 
-#include "AliLog.h" 
-#include "AliITSAlignMille2.h"
-/// \cond CLASSIMP 
-ClassImp(AliITSAlignMille2Module) 
-/// \endcond 
-
-#define CORHW_
-
-AliAlignObjParams AliITSAlignMille2Module::fgTempAlignObj;
-    
-//-------------------------------------------------------------
-AliITSAlignMille2Module::AliITSAlignMille2Module() : 
-  TNamed(), 
-  fNSensVol(0), 
-  fIndex(-1),  
-  fVolumeID(0),
-  fNProcPoints(0),
-  fSensVolIndex(0),
-  fSensVolVolumeID(0),
-  fMatrix(NULL),
-  fSensVolMatrix(NULL),
-  fSensVolModifMatrix(NULL),
-  fParent(NULL)
-{ 
-  /// void constructor  
-  fMatrix = new TGeoHMatrix; 
-  fSensVolMatrix = new TGeoHMatrix; 
-  fSensVolModifMatrix = new TGeoHMatrix; 
-  fSensVolIndex.Set(1);
-  fSensVolVolumeID.Set(1);
-  fSigmaFactor[0]=fSigmaFactor[1]=fSigmaFactor[2]=1.0;
-} 
-
-//-------------------------------------------------------------
-AliITSAlignMille2Module::AliITSAlignMille2Module(Int_t index,UShort_t volid,char* symname,TGeoHMatrix *m,Int_t nsv,UShort_t *volidsv) : 
-  TNamed(), 
-  fNSensVol(0), 
-  fIndex(-1),  
-  fVolumeID(0),
-  fNProcPoints(0),
-  fSensVolIndex(0),
-  fSensVolVolumeID(0),  
-  fMatrix(NULL),
-  fSensVolMatrix(NULL),
-  fSensVolModifMatrix(NULL),
-  fParent(NULL)
-{ 
-  /// void constructor  
-  fMatrix = new TGeoHMatrix; 
-  fSensVolMatrix = new TGeoHMatrix; 
-  fSensVolModifMatrix = new TGeoHMatrix; 
-  fSigmaFactor[0]=fSigmaFactor[1]=fSigmaFactor[2]=1.0;
-  if (Set(index,volid,symname,m,nsv,volidsv)) {
-    AliInfo("Error in AliITSAlignMille2Module::Set() - initializing void supermodule...");
-  }
-} 
-
-//-------------------------------------------------------------
-AliITSAlignMille2Module::AliITSAlignMille2Module(UShort_t volid) : 
-  TNamed(), 
-  fNSensVol(0), 
-  fIndex(-1),  
-  fVolumeID(0),
-  fNProcPoints(0),
-  fSensVolIndex(0),
-  fSensVolVolumeID(0),
-  fMatrix(NULL),
-  fSensVolMatrix(NULL),
-  fSensVolModifMatrix(NULL),
-  fParent(NULL)
-{ 
-  /// simple constructor building a supermodule from a single sensitive volume 
-  fMatrix = new TGeoHMatrix; 
-  fSensVolMatrix = new TGeoHMatrix; 
-  fSensVolModifMatrix = new TGeoHMatrix;   
-  // temporary align object, just use the rotation...
-  fSensVolIndex.Set(1);
-  fSensVolVolumeID.Set(1);
-  fSigmaFactor[0]=fSigmaFactor[1]=fSigmaFactor[2]=1.0;
-  //
-  fIndex = GetIndexFromVolumeID(volid);  
-  if (fIndex>=0 && gGeoManager) { // good sensitive module and geometry loaded
-    SetName(AliGeomManager::SymName(volid));
-    fVolumeID = volid;
-    AddSensitiveVolume(volid);
-    if (SensVolMatrix(volid, fMatrix))
-       AliInfo("Matrix not defined");
-  }
-  else {
-    AliInfo("Wrong VolumeID or Geometry not loaded - initializing void supermodule...");
-  }
-} 
-
-
-//_____________________________________________________________________________
-AliITSAlignMille2Module::AliITSAlignMille2Module(const AliITSAlignMille2Module &m) :
-  TNamed(m),
-  fNSensVol(m.fNSensVol),
-  fIndex(m.fIndex),
-  fVolumeID(m.fVolumeID),
-  fNProcPoints(0),
-  fSensVolIndex(m.fSensVolIndex),
-  fSensVolVolumeID(m.fSensVolVolumeID),
-  fMatrix(new TGeoHMatrix(*m.GetMatrix())),
-  fSensVolMatrix(new TGeoHMatrix),
-  fSensVolModifMatrix(new TGeoHMatrix),
-  fParent(m.fParent)
-{
-  // Copy constructor
-  fSensVolIndex = m.fSensVolIndex;
-  fSensVolVolumeID = m.fSensVolVolumeID;
-  for (int i=3;i--;) fSigmaFactor[i] = m.fSigmaFactor[i];
-}
-
-//_____________________________________________________________________________
-AliITSAlignMille2Module& AliITSAlignMille2Module::operator=(const AliITSAlignMille2Module &m)  
-{
-  // operator =
-  //
-  if(this==&m) return *this;
-  ((TNamed *)this)->operator=(m);
-  //
-  fNSensVol=m.fNSensVol;
-  fIndex=m.fIndex;
-  fVolumeID=m.fVolumeID;
-  for (int i=3;i--;) fSigmaFactor[i] = m.fSigmaFactor[i];
-  if (fMatrix) delete fMatrix;
-  fMatrix=new TGeoHMatrix(*m.GetMatrix());
-  fSensVolIndex = m.fSensVolIndex;
-  fSensVolVolumeID = m.fSensVolVolumeID;
-  fParent = m.fParent;
-  return *this;
-}
-
-
-//-------------------------------------------------------------
-AliITSAlignMille2Module::~AliITSAlignMille2Module() { 
-  /// Destructor 
-  delete fMatrix; 
-  delete fSensVolMatrix; 
-  delete fSensVolModifMatrix; 
-} 
-
-//-------------------------------------------------------------
-Int_t AliITSAlignMille2Module::Set(Int_t index, UShort_t volid, char* symname, TGeoHMatrix *m, Int_t nsv, UShort_t *volidsv) 
-{
-  // initialize a custom supermodule
-  // index, volid, symname and matrix must be given
-  // if (volidsv) add nsv sensitive volumes to the supermodules
-  // return 0 if success
-
-  if (index<2198) {
-    AliInfo("Index must be >= 2198");
-    return -1;
-  }
-  if (volid<14336) {
-    AliInfo("VolumeID must be >= 14336");
-    return -2;
-  }
-  
-  if (!symname) return -3;
-  for (Int_t i=0; i<2198; i++) {
-    if (!strcmp(symname,AliITSgeomTGeo::GetSymName(i))) {
-      AliInfo("Symname already used by a Sensitive Volume");
-      return -3;
-    }
-  }
-  
-  if (!m) return -4;
-
-  // can initialize needed stuffs
-  fIndex = index;
-  fVolumeID = volid;
-  SetName(symname);
-  //
-  (*fMatrix) = (*m);
-  //
-  fSensVolIndex.Set(nsv);
-  fSensVolVolumeID.Set(nsv);
-  // add sensitive volumes
-  for (Int_t i=0; i<nsv; i++) AddSensitiveVolume(volidsv[i]);
-
-  return 0;
-}
-
-//-------------------------------------------------------------
-Int_t AliITSAlignMille2Module::GetIndexFromVolumeID(UShort_t voluid) {
-  /// index from volume ID
-  AliGeomManager::ELayerID lay = AliGeomManager::VolUIDToLayer(voluid);
-  if (lay<1|| lay>6) return -1;
-  Int_t idx=Int_t(voluid)-2048*lay;
-  if (idx>=AliGeomManager::LayerSize(lay)) return -1;
-  for (Int_t ilay=1; ilay<lay; ilay++) 
-    idx += AliGeomManager::LayerSize(ilay);
-  return idx;
-}
-
-//-------------------------------------------------------------
-void AliITSAlignMille2Module::AddSensitiveVolume(UShort_t voluid)
-{
-  /// add a sensitive volume to this supermodule
-  if (GetIndexFromVolumeID(voluid)<0) return; // bad volid
-  //
-  // in principle, the correct size of fSensVol... arrays was set outside but check anyway
-  if (fSensVolVolumeID.GetSize()<fNSensVol) {
-    fSensVolVolumeID.Set(fNSensVol+1);
-    fSensVolIndex.Set(fNSensVol+1);
-  }
-  //
-  fSensVolVolumeID[fNSensVol] = Short_t(voluid);
-  fSensVolIndex[fNSensVol] = GetIndexFromVolumeID(voluid);
-  fNSensVol++;
-}
-
-//-------------------------------------------------------------
-void AliITSAlignMille2Module::DelSensitiveVolume(Int_t at)
-{
-  // Suppress sensor at position "at"
-  // in fact we are swapping with the last valid one 
-  int lastValid = --fNSensVol;
-  int tmpv = fSensVolIndex[at];
-  fSensVolIndex[at] = fSensVolIndex[lastValid];
-  tmpv = fSensVolVolumeID[at];
-  fSensVolVolumeID[at] = fSensVolVolumeID[lastValid];
-  fSensVolVolumeID[lastValid] = tmpv;
-  //
-}
-
-//-------------------------------------------------------------
-Bool_t AliITSAlignMille2Module::IsIn(UShort_t voluid) const 
-{
-  /// check if voluid is defined
-  if (!voluid) return kFALSE; // only positive voluid are accepted
-  for (Int_t i=0; i<fNSensVol; i++) if (UShort_t(fSensVolVolumeID[i])==voluid) return kTRUE;
-  return kFALSE;
-}
-
-//-------------------------------------------------------------
-Bool_t AliITSAlignMille2Module::BelongsTo(AliITSAlignMille2Module* parent) const
-{
-  /// check if parent contains the sensors of this volume
-  if (fNSensVol<1 || fNSensVol>=parent->GetNSensitiveVolumes()) return kFALSE;
-  return parent->IsIn( fSensVolVolumeID[0] );
-}
-
-//-------------------------------------------------------------
-TGeoHMatrix *AliITSAlignMille2Module::GetSensitiveVolumeModifiedMatrix(UShort_t voluid, Double_t *delta,Bool_t local)
-{
-  // modify the original TGeoHMatrix of the sensitive module 'voluid' according
-  // with a delta transform. applied to the supermodule matrix
-  // return NULL if error
-
-  if (!IsIn(voluid)) return NULL;
-  if (!gGeoManager)  return NULL;
-
-  // prepare the TGeoHMatrix
-  Double_t tr[3],ang[3];
-  tr[0]=delta[0]; // in centimeter
-  tr[1]=delta[1]; 
-  tr[2]=delta[2];
-  ang[0]=delta[3]; // psi   (X)  in deg
-  ang[1]=delta[4]; // theta (Y)
-  ang[2]=delta[5]; // phi   (Z)
-  //
-  fgTempAlignObj.SetRotation(ang[0],ang[1],ang[2]);
-  fgTempAlignObj.SetTranslation(tr[0],tr[1],tr[2]);
-  AliDebug(3,Form("Delta angles: psi=%f  theta=%f   phi=%f",ang[0],ang[1],ang[2]));
-  TGeoHMatrix hm;
-  fgTempAlignObj.GetMatrix(hm);
-  //printf("\n0: delta matrix\n");hm.Print();
-
-  // 1) start setting fSensVolModif = fSensVol
-  if (SensVolMatrix(voluid, fSensVolModifMatrix)) return NULL;
-  //
-  if (local) {
-    // 2) set fSensVolModif = SensVolRel
-    fSensVolModifMatrix->MultiplyLeft( &fMatrix->Inverse() );
-    // 3) multiply left by delta
-    fSensVolModifMatrix->MultiplyLeft( &hm );
-    // 4) multiply left by fMatrix
-    fSensVolModifMatrix->MultiplyLeft( fMatrix );
-  }
-  else fSensVolModifMatrix->MultiplyLeft( &hm );
-  //
-  return fSensVolModifMatrix;
-}
-
-//-------------------------------------------------------------
-AliAlignObjParams *AliITSAlignMille2Module::GetSensitiveVolumeMisalignment(UShort_t voluid, Double_t *deltalocal)
-{
-  // calculate misalignment of sens.vol. 'voluid' according with a displacement 'deltalocal'
-  // of the mother volume. The misalignment is returned as AliAlignObjParams object
-
-  if (!IsIn(voluid)) return NULL;
-  if (!gGeoManager) return NULL;
-  
-  // prepare the TGeoHMatrix
-  Double_t tr[3],ang[3];
-  tr[0]=deltalocal[0]; // in centimeter
-  tr[1]=deltalocal[1]; 
-  tr[2]=deltalocal[2];
-  ang[0]=deltalocal[3]; // psi   (X)  in deg
-  ang[1]=deltalocal[4]; // theta (Y)
-  ang[2]=deltalocal[5]; // phi   (Z)
-  //
-  fgTempAlignObj.SetRotation(ang[0],ang[1],ang[2]);
-  fgTempAlignObj.SetTranslation(tr[0],tr[1],tr[2]);
-  AliDebug(3,Form("Delta angles: psi=%f  theta=%f   phi=%f",ang[0],ang[1],ang[2]));
-  //
-  return GetSensitiveVolumeMisalignment(voluid,&fgTempAlignObj);
-}
-
-//-------------------------------------------------------------
-AliAlignObjParams *AliITSAlignMille2Module::GetSensitiveVolumeMisalignment(UShort_t voluid, AliAlignObjParams *a)
-{
-  // return the misalignment of the sens. vol. 'voluid' corresponding with 
-  // a misalignment 'a' in the mother volume
-  // return NULL if error
-
-  // Gsv = Gg * Gg-1 * Gsv   -> Lsv,g = Gg-1 * Gsv
-  // G'sv = Gg * Dg * Lsv,g === Gsv * Dsv
-  // Gg * Dg * Gg-1 * Gsv = Gsv * Gsv-1 * Gg * Dg * Gg-1 * Gsv
-  //
-  // => Dsv = (Gsv-1 * Gg * Dg * Gg-1 * Gsv)
-  //
-
-  if (!IsIn(voluid)) return NULL;
-  if (!gGeoManager) return NULL;
-
-  //a->Print("");
-
-  // prepare the Delta matrix Dg
-  TGeoHMatrix dg;
-  a->GetMatrix(dg);
-  //dg.Print();
-
-  // 1) start setting fSensVolModif = Gsv
-  if (SensVolMatrix(voluid, fSensVolModifMatrix)) return NULL;
-  //printf("\n1: modif=orig del sensvol\n");fSensVolModifMatrix->Print();
-
-  // 2) set fSensVolModif = Gg-1 * Gsv
-  fSensVolModifMatrix->MultiplyLeft( &fMatrix->Inverse() );
-  //printf("\n2: modif=relative del sensvol\n");fSensVolModifMatrix->Print();
-  // 3) set fSensVolModif = Dg * Gg-1 * Gsv
-  fSensVolModifMatrix->MultiplyLeft( &dg );
-  //printf("\n3: modif= delta*relative\n");fSensVolModifMatrix->Print();
-  
-  // 4) set fSensVolModif = Gg * Dg * Gg-1 * Gsv
-  fSensVolModifMatrix->MultiplyLeft( fMatrix );
-  //printf("\n4: modif=quasi,manca il Gsv-1...\n");fSensVolModifMatrix->Print();
-
-  // 5) set fSensVolModif = Gsv-1 * Gg * Dg * Gg-1 * Gsv
-  if (SensVolMatrix(voluid, &dg)) return NULL;
-  fSensVolModifMatrix->MultiplyLeft( &dg.Inverse() );
-  //printf("\n5: modif=finale\n");fSensVolModifMatrix->Print();
-  //
-  // >> RS
- // 6) mo' fSensVolModif dovrebbe essere la Dsv(loc) t.c. G'sv = Gsv*Dsv(loc)
-  // per trasformarla in Dsv(loc rispetto al Gsv0, non modificato) dovrebbe essere:
-  // Dsv(loc) -> Dpre * Dsv(loc) * Dpre-1
-  //TGeoHMatrix dpre; // dpre = Gsv0-1*Gsv
-  //if (SensVolOrigGlobalMatrix(voluid, &dg)) return NULL;
-  //if (SensVolMatrix(voluid, &dpre)) return NULL;
-  //dpre.MultiplyLeft( &dg.Inverse() );
-  //fSensVolModifMatrix->Multiply( &dpre.Inverse() );
-  //fSensVolModifMatrix->MultiplyLeft( &dpre );
-  // direi che NON FUNZIONA!!!!  
-
-  // << RS
-
-  // reset align object (may not be needed...)
-  fgTempAlignObj.SetVolUID(0);
-  fgTempAlignObj.SetSymName("");
-  fgTempAlignObj.SetTranslation(0,0,0);
-  fgTempAlignObj.SetRotation(0,0,0);
-  //
-  // >> RS
-#ifdef CORHW_
-  // correction for SPD y-shift
-  if (voluid>=2048 && voluid<4256) {
-    TGeoHMatrix deltay;
-    double dy[3]={0.,0.0081,0.};
-    deltay.SetTranslation(dy);
-    fSensVolModifMatrix->MultiplyLeft( &deltay );
-    fSensVolModifMatrix->Multiply( &deltay.Inverse() );
-  }
-#endif
-  // << RS
-  if (!fgTempAlignObj.SetMatrix(*fSensVolModifMatrix)) return NULL;
-  fgTempAlignObj.SetVolUID(voluid);
-  fgTempAlignObj.SetSymName(AliGeomManager::SymName(voluid));
-  //
-  return &fgTempAlignObj;
-}
-
-// >> RS
-//-------------------------------------------------------------
-AliAlignObjParams *AliITSAlignMille2Module::GetSensitiveVolumeTotalMisalignment(UShort_t voluid, Double_t *deltalocal)
-{
-  // calculate misalignment of sens.vol. 'voluid' according with a displacement 'deltalocal'
-  // of the mother volume. The misalignment is returned as AliAlignObjParams object including
-  // the (evenctual) prealignment => no merging needed
-
-  if (!IsIn(voluid)) return NULL;
-  if (!gGeoManager) return NULL;
-  
-  // prepare the TGeoHMatrix
-  Double_t tr[3],ang[3];
-  tr[0]=deltalocal[0]; // in centimeter
-  tr[1]=deltalocal[1]; 
-  tr[2]=deltalocal[2];
-  ang[0]=deltalocal[3]; // psi   (X)  in deg
-  ang[1]=deltalocal[4]; // theta (Y)
-  ang[2]=deltalocal[5]; // phi   (Z)
-
-  // reset align object (may not be needed...)
-  fgTempAlignObj.SetVolUID(0);
-  fgTempAlignObj.SetSymName("");
-  fgTempAlignObj.SetRotation(ang[0],ang[1],ang[2]);
-  fgTempAlignObj.SetTranslation(tr[0],tr[1],tr[2]);
-  AliDebug(3,Form("Delta angles: psi=%f  theta=%f   phi=%f",ang[0],ang[1],ang[2]));
-
-  // Gsv = Gg * Gg-1 * Gsv   -> Lsv,g = Gg-1 * Gsv
-  // G'sv = Gg * Dg * Lsv,g === DGsv * Gsv 
-  //
-  // => Dsv = (G0sv-1 * Gg * Dg * Gg-1 * GMsv)  //
-  //
-
-  // prepare the Delta matrix Dg
-  TGeoHMatrix dg;
-  fgTempAlignObj.GetMatrix(dg);
-  //dg.Print();
-
-  // 1) start setting fSensVolModif = Gsv
-  if (SensVolMatrix(voluid, fSensVolModifMatrix)) return NULL;
-  //printf("\n1: modif=orig del sensvol\n");fSensVolModifMatrix->Print();
-
-  // 2) set fSensVolModif = Gg-1 * Gsv
-  fSensVolModifMatrix->MultiplyLeft( &fMatrix->Inverse() );
-  //printf("\n2: modif=relative del sensvol\n");fSensVolModifMatrix->Print();
-  // 3) set fSensVolModif = Dg * Gg-1 * Gsv
-  fSensVolModifMatrix->MultiplyLeft( &dg );
-  //printf("\n3: modif= delta*relative\n");fSensVolModifMatrix->Print();
-  
-  // 4) set fSensVolModif = Gg * Dg * Gg-1 * Gsv
-  fSensVolModifMatrix->MultiplyLeft( fMatrix );
-  //printf("\n4: modif=quasi,manca il Gsv-1...\n");fSensVolModifMatrix->Print();
-
-  // 5) set fSensVolModif = G0sv-1 * Gg * Dg * Gg-1 * Gsv
-  // qui usa l'orig anziche' la prealigned...
-  if (SensVolOrigGlobalMatrix(voluid, &dg)) return NULL;
-  fSensVolModifMatrix->MultiplyLeft( &dg.Inverse() );
-  //printf("\n5: modif=finale\n");fSensVolModifMatrix->Print();
-
-  // reset align object (may not be needed...)
-  fgTempAlignObj.SetVolUID(0);
-  fgTempAlignObj.SetSymName("");
-  fgTempAlignObj.SetTranslation(0,0,0);
-  fgTempAlignObj.SetRotation(0,0,0);
-
-#ifdef CORHW_
-  // correction for SPD y-shift
-  if (voluid>=2048 && voluid<4256) {
-    TGeoHMatrix deltay;
-    double dy[3]={0.,0.0081,0.};
-    deltay.SetTranslation(dy);
-    fSensVolModifMatrix->MultiplyLeft( &deltay );
-    fSensVolModifMatrix->Multiply( &deltay.Inverse() );
-  }
-#endif
-  if (!fgTempAlignObj.SetMatrix(*fSensVolModifMatrix)) return NULL;
-  fgTempAlignObj.SetVolUID(voluid);
-  fgTempAlignObj.SetSymName(AliGeomManager::SymName(voluid));
-
-  
-  //fgTempAlignObj.Print("");
-
-  return &fgTempAlignObj;
-}
-//-------------------------------------------------------------
-
-//-------------------------------------------------------------
-AliAlignObjParams *AliITSAlignMille2Module::GetSensitiveVolumeGlobalMisalignment(UShort_t voluid, Double_t *deltalocal)
-{
-  // calculate misalignment of sens.vol. 'voluid' according with a displacement 'deltalocal'
-  // of the mother volume. The misalignment is returned as AliAlignObjParams object
-
-  if (!IsIn(voluid)) return NULL;
-  if (!gGeoManager) return NULL;
-  
-  // prepare the TGeoHMatrix
-  Double_t tr[3],ang[3];
-  tr[0]=deltalocal[0]; // in centimeter
-  tr[1]=deltalocal[1]; 
-  tr[2]=deltalocal[2];
-  ang[0]=deltalocal[3]; // psi   (X)  in deg
-  ang[1]=deltalocal[4]; // theta (Y)
-  ang[2]=deltalocal[5]; // phi   (Z)
-
-  // reset align object (may not be needed...)
-  fgTempAlignObj.SetTranslation(0,0,0);
-  fgTempAlignObj.SetRotation(0,0,0);
-
-  fgTempAlignObj.SetRotation(ang[0],ang[1],ang[2]);
-  fgTempAlignObj.SetTranslation(tr[0],tr[1],tr[2]);
-  AliDebug(3,Form("Delta angles: psi=%f  theta=%f   phi=%f",ang[0],ang[1],ang[2]));
-
-  // Gsv = Gg * Gg-1 * Gsv   -> Lsv,g = Gg-1 * Gsv
-  // G'sv = Gg * Dg * Lsv,g === DGsv * Gsv 
-  //
-  // => DGsv = (Gg * Dg * Gg-1)
-  //
-
-  // prepare the Delta matrix Dg
-  TGeoHMatrix dg;
-  fgTempAlignObj.GetMatrix(dg);
-  //dg.Print();
-
-  dg.MultiplyLeft( fMatrix );
-  dg.Multiply( &fMatrix->Inverse() );
-
-  // reset align object (may not be needed...)
-  fgTempAlignObj.SetTranslation(0,0,0);
-  fgTempAlignObj.SetRotation(0,0,0);
-
-  fgTempAlignObj.SetVolUID(voluid);
-  fgTempAlignObj.SetSymName(AliGeomManager::SymName(voluid));
-
-  if (!fgTempAlignObj.SetMatrix(dg)) return NULL;
-  
-  //fgTempAlignObj.Print("");
-
-  return &fgTempAlignObj;
-}
-// << RS
-
-//-------------------------------------------------------------
-TGeoHMatrix *AliITSAlignMille2Module::GetSensitiveVolumeMatrix(UShort_t voluid)
-{
-  // return TGeoHMatrix of the sens.vol. 'voluid' in the current geometry
-  if (SensVolMatrix(voluid,fSensVolMatrix)) return NULL;
-  return fSensVolMatrix;
-}
-
-//-------------------------------------------------------------
-TGeoHMatrix *AliITSAlignMille2Module::GetSensitiveVolumeOrigGlobalMatrix(UShort_t voluid)
-{
-  // return original ideal position (from AliGeomManager::GetOrigGlobalMatrix())
-  if (SensVolOrigGlobalMatrix(voluid,fSensVolMatrix)) return NULL;
-  return fSensVolMatrix;
-}
-//-------------------------------------------------------------
-Int_t AliITSAlignMille2Module::SensVolMatrix(UShort_t volid, TGeoHMatrix *m) 
-{
-  // set matrix for sensitive modules (SPD corrected)
-  // return 0 if success
-  Double_t rot[9];
-  Int_t idx=GetIndexFromVolumeID(volid);
-  if (idx<0) return -1;
-  if (!AliITSgeomTGeo::GetRotation(idx,rot)) return -2;
-  m->SetRotation(rot);
-  Double_t oLoc[3]={0,0,0};
-  Double_t oGlo[3]={0,0,0};
-  if (!AliITSgeomTGeo::LocalToGlobal(idx,oLoc,oGlo)) return -3;
-  m->SetTranslation(oGlo);
-  return 0;
-}
-
-//-------------------------------------------------------------
-Int_t AliITSAlignMille2Module::SensVolOrigGlobalMatrix(UShort_t volid, TGeoHMatrix *m) 
-{
-  // set original global matrix for sensitive modules (SPD corrected)
-  // return 0 if success
-  Int_t idx=GetIndexFromVolumeID(volid);
-  if (idx<0) return -1;
-  TGeoHMatrix mo;
-  if (!AliGeomManager::GetOrigGlobalMatrix(AliGeomManager::SymName(volid),mo)) (*m)=mo;
-
-#ifdef CORHW_
-  // SPD y-shift by 81 mu
-  if (volid<5000) { 
-    Double_t oLoc[3]={0.0,0.0081,0.0};
-    Double_t oGlo[3]={0,0,0};
-    m->LocalToMaster(oLoc,oGlo);
-    m->SetTranslation(oGlo);
-  }
-#endif
-  return 0;
-}
-
-//-------------------------------------------------------------
-UShort_t AliITSAlignMille2Module::GetVolumeIDFromSymname(const Char_t *symname) {
-  /// volume ID from symname
-  if (!symname) return 0;
-
-  for (UShort_t voluid=2000; voluid<13300; voluid++) {
-    Int_t modId;
-    AliGeomManager::ELayerID layerId = AliGeomManager::VolUIDToLayer(voluid,modId);
-    if (layerId>0 && layerId<7 && modId>=0 && modId<AliGeomManager::LayerSize(layerId)) {
-      if (!strcmp(symname,AliGeomManager::SymName(layerId,modId))) return voluid;
-    }
-  }
-
-  return 0;
-}
-
-//-------------------------------------------------------------
-UShort_t AliITSAlignMille2Module::GetVolumeIDFromIndex(Int_t index) {
-  /// volume ID from index
-  if (index<0 || index>2197) return 0;
-  return GetVolumeIDFromSymname(AliITSgeomTGeo::GetSymName(index));
-}
-
-//-------------------------------------------------------------
-void AliITSAlignMille2Module::Print(Option_t*) const 
-{
-  ///
-  printf("*** ITS SuperModule for AliITSAlignMille ***\n");
-  printf("symname  : %s\n",GetName());
-  printf("parent   : %s\n",fParent ? fParent->GetName() : "N/A");
-  printf("volumeID : %4d  | index : %4d\n",fVolumeID,fIndex);
-  printf("Factors  : X=%.2f Y=%.2f Z=%.2f | DOF: Tx:%d Ty:%d Tz:%d Phi:%d Theta:%d Psi:%d\n",
-        fSigmaFactor[0],fSigmaFactor[1],fSigmaFactor[2],
-        IsFreeDOF(AliITSAlignMille2::kDOFTX),IsFreeDOF(AliITSAlignMille2::kDOFTY),
-        IsFreeDOF(AliITSAlignMille2::kDOFTZ),IsFreeDOF(AliITSAlignMille2::kDOFPH),
-        IsFreeDOF(AliITSAlignMille2::kDOFTH),IsFreeDOF(AliITSAlignMille2::kDOFPS));
-  fMatrix->Print();
-  printf("%4d Sensitive volumes | %6d Processed Points\n",fNSensVol,fNProcPoints);
-  for (Int_t i=0; i<fNSensVol; i++) printf("   voluid[%d] = %d\n",i,UShort_t(fSensVolVolumeID[i]));
-}
-
-//-------------------------------------------------------------
-Bool_t AliITSAlignMille2Module::IsAlignable() const
-{
-  TGeoManager* geoManager = AliGeomManager::GetGeometry();
-  if (!geoManager) {
-    AliInfo("Couldn't initialize geometry");
-    return kFALSE;
-  }
-  return geoManager->GetAlignableEntry(GetName())!=0;
-}
-
-//-------------------------------------------------------------
-void AliITSAlignMille2Module::GetLocalMatrix(TGeoHMatrix &mat) const
-{
-  // return the local matrix for transformation to its parent
-  mat = *fMatrix;
-  if (fParent) mat.MultiplyLeft( &fParent->GetMatrix()->Inverse() );
-}
+/************************************************************************** \r
+ * Copyright(c) 2007-2009, ALICE Experiment at CERN, All rights reserved. * \r
+ *                                                                        * \r
+ * Author: The ALICE Off-line Project.                                    * \r
+ * Contributors are mentioned in the code where appropriate.              * \r
+ *                                                                        * \r
+ * Permission to use, copy, modify and distribute this software and its   * \r
+ * documentation strictly for non-commercial purposes is hereby granted   * \r
+ * without fee, provided that the above copyright notice appears in all   * \r
+ * copies and that both the copyright notice and this permission notice   * \r
+ * appear in the supporting documentation. The authors make no claims     * \r
+ * about the suitability of this software for any purpose. It is          * \r
+ * provided "as is" without express or implied warranty.                  * \r
+ **************************************************************************/ \r
\r
+/* $Id$    */ \r
+//----------------------------------------------------------------------------- \r
+/// \class AliITSAlignMille2Module\r
+/// Alignment class for the ALICE ITS detector \r
+/// \r
+/// This class is used by AliITSAlignMille to build custom supermodules    \r
+/// made of ITS sensitive modules. These supermodules are then aligned\r
+/// \r
+/// Custom supermodules must have VolumeID > 14335\r
+///\r
+/// \author M. Lunardon  \r
+//----------------------------------------------------------------------------- \r
\r
+#include <TGeoManager.h> \r
+#include <TGeoMatrix.h> \r
\r
+#include "AliITSAlignMille2Module.h" \r
+#include "AliITSgeomTGeo.h" \r
+#include "AliGeomManager.h" \r
+#include "AliAlignObjParams.h" \r
+#include "AliLog.h" \r
+#include "AliITSAlignMille2.h"\r
\r
+/// \cond CLASSIMP \r
+ClassImp(AliITSAlignMille2Module) \r
+/// \endcond \r
+\r
+#define CORHW_\r
+\r
+AliAlignObjParams AliITSAlignMille2Module::fgTempAlignObj;\r
+const Float_t AliITSAlignMille2Module::fgkDummyConstraint = 1e-2;//1.E3;\r
+    \r
+//-------------------------------------------------------------\r
+AliITSAlignMille2Module::AliITSAlignMille2Module() : \r
+  TNamed(), \r
+  fNSensVol(0), \r
+  fIndex(-1),  \r
+  fDetType(-1),\r
+  fVolumeID(0),\r
+  fNParTot(0),\r
+  fNParFree(0),\r
+  fParOffs(0),\r
+  fNProcPoints(0),\r
+  fParVals(0),\r
+  fParErrs(0),\r
+  fParCstr(0),\r
+  fSensVolIndex(0),\r
+  fSensVolVolumeID(0),\r
+  fMatrix(NULL),\r
+  fSensVolMatrix(NULL),\r
+  fSensVolModifMatrix(NULL),\r
+  fParent(NULL),\r
+  fChildren(0)\r
+{ \r
+  /// void constructor  \r
+  fMatrix = new TGeoHMatrix; \r
+  fSensVolMatrix = new TGeoHMatrix; \r
+  fSensVolModifMatrix = new TGeoHMatrix; \r
+  fSensVolIndex.Set(1);\r
+  fSensVolVolumeID.Set(1);\r
+  fSigmaFactor[0]=fSigmaFactor[1]=fSigmaFactor[2]=1.0;\r
+} \r
+\r
+//-------------------------------------------------------------\r
+AliITSAlignMille2Module::AliITSAlignMille2Module(Int_t index, UShort_t volid, const char* symname,\r
+                                                const TGeoHMatrix *m, Int_t nsv, const UShort_t *volidsv) : \r
+  TNamed(), \r
+  fNSensVol(0), \r
+  fIndex(-1),  \r
+  fDetType(-1),  \r
+  fVolumeID(0),\r
+  fNParTot(0),\r
+  fNParFree(0),\r
+  fParOffs(kMaxParGeom),\r
+  fNProcPoints(0),\r
+  fParVals(0),\r
+  fParErrs(0),\r
+  fParCstr(0),\r
+  fSensVolIndex(0),\r
+  fSensVolVolumeID(0),  \r
+  fMatrix(NULL),\r
+  fSensVolMatrix(NULL),\r
+  fSensVolModifMatrix(NULL),\r
+  fParent(NULL),\r
+  fChildren(0)\r
+{ \r
+  /// void constructor  \r
+  fMatrix = new TGeoHMatrix; \r
+  fSensVolMatrix = new TGeoHMatrix; \r
+  fSensVolModifMatrix = new TGeoHMatrix; \r
+  fSigmaFactor[0]=fSigmaFactor[1]=fSigmaFactor[2]=1.0;\r
+  for (int i=kMaxParGeom;i--;) fParOffs[i] = -1;\r
+  if (Set(index,volid,symname,m,nsv,volidsv)) {\r
+    AliInfo("Error in AliITSAlignMille2Module::Set() - initializing void supermodule...");\r
+  }\r
+  AssignDetType();\r
+} \r
+\r
+//-------------------------------------------------------------\r
+AliITSAlignMille2Module::AliITSAlignMille2Module(UShort_t volid) : \r
+  TNamed(), \r
+  fNSensVol(0), \r
+  fIndex(-1),    \r
+  fDetType(-1),\r
+  fVolumeID(0),\r
+  fNParTot(0),\r
+  fNParFree(0),\r
+  fParOffs(kMaxParGeom),\r
+  fNProcPoints(0),\r
+  fParVals(0),\r
+  fParErrs(0),\r
+  fParCstr(0),  \r
+  fSensVolIndex(0),\r
+  fSensVolVolumeID(0),\r
+  fMatrix(NULL),\r
+  fSensVolMatrix(NULL),\r
+  fSensVolModifMatrix(NULL),\r
+  fParent(NULL),\r
+  fChildren(0)\r
+{ \r
+  /// simple constructor building a supermodule from a single sensitive volume \r
+  fMatrix = new TGeoHMatrix; \r
+  fSensVolMatrix = new TGeoHMatrix; \r
+  fSensVolModifMatrix = new TGeoHMatrix;   \r
+  // temporary align object, just use the rotation...\r
+  fSensVolIndex.Set(1);\r
+  fSensVolVolumeID.Set(1);\r
+  fSigmaFactor[0]=fSigmaFactor[1]=fSigmaFactor[2]=1.0;\r
+  for (int i=kMaxParGeom;i--;) fParOffs[i] = -1;\r
+  //\r
+  fIndex = GetIndexFromVolumeID(volid);  \r
+  if (fIndex>=0 && gGeoManager) { // good sensitive module and geometry loaded\r
+    SetName(AliGeomManager::SymName(volid));\r
+    fVolumeID = volid;\r
+    AddSensitiveVolume(volid);\r
+    SetSensorsProvided(kTRUE);\r
+    if (SensVolMatrix(volid, fMatrix))\r
+       AliInfo("Matrix not defined");\r
+  }\r
+  else {\r
+    AliInfo("Wrong VolumeID or Geometry not loaded - initializing void supermodule...");\r
+  }\r
+  AssignDetType();\r
+} \r
+\r
+\r
+//_____________________________________________________________________________\r
+AliITSAlignMille2Module::AliITSAlignMille2Module(const AliITSAlignMille2Module &m) :\r
+  TNamed(m),\r
+  fNSensVol(m.fNSensVol),\r
+  fIndex(m.fIndex),  \r
+  fDetType(m.fDetType),\r
+  fVolumeID(m.fVolumeID),\r
+  fNParTot(m.fNParTot),\r
+  fNParFree(m.fNParFree),\r
+  fParOffs(m.fNParTot),\r
+  fNProcPoints(0),\r
+  fParVals(0),\r
+  fParErrs(0),\r
+  fParCstr(0),  \r
+  fSensVolIndex(m.fSensVolIndex),\r
+  fSensVolVolumeID(m.fSensVolVolumeID),\r
+  fMatrix(new TGeoHMatrix(*m.GetMatrix())),\r
+  fSensVolMatrix(new TGeoHMatrix),\r
+  fSensVolModifMatrix(new TGeoHMatrix),\r
+  fParent(m.fParent),\r
+  fChildren(0)\r
+{\r
+  // Copy constructor\r
+  fSensVolIndex = m.fSensVolIndex;\r
+  fSensVolVolumeID = m.fSensVolVolumeID;\r
+  for (int i=m.fNParTot;i--;) fParOffs[i] = m.fParOffs[i];\r
+  for (int i=3;i--;) fSigmaFactor[i] = m.fSigmaFactor[i];\r
+  if (fNParTot) {\r
+    fParVals = new Float_t[fNParTot];\r
+    fParErrs = new Float_t[fNParTot];\r
+    fParCstr = new Float_t[fNParTot];\r
+    for (int i=fNParTot;i--;) {\r
+      fParVals[i] = m.fParVals[i];\r
+      fParErrs[i] = m.fParErrs[i];\r
+      fParCstr[i] = m.fParCstr[i];\r
+    }\r
+  }\r
+}\r
+\r
+//_____________________________________________________________________________\r
+AliITSAlignMille2Module& AliITSAlignMille2Module::operator=(const AliITSAlignMille2Module &m)  \r
+{\r
+  // operator =\r
+  //\r
+  if(this==&m) return *this;\r
+  ((TNamed *)this)->operator=(m);\r
+  //\r
+  fNSensVol=m.fNSensVol;\r
+  fIndex=m.fIndex;\r
+  fDetType = m.fDetType;\r
+  fVolumeID=m.fVolumeID;\r
+  fNParTot  = m.fNParTot;\r
+  fNParFree = m.fNParFree;\r
+  delete[] fParVals; fParVals = 0;\r
+  delete[] fParErrs; fParErrs = 0;\r
+  delete[] fParCstr; fParCstr = 0;\r
+  //\r
+  if (fNParTot) {\r
+    fParVals = new Float_t[fNParTot];\r
+    fParErrs = new Float_t[fNParTot];\r
+    fParCstr = new Float_t[fNParTot];\r
+    for (int i=m.GetNParTot();i--;) {\r
+      fParVals[i] = m.fParVals[i];\r
+      fParErrs[i] = m.fParErrs[i];\r
+      fParCstr[i] = m.fParCstr[i];\r
+    }\r
+  }\r
+  //\r
+  fParOffs.Set(fNParTot);\r
+  for (int i=0;i<fNParTot;i++) fParOffs[i] = m.fParOffs[i];\r
+  for (int i=3;i--;) fSigmaFactor[i] = m.fSigmaFactor[i];\r
+  if (fMatrix) delete fMatrix;\r
+  fMatrix=new TGeoHMatrix(*m.GetMatrix());\r
+  fSensVolIndex = m.fSensVolIndex;\r
+  fSensVolVolumeID = m.fSensVolVolumeID;\r
+  fParent = m.fParent;\r
+  fChildren.Clear();\r
+  for (int i=0;i<m.GetNChildren();i++) fChildren.Add(m.GetChild(i));\r
+  return *this;\r
+}\r
+\r
+\r
+//-------------------------------------------------------------\r
+AliITSAlignMille2Module::~AliITSAlignMille2Module() { \r
+  /// Destructor \r
+  delete fMatrix; \r
+  delete fSensVolMatrix; \r
+  delete fSensVolModifMatrix; \r
+  delete[] fParVals;\r
+  delete[] fParErrs;\r
+  delete[] fParCstr;\r
+  fChildren.Clear();\r
+} \r
+\r
+//-------------------------------------------------------------\r
+Int_t AliITSAlignMille2Module::Set(Int_t index, UShort_t volid, const char* symname, \r
+                                  const TGeoHMatrix *m, Int_t nsv, const UShort_t *volidsv) \r
+{\r
+  // initialize a custom supermodule\r
+  // index, volid, symname and matrix must be given\r
+  // if (volidsv) add nsv sensitive volumes to the supermodules\r
+  // return 0 if success\r
+\r
+  if (index<2198) {\r
+    AliInfo("Index must be >= 2198");\r
+    return -1;\r
+  }\r
+  if (volid<14336) {\r
+    AliInfo("VolumeID must be >= 14336");\r
+    return -2;\r
+  }\r
+  \r
+  if (!symname) return -3;\r
+  for (Int_t i=0; i<2198; i++) {\r
+    if (!strcmp(symname,AliITSgeomTGeo::GetSymName(i))) {\r
+      AliInfo("Symname already used by a Sensitive Volume");\r
+      return -3;\r
+    }\r
+  }\r
+  \r
+  if (!m) return -4;\r
+\r
+  // can initialize needed stuffs\r
+  fIndex = index;\r
+  fVolumeID = volid;\r
+  SetName(symname);\r
+  //\r
+  (*fMatrix) = (*m);\r
+  //\r
+  fSensVolIndex.Set(nsv);\r
+  fSensVolVolumeID.Set(nsv);\r
+  // add sensitive volumes\r
+  for (Int_t i=0; i<nsv; i++) AddSensitiveVolume(volidsv[i]);\r
+\r
+  return 0;\r
+}\r
+\r
+//-------------------------------------------------------------\r
+void AliITSAlignMille2Module::SetFreeDOF(Int_t dof,Double_t cstr)\r
+{\r
+  if (AliITSAlignMille2::IsZero(cstr)) fParCstr[dof] = 0;  // fixed parameter\r
+  else if (cstr>0)                     fParCstr[dof] = fgkDummyConstraint+1.; // the parameter is free and unconstrained\r
+  else                                 fParCstr[dof] = -cstr;                 // the parameter is free but constrained\r
+}\r
+\r
+//-------------------------------------------------------------\r
+Bool_t AliITSAlignMille2Module::IsSensor(UShort_t voluid) \r
+{\r
+  // Does this volid correspond to sensor ?\r
+  AliGeomManager::ELayerID layId = AliGeomManager::VolUIDToLayerSafe(voluid);\r
+  if (layId>0 && layId<7) {\r
+    Int_t mId = Int_t(voluid & 0x7ff);\r
+    if( mId>=0 && mId<AliGeomManager::LayerSize(layId)) return kTRUE;\r
+  }\r
+  return kFALSE;\r
+}\r
+\r
+//-------------------------------------------------------------\r
+Int_t AliITSAlignMille2Module::GetIndexFromVolumeID(UShort_t voluid) {\r
+  /// index from volume ID\r
+  AliGeomManager::ELayerID lay = AliGeomManager::VolUIDToLayer(voluid);\r
+  if (lay<1|| lay>6) return -1;\r
+  Int_t idx=Int_t(voluid)-2048*lay;\r
+  if (idx>=AliGeomManager::LayerSize(lay)) return -1;\r
+  for (Int_t ilay=1; ilay<lay; ilay++) \r
+    idx += AliGeomManager::LayerSize(ilay);\r
+  return idx;\r
+}\r
+\r
+//-------------------------------------------------------------\r
+void AliITSAlignMille2Module::AddSensitiveVolume(UShort_t voluid)\r
+{\r
+  /// add a sensitive volume to this supermodule\r
+  if (GetIndexFromVolumeID(voluid)<0) return; // bad volid\r
+  //\r
+  // in principle, the correct size of fSensVol... arrays was set outside but check anyway\r
+  if (fSensVolVolumeID.GetSize()<fNSensVol+1) {\r
+    fSensVolVolumeID.Set(fNSensVol+1);\r
+    fSensVolIndex.Set(fNSensVol+1);\r
+  }\r
+  //\r
+  fSensVolVolumeID[fNSensVol] = Short_t(voluid);\r
+  fSensVolIndex[fNSensVol] = GetIndexFromVolumeID(voluid);\r
+  fNSensVol++;\r
+}\r
+\r
+//-------------------------------------------------------------\r
+void AliITSAlignMille2Module::DelSensitiveVolume(Int_t at)\r
+{\r
+  // Suppress sensor at position "at"\r
+  // in fact we are swapping with the last valid one \r
+  int lastValid = --fNSensVol;\r
+  int tmpv = fSensVolIndex[at];\r
+  fSensVolIndex[at] = fSensVolIndex[lastValid];\r
+  tmpv = fSensVolVolumeID[at];\r
+  fSensVolVolumeID[at] = fSensVolVolumeID[lastValid];\r
+  fSensVolVolumeID[lastValid] = tmpv;\r
+  //\r
+}\r
+\r
+//-------------------------------------------------------------\r
+Bool_t AliITSAlignMille2Module::IsIn(UShort_t voluid) const \r
+{\r
+  /// check if voluid is defined\r
+  if (!voluid) return kFALSE; // only positive voluid are accepted\r
+  for (Int_t i=0; i<fNSensVol; i++) if (UShort_t(fSensVolVolumeID[i])==voluid) return kTRUE;\r
+  return kFALSE;\r
+}\r
+\r
+//-------------------------------------------------------------\r
+Bool_t AliITSAlignMille2Module::BelongsTo(AliITSAlignMille2Module* parent) const\r
+{\r
+  /// check if parent contains the sensors of this volume\r
+  if (fNSensVol<1 || fNSensVol>=parent->GetNSensitiveVolumes()) return kFALSE;\r
+  return parent->IsIn( fSensVolVolumeID[0] );\r
+}\r
+\r
+//-------------------------------------------------------------\r
+TGeoHMatrix *AliITSAlignMille2Module::GetSensitiveVolumeModifiedMatrix(UShort_t voluid, Double_t *delta,Bool_t local)\r
+{\r
+  // modify the original TGeoHMatrix of the sensitive module 'voluid' according\r
+  // with a delta transform. applied to the supermodule matrix\r
+  // return NULL if error\r
+\r
+  if (!IsIn(voluid)) return NULL;\r
+  if (!gGeoManager)  return NULL;\r
+\r
+  // prepare the TGeoHMatrix\r
+  Double_t tr[3],ang[3];\r
+  tr[0]=delta[0]; // in centimeter\r
+  tr[1]=delta[1]; \r
+  tr[2]=delta[2];\r
+  ang[0]=delta[3]; // psi   (X)  in deg\r
+  ang[1]=delta[4]; // theta (Y)\r
+  ang[2]=delta[5]; // phi   (Z)\r
+  //\r
+  fgTempAlignObj.SetRotation(ang[0],ang[1],ang[2]);\r
+  fgTempAlignObj.SetTranslation(tr[0],tr[1],tr[2]);\r
+  AliDebug(3,Form("Delta angles: psi=%f  theta=%f   phi=%f",ang[0],ang[1],ang[2]));\r
+  TGeoHMatrix hm;\r
+  fgTempAlignObj.GetMatrix(hm);\r
+  //printf("\n0: delta matrix\n");hm.Print();\r
+\r
+  // 1) start setting fSensVolModif = fSensVol\r
+  if (SensVolMatrix(voluid, fSensVolModifMatrix)) return NULL;\r
+  //\r
+  if (local) {\r
+    // 2) set fSensVolModif = SensVolRel\r
+    fSensVolModifMatrix->MultiplyLeft( &fMatrix->Inverse() );\r
+    // 3) multiply left by delta\r
+    fSensVolModifMatrix->MultiplyLeft( &hm );\r
+    // 4) multiply left by fMatrix\r
+    fSensVolModifMatrix->MultiplyLeft( fMatrix );\r
+  }\r
+  else fSensVolModifMatrix->MultiplyLeft( &hm );\r
+  //\r
+  return fSensVolModifMatrix;\r
+}\r
+\r
+//-------------------------------------------------------------\r
+AliAlignObjParams *AliITSAlignMille2Module::GetSensitiveVolumeMisalignment(UShort_t voluid, Double_t *deltalocal)\r
+{\r
+  // calculate misalignment of sens.vol. 'voluid' according with a displacement 'deltalocal'\r
+  // of the mother volume. The misalignment is returned as AliAlignObjParams object\r
+\r
+  if (!IsIn(voluid)) return NULL;\r
+  if (!gGeoManager) return NULL;\r
+  \r
+  // prepare the TGeoHMatrix\r
+  Double_t tr[3],ang[3];\r
+  tr[0]=deltalocal[0]; // in centimeter\r
+  tr[1]=deltalocal[1]; \r
+  tr[2]=deltalocal[2];\r
+  ang[0]=deltalocal[3]; // psi   (X)  in deg\r
+  ang[1]=deltalocal[4]; // theta (Y)\r
+  ang[2]=deltalocal[5]; // phi   (Z)\r
+  //\r
+  fgTempAlignObj.SetRotation(ang[0],ang[1],ang[2]);\r
+  fgTempAlignObj.SetTranslation(tr[0],tr[1],tr[2]);\r
+  AliDebug(3,Form("Delta angles: psi=%f  theta=%f   phi=%f",ang[0],ang[1],ang[2]));\r
+  //\r
+  return GetSensitiveVolumeMisalignment(voluid,&fgTempAlignObj);\r
+}\r
+\r
+//-------------------------------------------------------------\r
+AliAlignObjParams *AliITSAlignMille2Module::GetSensitiveVolumeMisalignment(UShort_t voluid, AliAlignObjParams *a)\r
+{\r
+  // return the misalignment of the sens. vol. 'voluid' corresponding with \r
+  // a misalignment 'a' in the mother volume\r
+  // return NULL if error\r
+\r
+  // Gsv = Gg * Gg-1 * Gsv   -> Lsv,g = Gg-1 * Gsv\r
+  // G'sv = Gg * Dg * Lsv,g === Gsv * Dsv\r
+  // Gg * Dg * Gg-1 * Gsv = Gsv * Gsv-1 * Gg * Dg * Gg-1 * Gsv\r
+  //\r
+  // => Dsv = (Gsv-1 * Gg * Dg * Gg-1 * Gsv)\r
+  //\r
+\r
+  if (!IsIn(voluid)) return NULL;\r
+  if (!gGeoManager) return NULL;\r
+\r
+  //a->Print("");\r
+\r
+  // prepare the Delta matrix Dg\r
+  TGeoHMatrix dg;\r
+  a->GetMatrix(dg);\r
+  //dg.Print();\r
+\r
+  // 1) start setting fSensVolModif = Gsv\r
+  if (SensVolMatrix(voluid, fSensVolModifMatrix)) return NULL;\r
+  //printf("\n1: modif=orig del sensvol\n");fSensVolModifMatrix->Print();\r
+\r
+  // 2) set fSensVolModif = Gg-1 * Gsv\r
+  fSensVolModifMatrix->MultiplyLeft( &fMatrix->Inverse() );\r
+  //printf("\n2: modif=relative del sensvol\n");fSensVolModifMatrix->Print();\r
\r
+  // 3) set fSensVolModif = Dg * Gg-1 * Gsv\r
+  fSensVolModifMatrix->MultiplyLeft( &dg );\r
+  //printf("\n3: modif= delta*relative\n");fSensVolModifMatrix->Print();\r
+  \r
+  // 4) set fSensVolModif = Gg * Dg * Gg-1 * Gsv\r
+  fSensVolModifMatrix->MultiplyLeft( fMatrix );\r
+  //printf("\n4: modif=quasi,manca il Gsv-1...\n");fSensVolModifMatrix->Print();\r
+\r
+  // 5) set fSensVolModif = Gsv-1 * Gg * Dg * Gg-1 * Gsv\r
+  if (SensVolMatrix(voluid, &dg)) return NULL;\r
+  fSensVolModifMatrix->MultiplyLeft( &dg.Inverse() );\r
+  //printf("\n5: modif=finale\n");fSensVolModifMatrix->Print();\r
+  //\r
+  // >> RS\r
+ // 6) mo' fSensVolModif dovrebbe essere la Dsv(loc) t.c. G'sv = Gsv*Dsv(loc)\r
+  // per trasformarla in Dsv(loc rispetto al Gsv0, non modificato) dovrebbe essere:\r
+  // Dsv(loc) -> Dpre * Dsv(loc) * Dpre-1\r
+  //TGeoHMatrix dpre; // dpre = Gsv0-1*Gsv\r
+  //if (SensVolOrigGlobalMatrix(voluid, &dg)) return NULL;\r
+  //if (SensVolMatrix(voluid, &dpre)) return NULL;\r
+  //dpre.MultiplyLeft( &dg.Inverse() );\r
+  //fSensVolModifMatrix->Multiply( &dpre.Inverse() );\r
+  //fSensVolModifMatrix->MultiplyLeft( &dpre );\r
+  // direi che NON FUNZIONA!!!!  \r
+\r
+  // << RS\r
+\r
+  // reset align object (may not be needed...)\r
+  fgTempAlignObj.SetVolUID(0);\r
+  fgTempAlignObj.SetSymName("");\r
+  fgTempAlignObj.SetTranslation(0,0,0);\r
+  fgTempAlignObj.SetRotation(0,0,0);\r
+  //\r
+  // >> RS\r
+#ifdef CORHW_\r
+  // correction for SPD y-shift\r
+  if (voluid>=2048 && voluid<4256) {\r
+    TGeoHMatrix deltay;\r
+    double dy[3]={0.,0.0081,0.};\r
+    deltay.SetTranslation(dy);\r
+    fSensVolModifMatrix->MultiplyLeft( &deltay );\r
+    fSensVolModifMatrix->Multiply( &deltay.Inverse() );\r
+  }\r
+#endif\r
+  // << RS\r
+  if (!fgTempAlignObj.SetMatrix(*fSensVolModifMatrix)) return NULL;\r
+  fgTempAlignObj.SetVolUID(voluid);\r
+  fgTempAlignObj.SetSymName(AliGeomManager::SymName(voluid));\r
+  //\r
+  return &fgTempAlignObj;\r
+}\r
+\r
+// >> RS\r
+//-------------------------------------------------------------\r
+AliAlignObjParams *AliITSAlignMille2Module::GetSensitiveVolumeTotalMisalignment(UShort_t voluid, Double_t *deltalocal)\r
+{\r
+  // calculate misalignment of sens.vol. 'voluid' according with a displacement 'deltalocal'\r
+  // of the mother volume. The misalignment is returned as AliAlignObjParams object including\r
+  // the (evenctual) prealignment => no merging needed\r
+\r
+  if (!IsIn(voluid)) return NULL;\r
+  if (!gGeoManager) return NULL;\r
+  \r
+  // prepare the TGeoHMatrix\r
+  Double_t tr[3],ang[3];\r
+  tr[0]=deltalocal[0]; // in centimeter\r
+  tr[1]=deltalocal[1]; \r
+  tr[2]=deltalocal[2];\r
+  ang[0]=deltalocal[3]; // psi   (X)  in deg\r
+  ang[1]=deltalocal[4]; // theta (Y)\r
+  ang[2]=deltalocal[5]; // phi   (Z)\r
+\r
+  // reset align object (may not be needed...)\r
+  fgTempAlignObj.SetVolUID(0);\r
+  fgTempAlignObj.SetSymName("");\r
+  fgTempAlignObj.SetRotation(ang[0],ang[1],ang[2]);\r
+  fgTempAlignObj.SetTranslation(tr[0],tr[1],tr[2]);\r
+  AliDebug(3,Form("Delta angles: psi=%f  theta=%f   phi=%f",ang[0],ang[1],ang[2]));\r
+\r
+  // Gsv = Gg * Gg-1 * Gsv   -> Lsv,g = Gg-1 * Gsv\r
+  // G'sv = Gg * Dg * Lsv,g === DGsv * Gsv \r
+  //\r
+  // => Dsv = (G0sv-1 * Gg * Dg * Gg-1 * GMsv)  //\r
+  //\r
+\r
+  // prepare the Delta matrix Dg\r
+  TGeoHMatrix dg;\r
+  fgTempAlignObj.GetMatrix(dg);\r
+  //dg.Print();\r
+\r
+  // 1) start setting fSensVolModif = Gsv\r
+  if (SensVolMatrix(voluid, fSensVolModifMatrix)) return NULL;\r
+  //printf("\n1: modif=orig del sensvol\n");fSensVolModifMatrix->Print();\r
+\r
+  // 2) set fSensVolModif = Gg-1 * Gsv\r
+  fSensVolModifMatrix->MultiplyLeft( &fMatrix->Inverse() );\r
+  //printf("\n2: modif=relative del sensvol\n");fSensVolModifMatrix->Print();\r
\r
+  // 3) set fSensVolModif = Dg * Gg-1 * Gsv\r
+  fSensVolModifMatrix->MultiplyLeft( &dg );\r
+  //printf("\n3: modif= delta*relative\n");fSensVolModifMatrix->Print();\r
+  \r
+  // 4) set fSensVolModif = Gg * Dg * Gg-1 * Gsv\r
+  fSensVolModifMatrix->MultiplyLeft( fMatrix );\r
+  //printf("\n4: modif=quasi,manca il Gsv-1...\n");fSensVolModifMatrix->Print();\r
+\r
+  // 5) set fSensVolModif = G0sv-1 * Gg * Dg * Gg-1 * Gsv\r
+  // qui usa l'orig anziche' la prealigned...\r
+  if (SensVolOrigGlobalMatrix(voluid, &dg)) return NULL;\r
+  fSensVolModifMatrix->MultiplyLeft( &dg.Inverse() );\r
+  //printf("\n5: modif=finale\n");fSensVolModifMatrix->Print();\r
+\r
+  // reset align object (may not be needed...)\r
+  fgTempAlignObj.SetVolUID(0);\r
+  fgTempAlignObj.SetSymName("");\r
+  fgTempAlignObj.SetTranslation(0,0,0);\r
+  fgTempAlignObj.SetRotation(0,0,0);\r
+\r
+#ifdef CORHW_\r
+  // correction for SPD y-shift\r
+  if (voluid>=2048 && voluid<4256) {\r
+    TGeoHMatrix deltay;\r
+    double dy[3]={0.,0.0081,0.};\r
+    deltay.SetTranslation(dy);\r
+    fSensVolModifMatrix->MultiplyLeft( &deltay );\r
+    fSensVolModifMatrix->Multiply( &deltay.Inverse() );\r
+  }\r
+#endif\r
+  if (!fgTempAlignObj.SetMatrix(*fSensVolModifMatrix)) return NULL;\r
+  fgTempAlignObj.SetVolUID(voluid);\r
+  fgTempAlignObj.SetSymName(AliGeomManager::SymName(voluid));\r
+\r
+  \r
+  //fgTempAlignObj.Print("");\r
+\r
+  return &fgTempAlignObj;\r
+}\r
+//-------------------------------------------------------------\r
+\r
+//-------------------------------------------------------------\r
+AliAlignObjParams *AliITSAlignMille2Module::GetSensitiveVolumeGlobalMisalignment(UShort_t voluid, Double_t *deltalocal)\r
+{\r
+  // calculate misalignment of sens.vol. 'voluid' according with a displacement 'deltalocal'\r
+  // of the mother volume. The misalignment is returned as AliAlignObjParams object\r
+\r
+  if (!IsIn(voluid)) return NULL;\r
+  if (!gGeoManager) return NULL;\r
+  \r
+  // prepare the TGeoHMatrix\r
+  Double_t tr[3],ang[3];\r
+  tr[0]=deltalocal[0]; // in centimeter\r
+  tr[1]=deltalocal[1]; \r
+  tr[2]=deltalocal[2];\r
+  ang[0]=deltalocal[3]; // psi   (X)  in deg\r
+  ang[1]=deltalocal[4]; // theta (Y)\r
+  ang[2]=deltalocal[5]; // phi   (Z)\r
+\r
+  // reset align object (may not be needed...)\r
+  fgTempAlignObj.SetTranslation(0,0,0);\r
+  fgTempAlignObj.SetRotation(0,0,0);\r
+\r
+  fgTempAlignObj.SetRotation(ang[0],ang[1],ang[2]);\r
+  fgTempAlignObj.SetTranslation(tr[0],tr[1],tr[2]);\r
+  AliDebug(3,Form("Delta angles: psi=%f  theta=%f   phi=%f",ang[0],ang[1],ang[2]));\r
+\r
+  // Gsv = Gg * Gg-1 * Gsv   -> Lsv,g = Gg-1 * Gsv\r
+  // G'sv = Gg * Dg * Lsv,g === DGsv * Gsv \r
+  //\r
+  // => DGsv = (Gg * Dg * Gg-1)\r
+  //\r
+\r
+  // prepare the Delta matrix Dg\r
+  TGeoHMatrix dg;\r
+  fgTempAlignObj.GetMatrix(dg);\r
+  //dg.Print();\r
+\r
+  dg.MultiplyLeft( fMatrix );\r
+  dg.Multiply( &fMatrix->Inverse() );\r
+\r
+  // reset align object (may not be needed...)\r
+  fgTempAlignObj.SetTranslation(0,0,0);\r
+  fgTempAlignObj.SetRotation(0,0,0);\r
+\r
+  fgTempAlignObj.SetVolUID(voluid);\r
+  fgTempAlignObj.SetSymName(AliGeomManager::SymName(voluid));\r
+\r
+  if (!fgTempAlignObj.SetMatrix(dg)) return NULL;\r
+  \r
+  //fgTempAlignObj.Print("");\r
+\r
+  return &fgTempAlignObj;\r
+}\r
+// << RS\r
+\r
+//-------------------------------------------------------------\r
+TGeoHMatrix *AliITSAlignMille2Module::GetSensitiveVolumeMatrix(UShort_t voluid)\r
+{\r
+  // return TGeoHMatrix of the sens.vol. 'voluid' in the current geometry\r
+  if (SensVolMatrix(voluid,fSensVolMatrix)) return NULL;\r
+  return fSensVolMatrix;\r
+}\r
+\r
+//-------------------------------------------------------------\r
+TGeoHMatrix *AliITSAlignMille2Module::GetSensitiveVolumeOrigGlobalMatrix(UShort_t voluid)\r
+{\r
+  // return original ideal position (from AliGeomManager::GetOrigGlobalMatrix())\r
+  if (SensVolOrigGlobalMatrix(voluid,fSensVolMatrix)) return NULL;\r
+  return fSensVolMatrix;\r
+}\r
+//-------------------------------------------------------------\r
+Int_t AliITSAlignMille2Module::SensVolMatrix(UShort_t volid, TGeoHMatrix *m) \r
+{\r
+  // set matrix for sensitive modules (SPD corrected)\r
+  // return 0 if success\r
+  Double_t rot[9];\r
+  Int_t idx=GetIndexFromVolumeID(volid);\r
+  if (idx<0) return -1;\r
+  if (!AliITSgeomTGeo::GetRotation(idx,rot)) return -2;\r
+  m->SetRotation(rot);\r
+  Double_t oLoc[3]={0,0,0};\r
+  Double_t oGlo[3]={0,0,0};\r
+  if (!AliITSgeomTGeo::LocalToGlobal(idx,oLoc,oGlo)) return -3;\r
+  m->SetTranslation(oGlo);\r
+  return 0;\r
+}\r
+\r
+//-------------------------------------------------------------\r
+Int_t AliITSAlignMille2Module::SensVolOrigGlobalMatrix(UShort_t volid, TGeoHMatrix *m) \r
+{\r
+  // set original global matrix for sensitive modules (SPD corrected)\r
+  // return 0 if success\r
+  Int_t idx=GetIndexFromVolumeID(volid);\r
+  if (idx<0) return -1;\r
+  TGeoHMatrix mo;\r
+  if (!AliGeomManager::GetOrigGlobalMatrix(AliGeomManager::SymName(volid),mo)) return -1;\r
+  (*m)=mo;\r
+  //\r
+#ifdef CORHW_\r
+  // SPD y-shift by 81 mu\r
+  if (volid<5000) { \r
+    Double_t oLoc[3]={0.0,0.0081,0.0};\r
+    Double_t oGlo[3]={0,0,0};\r
+    m->LocalToMaster(oLoc,oGlo);\r
+    m->SetTranslation(oGlo);\r
+  }\r
+#endif\r
+  return 0;\r
+}\r
+\r
+//-------------------------------------------------------------\r
+UShort_t AliITSAlignMille2Module::GetVolumeIDFromSymname(const Char_t *symname) {\r
+  /// volume ID from symname\r
+  if (!symname) return 0;\r
+\r
+  for (UShort_t voluid=2000; voluid<13300; voluid++) {\r
+    Int_t modId;\r
+    AliGeomManager::ELayerID layerId = AliGeomManager::VolUIDToLayer(voluid,modId);\r
+    if (layerId>0 && layerId<7 && modId>=0 && modId<AliGeomManager::LayerSize(layerId)) {\r
+      if (!strcmp(symname,AliGeomManager::SymName(layerId,modId))) return voluid;\r
+    }\r
+  }\r
+\r
+  return 0;\r
+}\r
+\r
+//-------------------------------------------------------------\r
+UShort_t AliITSAlignMille2Module::GetVolumeIDFromIndex(Int_t index) {\r
+  /// volume ID from index\r
+  if (index<0 || index>2197) return 0;\r
+  return GetVolumeIDFromSymname(AliITSgeomTGeo::GetSymName(index));\r
+}\r
+\r
+//-------------------------------------------------------------\r
+void AliITSAlignMille2Module::Print(Option_t*) const \r
+{\r
+  //\r
+  const char* typeName[] = {"SPD","SDD","SSD"};\r
+  printf("*** ITS SuperModule for AliITSAlignMille ***\n");\r
+  printf("symname  : %s (type: %s)\n",GetName(),fDetType<0 ? "N/A":typeName[fDetType]);\r
+  printf("parent   : %s | %d children\n",fParent ? fParent->GetName() : "N/A",GetNChildren());\r
+  printf("volumeID : %4d  | index : %4d | Geom.Params are %s\n",fVolumeID,fIndex,\r
+        GeomParamsGlobal() ? "Global":"Local");\r
+  printf("Factors  : X=%.2f Y=%.2f Z=%.2f\n"\r
+        "DOF: %cTx:%5d| %cTy:%5d| %cTz:%5d| %cPsi:%5d| %cTheta:%5d| %cPhi:%5d|",\r
+        fSigmaFactor[0],fSigmaFactor[1],fSigmaFactor[2],\r
+        IsFreeDOF(kDOFTX) ? '+':'-',GetParOffset(kDOFTX),IsFreeDOF(kDOFTY) ? '+':'-',GetParOffset(kDOFTY),\r
+        IsFreeDOF(kDOFTZ) ? '+':'-',GetParOffset(kDOFTZ),IsFreeDOF(kDOFPS) ? '+':'-',GetParOffset(kDOFPS),\r
+        IsFreeDOF(kDOFTH) ? '+':'-',GetParOffset(kDOFTH),IsFreeDOF(kDOFPH) ? '+':'-',GetParOffset(kDOFPH));\r
+  if (IsSDD()) {\r
+    printf("%cT0:%5d| %cDVl:%5d| %cDVr:%5d|",IsFreeDOF(kDOFT0)?'+':'-',GetParOffset(kDOFT0),\r
+          IsFreeDOF(kDOFDVL)?'+':'-',GetParOffset(kDOFDVL),IsFreeDOF(kDOFDVR)?'+':'-',GetParOffset(kDOFDVR));\r
+    if (IsVDriftLRSame()) printf("(dVL=dVR)");\r
+  }\r
+  printf("\n");\r
+  fMatrix->Print();\r
+  printf("%4d Sensitive volumes | %6d Processed Points\n",fNSensVol,fNProcPoints);\r
+  for (Int_t i=0; i<fNSensVol; i++) printf("   voluid[%d] = %d\n",i,UShort_t(fSensVolVolumeID[i]));\r
+}\r
+\r
+//-------------------------------------------------------------\r
+Bool_t AliITSAlignMille2Module::IsAlignable() const\r
+{\r
+  TGeoManager* geoManager = AliGeomManager::GetGeometry();\r
+  if (!geoManager) {\r
+    AliInfo("Couldn't initialize geometry");\r
+    return kFALSE;\r
+  }\r
+  return geoManager->GetAlignableEntry(GetName())!=0;\r
+}\r
+\r
+//-------------------------------------------------------------\r
+void AliITSAlignMille2Module::GetLocalMatrix(TGeoHMatrix &mat) const\r
+{\r
+  // return the local matrix for transformation to its parent\r
+  mat = *fMatrix;\r
+  if (fParent) mat.MultiplyLeft( &fParent->GetMatrix()->Inverse() );\r
+}\r
+\r
+//-------------------------------------------------------------\r
+void AliITSAlignMille2Module::AssignDetType()\r
+{\r
+  TString tp = GetName();\r
+  if      (tp.Contains("SPD",TString::kIgnoreCase)) fDetType = kSPD;\r
+  else if (tp.Contains("SDD",TString::kIgnoreCase)) fDetType = kSDD;\r
+  else if (tp.Contains("SSD",TString::kIgnoreCase)) fDetType = kSSD;\r
+  else fDetType = -1;\r
+  fNParTot = IsSDD() ? kMaxParTot:kMaxParGeom;\r
+  fNParFree = 0;\r
+  fParVals = new Float_t[fNParTot];\r
+  fParErrs = new Float_t[fNParTot];  \r
+  fParCstr = new Float_t[fNParTot];  \r
+  if (fParOffs.GetSize()<fNParTot) fParOffs.Set(fNParTot);\r
+  for (int i=fNParTot;i--;) {\r
+    fParVals[i] = fParErrs[i] = 0.; \r
+    fParCstr[i] = 0.;\r
+    fParOffs[i] = -1;\r
+  }\r
+}\r
+\r
+//-------------------------------------------------------------\r
+void AliITSAlignMille2Module::EvaluateDOF()\r
+{\r
+  fNParFree = 0;\r
+  for (int i=fNParTot;i--;) if (IsFreeDOF(i)) fNParFree++;\r
+}\r
+\r
+//-------------------------------------------------------------\r
+void AliITSAlignMille2Module::GetSensVolGlobalParams(UShort_t volid,Double_t *t, Double_t *r)\r
+{\r
+  // return global parameters of the sensor volid\r
+  for (int i=3;i--;) t[i] = r[i] = 0.;\r
+  if (SensVolMatrix(volid,fSensVolMatrix)) return;  \r
+  fgTempAlignObj.SetMatrix(*fSensVolMatrix);\r
+  fgTempAlignObj.GetPars(t,r);\r
+}\r
+\r
+//-------------------------------------------------------------\r
+void AliITSAlignMille2Module::GetSensVolLocalParams(UShort_t volid,Double_t *t, Double_t *r)\r
+{\r
+  // return parameters of the sensor volid in the current module\r
+  for (int i=3;i--;) t[i] = r[i] = 0.;\r
+  if (SensVolMatrix(volid,fSensVolMatrix)) return;  \r
+  fSensVolMatrix->MultiplyLeft( &fMatrix->Inverse() );\r
+  fgTempAlignObj.SetMatrix(*fSensVolMatrix);\r
+  fgTempAlignObj.GetPars(t,r);\r
+}\r
+\r
+//-------------------------------------------------------------\r
+void AliITSAlignMille2Module::GetSensVolGlobalParams(UShort_t volid,Double_t* loct,Double_t* locr,Double_t *t, Double_t *r)\r
+{\r
+  // return global parameters of the sensor volid modified by the localDelta params\r
+  for (int i=3;i--;) t[i] = r[i] = 0.;\r
+  if (SensVolMatrix(volid,fSensVolMatrix)) return;  \r
+  fgTempAlignObj.SetTranslation(loct[0],loct[1],loct[2]);\r
+  fgTempAlignObj.SetRotation(locr[0],locr[1],locr[2]);\r
+  //\r
+  fgTempAlignObj.GetMatrix(*fSensVolModifMatrix);      // obtain local delta\r
+  fSensVolModifMatrix->MultiplyLeft( fSensVolMatrix ); // obtain global delta\r
+  fgTempAlignObj.SetMatrix(*fSensVolModifMatrix);\r
+  fgTempAlignObj.GetPars(t,r);                         // obtain global params\r
+}\r
+\r
+//-------------------------------------------------------------\r
+void AliITSAlignMille2Module::GetSensVolLocalParams(UShort_t volid,Double_t* loct,Double_t* locr,Double_t *t, Double_t *r)\r
+{\r
+  // return parameters of the sensor volid (modified by the localDelta params) in the current volume\r
+  for (int i=3;i--;) t[i] = r[i] = 0.;\r
+  if (SensVolMatrix(volid,fSensVolMatrix)) return;  \r
+  fgTempAlignObj.SetTranslation(loct[0],loct[1],loct[2]);\r
+  fgTempAlignObj.SetRotation(locr[0],locr[1],locr[2]);\r
+  //\r
+  fgTempAlignObj.GetMatrix(*fSensVolModifMatrix);      // obtain local delta\r
+  fSensVolModifMatrix->MultiplyLeft( fSensVolMatrix ); // obtain global delta\r
+  fSensVolModifMatrix->MultiplyLeft( &fMatrix->Inverse() ); // obtain delta in current volume\r
+  fgTempAlignObj.SetMatrix(*fSensVolModifMatrix);\r
+  fgTempAlignObj.GetPars(t,r);                         // obtain params\r
+}\r
+\r
+//-------------------------------------------------------------\r
+void AliITSAlignMille2Module::SetParVals(Double_t *vl,Int_t npar)\r
+{\r
+  for (int i=TMath::Min(npar,(Int_t)fNParTot);i--;) fParVals[i] = vl[i];\r
+}\r
+\r
+//-------------------------------------------------------------\r
+void AliITSAlignMille2Module::GetGeomParamsGlo(Double_t *pars)\r
+{\r
+  // recompute parameters from local to global frame\r
+  //\r
+  // is there anything to do?\r
+  if (GeomParamsGlobal()) {for (int i=kMaxParGeom;i--;) pars[i] = fParVals[i]; return;}\r
+  //\r
+  // IMPORTANT: It is assumed that the parents params are defined in a same way (local or global)\r
+  // as for the current module. Since in the mp2 the modules are stored from parents to children,\r
+  // it is safe to call this method in loop staring from the lowest level child, i.e. from the end\r
+  // of the modules array.\r
+  //\r
+  // DeltaGlobal = (ModifParents)*DeltaLocal*(ModifParents)^-1 \r
+  //\r
+  *fSensVolMatrix = *fMatrix;   // current global matrix\r
+  AliITSAlignMille2Module* parent = GetParent();\r
+  while (parent) {\r
+    if (parent->GeomParamsGlobal()) {\r
+      AliError("Cannot convert params to Global when the parents are already Global\n");\r
+      for (int i=kMaxParGeom;i--;) pars[i] = 0;\r
+      return;\r
+    }\r
+    fSensVolMatrix->MultiplyLeft( &parent->GetMatrix()->Inverse() ); // Local Matrix\r
+    Float_t *parpar = parent->GetParVals();\r
+    fgTempAlignObj.SetTranslation(parpar[0],parpar[1],parpar[2]);\r
+    fgTempAlignObj.SetRotation(parpar[3],parpar[4],parpar[5]);\r
+    fgTempAlignObj.GetMatrix(*fSensVolModifMatrix);\r
+    fSensVolMatrix->MultiplyLeft(fSensVolModifMatrix);\r
+    fSensVolMatrix->MultiplyLeft(parent->GetMatrix());  // global matrix after parents modifications\r
+    parent = parent->GetParent();\r
+  }\r
+  //\r
+  fgTempAlignObj.SetTranslation(fParVals[0],fParVals[1],fParVals[2]);\r
+  fgTempAlignObj.SetRotation(fParVals[3],fParVals[4],fParVals[5]);\r
+  fgTempAlignObj.GetMatrix(*fSensVolModifMatrix);  // local delta matrix\r
+  fSensVolModifMatrix->Multiply( &fSensVolMatrix->Inverse() );\r
+  fSensVolModifMatrix->MultiplyLeft( fSensVolMatrix );\r
+  fgTempAlignObj.SetMatrix( *fSensVolModifMatrix );  // global delta matrix\r
+  fgTempAlignObj.GetPars(pars,pars+3);\r
+  //\r
+}\r
+\r
+//-------------------------------------------------------------\r
+void AliITSAlignMille2Module::GetGeomParamsLoc(Double_t *pars)\r
+{\r
+  // recompute parameters from global to local frame\r
+  //\r
+  // is there anything to do?\r
+  if (!GeomParamsGlobal()) {for (int i=kMaxParGeom;i--;) pars[i] = fParVals[i]; return;}\r
+  //\r
+  // IMPORTANT: It is assumed that the parents params are defined in a same way (local or global)\r
+  // as for the current module. Since in the mp2 the modules are stored from parents to children,\r
+  // it is safe to call this method in loop staring from the lowest level child, i.e. from the end\r
+  // of the modules array.\r
+  //\r
+  //  DeltaLocal = (DeltaParents*GlobalMat)^-1*DeltaGlobal*(DeltaParents*GlobalMat)\r
+  //\r
+  AliITSAlignMille2Module* parent = GetParent();\r
+  fgTempAlignObj.SetTranslation(0.,0.,0.);\r
+  fgTempAlignObj.SetRotation(0.,0.,0.);\r
+  fgTempAlignObj.GetMatrix(*fSensVolMatrix); // get no-shift matrix\r
+  //\r
+  while (parent) { // accumulate the product of parents global modifications\r
+    if (!parent->GeomParamsGlobal()) {\r
+      AliError("Cannot convert params to Local when the parents are already Local\n");\r
+      for (int i=kMaxParGeom;i--;) pars[i] = 0;\r
+      return;\r
+    }\r
+    Float_t *parpar = parent->GetParVals();\r
+    fgTempAlignObj.SetTranslation(parpar[0],parpar[1],parpar[2]);\r
+    fgTempAlignObj.SetRotation(parpar[3],parpar[4],parpar[5]);\r
+    fgTempAlignObj.GetMatrix(*fSensVolModifMatrix);\r
+    fSensVolMatrix->Multiply(fSensVolModifMatrix); \r
+    parent = parent->GetParent();\r
+  }\r
+  // global matrix after parents modifications\r
+  fSensVolMatrix->Multiply(fMatrix);\r
+  //\r
+  fgTempAlignObj.SetTranslation(fParVals[0],fParVals[1],fParVals[2]);\r
+  fgTempAlignObj.SetRotation(fParVals[3],fParVals[4],fParVals[5]);\r
+  fgTempAlignObj.GetMatrix(*fSensVolModifMatrix);  // global delta matrix\r
+  fSensVolModifMatrix->MultiplyLeft( &fSensVolMatrix->Inverse() );\r
+  fSensVolModifMatrix->Multiply( fSensVolMatrix );\r
+  fgTempAlignObj.SetMatrix( *fSensVolModifMatrix );  // local delta matrix\r
+  fgTempAlignObj.GetPars(pars,pars+3);\r
+  //\r
+}\r
+\r
+\r
+//-------------------------------------------------------------\r
+void AliITSAlignMille2Module::CalcDerivDPosDPar(Int_t sensVol,const Double_t* pl, Double_t *deriv)\r
+{\r
+  // calculate jacobian of the global position vs Parameters (dPos/dParam) \r
+  // for the point in the sensor sensVol\r
+  const double kDel = 0.01;\r
+  double pos0[3],pos1[3],pos2[3],pos3[3];\r
+  double delta[kMaxParGeom];\r
+  //\r
+  for (int ip=kMaxParGeom;ip--;) delta[ip] = 0;\r
+  //\r
+  for (int ip=kMaxParGeom;ip--;) {\r
+    //\r
+    delta[ip] -= kDel;\r
+    GetSensitiveVolumeModifiedMatrix(sensVol,delta,!GeomParamsGlobal())->LocalToMaster(pl,pos0);    \r
+    delta[ip] += kDel/2;\r
+    GetSensitiveVolumeModifiedMatrix(sensVol,delta,!GeomParamsGlobal())->LocalToMaster(pl,pos1);    \r
+    delta[ip] += kDel;\r
+    GetSensitiveVolumeModifiedMatrix(sensVol,delta,!GeomParamsGlobal())->LocalToMaster(pl,pos2);    \r
+    delta[ip] += kDel/2;\r
+    GetSensitiveVolumeModifiedMatrix(sensVol,delta,!GeomParamsGlobal())->LocalToMaster(pl,pos3);    \r
+    //\r
+    delta[ip] = 0;\r
+    double *curd = deriv + ip*3;\r
+    for (int i=3;i--;) curd[i] = (8.*(pos2[i]-pos1[i]) - (pos3[i]-pos0[i]))/6./kDel;\r
+  }\r
+  //\r
+}\r
+\r
+//-------------------------------------------------------------\r
+void AliITSAlignMille2Module::CalcDerivGloLoc(Int_t idx,Double_t *deriv)\r
+{\r
+  // calculate derivative of global params vs local param idx:  deriv[j] = dParGlo[j]/dParLoc[idx]\r
+  Double_t lpar[kMaxParGeom];\r
+  for (int i=kMaxParGeom;i--;) lpar[i] = 0.;\r
+  //  using f(x+h),f(x-h),f(x+h/2),f(x-h2)...\r
+  Double_t par1[kMaxParGeom]; // f(x-h)\r
+  Double_t par2[kMaxParGeom]; // f(x-h/2)\r
+  Double_t par3[kMaxParGeom]; // f(x+h/2)\r
+  Double_t par4[kMaxParGeom]; // f(x+h)\r
+  //\r
+  const Double_t dpar = 1e-3;\r
+  //\r
+  // first values\r
+  lpar[idx] -= dpar;\r
+  GetGlobalParams(lpar,lpar+3, par1,par1+3);\r
+  //\r
+  // second values\r
+  lpar[idx] += dpar/2;\r
+  GetGlobalParams(lpar,lpar+3, par2,par2+3);\r
+  //\r
+  // third values\r
+  lpar[idx] += dpar;\r
+  GetGlobalParams(lpar,lpar+3, par3,par3+3);\r
+  //\r
+  // fourth values\r
+  lpar[idx] += dpar/2;\r
+  GetGlobalParams(lpar,lpar+3, par4,par4+3);\r
+  //\r
+  Double_t h2 = 1./(2.*dpar);\r
+  for (int i=kMaxParGeom;i--;) {\r
+    Double_t d0 = par4[i]-par1[i];\r
+    Double_t d2 = 2.*(par3[i]-par2[i]);\r
+    deriv[i] = h2*(4*d2 - d0)/3.;\r
+    if (TMath::Abs(deriv[i]) < 1.0e-9) deriv[i] = 0.0;\r
+  }\r
+  //\r
+}\r
+\r
+//-------------------------------------------------------------\r
+void AliITSAlignMille2Module::CalcDerivLocGlo(Double_t *deriv)\r
+{\r
+  // calculate derivative of local params vs global params:  deriv[i][j] = dParLoc[i]/dParGlo[j]\r
+  Double_t gpar[kMaxParGeom];\r
+  for (int i=kMaxParGeom;i--;) gpar[i] = 0.;\r
+  //  using f(x+h),f(x-h),f(x+h/2),f(x-h2)...\r
+  Double_t par1[kMaxParGeom]; // f(x-h)\r
+  Double_t par2[kMaxParGeom]; // f(x-h/2)\r
+  Double_t par3[kMaxParGeom]; // f(x+h/2)\r
+  Double_t par4[kMaxParGeom]; // f(x+h)\r
+  //\r
+  const Double_t dpar = 1e-3;\r
+  //\r
+  for (int ig=kMaxParGeom;ig--;) {\r
+    // first values\r
+    gpar[ig] -= dpar;\r
+    GetLocalParams(gpar,gpar+3, par1,par1+3);\r
+    //\r
+    // second values\r
+    gpar[ig] += dpar/2;\r
+    GetLocalParams(gpar,gpar+3, par2,par2+3);\r
+    //\r
+    // third values\r
+    gpar[ig] += dpar;\r
+    GetLocalParams(gpar,gpar+3, par3,par3+3);\r
+    //\r
+    // fourth values\r
+    gpar[ig] += dpar/2;\r
+    GetLocalParams(gpar,gpar+3, par4,par4+3);\r
+    //\r
+    Double_t h2 = 1./(2.*dpar);\r
+    for (int i=kMaxParGeom;i--;) {\r
+      Double_t d0 = par4[i]-par1[i];\r
+      Double_t d2 = 2.*(par3[i]-par2[i]);\r
+      int idig = i*kMaxParGeom + ig;\r
+      deriv[idig] = h2*(4*d2 - d0)/3.;\r
+      if (TMath::Abs(deriv[idig]) < 1.0e-9) deriv[idig] = 0.0;\r
+    }\r
+  }\r
+  //\r
+}\r
+\r
+//________________________________________________________________________________________________________\r
+void AliITSAlignMille2Module::CalcDerivGloLoc(Int_t sensVol,Int_t paridx,Double_t* derivative)\r
+{\r
+  /// calculate numerically the derivatives of global params vs local param paridx for sensor sensVol: dPglob/dPloc_paridx\r
+  //\r
+  Double_t lpar[kMaxParGeom];\r
+  for (int i=kMaxParGeom;i--;) lpar[i] = 0.;\r
+  //  using f(x+h),f(x-h),f(x+h/2),f(x-h2)...\r
+  Double_t par1[kMaxParGeom]; // f(x-h)\r
+  Double_t par2[kMaxParGeom]; // f(x-h/2)\r
+  Double_t par3[kMaxParGeom]; // f(x+h/2)\r
+  Double_t par4[kMaxParGeom]; // f(x+h)\r
+  //\r
+  const Double_t dpar = 1e-3;\r
+  //\r
+  // first values\r
+  lpar[paridx] -= dpar;\r
+  GetSensVolGlobalParams(sensVol,lpar,lpar+3, par1,par1+3);\r
+  //\r
+  // second values\r
+  lpar[paridx] += dpar/2;\r
+  GetSensVolGlobalParams(sensVol,lpar,lpar+3, par2,par2+3);\r
+  //\r
+  // third values\r
+  lpar[paridx] += dpar;\r
+  GetSensVolGlobalParams(sensVol,lpar,lpar+3, par3,par3+3);\r
+  //\r
+  // fourth values\r
+  lpar[paridx] += dpar/2;\r
+  GetSensVolGlobalParams(sensVol,lpar,lpar+3, par4,par4+3);\r
+  //\r
+  Double_t h2 = 1./(2.*dpar);\r
+  for (int i=kMaxParGeom;i--;) {\r
+    Double_t d0 = par4[i]-par1[i];\r
+    Double_t d2 = 2.*(par3[i]-par2[i]);\r
+    derivative[i] = h2*(4*d2 - d0)/3.;\r
+    if (TMath::Abs(derivative[i]) < 1.0e-9) derivative[i] = 0.0;\r
+  }\r
+  //\r
+}\r
+\r
+//________________________________________________________________________________________________________\r
+void AliITSAlignMille2Module::CalcDerivCurLoc(Int_t sensVol,Int_t paridx,Double_t* derivative)  \r
+{\r
+  /// calculate numerically the derivatives of sensor params in the current volume vs sensor local param paridx\r
+  //\r
+  Double_t lpar[kMaxParGeom];\r
+  for (int i=kMaxParGeom;i--;) lpar[i] = 0.;\r
+  //  using f(x+h),f(x-h),f(x+h/2),f(x-h2)...\r
+  Double_t par1[kMaxParGeom]; // f(x-h)\r
+  Double_t par2[kMaxParGeom]; // f(x-h/2)\r
+  Double_t par3[kMaxParGeom]; // f(x+h/2)\r
+  Double_t par4[kMaxParGeom]; // f(x+h)\r
+  //\r
+  const Double_t dpar = 1e-3;\r
+  //\r
+  // first values\r
+  lpar[paridx] -= dpar;\r
+  GetSensVolLocalParams(sensVol,lpar,lpar+3, par1,par1+3);\r
+  //\r
+  // second values\r
+  lpar[paridx] += dpar/2;\r
+  GetSensVolLocalParams(sensVol,lpar,lpar+3, par2,par2+3);\r
+  //\r
+  // third values\r
+  lpar[paridx] += dpar;\r
+  GetSensVolLocalParams(sensVol,lpar,lpar+3, par3,par3+3);\r
+  //\r
+  // fourth values\r
+  lpar[paridx] += dpar/2;\r
+  GetSensVolLocalParams(sensVol,lpar,lpar+3, par4,par4+3);\r
+  //\r
+  Double_t h2 = 1./(2.*dpar);\r
+  for (int i=kMaxParGeom;i--;) {\r
+    Double_t d0 = par4[i]-par1[i];\r
+    Double_t d2 = 2.*(par3[i]-par2[i]);\r
+    derivative[i] = h2*(4*d2 - d0)/3.;\r
+    if (TMath::Abs(derivative[i]) < 1.0e-9) derivative[i] = 0.0;\r
+  }\r
+  //\r
+}\r
+\r
+\r
+//-------------------------------------------------------------\r
+void AliITSAlignMille2Module::GetGlobalParams(Double_t *t, Double_t *r)\r
+{\r
+  // global parameters of the module\r
+  fgTempAlignObj.SetMatrix( *fMatrix );\r
+  fgTempAlignObj.GetPars(t,r);\r
+}\r
+\r
+//-------------------------------------------------------------\r
+void AliITSAlignMille2Module::GetGlobalParams(const Double_t* loct, const Double_t* locr, Double_t *t, Double_t *r)\r
+{\r
+  // global parameters of the module after the modification by local loct,locr\r
+  fgTempAlignObj.SetTranslation(loct[0],loct[1],loct[2]);\r
+  fgTempAlignObj.SetRotation(locr[0],locr[1],locr[2]);\r
+  fgTempAlignObj.GetMatrix(*fSensVolModifMatrix);  \r
+  *fSensVolMatrix = *fMatrix;\r
+  fSensVolMatrix->Multiply(fSensVolModifMatrix);\r
+  fgTempAlignObj.SetMatrix(*fSensVolMatrix);\r
+  fgTempAlignObj.GetPars(t,r);\r
+}\r
+\r
+//-------------------------------------------------------------\r
+void AliITSAlignMille2Module::GetLocalParams(const Double_t* glot, const Double_t* glor, Double_t *t, Double_t *r)\r
+{\r
+  // obtain local delta parameters from global delta params\r
+  fgTempAlignObj.SetTranslation(glot[0],glot[1],glot[2]);\r
+  fgTempAlignObj.SetRotation(glor[0],glor[1],glor[2]);\r
+  fgTempAlignObj.GetMatrix(*fSensVolMatrix);  \r
+  fSensVolMatrix->Multiply( fMatrix );\r
+  fSensVolMatrix->MultiplyLeft( &fMatrix->Inverse() );\r
+  fgTempAlignObj.SetMatrix(*fSensVolMatrix);\r
+  fgTempAlignObj.GetPars(t,r);\r
+}\r