]> git.uio.no Git - u/mrichter/AliRoot.git/blobdiff - ITS/AliITSAlignMille2Module.cxx
Stupid bug fix in new superlight mode (from Zurich airport)
[u/mrichter/AliRoot.git] / ITS / AliITSAlignMille2Module.cxx
index 287c439caea5595c5b13257d0f2e4d25defd2c21..74427b46186ca8c86543c47bf830e9884f598936 100644 (file)
-/************************************************************************** \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 = 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,char* symname,TGeoHMatrix *m,Int_t nsv,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
-    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, char* symname, TGeoHMatrix *m, Int_t nsv, 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 (cstr>0)      fParCstr[dof] = fgkDummyConstraint+1.; // the parameter is free and unconstrained\r
-  else if (cstr<0) fParCstr[dof] = -cstr;                 // the parameter is free but constrained\r
-  else             fParCstr[dof] = 0;                     // fixed parameter\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) {\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) ? '+':'-',fParOffs[kDOFTX],IsFreeDOF(kDOFTY) ? '+':'-',fParOffs[kDOFTY],\r
-        IsFreeDOF(kDOFTZ) ? '+':'-',fParOffs[kDOFTZ],IsFreeDOF(kDOFPS) ? '+':'-',fParOffs[kDOFPS],\r
-        IsFreeDOF(kDOFTH) ? '+':'-',fParOffs[kDOFTH],IsFreeDOF(kDOFPH) ? '+':'-',fParOffs[kDOFPH]);\r
-  if (IsSDD()) printf("%cT0:%5d| %cDV:%5d|",IsFreeDOF(kDOFT0)?'+':'-',fParOffs[kDOFT0],\r
-                     IsFreeDOF(kDOFDV)?'+':'-',fParOffs[kDOFDV]);\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() ? 8:6;\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
-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
-\r
+/************************************************************************** 
+ * 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_
+
+
+const Float_t AliITSAlignMille2Module::fgkDummyConstraint = 1e-2;//1.E3;
+    
+//-------------------------------------------------------------
+AliITSAlignMille2Module::AliITSAlignMille2Module() : 
+  TNamed(), 
+  fNSensVol(0), 
+  fIndex(-1),  
+  fDetType(-1),
+  fVolumeID(0),
+  fNParTot(0),
+  fNParFree(0),
+  fParOffs(0),
+  fNProcPoints(0),
+  fParVals(0),
+  fParErrs(0),
+  fParCstr(0),
+  fSensVolIndex(0),
+  fSensVolVolumeID(0),
+  fMatrix(NULL),
+  fSensVolMatrix(NULL),
+  fSensVolModifMatrix(NULL),
+  fParent(NULL),
+  fChildren(0)
+{ 
+  /// 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, const char* symname,
+                                                const TGeoHMatrix *m, Int_t nsv, const UShort_t *volidsv) : 
+  TNamed(), 
+  fNSensVol(0), 
+  fIndex(-1),  
+  fDetType(-1),  
+  fVolumeID(0),
+  fNParTot(0),
+  fNParFree(0),
+  fParOffs(kMaxParGeom),
+  fNProcPoints(0),
+  fParVals(0),
+  fParErrs(0),
+  fParCstr(0),
+  fSensVolIndex(0),
+  fSensVolVolumeID(0),  
+  fMatrix(NULL),
+  fSensVolMatrix(NULL),
+  fSensVolModifMatrix(NULL),
+  fParent(NULL),
+  fChildren(0)
+{ 
+  /// void constructor  
+  fMatrix = new TGeoHMatrix; 
+  fSensVolMatrix = new TGeoHMatrix; 
+  fSensVolModifMatrix = new TGeoHMatrix; 
+  fSigmaFactor[0]=fSigmaFactor[1]=fSigmaFactor[2]=1.0;
+  for (int i=kMaxParGeom;i--;) fParOffs[i] = -1;
+  if (Set(index,volid,symname,m,nsv,volidsv)) {
+    AliInfo("Error in AliITSAlignMille2Module::Set() - initializing void supermodule...");
+  }
+  AssignDetType();
+} 
+
+//-------------------------------------------------------------
+AliITSAlignMille2Module::AliITSAlignMille2Module(UShort_t volid) : 
+  TNamed(), 
+  fNSensVol(0), 
+  fIndex(-1),    
+  fDetType(-1),
+  fVolumeID(0),
+  fNParTot(0),
+  fNParFree(0),
+  fParOffs(kMaxParGeom),
+  fNProcPoints(0),
+  fParVals(0),
+  fParErrs(0),
+  fParCstr(0),  
+  fSensVolIndex(0),
+  fSensVolVolumeID(0),
+  fMatrix(NULL),
+  fSensVolMatrix(NULL),
+  fSensVolModifMatrix(NULL),
+  fParent(NULL),
+  fChildren(0)
+{ 
+  /// 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;
+  for (int i=kMaxParGeom;i--;) fParOffs[i] = -1;
+  //
+  fIndex = GetIndexFromVolumeID(volid);  
+  if (fIndex>=0 && gGeoManager) { // good sensitive module and geometry loaded
+    SetName(AliGeomManager::SymName(volid));
+    fVolumeID = volid;
+    AddSensitiveVolume(volid);
+    SetSensorsProvided(kTRUE);
+    if (SensVolMatrix(volid, fMatrix))
+       AliInfo("Matrix not defined");
+  }
+  else {
+    AliInfo("Wrong VolumeID or Geometry not loaded - initializing void supermodule...");
+  }
+  AssignDetType();
+} 
+
+
+//_____________________________________________________________________________
+AliITSAlignMille2Module::AliITSAlignMille2Module(const AliITSAlignMille2Module &m) :
+  TNamed(m),
+  fNSensVol(m.fNSensVol),
+  fIndex(m.fIndex),  
+  fDetType(m.fDetType),
+  fVolumeID(m.fVolumeID),
+  fNParTot(m.fNParTot),
+  fNParFree(m.fNParFree),
+  fParOffs(m.fNParTot),
+  fNProcPoints(0),
+  fParVals(0),
+  fParErrs(0),
+  fParCstr(0),  
+  fSensVolIndex(m.fSensVolIndex),
+  fSensVolVolumeID(m.fSensVolVolumeID),
+  fMatrix(new TGeoHMatrix(*m.GetMatrix())),
+  fSensVolMatrix(new TGeoHMatrix),
+  fSensVolModifMatrix(new TGeoHMatrix),
+  fParent(m.fParent),
+  fChildren(0)
+{
+  // Copy constructor
+  fSensVolIndex = m.fSensVolIndex;
+  fSensVolVolumeID = m.fSensVolVolumeID;
+  for (int i=m.fNParTot;i--;) fParOffs[i] = m.fParOffs[i];
+  for (int i=3;i--;) fSigmaFactor[i] = m.fSigmaFactor[i];
+  if (fNParTot) {
+    fParVals = new Float_t[fNParTot];
+    fParErrs = new Float_t[fNParTot];
+    fParCstr = new Float_t[fNParTot];
+    for (int i=fNParTot;i--;) {
+      fParVals[i] = m.fParVals[i];
+      fParErrs[i] = m.fParErrs[i];
+      fParCstr[i] = m.fParCstr[i];
+    }
+  }
+}
+
+//_____________________________________________________________________________
+AliITSAlignMille2Module& AliITSAlignMille2Module::operator=(const AliITSAlignMille2Module &m)  
+{
+  // operator =
+  //
+  if(this==&m) return *this;
+  this->TNamed::operator=(m);
+  //
+  fNSensVol=m.fNSensVol;
+  fIndex=m.fIndex;
+  fDetType = m.fDetType;
+  fVolumeID=m.fVolumeID;
+  fNParTot  = m.fNParTot;
+  fNParFree = m.fNParFree; 
+  fNProcPoints = m.fNProcPoints; 
+  delete[] fParVals; fParVals = 0;
+  delete[] fParErrs; fParErrs = 0;
+  delete[] fParCstr; fParCstr = 0;
+  //
+  if (fNParTot) {
+    fParVals = new Float_t[fNParTot];
+    fParErrs = new Float_t[fNParTot];
+    fParCstr = new Float_t[fNParTot];
+    for (int i=m.GetNParTot();i--;) {
+      fParVals[i] = m.fParVals[i];
+      fParErrs[i] = m.fParErrs[i];
+      fParCstr[i] = m.fParCstr[i];
+    }
+  }
+  //
+  fParOffs.Set(fNParTot);
+  for (int i=0;i<fNParTot;i++) fParOffs[i] = m.fParOffs[i];
+  for (int i=0;i<3;i++) fSigmaFactor[i] = m.fSigmaFactor[i];
+  if (fMatrix) delete fMatrix;
+  fMatrix=new TGeoHMatrix(*m.GetMatrix());
+  if(fSensVolMatrix) delete fSensVolMatrix;
+  fSensVolMatrix = new TGeoHMatrix(*m.fSensVolMatrix);
+  if(fSensVolModifMatrix) delete fSensVolModifMatrix;
+  fSensVolModifMatrix = new TGeoHMatrix(*m.fSensVolModifMatrix);
+  fSensVolIndex = m.fSensVolIndex;
+  fSensVolVolumeID = m.fSensVolVolumeID;
+  fParent = m.fParent;
+  fChildren.Clear();
+  for (int i=0;i<m.GetNChildren();i++) fChildren.Add(m.GetChild(i));
+  return *this;
+}
+
+
+//-------------------------------------------------------------
+AliITSAlignMille2Module::~AliITSAlignMille2Module() { 
+  /// Destructor 
+  delete fMatrix; 
+  delete fSensVolMatrix; 
+  delete fSensVolModifMatrix; 
+  delete[] fParVals;
+  delete[] fParErrs;
+  delete[] fParCstr;
+  fChildren.Clear();
+} 
+
+//-------------------------------------------------------------
+Int_t AliITSAlignMille2Module::Set(Int_t index, UShort_t volid, const char* symname, 
+                                  const TGeoHMatrix *m, Int_t nsv, const 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;
+}
+
+//-------------------------------------------------------------
+void AliITSAlignMille2Module::SetFreeDOF(Int_t dof,Double_t cstr)
+{
+  if (AliITSAlignMille2::IsZero(cstr)) fParCstr[dof] = 0;  // fixed parameter
+  else if (cstr>0)                     fParCstr[dof] = fgkDummyConstraint+1.; // the parameter is free and unconstrained
+  else                                 fParCstr[dof] = -cstr;                 // the parameter is free but constrained
+}
+
+//-------------------------------------------------------------
+Bool_t AliITSAlignMille2Module::IsSensor(UShort_t voluid) 
+{
+  // Does this volid correspond to sensor ?
+  AliGeomManager::ELayerID layId = AliGeomManager::VolUIDToLayerSafe(voluid);
+  if (layId>0 && layId<7) {
+    Int_t mId = Int_t(voluid & 0x7ff);
+    if( mId>=0 && mId<AliGeomManager::LayerSize(layId)) return kTRUE;
+  }
+  return kFALSE;
+}
+
+//-------------------------------------------------------------
+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+1) {
+    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, const 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)
+  //
+  static AliAlignObjParams tempAlignObj;
+  tempAlignObj.SetRotation(ang[0],ang[1],ang[2]);
+  tempAlignObj.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;
+  tempAlignObj.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, const 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)
+  //
+  static AliAlignObjParams tempAlignObj;
+  tempAlignObj.SetRotation(ang[0],ang[1],ang[2]);
+  tempAlignObj.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,&tempAlignObj);
+}
+
+//-------------------------------------------------------------
+AliAlignObjParams *AliITSAlignMille2Module::GetSensitiveVolumeMisalignment(UShort_t voluid, const 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...)
+  static AliAlignObjParams tempAlignObj;
+  tempAlignObj.SetVolUID(0);
+  tempAlignObj.SetSymName("");
+  tempAlignObj.SetTranslation(0,0,0);
+  tempAlignObj.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 (!tempAlignObj.SetMatrix(*fSensVolModifMatrix)) return NULL;
+  tempAlignObj.SetVolUID(voluid);
+  tempAlignObj.SetSymName(AliGeomManager::SymName(voluid));
+  //
+  return &tempAlignObj;
+}
+
+// >> RS
+//-------------------------------------------------------------
+AliAlignObjParams *AliITSAlignMille2Module::GetSensitiveVolumeTotalMisalignment(UShort_t voluid, const 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...)
+  static AliAlignObjParams tempAlignObj;
+  tempAlignObj.SetVolUID(0);
+  tempAlignObj.SetSymName("");
+  tempAlignObj.SetRotation(ang[0],ang[1],ang[2]);
+  tempAlignObj.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;
+  tempAlignObj.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...)
+  tempAlignObj.SetVolUID(0);
+  tempAlignObj.SetSymName("");
+  tempAlignObj.SetTranslation(0,0,0);
+  tempAlignObj.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 (!tempAlignObj.SetMatrix(*fSensVolModifMatrix)) return NULL;
+  tempAlignObj.SetVolUID(voluid);
+  tempAlignObj.SetSymName(AliGeomManager::SymName(voluid));
+
+  
+  //tempAlignObj.Print("");
+
+  return &tempAlignObj;
+}
+//-------------------------------------------------------------
+
+//-------------------------------------------------------------
+AliAlignObjParams *AliITSAlignMille2Module::GetSensitiveVolumeGlobalMisalignment(UShort_t voluid, const 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...)
+  static AliAlignObjParams tempAlignObj;
+  tempAlignObj.SetTranslation(0,0,0);
+  tempAlignObj.SetRotation(0,0,0);
+
+  tempAlignObj.SetRotation(ang[0],ang[1],ang[2]);
+  tempAlignObj.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;
+  tempAlignObj.GetMatrix(dg);
+  //dg.Print();
+
+  dg.MultiplyLeft( fMatrix );
+  dg.Multiply( &fMatrix->Inverse() );
+
+  // reset align object (may not be needed...)
+  tempAlignObj.SetTranslation(0,0,0);
+  tempAlignObj.SetRotation(0,0,0);
+
+  tempAlignObj.SetVolUID(voluid);
+  tempAlignObj.SetSymName(AliGeomManager::SymName(voluid));
+
+  if (!tempAlignObj.SetMatrix(dg)) return NULL;
+  
+  //tempAlignObj.Print("");
+
+  return &tempAlignObj;
+}
+// << 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)) return -1;
+  (*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 
+{
+  // print data
+  //
+  const char* typeName[] = {"SPD","SDD","SSD"};
+  printf("*** ITS SuperModule for AliITSAlignMille ***\n");
+  printf("symname  : %s (type: %s)\n",GetName(),fDetType<0 ? "N/A":typeName[fDetType]);
+  printf("parent   : %s | %d children\n",fParent ? fParent->GetName() : "N/A",GetNChildren());
+  printf("volumeID : %4d  | index : %4d | Geom.Params are %s\n",fVolumeID,fIndex,
+        GeomParamsGlobal() ? "Global":"Local");
+  printf("Factors  : X=%.2f Y=%.2f Z=%.2f\n"
+        "DOF: %cTx:%5d| %cTy:%5d| %cTz:%5d| %cPsi:%5d| %cTheta:%5d| %cPhi:%5d|",
+        fSigmaFactor[0],fSigmaFactor[1],fSigmaFactor[2],
+        IsFreeDOF(kDOFTX) ? '+':'-',GetParOffset(kDOFTX),IsFreeDOF(kDOFTY) ? '+':'-',GetParOffset(kDOFTY),
+        IsFreeDOF(kDOFTZ) ? '+':'-',GetParOffset(kDOFTZ),IsFreeDOF(kDOFPS) ? '+':'-',GetParOffset(kDOFPS),
+        IsFreeDOF(kDOFTH) ? '+':'-',GetParOffset(kDOFTH),IsFreeDOF(kDOFPH) ? '+':'-',GetParOffset(kDOFPH));
+  if (IsSDD()) {
+    printf("%cT0:%5d| %cDVl:%5d| %cDVr:%5d|",IsFreeDOF(kDOFT0)?'+':'-',GetParOffset(kDOFT0),
+          IsFreeDOF(kDOFDVL)?'+':'-',GetParOffset(kDOFDVL),IsFreeDOF(kDOFDVR)?'+':'-',GetParOffset(kDOFDVR));
+    if (IsVDriftLRSame()) printf("(dVL=dVR)");
+  }
+  printf("\n");
+  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
+{
+  // it it alignable?
+  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() );
+}
+
+//-------------------------------------------------------------
+void AliITSAlignMille2Module::AssignDetType()
+{
+  // assign the detector type
+  TString tp = GetName();
+  if      (tp.Contains("SPD",TString::kIgnoreCase)) fDetType = kSPD;
+  else if (tp.Contains("SDD",TString::kIgnoreCase)) fDetType = kSDD;
+  else if (tp.Contains("SSD",TString::kIgnoreCase)) fDetType = kSSD;
+  else fDetType = -1;
+  fNParTot = IsSDD() ? kMaxParTot:kMaxParGeom;
+  fNParFree = 0;
+  fParVals = new Float_t[fNParTot];
+  fParErrs = new Float_t[fNParTot];  
+  fParCstr = new Float_t[fNParTot];  
+  if (fParOffs.GetSize()<fNParTot) fParOffs.Set(fNParTot);
+  for (int i=fNParTot;i--;) {
+    fParVals[i] = fParErrs[i] = 0.; 
+    fParCstr[i] = 0.;
+    fParOffs[i] = -1;
+  }
+}
+
+//-------------------------------------------------------------
+void AliITSAlignMille2Module::EvaluateDOF()
+{
+  // count d.o.f.
+  fNParFree = 0;
+  for (int i=fNParTot;i--;) if (IsFreeDOF(i)) fNParFree++;
+}
+
+//-------------------------------------------------------------
+void AliITSAlignMille2Module::GetSensVolGlobalParams(UShort_t volid,Double_t *t, Double_t *r)
+{
+  // return global parameters of the sensor volid
+  for (int i=3;i--;) t[i] = r[i] = 0.;
+  if (SensVolMatrix(volid,fSensVolMatrix)) return;  
+  AliAlignObjParams tempAlignObj;
+  tempAlignObj.SetMatrix(*fSensVolMatrix);
+  tempAlignObj.GetPars(t,r);
+}
+
+//-------------------------------------------------------------
+void AliITSAlignMille2Module::GetSensVolLocalParams(UShort_t volid,Double_t *t, Double_t *r)
+{
+  // return parameters of the sensor volid in the current module
+  for (int i=3;i--;) t[i] = r[i] = 0.;
+  if (SensVolMatrix(volid,fSensVolMatrix)) return;  
+  fSensVolMatrix->MultiplyLeft( &fMatrix->Inverse() );
+  AliAlignObjParams tempAlignObj;  
+  tempAlignObj.SetMatrix(*fSensVolMatrix);
+  tempAlignObj.GetPars(t,r);
+}
+
+//-------------------------------------------------------------
+void AliITSAlignMille2Module::GetSensVolGlobalParams(UShort_t volid,const Double_t* loct, const Double_t* locr,Double_t *t, Double_t *r)
+{
+  // return global parameters of the sensor volid modified by the localDelta params
+  for (int i=3;i--;) t[i] = r[i] = 0.;
+  if (SensVolMatrix(volid,fSensVolMatrix)) return;  
+  AliAlignObjParams tempAlignObj;
+  tempAlignObj.SetTranslation(loct[0],loct[1],loct[2]);
+  tempAlignObj.SetRotation(locr[0],locr[1],locr[2]);
+  //
+  tempAlignObj.GetMatrix(*fSensVolModifMatrix);      // obtain local delta
+  fSensVolModifMatrix->MultiplyLeft( fSensVolMatrix ); // obtain global delta
+  tempAlignObj.SetMatrix(*fSensVolModifMatrix);
+  tempAlignObj.GetPars(t,r);                         // obtain global params
+}
+
+//-------------------------------------------------------------
+void AliITSAlignMille2Module::GetSensVolLocalParams(UShort_t volid,const Double_t* loct,const Double_t* locr,Double_t *t, Double_t *r)
+{
+  // return parameters of the sensor volid (modified by the localDelta params) in the current volume
+  for (int i=3;i--;) t[i] = r[i] = 0.;
+  if (SensVolMatrix(volid,fSensVolMatrix)) return;  
+  AliAlignObjParams tempAlignObj;
+  tempAlignObj.SetTranslation(loct[0],loct[1],loct[2]);
+  tempAlignObj.SetRotation(locr[0],locr[1],locr[2]);
+  //
+  tempAlignObj.GetMatrix(*fSensVolModifMatrix);      // obtain local delta
+  fSensVolModifMatrix->MultiplyLeft( fSensVolMatrix ); // obtain global delta
+  fSensVolModifMatrix->MultiplyLeft( &fMatrix->Inverse() ); // obtain delta in current volume
+  tempAlignObj.SetMatrix(*fSensVolModifMatrix);
+  tempAlignObj.GetPars(t,r);                         // obtain params
+}
+
+//-------------------------------------------------------------
+void AliITSAlignMille2Module::SetParVals(Double_t *vl,Int_t npar)
+{
+  // set parameters
+  for (int i=TMath::Min(npar,(Int_t)fNParTot);i--;) fParVals[i] = vl[i];
+}
+
+//-------------------------------------------------------------
+void AliITSAlignMille2Module::GetGeomParamsGlo(Double_t *pars)
+{
+  // recompute parameters from local to global frame
+  //
+  // is there anything to do?
+  if (GeomParamsGlobal()) {for (int i=kMaxParGeom;i--;) pars[i] = fParVals[i]; return;}
+  //
+  // IMPORTANT: It is assumed that the parents params are defined in a same way (local or global)
+  // as for the current module. Since in the mp2 the modules are stored from parents to children,
+  // it is safe to call this method in loop staring from the lowest level child, i.e. from the end
+  // of the modules array.
+  //
+  // DeltaGlobal = (ModifParents)*DeltaLocal*(ModifParents)^-1 
+  //
+  *fSensVolMatrix = *fMatrix;   // current global matrix
+  AliAlignObjParams tempAlignObj;
+  AliITSAlignMille2Module* parent = GetParent();
+  while (parent) {
+    if (parent->GeomParamsGlobal()) {
+      AliError("Cannot convert params to Global when the parents are already Global\n");
+      for (int i=kMaxParGeom;i--;) pars[i] = 0;
+      return;
+    }
+    fSensVolMatrix->MultiplyLeft( &parent->GetMatrix()->Inverse() ); // Local Matrix
+    Float_t *parpar = parent->GetParVals();
+    tempAlignObj.SetTranslation(parpar[0],parpar[1],parpar[2]);
+    tempAlignObj.SetRotation(parpar[3],parpar[4],parpar[5]);
+    tempAlignObj.GetMatrix(*fSensVolModifMatrix);
+    fSensVolMatrix->MultiplyLeft(fSensVolModifMatrix);
+    fSensVolMatrix->MultiplyLeft(parent->GetMatrix());  // global matrix after parents modifications
+    parent = parent->GetParent();
+  }
+  //
+  tempAlignObj.SetTranslation(fParVals[0],fParVals[1],fParVals[2]);
+  tempAlignObj.SetRotation(fParVals[3],fParVals[4],fParVals[5]);
+  tempAlignObj.GetMatrix(*fSensVolModifMatrix);  // local delta matrix
+  fSensVolModifMatrix->Multiply( &fSensVolMatrix->Inverse() );
+  fSensVolModifMatrix->MultiplyLeft( fSensVolMatrix );
+  tempAlignObj.SetMatrix( *fSensVolModifMatrix );  // global delta matrix
+  tempAlignObj.GetPars(pars,pars+3);
+  //
+}
+
+//-------------------------------------------------------------
+void AliITSAlignMille2Module::GetGeomParamsLoc(Double_t *pars)
+{
+  // recompute parameters from global to local frame
+  //
+  // is there anything to do?
+  if (!GeomParamsGlobal()) {for (int i=kMaxParGeom;i--;) pars[i] = fParVals[i]; return;}
+  //
+  // IMPORTANT: It is assumed that the parents params are defined in a same way (local or global)
+  // as for the current module. Since in the mp2 the modules are stored from parents to children,
+  // it is safe to call this method in loop staring from the lowest level child, i.e. from the end
+  // of the modules array.
+  //
+  //  DeltaLocal = (DeltaParents*GlobalMat)^-1*DeltaGlobal*(DeltaParents*GlobalMat)
+  //
+  AliITSAlignMille2Module* parent = GetParent();
+  AliAlignObjParams tempAlignObj;
+  tempAlignObj.SetTranslation(0.,0.,0.);
+  tempAlignObj.SetRotation(0.,0.,0.);
+  tempAlignObj.GetMatrix(*fSensVolMatrix); // get no-shift matrix
+  //
+  while (parent) { // accumulate the product of parents global modifications
+    if (!parent->GeomParamsGlobal()) {
+      AliError("Cannot convert params to Local when the parents are already Local\n");
+      for (int i=kMaxParGeom;i--;) pars[i] = 0;
+      return;
+    }
+    Float_t *parpar = parent->GetParVals();
+    tempAlignObj.SetTranslation(parpar[0],parpar[1],parpar[2]);
+    tempAlignObj.SetRotation(parpar[3],parpar[4],parpar[5]);
+    tempAlignObj.GetMatrix(*fSensVolModifMatrix);
+    fSensVolMatrix->Multiply(fSensVolModifMatrix); 
+    parent = parent->GetParent();
+  }
+  // global matrix after parents modifications
+  fSensVolMatrix->Multiply(fMatrix);
+  //
+  tempAlignObj.SetTranslation(fParVals[0],fParVals[1],fParVals[2]);
+  tempAlignObj.SetRotation(fParVals[3],fParVals[4],fParVals[5]);
+  tempAlignObj.GetMatrix(*fSensVolModifMatrix);  // global delta matrix
+  fSensVolModifMatrix->MultiplyLeft( &fSensVolMatrix->Inverse() );
+  fSensVolModifMatrix->Multiply( fSensVolMatrix );
+  tempAlignObj.SetMatrix( *fSensVolModifMatrix );  // local delta matrix
+  tempAlignObj.GetPars(pars,pars+3);
+  //
+}
+
+
+//-------------------------------------------------------------
+void AliITSAlignMille2Module::CalcDerivDPosDPar(Int_t sensVol,const Double_t* pl, Double_t *deriv)
+{
+  // calculate jacobian of the global position vs Parameters (dPos/dParam) 
+  // for the point in the sensor sensVol
+  const double kDel = 0.01;
+  double pos0[3],pos1[3],pos2[3],pos3[3];
+  double delta[kMaxParGeom];
+  //
+  for (int ip=kMaxParGeom;ip--;) delta[ip] = 0;
+  //
+  for (int ip=kMaxParGeom;ip--;) {
+    //
+    delta[ip] -= kDel;
+    GetSensitiveVolumeModifiedMatrix(sensVol,delta,!GeomParamsGlobal())->LocalToMaster(pl,pos0);    
+    delta[ip] += kDel/2;
+    GetSensitiveVolumeModifiedMatrix(sensVol,delta,!GeomParamsGlobal())->LocalToMaster(pl,pos1);    
+    delta[ip] += kDel;
+    GetSensitiveVolumeModifiedMatrix(sensVol,delta,!GeomParamsGlobal())->LocalToMaster(pl,pos2);    
+    delta[ip] += kDel/2;
+    GetSensitiveVolumeModifiedMatrix(sensVol,delta,!GeomParamsGlobal())->LocalToMaster(pl,pos3);    
+    //
+    delta[ip] = 0;
+    double *curd = deriv + ip*3;
+    for (int i=3;i--;) curd[i] = (8.*(pos2[i]-pos1[i]) - (pos3[i]-pos0[i]))/6./kDel;
+  }
+  //
+}
+
+//-------------------------------------------------------------
+void AliITSAlignMille2Module::CalcDerivGloLoc(Int_t idx,Double_t *deriv)
+{
+  // calculate derivative of global params vs local param idx:  deriv[j] = dParGlo[j]/dParLoc[idx]
+  Double_t lpar[kMaxParGeom];
+  for (int i=kMaxParGeom;i--;) lpar[i] = 0.;
+  //  using f(x+h),f(x-h),f(x+h/2),f(x-h2)...
+  Double_t par1[kMaxParGeom]; // f(x-h)
+  Double_t par2[kMaxParGeom]; // f(x-h/2)
+  Double_t par3[kMaxParGeom]; // f(x+h/2)
+  Double_t par4[kMaxParGeom]; // f(x+h)
+  //
+  const Double_t dpar = 1e-3;
+  //
+  // first values
+  lpar[idx] -= dpar;
+  GetGlobalParams(lpar,lpar+3, par1,par1+3);
+  //
+  // second values
+  lpar[idx] += dpar/2;
+  GetGlobalParams(lpar,lpar+3, par2,par2+3);
+  //
+  // third values
+  lpar[idx] += dpar;
+  GetGlobalParams(lpar,lpar+3, par3,par3+3);
+  //
+  // fourth values
+  lpar[idx] += dpar/2;
+  GetGlobalParams(lpar,lpar+3, par4,par4+3);
+  //
+  Double_t h2 = 1./(2.*dpar);
+  for (int i=kMaxParGeom;i--;) {
+    Double_t d0 = par4[i]-par1[i];
+    Double_t d2 = 2.*(par3[i]-par2[i]);
+    deriv[i] = h2*(4*d2 - d0)/3.;
+    if (TMath::Abs(deriv[i]) < 1.0e-9) deriv[i] = 0.0;
+  }
+  //
+}
+
+//-------------------------------------------------------------
+void AliITSAlignMille2Module::CalcDerivLocGlo(Double_t *deriv)
+{
+  // calculate derivative of local params vs global params:  deriv[i][j] = dParLoc[i]/dParGlo[j]
+  Double_t gpar[kMaxParGeom];
+  for (int i=kMaxParGeom;i--;) gpar[i] = 0.;
+  //  using f(x+h),f(x-h),f(x+h/2),f(x-h2)...
+  Double_t par1[kMaxParGeom]; // f(x-h)
+  Double_t par2[kMaxParGeom]; // f(x-h/2)
+  Double_t par3[kMaxParGeom]; // f(x+h/2)
+  Double_t par4[kMaxParGeom]; // f(x+h)
+  //
+  const Double_t dpar = 1e-3;
+  //
+  for (int ig=kMaxParGeom;ig--;) {
+    // first values
+    gpar[ig] -= dpar;
+    GetLocalParams(gpar,gpar+3, par1,par1+3);
+    //
+    // second values
+    gpar[ig] += dpar/2;
+    GetLocalParams(gpar,gpar+3, par2,par2+3);
+    //
+    // third values
+    gpar[ig] += dpar;
+    GetLocalParams(gpar,gpar+3, par3,par3+3);
+    //
+    // fourth values
+    gpar[ig] += dpar/2;
+    GetLocalParams(gpar,gpar+3, par4,par4+3);
+    //
+    Double_t h2 = 1./(2.*dpar);
+    for (int i=kMaxParGeom;i--;) {
+      Double_t d0 = par4[i]-par1[i];
+      Double_t d2 = 2.*(par3[i]-par2[i]);
+      int idig = i*kMaxParGeom + ig;
+      deriv[idig] = h2*(4*d2 - d0)/3.;
+      if (TMath::Abs(deriv[idig]) < 1.0e-9) deriv[idig] = 0.0;
+    }
+  }
+  //
+}
+
+//________________________________________________________________________________________________________
+void AliITSAlignMille2Module::CalcDerivGloLoc(Int_t sensVol,Int_t paridx,Double_t* derivative)
+{
+  /// calculate numerically the derivatives of global params vs local param paridx for sensor sensVol: dPglob/dPloc_paridx
+  //
+  Double_t lpar[kMaxParGeom];
+  for (int i=kMaxParGeom;i--;) lpar[i] = 0.;
+  //  using f(x+h),f(x-h),f(x+h/2),f(x-h2)...
+  Double_t par1[kMaxParGeom]; // f(x-h)
+  Double_t par2[kMaxParGeom]; // f(x-h/2)
+  Double_t par3[kMaxParGeom]; // f(x+h/2)
+  Double_t par4[kMaxParGeom]; // f(x+h)
+  //
+  const Double_t dpar = 1e-3;
+  //
+  // first values
+  lpar[paridx] -= dpar;
+  GetSensVolGlobalParams(sensVol,lpar,lpar+3, par1,par1+3);
+  //
+  // second values
+  lpar[paridx] += dpar/2;
+  GetSensVolGlobalParams(sensVol,lpar,lpar+3, par2,par2+3);
+  //
+  // third values
+  lpar[paridx] += dpar;
+  GetSensVolGlobalParams(sensVol,lpar,lpar+3, par3,par3+3);
+  //
+  // fourth values
+  lpar[paridx] += dpar/2;
+  GetSensVolGlobalParams(sensVol,lpar,lpar+3, par4,par4+3);
+  //
+  Double_t h2 = 1./(2.*dpar);
+  for (int i=kMaxParGeom;i--;) {
+    Double_t d0 = par4[i]-par1[i];
+    Double_t d2 = 2.*(par3[i]-par2[i]);
+    derivative[i] = h2*(4*d2 - d0)/3.;
+    if (TMath::Abs(derivative[i]) < 1.0e-9) derivative[i] = 0.0;
+  }
+  //
+}
+
+//________________________________________________________________________________________________________
+void AliITSAlignMille2Module::CalcDerivCurLoc(Int_t sensVol,Int_t paridx,Double_t* derivative)  
+{
+  /// calculate numerically the derivatives of sensor params in the current volume vs sensor local param paridx
+  //
+  Double_t lpar[kMaxParGeom];
+  for (int i=kMaxParGeom;i--;) lpar[i] = 0.;
+  //  using f(x+h),f(x-h),f(x+h/2),f(x-h2)...
+  Double_t par1[kMaxParGeom]; // f(x-h)
+  Double_t par2[kMaxParGeom]; // f(x-h/2)
+  Double_t par3[kMaxParGeom]; // f(x+h/2)
+  Double_t par4[kMaxParGeom]; // f(x+h)
+  //
+  const Double_t dpar = 1e-3;
+  //
+  // first values
+  lpar[paridx] -= dpar;
+  GetSensVolLocalParams(sensVol,lpar,lpar+3, par1,par1+3);
+  //
+  // second values
+  lpar[paridx] += dpar/2;
+  GetSensVolLocalParams(sensVol,lpar,lpar+3, par2,par2+3);
+  //
+  // third values
+  lpar[paridx] += dpar;
+  GetSensVolLocalParams(sensVol,lpar,lpar+3, par3,par3+3);
+  //
+  // fourth values
+  lpar[paridx] += dpar/2;
+  GetSensVolLocalParams(sensVol,lpar,lpar+3, par4,par4+3);
+  //
+  Double_t h2 = 1./(2.*dpar);
+  for (int i=kMaxParGeom;i--;) {
+    Double_t d0 = par4[i]-par1[i];
+    Double_t d2 = 2.*(par3[i]-par2[i]);
+    derivative[i] = h2*(4*d2 - d0)/3.;
+    if (TMath::Abs(derivative[i]) < 1.0e-9) derivative[i] = 0.0;
+  }
+  //
+}
+
+
+//-------------------------------------------------------------
+void AliITSAlignMille2Module::GetGlobalParams(Double_t *t, Double_t *r) const
+{
+  // global parameters of the module
+  AliAlignObjParams tempAlignObj;
+  tempAlignObj.SetMatrix( *fMatrix );
+  tempAlignObj.GetPars(t,r);
+}
+
+//-------------------------------------------------------------
+void AliITSAlignMille2Module::GetGlobalParams(const Double_t* loct, const Double_t* locr, Double_t *t, Double_t *r)
+{
+  // global parameters of the module after the modification by local loct,locr
+  AliAlignObjParams tempAlignObj;
+  tempAlignObj.SetTranslation(loct[0],loct[1],loct[2]);
+  tempAlignObj.SetRotation(locr[0],locr[1],locr[2]);
+  tempAlignObj.GetMatrix(*fSensVolModifMatrix);  
+  *fSensVolMatrix = *fMatrix;
+  fSensVolMatrix->Multiply(fSensVolModifMatrix);
+  tempAlignObj.SetMatrix(*fSensVolMatrix);
+  tempAlignObj.GetPars(t,r);
+}
+
+//-------------------------------------------------------------
+void AliITSAlignMille2Module::GetLocalParams(const Double_t* glot, const Double_t* glor, Double_t *t, Double_t *r)
+{
+  // obtain local delta parameters from global delta params
+  AliAlignObjParams tempAlignObj;
+  tempAlignObj.SetTranslation(glot[0],glot[1],glot[2]);
+  tempAlignObj.SetRotation(glor[0],glor[1],glor[2]);
+  tempAlignObj.GetMatrix(*fSensVolMatrix);  
+  fSensVolMatrix->Multiply( fMatrix );
+  fSensVolMatrix->MultiplyLeft( &fMatrix->Inverse() );
+  tempAlignObj.SetMatrix(*fSensVolMatrix);
+  tempAlignObj.GetPars(t,r);
+}