]> git.uio.no Git - u/mrichter/AliRoot.git/blobdiff - ITS/AliITSAlignMille2Module.cxx
cleanup
[u/mrichter/AliRoot.git] / ITS / AliITSAlignMille2Module.cxx
index 574d58276cf463571f6a659ceec21d3bab173a60..1cdab045af5a5f955e5e26624e06ae22b5947bec 100644 (file)
@@ -42,21 +42,30 @@ ClassImp(AliITSAlignMille2Module)
 \r
 #define CORHW_\r
 \r
-AliAlignObjParams AliITSAlignMille2Module::fgTempAlignObj;\r
+\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
+  fParent(NULL),\r
+  fChildren(0)\r
 { \r
   /// void constructor  \r
   fMatrix = new TGeoHMatrix; \r
@@ -68,42 +77,61 @@ AliITSAlignMille2Module::AliITSAlignMille2Module() :
 } \r
 \r
 //-------------------------------------------------------------\r
-AliITSAlignMille2Module::AliITSAlignMille2Module(Int_t index,UShort_t volid,char* symname,TGeoHMatrix *m,Int_t nsv,UShort_t *volidsv) : \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
+  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
+  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
+  fParent(NULL),\r
+  fChildren(0)\r
 { \r
   /// simple constructor building a supermodule from a single sensitive volume \r
   fMatrix = new TGeoHMatrix; \r
@@ -113,18 +141,21 @@ AliITSAlignMille2Module::AliITSAlignMille2Module(UShort_t volid) :
   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
@@ -132,20 +163,39 @@ AliITSAlignMille2Module::AliITSAlignMille2Module(UShort_t volid) :
 AliITSAlignMille2Module::AliITSAlignMille2Module(const AliITSAlignMille2Module &m) :\r
   TNamed(m),\r
   fNSensVol(m.fNSensVol),\r
-  fIndex(m.fIndex),\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
+  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
@@ -154,17 +204,44 @@ AliITSAlignMille2Module& AliITSAlignMille2Module::operator=(const AliITSAlignMil
   // operator =\r
   //\r
   if(this==&m) return *this;\r
-  ((TNamed *)this)->operator=(m);\r
+  this->TNamed::operator=(m);\r
   //\r
   fNSensVol=m.fNSensVol;\r
   fIndex=m.fIndex;\r
+  fDetType = m.fDetType;\r
   fVolumeID=m.fVolumeID;\r
-  for (int i=3;i--;) fSigmaFactor[i] = m.fSigmaFactor[i];\r
+  fNParTot  = m.fNParTot;\r
+  fNParFree = m.fNParFree; \r
+  fNProcPoints = m.fNProcPoints; \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=0;i<3;i++) fSigmaFactor[i] = m.fSigmaFactor[i];\r
   if (fMatrix) delete fMatrix;\r
   fMatrix=new TGeoHMatrix(*m.GetMatrix());\r
+  if(fSensVolMatrix) delete fSensVolMatrix;\r
+  fSensVolMatrix = new TGeoHMatrix(*m.fSensVolMatrix);\r
+  if(fSensVolModifMatrix) delete fSensVolModifMatrix;\r
+  fSensVolModifMatrix = new TGeoHMatrix(*m.fSensVolModifMatrix);\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
@@ -175,10 +252,15 @@ AliITSAlignMille2Module::~AliITSAlignMille2Module() {
   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
+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
@@ -219,6 +301,26 @@ Int_t AliITSAlignMille2Module::Set(Int_t index, UShort_t volid, char* symname, T
   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
@@ -238,7 +340,7 @@ void AliITSAlignMille2Module::AddSensitiveVolume(UShort_t voluid)
   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
+  if (fSensVolVolumeID.GetSize()<fNSensVol+1) {\r
     fSensVolVolumeID.Set(fNSensVol+1);\r
     fSensVolIndex.Set(fNSensVol+1);\r
   }\r
@@ -280,7 +382,7 @@ Bool_t AliITSAlignMille2Module::BelongsTo(AliITSAlignMille2Module* parent) const
 }\r
 \r
 //-------------------------------------------------------------\r
-TGeoHMatrix *AliITSAlignMille2Module::GetSensitiveVolumeModifiedMatrix(UShort_t voluid, Double_t *delta,Bool_t local)\r
+TGeoHMatrix *AliITSAlignMille2Module::GetSensitiveVolumeModifiedMatrix(UShort_t voluid, const 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
@@ -298,11 +400,12 @@ TGeoHMatrix *AliITSAlignMille2Module::GetSensitiveVolumeModifiedMatrix(UShort_t
   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
+  static AliAlignObjParams tempAlignObj;\r
+  tempAlignObj.SetRotation(ang[0],ang[1],ang[2]);\r
+  tempAlignObj.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
+  tempAlignObj.GetMatrix(hm);\r
   //printf("\n0: delta matrix\n");hm.Print();\r
 \r
   // 1) start setting fSensVolModif = fSensVol\r
@@ -322,7 +425,7 @@ TGeoHMatrix *AliITSAlignMille2Module::GetSensitiveVolumeModifiedMatrix(UShort_t
 }\r
 \r
 //-------------------------------------------------------------\r
-AliAlignObjParams *AliITSAlignMille2Module::GetSensitiveVolumeMisalignment(UShort_t voluid, Double_t *deltalocal)\r
+AliAlignObjParams *AliITSAlignMille2Module::GetSensitiveVolumeMisalignment(UShort_t voluid, const 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
@@ -339,15 +442,16 @@ AliAlignObjParams *AliITSAlignMille2Module::GetSensitiveVolumeMisalignment(UShor
   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
+  static AliAlignObjParams tempAlignObj;\r
+  tempAlignObj.SetRotation(ang[0],ang[1],ang[2]);\r
+  tempAlignObj.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
+  return GetSensitiveVolumeMisalignment(voluid,&tempAlignObj);\r
 }\r
 \r
 //-------------------------------------------------------------\r
-AliAlignObjParams *AliITSAlignMille2Module::GetSensitiveVolumeMisalignment(UShort_t voluid, AliAlignObjParams *a)\r
+AliAlignObjParams *AliITSAlignMille2Module::GetSensitiveVolumeMisalignment(UShort_t voluid, const AliAlignObjParams *a)\r
 {\r
   // return the misalignment of the sens. vol. 'voluid' corresponding with \r
   // a misalignment 'a' in the mother volume\r
@@ -406,10 +510,11 @@ AliAlignObjParams *AliITSAlignMille2Module::GetSensitiveVolumeMisalignment(UShor
   // << 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
+  static AliAlignObjParams tempAlignObj;\r
+  tempAlignObj.SetVolUID(0);\r
+  tempAlignObj.SetSymName("");\r
+  tempAlignObj.SetTranslation(0,0,0);\r
+  tempAlignObj.SetRotation(0,0,0);\r
   //\r
   // >> RS\r
 #ifdef CORHW_\r
@@ -423,16 +528,16 @@ AliAlignObjParams *AliITSAlignMille2Module::GetSensitiveVolumeMisalignment(UShor
   }\r
 #endif\r
   // << RS\r
-  if (!fgTempAlignObj.SetMatrix(*fSensVolModifMatrix)) return NULL;\r
-  fgTempAlignObj.SetVolUID(voluid);\r
-  fgTempAlignObj.SetSymName(AliGeomManager::SymName(voluid));\r
+  if (!tempAlignObj.SetMatrix(*fSensVolModifMatrix)) return NULL;\r
+  tempAlignObj.SetVolUID(voluid);\r
+  tempAlignObj.SetSymName(AliGeomManager::SymName(voluid));\r
   //\r
-  return &fgTempAlignObj;\r
+  return &tempAlignObj;\r
 }\r
 \r
 // >> RS\r
 //-------------------------------------------------------------\r
-AliAlignObjParams *AliITSAlignMille2Module::GetSensitiveVolumeTotalMisalignment(UShort_t voluid, Double_t *deltalocal)\r
+AliAlignObjParams *AliITSAlignMille2Module::GetSensitiveVolumeTotalMisalignment(UShort_t voluid, const 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
@@ -451,10 +556,11 @@ AliAlignObjParams *AliITSAlignMille2Module::GetSensitiveVolumeTotalMisalignment(
   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
+  static AliAlignObjParams tempAlignObj;\r
+  tempAlignObj.SetVolUID(0);\r
+  tempAlignObj.SetSymName("");\r
+  tempAlignObj.SetRotation(ang[0],ang[1],ang[2]);\r
+  tempAlignObj.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
@@ -465,7 +571,7 @@ AliAlignObjParams *AliITSAlignMille2Module::GetSensitiveVolumeTotalMisalignment(
 \r
   // prepare the Delta matrix Dg\r
   TGeoHMatrix dg;\r
-  fgTempAlignObj.GetMatrix(dg);\r
+  tempAlignObj.GetMatrix(dg);\r
   //dg.Print();\r
 \r
   // 1) start setting fSensVolModif = Gsv\r
@@ -491,10 +597,10 @@ AliAlignObjParams *AliITSAlignMille2Module::GetSensitiveVolumeTotalMisalignment(
   //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
+  tempAlignObj.SetVolUID(0);\r
+  tempAlignObj.SetSymName("");\r
+  tempAlignObj.SetTranslation(0,0,0);\r
+  tempAlignObj.SetRotation(0,0,0);\r
 \r
 #ifdef CORHW_\r
   // correction for SPD y-shift\r
@@ -506,19 +612,19 @@ AliAlignObjParams *AliITSAlignMille2Module::GetSensitiveVolumeTotalMisalignment(
     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
+  if (!tempAlignObj.SetMatrix(*fSensVolModifMatrix)) return NULL;\r
+  tempAlignObj.SetVolUID(voluid);\r
+  tempAlignObj.SetSymName(AliGeomManager::SymName(voluid));\r
 \r
   \r
-  //fgTempAlignObj.Print("");\r
+  //tempAlignObj.Print("");\r
 \r
-  return &fgTempAlignObj;\r
+  return &tempAlignObj;\r
 }\r
 //-------------------------------------------------------------\r
 \r
 //-------------------------------------------------------------\r
-AliAlignObjParams *AliITSAlignMille2Module::GetSensitiveVolumeGlobalMisalignment(UShort_t voluid, Double_t *deltalocal)\r
+AliAlignObjParams *AliITSAlignMille2Module::GetSensitiveVolumeGlobalMisalignment(UShort_t voluid, const 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
@@ -536,11 +642,12 @@ AliAlignObjParams *AliITSAlignMille2Module::GetSensitiveVolumeGlobalMisalignment
   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
+  static AliAlignObjParams tempAlignObj;\r
+  tempAlignObj.SetTranslation(0,0,0);\r
+  tempAlignObj.SetRotation(0,0,0);\r
 \r
-  fgTempAlignObj.SetRotation(ang[0],ang[1],ang[2]);\r
-  fgTempAlignObj.SetTranslation(tr[0],tr[1],tr[2]);\r
+  tempAlignObj.SetRotation(ang[0],ang[1],ang[2]);\r
+  tempAlignObj.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
@@ -551,24 +658,24 @@ AliAlignObjParams *AliITSAlignMille2Module::GetSensitiveVolumeGlobalMisalignment
 \r
   // prepare the Delta matrix Dg\r
   TGeoHMatrix dg;\r
-  fgTempAlignObj.GetMatrix(dg);\r
+  tempAlignObj.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
+  tempAlignObj.SetTranslation(0,0,0);\r
+  tempAlignObj.SetRotation(0,0,0);\r
 \r
-  fgTempAlignObj.SetVolUID(voluid);\r
-  fgTempAlignObj.SetSymName(AliGeomManager::SymName(voluid));\r
+  tempAlignObj.SetVolUID(voluid);\r
+  tempAlignObj.SetSymName(AliGeomManager::SymName(voluid));\r
 \r
-  if (!fgTempAlignObj.SetMatrix(dg)) return NULL;\r
+  if (!tempAlignObj.SetMatrix(dg)) return NULL;\r
   \r
-  //fgTempAlignObj.Print("");\r
+  //tempAlignObj.Print("");\r
 \r
-  return &fgTempAlignObj;\r
+  return &tempAlignObj;\r
 }\r
 // << RS\r
 \r
@@ -612,9 +719,9 @@ Int_t AliITSAlignMille2Module::SensVolOrigGlobalMatrix(UShort_t volid, TGeoHMatr
   Int_t idx=GetIndexFromVolumeID(volid);\r
   if (idx<0) return -1;\r
   TGeoHMatrix mo;\r
-  if (!AliGeomManager::GetOrigGlobalMatrix(AliGeomManager::SymName(volid),mo));\r
+  if (!AliGeomManager::GetOrigGlobalMatrix(AliGeomManager::SymName(volid),mo)) return -1;\r
   (*m)=mo;\r
-\r
+  //\r
 #ifdef CORHW_\r
   // SPD y-shift by 81 mu\r
   if (volid<5000) { \r
@@ -653,16 +760,26 @@ UShort_t AliITSAlignMille2Module::GetVolumeIDFromIndex(Int_t index) {
 //-------------------------------------------------------------\r
 void AliITSAlignMille2Module::Print(Option_t*) const \r
 {\r
-  ///\r
+  // print data\r
+  //\r
+  const char* typeName[] = {"SPD","SDD","SSD"};\r
   printf("*** ITS SuperModule for AliITSAlignMille ***\n");\r
-  printf("symname  : %s\n",GetName());\r
-  printf("parent   : %s\n",fParent ? fParent->GetName() : "N/A");\r
-  printf("volumeID : %4d  | index : %4d\n",fVolumeID,fIndex);\r
-  printf("Factors  : X=%.2f Y=%.2f Z=%.2f | DOF: Tx:%d Ty:%d Tz:%d Phi:%d Theta:%d Psi:%d\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(AliITSAlignMille2::kDOFTX),IsFreeDOF(AliITSAlignMille2::kDOFTY),\r
-        IsFreeDOF(AliITSAlignMille2::kDOFTZ),IsFreeDOF(AliITSAlignMille2::kDOFPH),\r
-        IsFreeDOF(AliITSAlignMille2::kDOFTH),IsFreeDOF(AliITSAlignMille2::kDOFPS));\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
@@ -671,6 +788,7 @@ void AliITSAlignMille2Module::Print(Option_t*) const
 //-------------------------------------------------------------\r
 Bool_t AliITSAlignMille2Module::IsAlignable() const\r
 {\r
+  // it it alignable?\r
   TGeoManager* geoManager = AliGeomManager::GetGeometry();\r
   if (!geoManager) {\r
     AliInfo("Couldn't initialize geometry");\r
@@ -686,3 +804,420 @@ void AliITSAlignMille2Module::GetLocalMatrix(TGeoHMatrix &mat) const
   mat = *fMatrix;\r
   if (fParent) mat.MultiplyLeft( &fParent->GetMatrix()->Inverse() );\r
 }\r
+\r
+//-------------------------------------------------------------\r
+void AliITSAlignMille2Module::AssignDetType()\r
+{\r
+  // assign the detector type\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
+  // count d.o.f.\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
+  AliAlignObjParams tempAlignObj;\r
+  tempAlignObj.SetMatrix(*fSensVolMatrix);\r
+  tempAlignObj.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
+  AliAlignObjParams tempAlignObj;  \r
+  tempAlignObj.SetMatrix(*fSensVolMatrix);\r
+  tempAlignObj.GetPars(t,r);\r
+}\r
+\r
+//-------------------------------------------------------------\r
+void AliITSAlignMille2Module::GetSensVolGlobalParams(UShort_t volid,const Double_t* loct, const 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
+  AliAlignObjParams tempAlignObj;\r
+  tempAlignObj.SetTranslation(loct[0],loct[1],loct[2]);\r
+  tempAlignObj.SetRotation(locr[0],locr[1],locr[2]);\r
+  //\r
+  tempAlignObj.GetMatrix(*fSensVolModifMatrix);      // obtain local delta\r
+  fSensVolModifMatrix->MultiplyLeft( fSensVolMatrix ); // obtain global delta\r
+  tempAlignObj.SetMatrix(*fSensVolModifMatrix);\r
+  tempAlignObj.GetPars(t,r);                         // obtain global params\r
+}\r
+\r
+//-------------------------------------------------------------\r
+void AliITSAlignMille2Module::GetSensVolLocalParams(UShort_t volid,const Double_t* loct,const 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
+  AliAlignObjParams tempAlignObj;\r
+  tempAlignObj.SetTranslation(loct[0],loct[1],loct[2]);\r
+  tempAlignObj.SetRotation(locr[0],locr[1],locr[2]);\r
+  //\r
+  tempAlignObj.GetMatrix(*fSensVolModifMatrix);      // obtain local delta\r
+  fSensVolModifMatrix->MultiplyLeft( fSensVolMatrix ); // obtain global delta\r
+  fSensVolModifMatrix->MultiplyLeft( &fMatrix->Inverse() ); // obtain delta in current volume\r
+  tempAlignObj.SetMatrix(*fSensVolModifMatrix);\r
+  tempAlignObj.GetPars(t,r);                         // obtain params\r
+}\r
+\r
+//-------------------------------------------------------------\r
+void AliITSAlignMille2Module::SetParVals(Double_t *vl,Int_t npar)\r
+{\r
+  // set parameters\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
+  AliAlignObjParams tempAlignObj;\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
+    tempAlignObj.SetTranslation(parpar[0],parpar[1],parpar[2]);\r
+    tempAlignObj.SetRotation(parpar[3],parpar[4],parpar[5]);\r
+    tempAlignObj.GetMatrix(*fSensVolModifMatrix);\r
+    fSensVolMatrix->MultiplyLeft(fSensVolModifMatrix);\r
+    fSensVolMatrix->MultiplyLeft(parent->GetMatrix());  // global matrix after parents modifications\r
+    parent = parent->GetParent();\r
+  }\r
+  //\r
+  tempAlignObj.SetTranslation(fParVals[0],fParVals[1],fParVals[2]);\r
+  tempAlignObj.SetRotation(fParVals[3],fParVals[4],fParVals[5]);\r
+  tempAlignObj.GetMatrix(*fSensVolModifMatrix);  // local delta matrix\r
+  fSensVolModifMatrix->Multiply( &fSensVolMatrix->Inverse() );\r
+  fSensVolModifMatrix->MultiplyLeft( fSensVolMatrix );\r
+  tempAlignObj.SetMatrix( *fSensVolModifMatrix );  // global delta matrix\r
+  tempAlignObj.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
+  AliAlignObjParams tempAlignObj;\r
+  tempAlignObj.SetTranslation(0.,0.,0.);\r
+  tempAlignObj.SetRotation(0.,0.,0.);\r
+  tempAlignObj.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
+    tempAlignObj.SetTranslation(parpar[0],parpar[1],parpar[2]);\r
+    tempAlignObj.SetRotation(parpar[3],parpar[4],parpar[5]);\r
+    tempAlignObj.GetMatrix(*fSensVolModifMatrix);\r
+    fSensVolMatrix->Multiply(fSensVolModifMatrix); \r
+    parent = parent->GetParent();\r
+  }\r
+  // global matrix after parents modifications\r
+  fSensVolMatrix->Multiply(fMatrix);\r
+  //\r
+  tempAlignObj.SetTranslation(fParVals[0],fParVals[1],fParVals[2]);\r
+  tempAlignObj.SetRotation(fParVals[3],fParVals[4],fParVals[5]);\r
+  tempAlignObj.GetMatrix(*fSensVolModifMatrix);  // global delta matrix\r
+  fSensVolModifMatrix->MultiplyLeft( &fSensVolMatrix->Inverse() );\r
+  fSensVolModifMatrix->Multiply( fSensVolMatrix );\r
+  tempAlignObj.SetMatrix( *fSensVolModifMatrix );  // local delta matrix\r
+  tempAlignObj.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) const\r
+{\r
+  // global parameters of the module\r
+  AliAlignObjParams tempAlignObj;\r
+  tempAlignObj.SetMatrix( *fMatrix );\r
+  tempAlignObj.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
+  AliAlignObjParams tempAlignObj;\r
+  tempAlignObj.SetTranslation(loct[0],loct[1],loct[2]);\r
+  tempAlignObj.SetRotation(locr[0],locr[1],locr[2]);\r
+  tempAlignObj.GetMatrix(*fSensVolModifMatrix);  \r
+  *fSensVolMatrix = *fMatrix;\r
+  fSensVolMatrix->Multiply(fSensVolModifMatrix);\r
+  tempAlignObj.SetMatrix(*fSensVolMatrix);\r
+  tempAlignObj.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
+  AliAlignObjParams tempAlignObj;\r
+  tempAlignObj.SetTranslation(glot[0],glot[1],glot[2]);\r
+  tempAlignObj.SetRotation(glor[0],glor[1],glor[2]);\r
+  tempAlignObj.GetMatrix(*fSensVolMatrix);  \r
+  fSensVolMatrix->Multiply( fMatrix );\r
+  fSensVolMatrix->MultiplyLeft( &fMatrix->Inverse() );\r
+  tempAlignObj.SetMatrix(*fSensVolMatrix);\r
+  tempAlignObj.GetPars(t,r);\r
+}\r