Possibility of using tracks in magnetic field (with AliTrackFitterRiemann) - M. Lunardon
authormasera <masera@f7af4fe6-9843-0410-8265-dc069ae4e863>
Thu, 28 Aug 2008 14:31:46 +0000 (14:31 +0000)
committermasera <masera@f7af4fe6-9843-0410-8265-dc069ae4e863>
Thu, 28 Aug 2008 14:31:46 +0000 (14:31 +0000)
ITS/AliITSAlignMille.cxx
ITS/AliITSAlignMille.h
ITS/AliITSAlignMilleModule.cxx
ITS/AliITSAlignMilleModule.h
ITS/ITSAlignMille.C
ITS/MakeITSMilleSuperModules.C [new file with mode: 0644]

index 18ec774..e2f1ac2 100644 (file)
@@ -17,7 +17,7 @@
 
 //-----------------------------------------------------------------------------
 /// \class AliITSAlignMille
-/// Alignment class fro the ALICE ITS detector
+/// Alignment class for the ALICE ITS detector
 ///
 /// ITS specific alignment class which interface to AliMillepede.   
 /// For each track ProcessTrack calculates the local and global derivatives
@@ -43,7 +43,8 @@
 #include "AliTrackPointArray.h"
 #include "AliAlignObjParams.h"
 #include "AliLog.h"
-#include "TSystem.h"  // come si fa?
+#include "TSystem.h"
+#include "AliTrackFitterRieman.h"
 
 /// \cond CLASSIMP
 ClassImp(AliITSAlignMille)
@@ -59,7 +60,7 @@ AliITSAlignMille::AliITSAlignMille(const Char_t *configFilename, Bool_t initmill
     fResCutInitial(100.), 
     fResCut(100.),
     fNGlobal(ITSMILLE_NDETELEM*ITSMILLE_NPARCH),
-    fNLocal(ITSMILLE_NLOCAL),
+    fNLocal(4),
     fNStdDev(ITSMILLE_NSTDEV),
     fIsMilleInit(kFALSE),
     fParSigTranslations(0.0100),
@@ -67,12 +68,18 @@ AliITSAlignMille::AliITSAlignMille(const Char_t *configFilename, Bool_t initmill
     fTrack(NULL),
     fCluster(),
     fGlobalDerivatives(NULL),
+    fSigmaXfactor(1.0),
+    fSigmaZfactor(1.0),
     fTempAlignObj(NULL),
     fDerivativeXLoc(0),
     fDerivativeZLoc(0),
-    fDeltaPar(0),
     fMinNPtsPerTrack(3),
     fInitTrackParamsMeth(1),
+    fProcessedPoints(NULL),
+    fTotBadLocEqPoints(0),
+    fRieman(NULL),
+    fRequirePoints(kFALSE),
+    fTempExcludedModule(-1),
     fGeometryFileName("geometry.root"),
     fPreAlignmentFileName(""),
     fGeoManager(0),
@@ -83,21 +90,42 @@ AliITSAlignMille::AliITSAlignMille(const Char_t *configFilename, Bool_t initmill
     fUseLocalShifts(kTRUE),
     fUseSuperModules(kFALSE),
     fUsePreAlignment(kFALSE),
+    fUseSortedTracks(kTRUE),
+    fBOn(kFALSE),
+    fBField(0.0),
     fNSuperModules(0),
-    fCurrentModuleHMatrix(NULL)
+    fCurrentModuleHMatrix(NULL),
+    fIsConfigured(kFALSE),
+    fBug(0)
 {
   /// main constructor that takes input from configuration file
   
   fMillepede = new AliMillepede();
   fGlobalDerivatives = new Double_t[fNGlobal];
-  //fTempHMat = new TGeoHMatrix;
-  //fCurrentModuleHMatrix = new TGeoHMatrix;
-  
+
+  for (Int_t i=0; i<ITSMILLE_NDETELEM*2; i++) {
+    fPreAlignQF[i]=-1;
+    fSensVolSigmaXfactor[i]=1.0;
+    fSensVolSigmaZfactor[i]=1.0;
+  }
+
+  for (Int_t i=0; i<6; i++) {
+    fNReqLayUp[i]=0;
+    fNReqLayDown[i]=0;
+    fNReqLay[i]=0;
+  }
+  for (Int_t i=0; i<3; i++) {
+    fNReqDetUp[i]=0;
+    fNReqDetDown[i]=0;
+    fNReqDet[i]=0;
+  }
+
   Int_t lc=LoadConfig(configFilename);
   if (lc) {
     AliInfo(Form("Error %d loading configuration from %s",lc,configFilename));
   }
   else {    
+    fIsConfigured=kTRUE;
     if (initmille && fNGlobal<20000) {
       AliInfo(Form("Initializing Millepede with %d gpar, %d lpar and %d stddev ...",fNGlobal, fNLocal, fNStdDev));
       Init(fNGlobal, fNLocal, fNStdDev);      
@@ -109,22 +137,23 @@ AliITSAlignMille::AliITSAlignMille(const Char_t *configFilename, Bool_t initmill
     }
   }
   
-  fDeltaPar=0.0; // not used at the moment - to be checked later...
-  
+  if (fNModules) {
+    fProcessedPoints=new Int_t[fNModules];
+    for (Int_t ipp=0; ipp<fNModules; ipp++) fProcessedPoints[ipp]=0;
+  }
 }
 
 AliITSAlignMille::~AliITSAlignMille() {
   /// Destructor
   if (fMillepede) delete fMillepede;
   delete [] fGlobalDerivatives;
-  //delete fCurrentModuleHMatrix;
-  //delete fTempHMat;
   for (int i=0; i<fNModules; i++) delete fMilleModule[i];
   for (int i=0; i<fNSuperModules; i++) delete fSuperModule[i];
+  if (fNModules) delete [] fProcessedPoints;
+  if (fRieman) delete fRieman;
 }
 
 ///////////////////////////////////////////////////////////////////////
-
 Int_t AliITSAlignMille::LoadConfig(const Char_t *cfile) {
   /// return 0 if success
   ///        1 if error in module index or voluid
@@ -135,7 +164,7 @@ Int_t AliITSAlignMille::LoadConfig(const Char_t *cfile) {
   Char_t st[200],st2[200];
   Char_t tmp[100];
   Int_t idx,itx,ity,itz,ith,ips,iph;
-  Float_t f1;
+  Float_t f1,f2;
   UShort_t voluid;
   Int_t nmod=0;
 
@@ -179,6 +208,21 @@ Int_t AliITSAlignMille::LoadConfig(const Char_t *cfile) {
       if (LoadSuperModuleFile(st2)) return -1;
     }
 
+    if (strstr(st,"SET_B_FIELD")) {
+      sscanf(st,"%s %f",tmp,&f1);
+      if (f1>0) {
+       fBField = f1;
+       fBOn = kTRUE;
+       fNLocal = 5; // helices
+       fRieman = new AliTrackFitterRieman();
+      }  
+      else {
+       fBField = 0.0;
+       fBOn = kFALSE;
+       fNLocal = 4;
+      }
+    }
+
     if (strstr(st,"SET_PARSIG_TRA")) {
       sscanf(st,"%s %f",tmp,&f1);
       fParSigTranslations=f1;
@@ -204,17 +248,52 @@ Int_t AliITSAlignMille::LoadConfig(const Char_t *cfile) {
       fResCut=f1;
     }
 
+    if (strstr(st,"SET_LOCALSIGMAFACTOR")) {
+      sscanf(st,"%s %f %f",tmp,&f1,&f2);
+      if (f1>0 && f2>0) {
+       fSigmaXfactor=f1;
+       fSigmaZfactor=f2;
+      }
+    }
+
     if (strstr(st,"SET_STARTFAC")) {
       sscanf(st,"%s %f",tmp,&f1);
       fStartFac=f1;
     }
 
+    if (strstr(st,"REQUIRE_POINT")) {
+      // syntax:   REQUIRE_POINT where ndet updw nreqpts
+      //    where = LAYER or DETECTOR
+      //    ndet = detector number: 1-6 for LAYER and 1-3 for DETECTOR (SPD=1, SDD=2, SSD=3)
+      //    updw = 1 for Y>0, -1 for Y<0, 0 if not specified
+      //    nreqpts = minimum number of points of that type
+      sscanf(st,"%s %s %d %d %d",tmp,st2,&itx,&ity,&itz);
+      itx--;
+      if (strstr(st2,"LAYER")) {
+       if (itx<0 || itx>5) return -7;
+       if (ity>0) fNReqLayUp[itx]=itz;
+       else if (ity<0) fNReqLayDown[itx]=itz;
+       else fNReqLay[itx]=itz;
+       fRequirePoints=kTRUE;
+      }
+      else if (strstr(st2,"DETECTOR")) { // DETECTOR
+       if (itx<0 || itx>2) return -7;
+       if (ity>0) fNReqDetUp[itx]=itz;
+       else if (ity<0) fNReqDetDown[itx]=itz;
+       else fNReqDet[itx]=itz; 
+       fRequirePoints=kTRUE;
+      }
+    }
+    
+
     if (strstr(st,"SET_LOCAL_SHIFTS")) { // only enabled mode...
       fUseLocalShifts = kTRUE;
     }
 
     if (strstr(st,"MODULE_INDEX")) { // works only for sensitive modules
-      sscanf(st,"%s %d %d %d %d %d %d %d",tmp,&idx,&itx,&ity,&itz,&iph,&ith,&ips);
+      f1=0; f2=0;
+      sscanf(st,"%s %d %d %d %d %d %d %d %f %f",tmp,&idx,&itx,&ity,&itz,&iph,&ith,&ips,&f1,&f2);
+      if (idx<0 || idx>2197) return 1; // bad index
       voluid=GetModuleVolumeID(idx);
       if (!voluid || voluid>14300) return 1; // bad index
       fModuleIndex[nmod]=idx;
@@ -226,11 +305,14 @@ Int_t AliITSAlignMille::LoadConfig(const Char_t *cfile) {
       fFreeParam[nmod][4]=ith;
       fFreeParam[nmod][5]=ips;
       fMilleModule[nmod] = new AliITSAlignMilleModule(voluid);
+      if (f1>0) fSensVolSigmaXfactor[idx]=f1;
+      if (f2>0) fSensVolSigmaZfactor[idx]=f2;
       nmod++;
     }
    
     if (strstr(st,"MODULE_VOLUID")) {
-      sscanf(st,"%s %d %d %d %d %d %d %d",tmp,&idx,&itx,&ity,&itz,&iph,&ith,&ips);
+      f1=0; f2=0;
+      sscanf(st,"%s %d %d %d %d %d %d %d %f %f",tmp,&idx,&itx,&ity,&itz,&iph,&ith,&ips,&f1,&f2);
       voluid=UShort_t(idx);
       if (voluid>14335 && fUseSuperModules) { // custom supermodule
        int ism=-1;
@@ -247,7 +329,18 @@ Int_t AliITSAlignMille::LoadConfig(const Char_t *cfile) {
        fFreeParam[nmod][4]=ith;
        fFreeParam[nmod][5]=ips;
        fMilleModule[nmod] = new AliITSAlignMilleModule(*fSuperModule[ism]);
-       nmod++;
+       if (f1>0) {
+         for (int kk=0; kk<fMilleModule[nmod]->GetNSensitiveVolumes(); kk++) {
+           idx=AliITSAlignMilleModule::GetIndexFromVolumeID(fMilleModule[nmod]->GetSensitiveVolumeVolumeID()[kk]);
+           if (idx>=0) fSensVolSigmaXfactor[idx]=f1;
+         }
+       }
+       if (f2>0) {
+         for (int kk=0; kk<fMilleModule[nmod]->GetNSensitiveVolumes(); kk++) {
+           idx=AliITSAlignMilleModule::GetIndexFromVolumeID(fMilleModule[nmod]->GetSensitiveVolumeVolumeID()[kk]);
+           if (idx>=0) fSensVolSigmaZfactor[idx]=f2;
+         }
+       }       nmod++;
       }
       else { // sensitive volume
        idx=GetModuleIndex(voluid);
@@ -261,6 +354,8 @@ Int_t AliITSAlignMille::LoadConfig(const Char_t *cfile) {
        fFreeParam[nmod][4]=ith;
        fFreeParam[nmod][5]=ips;
        fMilleModule[nmod] = new AliITSAlignMilleModule(voluid);
+       if (f1>0) fSensVolSigmaXfactor[idx]=f1;
+       if (f2>0) fSensVolSigmaZfactor[idx]=f2;
        nmod++;
       }
     }
@@ -275,6 +370,30 @@ Int_t AliITSAlignMille::LoadConfig(const Char_t *cfile) {
   return 0;
 }
 
+void AliITSAlignMille::SetRequiredPoint(Char_t* where, Int_t ndet, Int_t updw, Int_t nreqpts) 
+{
+  // set minimum number of points in specific detector or layer
+  // where = LAYER or DETECTOR
+  // ndet = detector number: 1-6 for LAYER and 1-3 for DETECTOR (SPD=1, SDD=2, SSD=3)
+  // updw = 1 for Y>0, -1 for Y<0, 0 if not specified
+  // nreqpts = minimum number of points of that type
+  ndet--;
+  if (strstr(where,"LAYER")) {
+    if (ndet<0 || ndet>5) return;
+    if (updw>0) fNReqLayUp[ndet]=nreqpts;
+    else if (updw<0) fNReqLayDown[ndet]=nreqpts;
+    else fNReqLay[ndet]=nreqpts;
+    fRequirePoints=kTRUE;
+  }
+  else if (strstr(where,"DETECTOR")) {
+    if (ndet<0 || ndet>2) return;
+    if (updw>0) fNReqDetUp[ndet]=nreqpts;
+    else if (updw<0) fNReqDetDown[ndet]=nreqpts;
+    else fNReqDet[ndet]=nreqpts;       
+    fRequirePoints=kTRUE;
+  }
+}
+
 Int_t AliITSAlignMille::GetModuleIndex(const Char_t *symname) {
   /// index from symname
   if (!symname) return -1;
@@ -333,7 +452,6 @@ void AliITSAlignMille::InitGeometry() {
     return;
   }
   // temporary align object, just use the rotation...
-  //fTempAlignObj=new AliAlignObjParams(AliITSgeomTGeo::GetSymName(7),2055,0,0,0,0,0,0,kFALSE);
   fTempAlignObj=new AliAlignObjParams;
 }
 
@@ -350,7 +468,7 @@ void AliITSAlignMille::Init(Int_t nGlobal,  /* number of global paramers */
     for (Int_t j=0; j<ITSMILLE_NPARCH; j++) {
       if (!fFreeParam[i][j]) FixParameter(i*ITSMILLE_NPARCH+j,0.0);
       else {
-       // pepopepo: da sistemare il settaggio delle sigma...
+       // pepopepo: da verificare il settaggio delle sigma, ma forse va bene...
        Double_t parsig=0;
        if (j<3) parsig=fParSigTranslations; // translations (0.0100 cm)
        else parsig=fParSigRotations; // rotations (1/10 deg)
@@ -419,6 +537,11 @@ Int_t AliITSAlignMille::ApplyToGeometry() {
 
   for (int ix=0; ix<nprea; ix++) {
     AliAlignObjParams *preo=(AliAlignObjParams*) prea->UncheckedAt(ix);
+    Int_t index=AliITSAlignMilleModule::GetIndexFromVolumeID(preo->GetVolUID());
+    if (index>=0) {
+      fPreAlignQF[index] = (int) preo->GetUniqueID();
+      //printf("index=%d   QF=%d\n",index,preo->GetUniqueID());
+    }
     if (!preo->ApplyToGeometry()) return -4;
   }
   pref->Close();
@@ -428,16 +551,205 @@ Int_t AliITSAlignMille::ApplyToGeometry() {
   return 0;
 }
 
+Int_t AliITSAlignMille::GetPreAlignmentQualityFactor(Int_t index) {
+  /// works for sensitive volumes
+  if (!fUsePreAlignment || index<0 || index>2197) return -1;
+  return fPreAlignQF[index];
+}
+
+AliTrackPointArray *AliITSAlignMille::PrepareTrack(AliTrackPointArray *atp) {
+  /// create a new AliTrackPointArray keeping only defined modules
+  /// move points according to a given prealignment, if any
+  /// sort alitrackpoints w.r.t. global Y direction, if selected
+
+  AliTrackPointArray *atps=NULL;
+  Int_t idx[20];
+  Int_t npts=atp->GetNPoints();
+
+  /// checks if AliTrackPoints belong to defined modules
+  Int_t ngoodpts=0;
+  Int_t intidx[20];
+  
+  for (int j=0; j<npts; j++) {
+    intidx[j] = IsContained(atp->GetVolumeID()[j]);
+    if (intidx[j]>=0) ngoodpts++;
+  }
+  AliDebug(3,Form("Number of points in defined modules: %d",ngoodpts));
+
+  // reject track if not enough points are left
+  if (ngoodpts<fMinNPtsPerTrack) {
+    AliInfo("Track with not enough points!");
+    return NULL;
+  }
+
+  AliTrackPoint p;
+  // check points in specific places
+  if (fRequirePoints) {
+    Int_t nlayup[6],nlaydown[6],nlay[6];
+    Int_t ndetup[3],ndetdown[3],ndet[3];
+    for (Int_t j=0; j<6; j++) {nlayup[j]=0; nlaydown[j]=0; nlay[j]=0;}
+    for (Int_t j=0; j<3; j++) {ndetup[j]=0; ndetdown[j]=0; ndet[j]=0;}
+    
+    for (int i=0; i<npts; i++) {
+      // skip not defined points
+      if (intidx[i]<0) continue;
+      Float_t xx=atp->GetX()[i];
+      Float_t yy=atp->GetY()[i];
+      Float_t r=TMath::Sqrt(xx*xx + yy*yy);
+      int lay=-1;
+      if (r<5) lay=0;
+      else if (r>5 && r<10) lay=1;
+      else if (r>10 && r<18) lay=2;
+      else if (r>18 && r<30) lay=3;
+      else if (r>30 && r<40) lay=4;
+      else if (r>40) lay=5;
+      if (lay<0) continue;
+      int det=lay/2;
+      //printf("Point %d - x=%f  y=%f  R=%f  lay=%d  det=%d\n",i,xx,yy,r,lay,det);
+
+      if (yy>=0.0) { // UP point
+       nlayup[lay]++;
+       nlay[lay]++;
+       ndetup[det]++;
+       ndet[det]++;
+      }
+      else {
+       nlaydown[lay]++;
+       nlay[lay]++;
+       ndetdown[det]++;
+       ndet[det]++;
+      }
+    }
+    
+    // checks minimum values
+    Bool_t isok=kTRUE;
+    for (Int_t j=0; j<6; j++) {
+      if (nlayup[j]<fNReqLayUp[j]) isok=kFALSE; 
+      if (nlaydown[j]<fNReqLayDown[j]) isok=kFALSE; 
+      if (nlay[j]<fNReqLay[j]) isok=kFALSE; 
+    }
+    for (Int_t j=0; j<3; j++) {
+      if (ndetup[j]<fNReqDetUp[j]) isok=kFALSE; 
+      if (ndetdown[j]<fNReqDetDown[j]) isok=kFALSE; 
+      if (ndet[j]<fNReqDet[j]) isok=kFALSE; 
+    }
+    if (!isok) {
+      AliInfo("Track does not meet all location point requirements!");
+      return NULL;
+    }
+  }
+  
+  // build a new track with (sorted) (prealigned) good points
+  atps=new AliTrackPointArray(ngoodpts);
+
+  for (int i=0; i<npts; i++) idx[i]=i;
+  // sort track if required
+  if (fUseSortedTracks) TMath::Sort(npts,atp->GetY(),idx); // sort descending...
+
+  Int_t npto=0;
+  for (int i=0; i<npts; i++) {
+    // skip not defined points
+    if (intidx[idx[i]]<0) continue;
+    atp->GetPoint(p,idx[i]);
+
+    // prealign point if required
+    // get IDEAL matrix
+    TGeoHMatrix *svOrigMatrix = fMilleModule[intidx[idx[i]]]->GetSensitiveVolumeOrigGlobalMatrix(p.GetVolumeID());
+    // get back real local coordinates: use OriginalGlobalMatrix because AliTrackPoints were written
+    // with idel geometry  
+    Double_t pg[3],pl[3];
+    pg[0]=p.GetX();
+    pg[1]=p.GetY();
+    pg[2]=p.GetZ();
+    AliDebug(3,Form("Global coordinates of measured point : X=%f  Y=%f  Z=%f \n",pg[0],pg[1],pg[2]));
+    svOrigMatrix->MasterToLocal(pg,pl);
+
+    AliDebug(3,Form("Local coordinates of measured point : X=%f  Y=%f  Z=%f \n",pl[0],pl[1],pl[2]));
+
+    // update covariance matrix
+    TGeoHMatrix hcov;
+    Double_t hcovel[9];
+    hcovel[0]=double(p.GetCov()[0]);
+    hcovel[1]=double(p.GetCov()[1]);
+    hcovel[2]=double(p.GetCov()[2]);
+    hcovel[3]=double(p.GetCov()[1]);
+    hcovel[4]=double(p.GetCov()[3]);
+    hcovel[5]=double(p.GetCov()[4]);
+    hcovel[6]=double(p.GetCov()[2]);
+    hcovel[7]=double(p.GetCov()[4]);
+    hcovel[8]=double(p.GetCov()[5]);
+    hcov.SetRotation(hcovel);
+    // now rotate in local system
+    hcov.Multiply(svOrigMatrix);
+    hcov.MultiplyLeft(&svOrigMatrix->Inverse());
+    // now hcov is LOCAL COVARIANCE MATRIX
+
+
+    // pepopepo
+    if (fBug==1) {
+      // correzione bug LAYER 5  SSD temporanea..
+      int ssdidx=AliITSAlignMilleModule::GetIndexFromVolumeID(p.GetVolumeID());
+      if (ssdidx>=500 && ssdidx<1248) {
+       int ladder=(ssdidx-500)%22;
+      if (ladder==18) p.SetVolumeID(AliITSAlignMilleModule::GetVolumeIDFromIndex(ssdidx+1));
+      if (ladder==19) p.SetVolumeID(AliITSAlignMilleModule::GetVolumeIDFromIndex(ssdidx-1));
+      }
+    }
+
+    /// get (evenctually prealigned) matrix of sens. vol.
+    TGeoHMatrix *svMatrix = fMilleModule[intidx[idx[i]]]->GetSensitiveVolumeMatrix(p.GetVolumeID());
+    // modify global coordinates according with pre-aligment
+    svMatrix->LocalToMaster(pl,pg);
+    // now rotate in local system
+    hcov.Multiply(&svMatrix->Inverse());
+    hcov.MultiplyLeft(svMatrix);
+    // hcov is back in GLOBAL RF
+    Float_t pcov[6];
+    pcov[0]=hcov.GetRotationMatrix()[0];
+    pcov[1]=hcov.GetRotationMatrix()[1];
+    pcov[2]=hcov.GetRotationMatrix()[2];
+    pcov[3]=hcov.GetRotationMatrix()[4];
+    pcov[4]=hcov.GetRotationMatrix()[5];
+    pcov[5]=hcov.GetRotationMatrix()[8];
+
+    p.SetXYZ(pg[0],pg[1],pg[2],pcov);
+    AliDebug(3,Form("New global coordinates of measured point : X=%f  Y=%f  Z=%f \n",pg[0],pg[1],pg[2]));
+    atps->AddPoint(npto,&p);
+    AliDebug(2,Form("Adding point[%d] = ( %f , %f , %f )     volid = %d",npto,atps->GetX()[npto],atps->GetY()[npto],atps->GetZ()[npto],atps->GetVolumeID()[npto] ));
+
+    npto++;
+  }
+
+  return atps;
+}
+
+
+
+AliTrackPointArray *AliITSAlignMille::SortTrack(AliTrackPointArray *atp) {
+  /// sort alitrackpoints w.r.t. global Y direction
+  AliTrackPointArray *atps=NULL;
+  Int_t idx[20];
+  Int_t npts=atp->GetNPoints();
+  AliTrackPoint p;
+  atps=new AliTrackPointArray(npts);
+
+  TMath::Sort(npts,atp->GetY(),idx);
+
+  for (int i=0; i<npts; i++) {
+    atp->GetPoint(p,idx[i]);
+    atps->AddPoint(i,&p);
+    AliDebug(2,Form("Point[%d] = ( %f , %f , %f )     volid = %d",i,atps->GetX()[i],atps->GetY()[i],atps->GetZ()[i],atps->GetVolumeID()[i] ));
+  }
+  return atps;
+}
+
+
 Int_t AliITSAlignMille::InitModuleParams() {
   /// initialize geometry parameters for a given detector
   /// for current cluster (fCluster)
   /// fGlobalInitParam[] is set as:
   ///    [tx,ty,tz,psi,theta,phi]
-  ///    (old was [tx,ty,tz,theta,psi,phi] ROOT's angles...)
-  /// *** At the moment: using Raffalele's angles definition ***
   ///
-  /// Num of Dets: ITSMILLE_NDETELEM = fgNDetElem
-  /// Num of Par : ITSMILLE_NPARCH = fgNParCh
   /// return 0 if success
 
   if (!fGeoManager) {
@@ -450,7 +762,7 @@ Int_t AliITSAlignMille::InitModuleParams() {
   // set the internal index (index in module list)
   UShort_t voluid=fCluster.GetVolumeID();
   Int_t k=fNModules-1;
-  while (k>=0 && !(fMilleModule[k]->IsIn(voluid)) ) k--;  // new
+  while (k>=0 && !(fMilleModule[k]->IsIn(voluid)) ) k--; 
   if (k<0) return -3;    
   fCurrentModuleInternalIndex=k; // the internal index of the SUPERMODULE
 
@@ -467,68 +779,56 @@ Int_t AliITSAlignMille::InitModuleParams() {
   fModuleInitParam[3] = 0.0; // psi   (X)
   fModuleInitParam[4] = 0.0; // theta (Y)
   fModuleInitParam[5] = 0.0; // phi   (Z)
-
-  /// get global (corrected) matrix  
-  //  if (!AliITSgeomTGeo::GetOrigMatrix(index,*fCurrentModuleHMatrix)) return -3;
-//   Double_t rott[9];
-//   if (!AliITSgeomTGeo::GetRotation(index,rott)) return -3;
-//   fCurrentModuleHMatrix->SetRotation(rott);
-//   Double_t oLoc[3]={0,0,0};
-//   if (!AliITSgeomTGeo::LocalToGlobal(index,oLoc,fCurrentModuleTranslation)) return -4;
-//   fCurrentModuleHMatrix->SetTranslation(fCurrentModuleTranslation);
   
-// new
   fCurrentModuleHMatrix = fMilleModule[fCurrentModuleInternalIndex]->GetMatrix();
 
   for (int ii=0; ii<3; ii++)
     fCurrentModuleTranslation[ii]=fCurrentModuleHMatrix->GetTranslation()[ii];
 
-  TGeoHMatrix *svOrigMatrix = fMilleModule[fCurrentModuleInternalIndex]->GetSensitiveVolumeOrigGlobalMatrix(voluid);
-
-  /// get back local coordinates
+  /// get (evenctually prealigned) matrix of sens. vol.
+  TGeoHMatrix *svMatrix = fMilleModule[fCurrentModuleInternalIndex]->GetSensitiveVolumeMatrix(voluid);
+  
   fMeasGlo[0] = fCluster.GetX();
   fMeasGlo[1] = fCluster.GetY();
-  fMeasGlo[2] = fCluster.GetZ();
-  svOrigMatrix->MasterToLocal(fMeasGlo,fMeasLoc);
-  //svMatrix->MasterToLocal(fMeasGlo,fMeasLoc);
+  fMeasGlo[2] = fCluster.GetZ(); 
+  svMatrix->MasterToLocal(fMeasGlo,fMeasLoc);  
   AliDebug(2,Form("Local coordinates of measured point : X=%f  Y=%f  Z=%f \n",fMeasLoc[0] ,fMeasLoc[1] ,fMeasLoc[2] ));
-
-  TGeoHMatrix *svMatrix = fMilleModule[fCurrentModuleInternalIndex]->GetSensitiveVolumeMatrix(voluid);
   
-  // modify global coordinates according with pre-aligment
-  svMatrix->LocalToMaster(fMeasLoc,fMeasGlo);
-  fCluster.SetXYZ(fMeasGlo[0],fMeasGlo[1] ,fMeasGlo[2]);
-  AliDebug(2,Form("New global coordinates of measured point : X=%f  Y=%f  Z=%f \n",fMeasGlo[0] ,fMeasGlo[1] ,fMeasGlo[2] ));
-
-  // mettere il new GetLocalSigma...
   // set stdev from cluster
   TGeoHMatrix hcov;
   Double_t hcovel[9];
   hcovel[0]=double(fCluster.GetCov()[0]);
   hcovel[1]=double(fCluster.GetCov()[1]);
-  hcovel[2]=double(fCluster.GetCov()[3]);
+  hcovel[2]=double(fCluster.GetCov()[2]);
   hcovel[3]=double(fCluster.GetCov()[1]);
-  hcovel[4]=double(fCluster.GetCov()[2]);
+  hcovel[4]=double(fCluster.GetCov()[3]);
   hcovel[5]=double(fCluster.GetCov()[4]);
-  hcovel[6]=double(fCluster.GetCov()[3]);
+  hcovel[6]=double(fCluster.GetCov()[2]);
   hcovel[7]=double(fCluster.GetCov()[4]);
   hcovel[8]=double(fCluster.GetCov()[5]);
   hcov.SetRotation(hcovel);
   // now rotate in local system
-  hcov.MultiplyLeft(&svMatrix->Inverse());
   hcov.Multiply(svMatrix);
+  hcov.MultiplyLeft(&svMatrix->Inverse());
 
-  // per i ruotati c'e' delle sigmaY che compaiono... prob
-  // e' un problema di troncamento
+  // set local sigmas
   fSigmaLoc[0] = TMath::Sqrt(TMath::Abs(hcov.GetRotationMatrix()[0]));
   fSigmaLoc[1] = TMath::Sqrt(TMath::Abs(hcov.GetRotationMatrix()[4]));
   fSigmaLoc[2] = TMath::Sqrt(TMath::Abs(hcov.GetRotationMatrix()[8]));
 
-  // set minimum value for SigmaLoc to 10 micron
+  // set minimum value for SigmaLoc to 10 micron 
   if (fSigmaLoc[0]<0.0010) fSigmaLoc[0]=0.0010;
   if (fSigmaLoc[2]<0.0010) fSigmaLoc[2]=0.0010;
 
-    AliDebug(2,Form("Setting StDev from CovMat : fSigmaLocX=%f  fSigmaLocY=%f fSigmaLocZ=%f \n",fSigmaLoc[0] ,fSigmaLoc[1] ,fSigmaLoc[2] ));
+  // multiply local sigmas by global factor
+  fSigmaLoc[0] *= fSigmaXfactor;
+  fSigmaLoc[2] *= fSigmaZfactor;
+
+  // multiply local sigmas by individual factor
+  fSigmaLoc[0] *= fSensVolSigmaXfactor[index];
+  fSigmaLoc[2] *= fSensVolSigmaZfactor[index];
+
+  AliDebug(2,Form("Setting StDev from CovMat : fSigmaLocX=%g  fSigmaLocY=%g fSigmaLocZ=%g \n",fSigmaLoc[0] ,fSigmaLoc[1] ,fSigmaLoc[2] ));
    
   return 0;
 }
@@ -540,20 +840,14 @@ void AliITSAlignMille::SetCurrentModule(Int_t index) {
     return;
   }
   UShort_t voluid=GetModuleVolumeID(index);
-  //Int_t k=IsDefined(voluid);
   Int_t k=IsContained(voluid);
   if (k>=0){
-    //if (voluid<14336) 
     fCluster.SetVolumeID(voluid);
-    //else {
-    //fCluster.SetVolumeID(fMilleModule[k]->GetSensitiveVolumeVolumeID()[0]);
-    //printf("current module is a supermodule: fCluster set to first sensitive volume of the supermodule\n");
-    //}
     fCluster.SetXYZ(0,0,0);
     InitModuleParams();
   }
   else
-    printf("module %d not defined\n",index);    
+    AliInfo(Form("module %d not defined\n",index));    
 }
 
 void AliITSAlignMille::SetCurrentSensitiveModule(Int_t index) {
@@ -564,19 +858,18 @@ void AliITSAlignMille::SetCurrentSensitiveModule(Int_t index) {
   }
   UShort_t voluid=AliITSAlignMilleModule::GetVolumeIDFromIndex(index);
   Int_t k=IsDefined(voluid);
-  //printf("---> voluid=%d   k=%d\n",voluid,k);
   if (k>=0){
     fCluster.SetVolumeID(voluid);
     fCluster.SetXYZ(0,0,0);
     InitModuleParams();
   }
   else
-    printf("module %d not defined\n",index);    
+    AliInfo(Form("module %d not defined\n",index));    
 }
 
 void AliITSAlignMille::Print(Option_t*) const 
 {
-  ///
+  /// print infos
   printf("*** AliMillepede for ITS ***\n");
   printf("    number of defined super modules: %d\n",fNModules);
   
@@ -595,18 +888,36 @@ void AliITSAlignMille::Print(Option_t*) const
   else
     printf("    prealignment not used\n");    
 
+  if (fBOn) 
+    printf("    B Field set to %f T - using Riemann's helices\n",fBField);
+  else
+    printf("    B Field OFF - using straight lines \n");
+
   if (fUseLocalShifts) 
     printf("    Alignment shifts will be computed in LOCAL RS\n");
   else
     printf("    Alignment shifts will be computed in GLOBAL RS\n");    
+
+  if (fRequirePoints) printf("    Required points in tracks:\n");
+  for (Int_t i=0; i<6; i++) {
+    if (fNReqLayUp[i]>0) printf("        Layer %d : %d points with Y>0\n",i+1,fNReqLayUp[i]);
+    if (fNReqLayDown[i]>0) printf("        Layer %d : %d points with Y<0\n",i+1,fNReqLayDown[i]);
+    if (fNReqLay[i]>0) printf("        Layer %d : %d points \n",i+1,fNReqLay[i]);
+  }
+  for (Int_t i=0; i<3; i++) {
+    if (fNReqDetUp[i]>0) printf("        Detector %d : %d points with Y>0\n",i+1,fNReqDetUp[i]);
+    if (fNReqDetDown[i]>0) printf("        Detector %d : %d points with Y<0\n",i+1,fNReqDetDown[i]);
+    if (fNReqDet[i]>0) printf("        Detector %d : %d points \n",i+1,fNReqDet[i]);
+  }
   
-  printf("    Millepede configuration parameters:\n");
-  printf("       init parsig for translations  : %.4f\n",fParSigTranslations);
-  printf("       init parsig for rotations     : %.4f\n",fParSigRotations);
-  printf("       init value for chi2 cut       : %.4f\n",fStartFac);
-  printf("       first iteration cut value     : %.4f\n",fResCutInitial);
-  printf("       other iterations cut value    : %.4f\n",fResCut);
-  printf("       number of stddev for chi2 cut : %d\n",fNStdDev);
+  printf("\n    Millepede configuration parameters:\n");
+  printf("        init parsig for translations  : %.4f\n",fParSigTranslations);
+  printf("        init parsig for rotations     : %.4f\n",fParSigRotations);
+  printf("        init value for chi2 cut       : %.4f\n",fStartFac);
+  printf("        first iteration cut value     : %.4f\n",fResCutInitial);
+  printf("        other iterations cut value    : %.4f\n",fResCut);
+  printf("        number of stddev for chi2 cut : %d\n",fNStdDev);
+  printf("        mult. fact. for local sigmas  : %.4f %.4f\n",fSigmaXfactor, fSigmaZfactor);
 
   printf("List of defined modules:\n");
   printf("  intidx\tindex\tvoluid\tname\n");
@@ -638,6 +949,37 @@ void AliITSAlignMille::PrintCurrentModuleInfo()
   fMilleModule[k]->Print("");
 }
 
+Bool_t AliITSAlignMille::InitRiemanFit() {
+  // Initialize Riemann Fitter for current track
+  // return kFALSE if error
+
+  if (!fBOn) return kFALSE;
+
+  Int_t npts=0;
+  AliTrackPoint ap;
+  npts = fTrack->GetNPoints();
+  AliDebug(3,Form("Fitting track with %d points",npts));
+
+  fRieman->Reset();
+  fRieman->SetTrackPointArray(fTrack);
+
+  TArrayI ai(npts);
+  for (Int_t ipt=0; ipt<npts; ipt++) ai[ipt]=fTrack->GetVolumeID()[ipt];
+  
+  // fit track with 5 params in his own tracking-rotated reference system
+  // xc = -p[1]/p[0];
+  // yc = 1/p[0];
+  // R  = sqrt( x0*x0 + y0*y0 - y0*p[2]);
+  if (!fRieman->Fit(&ai,NULL,(AliGeomManager::ELayerID)1,(AliGeomManager::ELayerID)6)) {
+    return kFALSE;
+  }
+
+  for (int i=0; i<5; i++)
+    fLocalInitParam[i] = fRieman->GetParam()[i];
+  
+  return kTRUE;
+}
+
 
 void AliITSAlignMille::InitTrackParams(int meth) {
   /// initialize local parameters with different methods
@@ -661,6 +1003,7 @@ void AliITSAlignMille::InitTrackParams(int meth) {
     
     // test #1: linear fit in x(y) and z(y)
     npts = fTrack->GetNPoints();
+    AliDebug(3,Form("*** initializing track with %d points ***",npts));
 
     f1=new TF1("f1","[0]+x*[1]",-50,50);
 
@@ -691,19 +1034,28 @@ void AliITSAlignMille::InitTrackParams(int meth) {
     
     // test #1: linear fit in x(y) and z(y)
     npts = fTrack->GetNPoints();
+    AliDebug(3,Form("*** initializing track with %d points ***",npts));
+
     for (Int_t isig=0; isig<npts; isig++) {
       fTrack->GetPoint(ap,isig);
       sigmax[isig]=ap.GetCov()[0]; 
       if (sigmax[isig]<1.0e-07) sigmax[isig]=1.0e-07; // minimum sigma=3 mu
       sigmax[isig]=TMath::Sqrt(sigmax[isig]);
 
-      sigmay[isig]=ap.GetCov()[2]; 
+      sigmay[isig]=ap.GetCov()[3]; 
       if (sigmay[isig]<1.0e-07) sigmay[isig]=1.0e-07; // minimum sigma=3 mu
       sigmay[isig]=TMath::Sqrt(sigmay[isig]);
 
       sigmaz[isig]=ap.GetCov()[5]; 
       if (sigmaz[isig]<1.0e-07) sigmaz[isig]=1.0e-07; // minimum sigma=3 mu
       sigmaz[isig]=TMath::Sqrt(sigmaz[isig]);      
+
+      if (fTempExcludedModule>=0 && fTempExcludedModule==AliITSAlignMilleModule::GetIndexFromVolumeID(ap.GetVolumeID())) {
+       sigmax[isig] *= 1000.;
+       sigmay[isig] *= 1000.;
+       sigmaz[isig] *= 1000.;
+       fTempExcludedModule=-1;
+      }
     }
 
     f1=new TF1("f1","[0]+x*[1]",-50,50);
@@ -772,7 +1124,7 @@ Int_t AliITSAlignMille::CheckCurrentTrack() {
       ngoodpts++;
     }
   }
-  // pepo da controllare...
+
   if (ngoodpts<fMinNPtsPerTrack) return 0;
 
   return ngoodpts;
@@ -789,105 +1141,158 @@ Int_t AliITSAlignMille::ProcessTrack(AliTrackPointArray *track) {
   }
 
   Int_t npts = track->GetNPoints();
-  AliDebug(2,Form("\n*** Processing track with %d points ***\n",npts));
-  fTrack = track;
-
-  // checks if there are enough good points
-  if (!CheckCurrentTrack()) {
-    AliInfo("Track with not enough good points - will not be used...");
-    return -1;
-  }
+  AliDebug(2,Form("*** Input track with %d points ***",npts));
 
-  // set local starting parameters (to be substituted by ESD track parms)
-  // local parms (fLocalInitParam[]) are:
-  //      [0] = global x coord. of straight line intersection at y=0 plane
-  //      [1] = global z coord. of straight line intersection at y=0 plane
-  //      [2] = px/py  
-  //      [3] = pz/py
-  InitTrackParams(fInitTrackParamsMeth);  
+  // preprocessing of the input track: keep only points in defined volumes,
+  // move points if prealignment is set, sort by Yglo if required
+  
+  fTrack=PrepareTrack(track);
+  if (!fTrack) return -1;
 
+  npts = fTrack->GetNPoints();
+  AliDebug(2,Form("*** Processing prepared track with %d points ***",npts));
+  
+  if (!fBOn) { // straight lines  
+    // set local starting parameters (to be substituted by ESD track parms)
+    // local parms (fLocalInitParam[]) are:
+    //      [0] = global x coord. of straight line intersection at y=0 plane
+    //      [1] = global z coord. of straight line intersection at y=0 plane
+    //      [2] = px/py  
+    //      [3] = pz/py
+    InitTrackParams(fInitTrackParamsMeth);  
+  } 
+  else {
+    // local parms (fLocalInitParam[]) are the Riemann Fitter params
+    if (!InitRiemanFit()) {
+      AliInfo("Riemann fit failed! skipping this track...");
+      delete fTrack;
+      fTrack=NULL;
+      return -5;
+    }
+  }
+  
+  Int_t nloceq=0;
+  MilleData *md = new MilleData[npts];
+  
   for (Int_t ipt=0; ipt<npts; ipt++) {
     fTrack->GetPoint(fCluster,ipt);
-    if (!CheckVolumeID(fCluster.GetVolumeID())) continue;
-    AliDebug(2,Form("  Original Point = ( %f , %f , %f )   volid=%d\n",fCluster.GetX(),fCluster.GetY(),fCluster.GetZ(),fCluster.GetVolumeID()));
+    AliDebug(2,Form("\n--- processing point %d --- \n",ipt));    
 
     // set geometry parameters for the the current module
-    AliDebug(2,Form("\n--- processing point %d --- \n",ipt));    
     if (InitModuleParams()) continue;
-
     AliDebug(2,Form("    VolID=%d  Index=%d  InternalIdx=%d  symname=%s\n", track->GetVolumeID()[ipt], fCurrentModuleIndex ,fCurrentModuleInternalIndex, AliGeomManager::SymName(track->GetVolumeID()[ipt]) ));
-    AliDebug(2,Form("  Preprocessed Point = ( %f , %f , %f ) \n",fCluster.GetX(),fCluster.GetY(),fCluster.GetZ()));
+    AliDebug(2,Form("    Preprocessed Point = ( %f , %f , %f ) \n",fCluster.GetX(),fCluster.GetY(),fCluster.GetZ()));
+    
+    if (!AddLocalEquation(md[nloceq])) {
+      nloceq++;    
+      fProcessedPoints[fCurrentModuleInternalIndex]++;
+    }
+    else {
+      fTotBadLocEqPoints++;
+    }
     
-    if (SetLocalEquations()) return -1;    
-
   } // end loop over points
   
+  delete fTrack;
+  fTrack=NULL;
+
+  // not enough good points!
+  if (nloceq<fMinNPtsPerTrack) {
+    delete [] md;      
+    return -1;
+  }
+  
+  // finally send local equations to millepede
+  SetLocalEquations(md,nloceq);
+
+  delete [] md;
+  
   return 0;
 }
 
 Int_t AliITSAlignMille::CalcIntersectionPoint(Double_t *lpar, Double_t *gpar) {
-  /// calculate track intersection point in local coordinates
-  /// according with a given set of parameters (local(4) and global(6))
+  /// calculate intersection point of track with current module in local coordinates
+  /// according with a given set of parameters (local(4/5) and global(6))
   /// and fill fPintLoc/Glo
-  ///    local are:   pgx0, pgz0, ugx0, ugz0
+  ///    local are:   pgx0, pgz0, ugx, ugz   OR   riemann fitters pars
   ///    global are:  tx,ty,tz,psi,theta,phi (Raff's delta angles in deg.)
   /// return 0 if success
   
-  AliDebug(3,Form("lpar = %g %g %g %g \ngpar= %g %g %g %g %g %g\n",lpar[0],lpar[1],lpar[2],lpar[3],gpar[0],gpar[1],gpar[2],gpar[3],gpar[4],gpar[5]));
-  
-  // vector of initial straight line direction in glob. coord
-  // ATTENZIONE: forse va rinormalizzato tutto...
-  Double_t v0g[3];
-  //Double_t 
-  v0g[0]=lpar[2];
-  v0g[1]=1.0;
-  v0g[2]=lpar[3];
+  AliDebug(3,Form("lpar = %g %g %g %g %g\ngpar= %g %g %g %g %g %g\n",lpar[0],lpar[1],lpar[2],lpar[3],lpar[4],gpar[0],gpar[1],gpar[2],gpar[3],gpar[4],gpar[5]));
+  AliDebug(3,Form("deltalpar = %g %g %g %g %g\n",lpar[0]-fLocalInitParam[0],lpar[1]-fLocalInitParam[1],lpar[2]-fLocalInitParam[2],lpar[3]-fLocalInitParam[3],lpar[4]-fLocalInitParam[4]));
 
-  // intercept in yg=0 plane in glob coord
-  Double_t p0g[3];
-  p0g[0]=lpar[0];
-  p0g[1]=0.0;
-  p0g[2]=lpar[1];
-
-
-  // prepare the TGeoHMatrix
-//   Double_t tr[3],ang[3];
-//   //Double_t rad2deg=180./TMath::Pi();
-//   if (fUseLocalShifts) { // just Delta matrix
-//     tr[0]=gpar[0]; 
-//     tr[1]=gpar[1]; 
-//     tr[2]=gpar[2];
-//     ang[0]=gpar[3]; // psi   (X)
-//     ang[1]=gpar[4]; // theta (Y)
-//     ang[2]=gpar[5]; // phi   (Z)
-//   }
-//   else { // total matrix with shifted parameter
-//     AliInfo("global shifts not implemented yet!");
-//     return -1;
-//   }
-
-//   //printf("fTempRot = 0x%x  - ang = %g %g %g \n",fTempRot,gpar[5]*rad2deg,gpar[3]*rad2deg,gpar[4]*rad2deg);
-
-//   fTempAlignObj->SetRotation(ang[0],ang[1],ang[2]);
-//   AliDebug(3,Form("Delta angles: psi=%f  theta=%f   phi=%f",ang[0],ang[1],ang[2]));
-//   TGeoHMatrix hm;
-//   fTempAlignObj->GetMatrix(hm);
-//   fTempHMat->SetRotation(hm.GetRotationMatrix());
-//   fTempHMat->SetTranslation(tr);
   
-//   // in this case the gpar[] array contains only shifts
-//   // and fInitModuleParam[] are set to 0
-//   // fCurrentModuleHMatrix is then modified as fCurrentHM*fTempHM
-//   if (fUseLocalShifts) 
-//     fTempHMat->MultiplyLeft(fCurrentModuleHMatrix);
+  // prepare the TGeoHMatrix
   TGeoHMatrix *fTempHMat = fMilleModule[fCurrentModuleInternalIndex]->GetSensitiveVolumeModifiedMatrix(fCluster.GetVolumeID(),gpar);
   if (!fTempHMat) return -1;
-
+  
+  Double_t v0g[3]; // vector with straight line direction in global coord.
+  Double_t p0g[3]; // point of the straight line (glo)
+  
+  if (fBOn) { // B FIELD!
+    AliTrackPoint prf; 
+    for (int ip=0; ip<5; ip++)
+      fRieman->SetParam(ip,lpar[ip]);
+
+    if (!fRieman->GetPCA(fCluster,prf))  {
+      AliInfo(Form("error in GetPCA for point %d",fCluster.GetVolumeID()));
+      return -3;
+    }
+    // now determine straight line passing tangent to fit curve at prf
+    // ugx = dX/dY_glo = DeltaX/DeltaY_glo
+    // mo' P1=(X,Y,Z)_glo_prf
+    //       => (x,y,Z)_trk_prf ruotando di alpha...
+    Double_t alpha=fRieman->GetAlpha();
+    Double_t x1g = prf.GetX();
+    Double_t y1g = prf.GetY();
+    Double_t z1g = prf.GetZ();
+    Double_t x1t =  x1g*TMath::Cos(alpha) + y1g*TMath::Sin(alpha);
+    Double_t y1t = -x1g*TMath::Sin(alpha) + y1g*TMath::Cos(alpha);
+    Double_t z1t =  z1g;    
+
+    Double_t x2t = x1t+1.0;
+    Double_t y2t = y1t+fRieman->GetDYat(x1t);
+    Double_t z2t = z1t+fRieman->GetDZat(x1t);
+    Double_t x2g =  x2t*TMath::Cos(alpha) - y2t*TMath::Sin(alpha);
+    Double_t y2g =  x2t*TMath::Sin(alpha) + y2t*TMath::Cos(alpha);
+    Double_t z2g =  z2t;  
+
+    AliDebug(3,Form("Riemann frame:  fAlpha = %f  =  %f  ",alpha,alpha*180./TMath::Pi()));
+    AliDebug(3,Form("   prf_glo=( %f , %f , %f )  prf_rf=( %f , %f , %f )\n", x1g,y1g,z1g, x1t,y1t,z1t));
+    AliDebug(3,Form("   mov_glo=( %f , %f , %f )      rf=( %f , %f , %f )\n",x2g,y2g,z2g, x2t,y2t,z2t));
+        
+    if (TMath::Abs(y2g-y1g)<1e-15) {
+      AliInfo("DeltaY=0! Cannot proceed...");
+      return -1;
+    }
+    // ugx,1,ugz
+    v0g[0] = (x2g-x1g)/(y2g-y1g);
+    v0g[1]=1.0;
+    v0g[2] = (z2g-z1g)/(y2g-y1g);
+    
+    // point: just keep prf
+    p0g[0]=x1g;
+    p0g[1]=y1g;
+    p0g[2]=z1g;
+  }  
+  else { // staight line
+    // vector of initial straight line direction in glob. coord
+    v0g[0]=lpar[2];
+    v0g[1]=1.0;
+    v0g[2]=lpar[3];
+    
+    // intercept in yg=0 plane in glob coord
+    p0g[0]=lpar[0];
+    p0g[1]=0.0;
+    p0g[2]=lpar[1];
+  }
+  AliDebug(3,Form("Line vector: ( %f , %f , %f )  point:( %f , %f , %f )\n",v0g[0],v0g[1],v0g[2],p0g[0],p0g[1],p0g[2]));
+  
   // same in local coord.
   Double_t p0l[3],v0l[3];
   fTempHMat->MasterToLocalVect(v0g,v0l);
   fTempHMat->MasterToLocal(p0g,p0l);
-
+  
   if (TMath::Abs(v0l[1])<1e-15) {
     AliInfo("Track Y direction in local frame is zero! Cannot proceed...");
     return -1;
@@ -901,14 +1306,14 @@ Int_t AliITSAlignMille::CalcIntersectionPoint(Double_t *lpar, Double_t *gpar) {
   // global intersection point
   fTempHMat->LocalToMaster(fPintLoc,fPintGlo);
   AliDebug(3,Form("Intesect. point: L( %f , %f , %f )  G( %f , %f , %f )\n",fPintLoc[0],fPintLoc[1],fPintLoc[2],fPintGlo[0],fPintGlo[1],fPintGlo[2]));
-
+  
   return 0;
 }
 
 Int_t AliITSAlignMille::CalcDerivatives(Int_t paridx, Bool_t islpar) {
   /// calculate numerically (ROOT's style) the derivatives for
   /// local X intersection  and local Z intersection
-  /// parlist: local  (islpar=kTRUE)  pgx0, pgz0, ugx0, ugz0
+  /// parlist: local  (islpar=kTRUE)  pgx0, pgz0, ugx0, ugz0  OR riemann's params
   ///          global (islpar=kFALSE) tx, ty, tz, psi, theta, phi (Raf's angles in deg)
   /// return 0 if success
   
@@ -918,23 +1323,50 @@ Int_t AliITSAlignMille::CalcDerivatives(Int_t paridx, Bool_t islpar) {
   for (Int_t i=0; i<ITSMILLE_NLOCAL; i++) lpar[i]=fLocalInitParam[i];
   for (Int_t i=0; i<ITSMILLE_NPARCH; i++) gpar[i]=fModuleInitParam[i];
 
-  // pepopepo  
   // trial with fixed dpar...
   Double_t dpar=0.0;
-  if (islpar) {
+
+  if (islpar) { // track parameters
     //dpar=fLocalInitParam[paridx]*0.001;
     // set minimum dpar
-    if (paridx<2) dpar=1.0e-4; // translations
-    else dpar=1.0e-6; // direction
+    if (!fBOn) {
+      if (paridx<2) dpar=1.0e-4; // translations
+      else dpar=1.0e-6; // direction
+    }
+    else { // B Field
+      // pepo: proviamo con 1/1000, poi evenctually 1/100...
+      Double_t dfrac=0.01;
+      switch(paridx) {
+      case 0:
+       // RMS cosmics: 1e-4
+       dpar = TMath::Max(1.0e-6,TMath::Abs(fLocalInitParam[paridx]*dfrac)); 
+       break;
+      case 1: 
+       // RMS cosmics: 0.2
+       dpar = TMath::Max(0.002,TMath::Abs(fLocalInitParam[paridx]*dfrac)); 
+       break;
+      case 2: 
+       // RMS cosmics: 9
+       dpar = TMath::Max(0.09,TMath::Abs(fLocalInitParam[paridx]*dfrac)); 
+       break;
+      case 3: 
+       // RMS cosmics: 7
+       dpar = TMath::Max(0.07,TMath::Abs(fLocalInitParam[paridx]*dfrac)); 
+       break;
+      case 4: 
+       // RMS cosmics: 0.3
+       dpar = TMath::Max(0.003,TMath::Abs(fLocalInitParam[paridx]*dfrac)); 
+       break;
+      }
+    }
   }
-  else {
+  else { // alignment global parameters
     //dpar=fModuleInitParam[paridx]*0.001;
     if (paridx<3) dpar=1.0e-4; // translations
     else dpar=1.0e-2; // angles    
   }
-  AliDebug(3,Form("\n+++ automatic dpar=%g\n",dpar));
-  if (fDeltaPar) dpar=fDeltaPar;
-  AliDebug(3,Form("+++ using dpar=%g\n\n",dpar));
+
+  AliDebug(3,Form("+++ using dpar=%g",dpar));
   
   // calculate derivative ROOT's like:
   //  using f(x+h),f(x-h),f(x+h/2),f(x-h2)...
@@ -985,18 +1417,20 @@ Int_t AliITSAlignMille::CalcDerivatives(Int_t paridx, Bool_t islpar) {
   return 0;
 }
 
-Int_t AliITSAlignMille::SetLocalEquations() {
-  /// Define local equation for current track and cluster in x coor.
+
+Int_t AliITSAlignMille::AddLocalEquation(MilleData &m) {
+  /// Define local equation for current cluster in X and Z coor.
+  /// and store them to memory
   /// return 0 if success
   
   // store first interaction point
-  CalcIntersectionPoint(fLocalInitParam, fModuleInitParam);  
+  if (CalcIntersectionPoint(fLocalInitParam, fModuleInitParam)) return -4;  
   for (Int_t i=0; i<3; i++) fPintLoc0[i]=fPintLoc[i];
   AliDebug(2,Form("Intesect. point: L( %f , %f , %f )",fPintLoc[0],fPintLoc[1],fPintLoc[2]));
   
   // calculate local derivatives numerically
   Double_t dXdL[ITSMILLE_NLOCAL],dZdL[ITSMILLE_NLOCAL];
-  for (Int_t i=0; i<ITSMILLE_NLOCAL; i++) {
+  for (Int_t i=0; i<fNLocal; i++) {
     if (CalcDerivatives(i,kTRUE)) return -1;
     dXdL[i]=fDerivativeXLoc;
     dZdL[i]=fDerivativeZLoc;
@@ -1010,34 +1444,100 @@ Int_t AliITSAlignMille::SetLocalEquations() {
   }
 
   AliDebug(2,Form("\n***************\n"));
-  for (Int_t i=0; i<ITSMILLE_NLOCAL; i++)
+  for (Int_t i=0; i<fNLocal; i++)
     AliDebug(2,Form("Local parameter %d - dXdpar = %g  - dZdpar = %g\n",i,dXdL[i],dZdL[i]));
   for (Int_t i=0; i<ITSMILLE_NPARCH; i++)
     AliDebug(2,Form("Global parameter %d - dXdpar = %g  - dZdpar = %g\n",i,dXdG[i],dZdG[i]));
   AliDebug(2,Form("\n***************\n"));
 
-  
-  AliDebug(2,Form("setting local equation X with fMeas=%.6f  and fSigma=%.6f",(fMeasLoc[0]-fPintLoc0[0]), fSigmaLoc[0]));
+  // check if at least 1 local and 1 global derivs. are not null
+  Double_t nonzero=0.0;
+  for (Int_t i=0; i<fNLocal; i++) nonzero += TMath::Abs(dXdL[i]);
+  if (nonzero==0.0) {
+    AliInfo("Aborting local equations for this point beacuse of zero local X derivatives!");
+    return -2;
+  }
+  nonzero=0.0;
+  for (Int_t i=0; i<ITSMILLE_NPARCH; i++) nonzero += TMath::Abs(dXdG[i]);
+  if (nonzero==0.0) {
+    AliInfo("Aborting local equations for this point beacuse of zero global X derivatives!");
+    return -2;
+  }
+  nonzero=0.0;
+  for (Int_t i=0; i<fNLocal; i++) nonzero += TMath::Abs(dZdL[i]);
+  if (nonzero==0.0) {
+    AliInfo("Aborting local equations for this point beacuse of zero local Z derivatives!");
+    return -2;
+  }
+  nonzero=0.0;
+  for (Int_t i=0; i<ITSMILLE_NPARCH; i++) nonzero += TMath::Abs(dZdG[i]);
+  if (nonzero==0.0) {
+    AliInfo("Aborting local equations for this point beacuse of zero global Z derivatives!");
+    return -2;
+  }
+
+  // ok, can copy to m
+
+  AliDebug(2,Form("Adding local equation X with fMeas=%.6f  and fSigma=%.6f",(fMeasLoc[0]-fPintLoc0[0]), fSigmaLoc[0]));
   // set equation for Xloc coordinate
-  for (Int_t i=0; i<ITSMILLE_NLOCAL; i++) 
-    SetLocalDerivative(i,dXdL[i]);
-  for (Int_t i=0; i<ITSMILLE_NPARCH; i++)
-    SetGlobalDerivative(fCurrentModuleInternalIndex*ITSMILLE_NPARCH+i,dXdG[i]);
-  fMillepede->SetLocalEquation(fGlobalDerivatives, fLocalDerivatives, (fMeasLoc[0]-fPintLoc0[0]), fSigmaLoc[0]);  
+  for (Int_t i=0; i<fNLocal; i++) {
+    m.idxlocX[i]=i;
+    m.derlocX[i]=dXdL[i];
+  }
+  for (Int_t i=0; i<ITSMILLE_NPARCH; i++) {
+    m.idxgloX[i]=fCurrentModuleInternalIndex*ITSMILLE_NPARCH+i;
+    m.dergloX[i]=dXdG[i];    
+  }
+  m.measX = fMeasLoc[0]-fPintLoc0[0];
+  m.sigmaX = fSigmaLoc[0];
   
-
-  AliDebug(2,Form("setting local equation Z with fMeas=%.6f  and fSigma=%.6f",(fMeasLoc[2]-fPintLoc0[2]), fSigmaLoc[2]));
+  AliDebug(2,Form("Adding local equation Z with fMeas=%.6f  and fSigma=%.6f",(fMeasLoc[2]-fPintLoc0[2]), fSigmaLoc[2]));
   // set equation for Zloc coordinate
-  for (Int_t i=0; i<ITSMILLE_NLOCAL; i++) 
-    SetLocalDerivative(i,dZdL[i]);
-  for (Int_t i=0; i<ITSMILLE_NPARCH; i++)
-    SetGlobalDerivative(fCurrentModuleInternalIndex*ITSMILLE_NPARCH+i,dZdG[i]);
-  fMillepede->SetLocalEquation(fGlobalDerivatives, fLocalDerivatives, (fMeasLoc[2]-fPintLoc0[2]), fSigmaLoc[2]);  
-  
+  for (Int_t i=0; i<fNLocal; i++) {
+    m.idxlocZ[i]=i;
+    m.derlocZ[i]=dZdL[i];
+  }
+  for (Int_t i=0; i<ITSMILLE_NPARCH; i++) {
+    m.idxgloZ[i]=fCurrentModuleInternalIndex*ITSMILLE_NPARCH+i;
+    m.dergloZ[i]=dZdG[i];    
+  }
+  m.measZ = fMeasLoc[2]-fPintLoc0[2];
+  m.sigmaZ = fSigmaLoc[2];
   return 0;
 }
 
 
+void AliITSAlignMille::SetLocalEquations(MilleData *m, Int_t neq) {
+  /// Set local equations with data stored in m
+  /// return 0 if success
+  
+  for (Int_t j=0; j<neq; j++) {
+    
+    AliDebug(2,Form("setting local equation X with fMeas=%.6f  and fSigma=%.6f",m[j].measX, m[j].sigmaX));
+    // set equation for Xloc coordinate
+    for (Int_t i=0; i<fNLocal; i++) 
+      SetLocalDerivative( m[j].idxlocX[i], m[j].derlocX[i] );
+    
+    for (Int_t i=0; i<ITSMILLE_NPARCH; i++)
+      SetGlobalDerivative( m[j].idxgloX[i], m[j].dergloX[i] );
+    
+    fMillepede->SetLocalEquation(fGlobalDerivatives, fLocalDerivatives, m[j].measX, m[j].sigmaX);  
+    
+    
+    AliDebug(2,Form("setting local equation Z with fMeas=%.6f  and fSigma=%.6f",m[j].measZ, m[j].sigmaZ));
+    // set equation for Zloc coordinate
+    for (Int_t i=0; i<fNLocal; i++) 
+      SetLocalDerivative( m[j].idxlocZ[i], m[j].derlocZ[i] );
+    
+    for (Int_t i=0; i<ITSMILLE_NPARCH; i++)
+      SetGlobalDerivative( m[j].idxgloZ[i], m[j].dergloZ[i] );
+    
+    fMillepede->SetLocalEquation(fGlobalDerivatives, fLocalDerivatives, m[j].measZ, m[j].sigmaZ);  
+  }
+}
+
+
 void AliITSAlignMille::LocalFit(Int_t iTrack, Double_t *lTrackParam, Int_t lSingleFit) {
   /// Call local fit for this track
   if (!fIsMilleInit) {
index a64fe52..59f8f8b 100644 (file)
@@ -14,6 +14,7 @@
 
 #include <TString.h>
 #include <TObject.h>
+#include <TArray.h>
 #include "AliTrackPointArray.h"
 
 class AliMillepede;
@@ -21,22 +22,40 @@ class AliAlignObjParams;
 class TGeoManager;
 class TGeoHMatrix;
 class AliITSAlignMilleModule;
+class AliTrackFitterRieman;
 
 // number of used objects
 #define ITSMILLE_NDETELEM    2198
 #define ITSMILLE_NPARCH         6
-#define ITSMILLE_NLOCAL         4
+#define ITSMILLE_NLOCAL         5
 #define ITSMILLE_NSTDEV         3       
 
+
+struct MilleData {
+  /// structure to store data for 2 LocalEquations (X and Z)
+  Double_t measX;
+  Double_t sigmaX;
+  Int_t    idxlocX[ITSMILLE_NLOCAL];
+  Double_t derlocX[ITSMILLE_NLOCAL];
+  Int_t    idxgloX[ITSMILLE_NPARCH];  
+  Double_t dergloX[ITSMILLE_NPARCH];
+
+  Double_t measZ;
+  Double_t sigmaZ;
+  Int_t    idxlocZ[ITSMILLE_NLOCAL];
+  Double_t derlocZ[ITSMILLE_NLOCAL];
+  Int_t    idxgloZ[ITSMILLE_NPARCH];  
+  Double_t dergloZ[ITSMILLE_NPARCH];
+};
+
 class AliITSAlignMille:public TObject
 {
-
 public:
   AliITSAlignMille(const Char_t *configFilename="AliITSAlignMille.conf", Bool_t initmille=kTRUE);
   virtual ~AliITSAlignMille();
   
   // geometry methods 
-  Int_t  GetModuleIndex(const Char_t *symname);
+  Int_t     GetModuleIndex(const Char_t *symname);
   Int_t     GetModuleIndex(UShort_t voluid);
   UShort_t  GetModuleVolumeID(const Char_t *symname);
   UShort_t  GetModuleVolumeID(Int_t index);
@@ -50,11 +69,16 @@ public:
   const Char_t* GetPreAlignmentFileName() {return fPreAlignmentFileName.Data();}
   void      PrintCurrentModuleInfo();
   void      Print(Option_t*) const;
+  Bool_t    IsConfigured() const {return fIsConfigured;}
+  void      SetRequiredPoint(Char_t* where, Int_t ndet, Int_t updw, Int_t nreqpts);
   
   // fitting methods
   void      SetMinNPtsPerTrack(Int_t pts=3) {fMinNPtsPerTrack=pts;}
   Int_t     ProcessTrack(AliTrackPointArray *track);
+  AliTrackPointArray *PrepareTrack(AliTrackPointArray *track); // build a new AliTrackPointArray with selected conditions
   void      InitTrackParams(int meth=1);
+  Bool_t    InitRiemanFit();
+  AliTrackFitterRieman  *GetRiemanFitter() const {return fRieman;}
   Int_t     InitModuleParams();
   Int_t     CheckCurrentTrack();
   Bool_t    CheckVolumeID(UShort_t voluid) const; // checks voluid for sensitive volumes
@@ -65,6 +89,8 @@ public:
   Double_t* GetLocalIntersectionPoint() {return fPintLoc;}
   Double_t* GetGlobalIntersectionPoint() {return fPintGlo;}
   void      SetInitTrackParamsMeth(Int_t meth=1) {fInitTrackParamsMeth=meth;}
+  AliTrackPointArray *SortTrack(AliTrackPointArray *atp);
+  void      SetTemporaryExcludedModule(Int_t index) {fTempExcludedModule=index;}
 
   // millepede methods
   void      FixParameter(Int_t param, Double_t value);
@@ -78,23 +104,40 @@ public:
   void      GlobalFit(Double_t *parameters,Double_t *errors,Double_t *pulls);
   void      PrintGlobalParameters();
   Double_t  GetParError(Int_t iPar);
-  Int_t     SetLocalEquations();
+  Int_t     AddLocalEquation(MilleData &m);
+  void      SetLocalEquations(MilleData *m, Int_t neq);
   
   // fitting stuffs
   AliTrackPointArray *GetCurrentTrack() {return fTrack;}
   AliTrackPoint      *GetCurrentCluster() {return &fCluster;}
+  void      SetCurrentTrack(AliTrackPointArray *atp) {fTrack=atp;}
+  void      SetCurrentCluster(AliTrackPoint &atp) {fCluster=atp;}
 
   // geometry stuffs
-  Int_t  GetNModules() const {return fNModules;}
-  Int_t  GetCurrentModuleIndex() const {return fCurrentModuleIndex;}
+  Int_t     GetNModules() const {return fNModules;}
+  Int_t     GetCurrentModuleIndex() const {return fCurrentModuleIndex;}
   TGeoHMatrix *GetCurrentModuleHMatrix() {return fCurrentModuleHMatrix;}
-  Double_t    *GetCurrentModuleTranslation() {return fCurrentModuleTranslation;}
-  Int_t  GetCurrentModuleInternalIndex() const {return fCurrentModuleInternalIndex;}
-  Int_t       *GetModuleIndexArray() {return fModuleIndex;}
+  Double_t *GetCurrentModuleTranslation() {return fCurrentModuleTranslation;}
+  Int_t     GetCurrentModuleInternalIndex() const {return fCurrentModuleInternalIndex;}
+  Int_t    *GetModuleIndexArray() {return fModuleIndex;}
+  Int_t    *GetProcessedPoints() {return fProcessedPoints;}
+  Int_t     GetTotBadLocEqPoints() const {return fTotBadLocEqPoints;}
   AliITSAlignMilleModule  *GetMilleModule(UShort_t voluid); // get pointer to the defined supermodule
   AliITSAlignMilleModule  *GetCurrentModule();
-  UShort_t    *GetModuleVolumeIDArray() {return fModuleVolumeID;}
-  
+  UShort_t *GetModuleVolumeIDArray() {return fModuleVolumeID;}
+
+  // debug stuffs
+  Double_t  *GetMeasLoc() { return fMeasLoc;}
+  Double_t  *GetSigmaLoc() { return fSigmaLoc;}
+  Double_t   GetBField() const {return fBField;}
+  Double_t  *GetLocalInitParam() {return fLocalInitParam;}
+  Double_t   GetLocalDX() const {return fDerivativeXLoc;}
+  Double_t   GetLocalDZ() const {return fDerivativeZLoc;}
+  Double_t   GetParSigTranslations() const {return fParSigTranslations;}
+  Double_t   GetParSigRotations() const {return fParSigRotations;}
+  Int_t      GetPreAlignmentQualityFactor(Int_t index); // if not prealign. return -1
+  void       SetBug(Int_t bug) {fBug=bug;} // 1:SSD inversion sens.18-19
+
  private:
 
   // configuration methods
@@ -135,13 +178,24 @@ public:
   Double_t      fMeasLoc[3]; // current point local coordinates (the original ones)
   Double_t      fMeasGlo[3]; // current point glob. coord (AliTrackPoint)
   Double_t      fSigmaLoc[3]; // stdev current point
-  //TGeoHMatrix  *fTempHMat; ///
+  Double_t      fSigmaXfactor; ///
+  Double_t      fSigmaZfactor; ///
   AliAlignObjParams *fTempAlignObj; ///
   Double_t      fDerivativeXLoc; // localX deriv.
   Double_t      fDerivativeZLoc; // localZ deriv.
-  Double_t      fDeltaPar; ///
   Int_t         fMinNPtsPerTrack; ///
   Int_t         fInitTrackParamsMeth; ///
+  Int_t        *fProcessedPoints; /// array of statistics of used points per module
+  Int_t         fTotBadLocEqPoints; /// total number of reject points because of bad EqLoc
+  AliTrackFitterRieman *fRieman; /// riemann fitter for helices
+  Bool_t        fRequirePoints;  // required points in specific layers
+  Int_t         fNReqLayUp[6];    /// number of points required in layer[n] with Y>0
+  Int_t         fNReqLayDown[6];  /// number of points required in layer[n] with Y<0
+  Int_t         fNReqLay[6];      /// number of points required in layer[n] 
+  Int_t         fNReqDetUp[3];    /// number of points required in Detector[n] with Y>0
+  Int_t         fNReqDetDown[3];  /// number of points required in Detector[n] with Y<0
+  Int_t         fNReqDet[3];      /// number of points required in Detector[n]
+  Int_t         fTempExcludedModule; /// single module temporary excluded from initial fit
 
   // geometry stuffs
   TString       fGeometryFileName;  ///
@@ -158,8 +212,16 @@ public:
   Bool_t        fUseLocalShifts; /// 
   Bool_t        fUseSuperModules; /// 
   Bool_t        fUsePreAlignment; /// 
+  Bool_t        fUseSortedTracks; /// default is kTRUE 
+  Bool_t        fBOn; /// magentic field ON
+  Double_t      fBField; /// value of magnetic field
   Int_t         fNSuperModules; /// number of custom supermodules in SM file
   TGeoHMatrix  *fCurrentModuleHMatrix; /// SuperModule matrix
+  Bool_t        fIsConfigured; ///
+  Int_t         fPreAlignQF[ITSMILLE_NDETELEM*2]; ///
+  Double_t      fSensVolSigmaXfactor[ITSMILLE_NDETELEM*2]; ///
+  Double_t      fSensVolSigmaZfactor[ITSMILLE_NDETELEM*2]; ///
+  Int_t         fBug; /// tag for temporary bug correction
 
   AliITSAlignMilleModule *fMilleModule[ITSMILLE_NDETELEM*2]; /// array of super modules to be aligned
 
index 164fe99..7ca5975 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 AliITSAlignMilleModule\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 "AliITSAlignMilleModule.h" \r
-#include "AliITSgeomTGeo.h" \r
-#include "AliGeomManager.h" \r
-#include "AliAlignObjParams.h" \r
-#include "AliLog.h" \r
\r
-/// \cond CLASSIMP \r
-ClassImp(AliITSAlignMilleModule) \r
-/// \endcond \r
-    \r
-//-------------------------------------------------------------\r
-AliITSAlignMilleModule::AliITSAlignMilleModule() : TNamed(), \r
-  fNSensVol(0), \r
-  fIndex(-1),  \r
-  fVolumeID(0),  \r
-  fMatrix(NULL),\r
-  fSensVolMatrix(NULL),\r
-  fSensVolModifMatrix(NULL),\r
-  fTempAlignObj(NULL)\r
-{ \r
-  /// void constructor  \r
-  fMatrix = new TGeoHMatrix; \r
-  fSensVolMatrix = new TGeoHMatrix; \r
-  fSensVolModifMatrix = new TGeoHMatrix; \r
-  fTempAlignObj=new AliAlignObjParams;\r
-} \r
-//-------------------------------------------------------------\r
-AliITSAlignMilleModule::AliITSAlignMilleModule(Int_t index, UShort_t volid, char* symname, TGeoHMatrix *m, Int_t nsv, UShort_t *volidsv) : TNamed(), \r
-  fNSensVol(0), \r
-  fIndex(-1),  \r
-  fVolumeID(0),  \r
-  fMatrix(NULL),\r
-  fSensVolMatrix(NULL),\r
-  fSensVolModifMatrix(NULL),\r
-  fTempAlignObj(NULL)\r
-{ \r
-  /// void constructor  \r
-  fMatrix = new TGeoHMatrix; \r
-  fSensVolMatrix = new TGeoHMatrix; \r
-  fSensVolModifMatrix = new TGeoHMatrix; \r
-  fTempAlignObj=new AliAlignObjParams;\r
-  if (Set(index,volid,symname,m,nsv,volidsv)) {\r
-    AliInfo("Error in AliITSAlignMilleModule::Set() - initializing void supermodule...");\r
-  }\r
-} \r
-//-------------------------------------------------------------\r
-AliITSAlignMilleModule::AliITSAlignMilleModule(UShort_t volid) : TNamed(), \r
-  fNSensVol(0), \r
-  fIndex(-1),  \r
-  fVolumeID(0),  \r
-  fMatrix(NULL),\r
-  fSensVolMatrix(NULL),\r
-  fSensVolModifMatrix(NULL),\r
-  fTempAlignObj(NULL)\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
-  fTempAlignObj=new AliAlignObjParams;\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
-    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
-} \r
-//-------------------------------------------------------------\r
-AliITSAlignMilleModule::~AliITSAlignMilleModule() { \r
-  /// Destructor \r
-  delete fMatrix; \r
-  delete fSensVolMatrix; \r
-  delete fSensVolModifMatrix; \r
-  delete fTempAlignObj;\r
-} \r
-//-------------------------------------------------------------\r
-Int_t AliITSAlignMilleModule::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
-  (*fMatrix) = (*m);\r
-\r
-  // add sensitive volumes\r
-  for (Int_t i=0; i<nsv; i++) AddSensitiveVolume(volidsv[i]);\r
-\r
-  return 0;\r
-}\r
-//-------------------------------------------------------------\r
-Int_t AliITSAlignMilleModule::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
-void AliITSAlignMilleModule::AddSensitiveVolume(UShort_t voluid)\r
-{\r
-  /// add a sensitive volume to this supermodule\r
-  if (GetIndexFromVolumeID(voluid)<0) return; // bad volid\r
-  fSensVolVolumeID[fNSensVol] = voluid;\r
-  fSensVolIndex[fNSensVol] = GetIndexFromVolumeID(voluid);\r
-  fNSensVol++;\r
-}\r
-//-------------------------------------------------------------\r
-Bool_t AliITSAlignMilleModule::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++) {\r
-    if (fSensVolVolumeID[i]==voluid) return kTRUE;\r
-  }\r
-  return kFALSE;\r
-}\r
-//-------------------------------------------------------------\r
-TGeoHMatrix *AliITSAlignMilleModule::GetSensitiveVolumeModifiedMatrix(UShort_t voluid, Double_t *deltalocal)\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]=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
-  fTempAlignObj->SetTranslation(0,0,0);\r
-  fTempAlignObj->SetRotation(0,0,0);\r
-\r
-  fTempAlignObj->SetRotation(ang[0],ang[1],ang[2]);\r
-  fTempAlignObj->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
-  fTempAlignObj->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
-  //printf("\n1: modif=orig del sensvol\n");fSensVolModifMatrix->Print();\r
-\r
-  // 2) set fSensVolModif = SensVolRel\r
-  fSensVolModifMatrix->MultiplyLeft( &fMatrix->Inverse() );\r
-  //printf("\n2: modif=relative del sensvol\n");fSensVolModifMatrix->Print();\r
\r
-  // 3) multiply left by delta\r
-  fSensVolModifMatrix->MultiplyLeft( &hm );\r
-  //printf("\n3: modif= delta*relative\n");fSensVolModifMatrix->Print();\r
-  \r
-  // 4) multiply left by fMatrix\r
-  fSensVolModifMatrix->MultiplyLeft( fMatrix );\r
-  //printf("\n4: modif=finale\n");fSensVolModifMatrix->Print();\r
-\r
-  return fSensVolModifMatrix;\r
-}\r
-//-------------------------------------------------------------\r
-AliAlignObjParams *AliITSAlignMilleModule::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
-  // reset align object (may not be needed...)\r
-  fTempAlignObj->SetTranslation(0,0,0);\r
-  fTempAlignObj->SetRotation(0,0,0);\r
-\r
-  fTempAlignObj->SetRotation(ang[0],ang[1],ang[2]);\r
-  fTempAlignObj->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,fTempAlignObj);\r
-}\r
-//-------------------------------------------------------------\r
-AliAlignObjParams *AliITSAlignMilleModule::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
-  // reset align object (may not be needed...)\r
-  fTempAlignObj->SetTranslation(0,0,0);\r
-  fTempAlignObj->SetRotation(0,0,0);\r
-\r
-  if (!fTempAlignObj->SetMatrix(*fSensVolModifMatrix)) return NULL;\r
-  fTempAlignObj->SetVolUID(voluid);\r
-  fTempAlignObj->SetSymName(AliGeomManager::SymName(voluid));\r
-  \r
-  //fTempAlignObj->Print("");\r
-\r
-  return fTempAlignObj;\r
-}\r
-//-------------------------------------------------------------\r
-TGeoHMatrix *AliITSAlignMilleModule::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
-TGeoHMatrix *AliITSAlignMilleModule::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 AliITSAlignMilleModule::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
-Int_t AliITSAlignMilleModule::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));\r
-  (*m)=mo;\r
-\r
-  // SPD y-shift by 81 mu\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
-  return 0;\r
-}\r
-//-------------------------------------------------------------\r
-UShort_t AliITSAlignMilleModule::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
-UShort_t AliITSAlignMilleModule::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
-void AliITSAlignMilleModule::Print(Option_t*) const \r
-{\r
-  ///\r
-  printf("*** ITS SuperModule for AliITSAlignMille ***\n");\r
-  printf("symname  : %s\n",GetName());\r
-  printf("volumeID : %d\n",fVolumeID);\r
-  printf("index    : %d\n",fIndex);\r
-  fMatrix->Print();\r
-  printf("number of sensitive modules : %d\n",fNSensVol);\r
-  for (Int_t i=0; i<fNSensVol; i++) printf("   voluid[%d] = %d\n",i,fSensVolVolumeID[i]);\r
-}\r
-//_____________________________________________________________________________\r
-AliITSAlignMilleModule::AliITSAlignMilleModule(const AliITSAlignMilleModule &m) :\r
-  TNamed(m),\r
-  fNSensVol(m.fNSensVol),\r
-  fIndex(m.fIndex),\r
-  fVolumeID(m.fVolumeID),\r
-  fMatrix(new TGeoHMatrix(*m.GetMatrix())),\r
-  fSensVolMatrix(new TGeoHMatrix),\r
-  fSensVolModifMatrix(new TGeoHMatrix),\r
-  fTempAlignObj(new AliAlignObjParams)\r
-{\r
-  // Copy constructor\r
-  for (int i=0; i<fNSensVol; i++) {\r
-    fSensVolIndex[i]=m.fSensVolIndex[i];\r
-    fSensVolVolumeID[i]=m.fSensVolVolumeID[i];\r
-  }\r
-}\r
-//_____________________________________________________________________________\r
-AliITSAlignMilleModule& AliITSAlignMilleModule::operator=(const AliITSAlignMilleModule &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
-  fVolumeID=m.fVolumeID;\r
-  delete fMatrix;\r
-  fMatrix=new TGeoHMatrix(*m.GetMatrix());\r
-  for (int i=0; i<fNSensVol; i++) {\r
-    fSensVolIndex[i]=m.fSensVolIndex[i];\r
-    fSensVolVolumeID[i]=m.fSensVolVolumeID[i];\r
-  }\r
-  return *this;\r
-}\r
-\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 AliITSAlignMilleModule
+/// 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 "AliITSAlignMilleModule.h" 
+#include "AliITSgeomTGeo.h" 
+#include "AliGeomManager.h" 
+#include "AliAlignObjParams.h" 
+#include "AliLog.h" 
+/// \cond CLASSIMP 
+ClassImp(AliITSAlignMilleModule) 
+/// \endcond 
+    
+//-------------------------------------------------------------
+AliITSAlignMilleModule::AliITSAlignMilleModule() : TNamed(), 
+  fNSensVol(0), 
+  fIndex(-1),  
+  fVolumeID(0),  
+  fMatrix(NULL),
+  fSensVolMatrix(NULL),
+  fSensVolModifMatrix(NULL),
+  fTempAlignObj(NULL)
+{ 
+  /// void constructor  
+  fMatrix = new TGeoHMatrix; 
+  fSensVolMatrix = new TGeoHMatrix; 
+  fSensVolModifMatrix = new TGeoHMatrix; 
+  fTempAlignObj=new AliAlignObjParams;
+} 
+//-------------------------------------------------------------
+AliITSAlignMilleModule::AliITSAlignMilleModule(Int_t index, UShort_t volid, char* symname, TGeoHMatrix *m, Int_t nsv, UShort_t *volidsv) : TNamed(), 
+  fNSensVol(0), 
+  fIndex(-1),  
+  fVolumeID(0),  
+  fMatrix(NULL),
+  fSensVolMatrix(NULL),
+  fSensVolModifMatrix(NULL),
+  fTempAlignObj(NULL)
+{ 
+  /// void constructor  
+  fMatrix = new TGeoHMatrix; 
+  fSensVolMatrix = new TGeoHMatrix; 
+  fSensVolModifMatrix = new TGeoHMatrix; 
+  fTempAlignObj=new AliAlignObjParams;
+  if (Set(index,volid,symname,m,nsv,volidsv)) {
+    AliInfo("Error in AliITSAlignMilleModule::Set() - initializing void supermodule...");
+  }
+} 
+//-------------------------------------------------------------
+AliITSAlignMilleModule::AliITSAlignMilleModule(UShort_t volid) : TNamed(), 
+  fNSensVol(0), 
+  fIndex(-1),  
+  fVolumeID(0),  
+  fMatrix(NULL),
+  fSensVolMatrix(NULL),
+  fSensVolModifMatrix(NULL),
+  fTempAlignObj(NULL)
+{ 
+  /// simple constructor building a supermodule from a single sensitive volume 
+  fMatrix = new TGeoHMatrix; 
+  fSensVolMatrix = new TGeoHMatrix; 
+  fSensVolModifMatrix = new TGeoHMatrix;   
+  // temporary align object, just use the rotation...
+  fTempAlignObj=new AliAlignObjParams;
+
+  fIndex = GetIndexFromVolumeID(volid);  
+  if (fIndex>=0 && gGeoManager) { // good sensitive module and geometry loaded
+    SetName(AliGeomManager::SymName(volid));
+    fVolumeID = volid;
+    AddSensitiveVolume(volid);
+    if (SensVolMatrix(volid, fMatrix))
+       AliInfo("Matrix not defined");
+  }
+  else {
+    AliInfo("Wrong VolumeID or Geometry not loaded - initializing void supermodule...");
+  }
+} 
+//-------------------------------------------------------------
+AliITSAlignMilleModule::~AliITSAlignMilleModule() { 
+  /// Destructor 
+  delete fMatrix; 
+  delete fSensVolMatrix; 
+  delete fSensVolModifMatrix; 
+  delete fTempAlignObj;
+} 
+//-------------------------------------------------------------
+Int_t AliITSAlignMilleModule::Set(Int_t index, UShort_t volid, char* symname, TGeoHMatrix *m, Int_t nsv, UShort_t *volidsv) 
+{
+  // initialize a custom supermodule
+  // index, volid, symname and matrix must be given
+  // if (volidsv) add nsv sensitive volumes to the supermodules
+  // return 0 if success
+
+  if (index<2198) {
+    AliInfo("Index must be >= 2198");
+    return -1;
+  }
+  if (volid<14336) {
+    AliInfo("VolumeID must be >= 14336");
+    return -2;
+  }
+  
+  if (!symname) return -3;
+  for (Int_t i=0; i<2198; i++) {
+    if (!strcmp(symname,AliITSgeomTGeo::GetSymName(i))) {
+      AliInfo("Symname already used by a Sensitive Volume");
+      return -3;
+    }
+  }
+  
+  if (!m) return -4;
+
+  // can initialize needed stuffs
+  fIndex = index;
+  fVolumeID = volid;
+  SetName(symname);
+  (*fMatrix) = (*m);
+
+  // add sensitive volumes
+  for (Int_t i=0; i<nsv; i++) AddSensitiveVolume(volidsv[i]);
+
+  return 0;
+}
+//-------------------------------------------------------------
+Int_t AliITSAlignMilleModule::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 AliITSAlignMilleModule::AddSensitiveVolume(UShort_t voluid)
+{
+  /// add a sensitive volume to this supermodule
+  if (GetIndexFromVolumeID(voluid)<0) return; // bad volid
+  fSensVolVolumeID[fNSensVol] = voluid;
+  fSensVolIndex[fNSensVol] = GetIndexFromVolumeID(voluid);
+  fNSensVol++;
+}
+//-------------------------------------------------------------
+Bool_t AliITSAlignMilleModule::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 (fSensVolVolumeID[i]==voluid) return kTRUE;
+  }
+  return kFALSE;
+}
+//-------------------------------------------------------------
+TGeoHMatrix *AliITSAlignMilleModule::GetSensitiveVolumeModifiedMatrix(UShort_t voluid, Double_t *deltalocal)
+{
+  // 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]=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...)
+  fTempAlignObj->SetTranslation(0,0,0);
+  fTempAlignObj->SetRotation(0,0,0);
+
+  fTempAlignObj->SetRotation(ang[0],ang[1],ang[2]);
+  fTempAlignObj->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;
+  fTempAlignObj->GetMatrix(hm);
+  //printf("\n0: delta matrix\n");hm.Print();
+
+  // 1) start setting fSensVolModif = fSensVol
+  if (SensVolMatrix(voluid, fSensVolModifMatrix)) return NULL;
+  //printf("\n1: modif=orig del sensvol\n");fSensVolModifMatrix->Print();
+
+  // 2) set fSensVolModif = SensVolRel
+  fSensVolModifMatrix->MultiplyLeft( &fMatrix->Inverse() );
+  //printf("\n2: modif=relative del sensvol\n");fSensVolModifMatrix->Print();
+  // 3) multiply left by delta
+  fSensVolModifMatrix->MultiplyLeft( &hm );
+  //printf("\n3: modif= delta*relative\n");fSensVolModifMatrix->Print();
+  
+  // 4) multiply left by fMatrix
+  fSensVolModifMatrix->MultiplyLeft( fMatrix );
+  //printf("\n4: modif=finale\n");fSensVolModifMatrix->Print();
+
+  return fSensVolModifMatrix;
+}
+//-------------------------------------------------------------
+AliAlignObjParams *AliITSAlignMilleModule::GetSensitiveVolumeMisalignment(UShort_t voluid, Double_t *deltalocal)
+{
+  // calculate misalignment of sens.vol. 'voluid' according with a displacement 'deltalocal'
+  // of the mother volume. The misalignment is returned as AliAlignObjParams object
+
+  if (!IsIn(voluid)) return NULL;
+  if (!gGeoManager) return NULL;
+  
+  // prepare the TGeoHMatrix
+  Double_t tr[3],ang[3];
+  tr[0]=deltalocal[0]; // in centimeter
+  tr[1]=deltalocal[1]; 
+  tr[2]=deltalocal[2];
+  ang[0]=deltalocal[3]; // psi   (X)  in deg
+  ang[1]=deltalocal[4]; // theta (Y)
+  ang[2]=deltalocal[5]; // phi   (Z)
+
+  // reset align object (may not be needed...)
+  fTempAlignObj->SetTranslation(0,0,0);
+  fTempAlignObj->SetRotation(0,0,0);
+
+  fTempAlignObj->SetRotation(ang[0],ang[1],ang[2]);
+  fTempAlignObj->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,fTempAlignObj);
+}
+//-------------------------------------------------------------
+AliAlignObjParams *AliITSAlignMilleModule::GetSensitiveVolumeMisalignment(UShort_t voluid, AliAlignObjParams *a)
+{
+  // return the misalignment of the sens. vol. 'voluid' corresponding with 
+  // a misalignment 'a' in the mother volume
+  // return NULL if error
+
+  // Gsv = Gg * Gg-1 * Gsv   -> Lsv,g = Gg-1 * Gsv
+  // G'sv = Gg * Dg * Lsv,g === Gsv * Dsv
+  // Gg * Dg * Gg-1 * Gsv = Gsv * Gsv-1 * Gg * Dg * Gg-1 * Gsv
+  //
+  // => Dsv = (Gsv-1 * Gg * Dg * Gg-1 * Gsv)
+  //
+
+  if (!IsIn(voluid)) return NULL;
+  if (!gGeoManager) return NULL;
+
+  //a->Print("");
+
+  // prepare the Delta matrix Dg
+  TGeoHMatrix dg;
+  a->GetMatrix(dg);
+  //dg.Print();
+
+  // 1) start setting fSensVolModif = Gsv
+  if (SensVolMatrix(voluid, fSensVolModifMatrix)) return NULL;
+  //printf("\n1: modif=orig del sensvol\n");fSensVolModifMatrix->Print();
+
+  // 2) set fSensVolModif = Gg-1 * Gsv
+  fSensVolModifMatrix->MultiplyLeft( &fMatrix->Inverse() );
+  //printf("\n2: modif=relative del sensvol\n");fSensVolModifMatrix->Print();
+  // 3) set fSensVolModif = Dg * Gg-1 * Gsv
+  fSensVolModifMatrix->MultiplyLeft( &dg );
+  //printf("\n3: modif= delta*relative\n");fSensVolModifMatrix->Print();
+  
+  // 4) set fSensVolModif = Gg * Dg * Gg-1 * Gsv
+  fSensVolModifMatrix->MultiplyLeft( fMatrix );
+  //printf("\n4: modif=quasi,manca il Gsv-1...\n");fSensVolModifMatrix->Print();
+
+  // 5) set fSensVolModif = Gsv-1 * Gg * Dg * Gg-1 * Gsv
+  if (SensVolMatrix(voluid, &dg)) return NULL;
+  fSensVolModifMatrix->MultiplyLeft( &dg.Inverse() );
+  //printf("\n5: modif=finale\n");fSensVolModifMatrix->Print();
+
+  // reset align object (may not be needed...)
+  fTempAlignObj->SetTranslation(0,0,0);
+  fTempAlignObj->SetRotation(0,0,0);
+
+  if (!fTempAlignObj->SetMatrix(*fSensVolModifMatrix)) return NULL;
+  fTempAlignObj->SetVolUID(voluid);
+  fTempAlignObj->SetSymName(AliGeomManager::SymName(voluid));
+  
+  //fTempAlignObj->Print("");
+
+  return fTempAlignObj;
+}
+//-------------------------------------------------------------
+TGeoHMatrix *AliITSAlignMilleModule::GetSensitiveVolumeMatrix(UShort_t voluid)
+{
+  // return TGeoHMatrix of the sens.vol. 'voluid' in the current geometry
+  if (SensVolMatrix(voluid,fSensVolMatrix)) return NULL;
+  return fSensVolMatrix;
+}
+//-------------------------------------------------------------
+TGeoHMatrix *AliITSAlignMilleModule::GetSensitiveVolumeOrigGlobalMatrix(UShort_t voluid)
+{
+  // return original ideal position (from AliGeomManager::GetOrigGlobalMatrix())
+  if (SensVolOrigGlobalMatrix(voluid,fSensVolMatrix)) return NULL;
+  return fSensVolMatrix;
+}
+//-------------------------------------------------------------
+Int_t AliITSAlignMilleModule::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 AliITSAlignMilleModule::SensVolOrigGlobalMatrix(UShort_t volid, TGeoHMatrix *m) 
+{
+  // set original global matrix for sensitive modules (SPD corrected)
+  // return 0 if success
+  Int_t idx=GetIndexFromVolumeID(volid);
+  if (idx<0) return -1;
+  TGeoHMatrix mo;
+  if (!AliGeomManager::GetOrigGlobalMatrix(AliGeomManager::SymName(volid),mo));
+  (*m)=mo;
+
+  // 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);
+  }
+  return 0;
+}
+//-------------------------------------------------------------
+UShort_t AliITSAlignMilleModule::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 AliITSAlignMilleModule::GetVolumeIDFromIndex(Int_t index) {
+  /// volume ID from index
+  if (index<0 || index>2197) return 0;
+  return GetVolumeIDFromSymname(AliITSgeomTGeo::GetSymName(index));
+}
+//-------------------------------------------------------------
+void AliITSAlignMilleModule::Print(Option_t*) const 
+{
+  ///
+  printf("*** ITS SuperModule for AliITSAlignMille ***\n");
+  printf("symname  : %s\n",GetName());
+  printf("volumeID : %d\n",fVolumeID);
+  printf("index    : %d\n",fIndex);
+  fMatrix->Print();
+  printf("number of sensitive modules : %d\n",fNSensVol);
+  for (Int_t i=0; i<fNSensVol; i++) printf("   voluid[%d] = %d\n",i,fSensVolVolumeID[i]);
+}
+//_____________________________________________________________________________
+AliITSAlignMilleModule::AliITSAlignMilleModule(const AliITSAlignMilleModule &m) :
+  TNamed(m),
+  fNSensVol(m.fNSensVol),
+  fIndex(m.fIndex),
+  fVolumeID(m.fVolumeID),
+  fMatrix(new TGeoHMatrix(*m.GetMatrix())),
+  fSensVolMatrix(new TGeoHMatrix),
+  fSensVolModifMatrix(new TGeoHMatrix),
+  fTempAlignObj(new AliAlignObjParams)
+{
+  // Copy constructor
+  for (int i=0; i<fNSensVol; i++) {
+    fSensVolIndex[i]=m.fSensVolIndex[i];
+    fSensVolVolumeID[i]=m.fSensVolVolumeID[i];
+  }
+}
+//_____________________________________________________________________________
+AliITSAlignMilleModule& AliITSAlignMilleModule::operator=(const AliITSAlignMilleModule &m)  
+{
+  // operator =
+  //
+  if(this==&m) return *this;
+  ((TNamed *)this)->operator=(m);
+  
+  fNSensVol=m.fNSensVol;
+  fIndex=m.fIndex;
+  fVolumeID=m.fVolumeID;
+  delete fMatrix;
+  fMatrix=new TGeoHMatrix(*m.GetMatrix());
+  for (int i=0; i<fNSensVol; i++) {
+    fSensVolIndex[i]=m.fSensVolIndex[i];
+    fSensVolVolumeID[i]=m.fSensVolVolumeID[i];
+  }
+  return *this;
+}
+
+//_____________________________________________________________________________
+
+
index 2d22bc7..c769299 100644 (file)
@@ -1,78 +1,78 @@
-#ifndef ALIITSALIGNMILLEMODULE_H\r
-#define ALIITSALIGNMILLEMODULE_H \r
-/* Copyright(c) 2007-2009 , ALICE Experiment at CERN, All rights reserved. * \r
- * See cxx source for full Copyright notice                               */  \r
\r
-/// \ingroup rec \r
-/// \class AliITSAlignMilleModule \r
-/// \brief Class for alignment of ITS \r
-// \r
-// Authors: Marcello Lunardon \r
-\r
-/* $Id$  */ \r
-//#include <TString.h> \r
-//#include <TObject.h> \r
-#include <TNamed.h> \r
-\r
-#define ITSMILLE_NSENSVOL    2198\r
-\r
-class AliAlignObjParams; \r
-class TGeoHMatrix; \r
-\r
-class AliITSAlignMilleModule : public TNamed \r
-{ \r
-public: \r
-  AliITSAlignMilleModule(); \r
-  AliITSAlignMilleModule(UShort_t volid); // basic single volume constructor\r
-  AliITSAlignMilleModule(Int_t index, UShort_t volid, char* symname, TGeoHMatrix *m, Int_t nsv=0, UShort_t *volidsv=NULL); // general constructor\r
-\r
-  AliITSAlignMilleModule(const AliITSAlignMilleModule& rhs); // copy constructor\r
-  AliITSAlignMilleModule& operator=(const AliITSAlignMilleModule& rhs);  \r
-    \r
-  virtual ~AliITSAlignMilleModule(); \r
-   \r
-  // geometry methods  \r
-  Int_t     GetIndex() const {return fIndex;} \r
-  UShort_t  GetVolumeID() const {return fVolumeID;}  \r
-  Int_t     GetNSensitiveVolumes() const {return fNSensVol;} \r
-  TGeoHMatrix *GetMatrix() const {return fMatrix;} \r
-  UShort_t *GetSensitiveVolumeVolumeID() {return fSensVolVolumeID;}\r
-\r
-  Int_t     Set(Int_t index, UShort_t volid, char* symname, TGeoHMatrix *m, Int_t nsv=0, UShort_t *volidsv=NULL); // initialize a super module\r
-  \r
-  // util\r
-  static Int_t GetIndexFromVolumeID(UShort_t volid);\r
-  static UShort_t GetVolumeIDFromSymname(const Char_t *symname);\r
-  static UShort_t GetVolumeIDFromIndex(Int_t index);\r
-\r
-  // methods\r
-  Bool_t    IsIn(UShort_t volid) const;\r
-  TGeoHMatrix *GetSensitiveVolumeMatrix(UShort_t voluid);\r
-  TGeoHMatrix *GetSensitiveVolumeOrigGlobalMatrix(UShort_t voluid);\r
-  TGeoHMatrix *GetSensitiveVolumeModifiedMatrix(UShort_t voluid, Double_t *deltalocal); \r
-  AliAlignObjParams *GetSensitiveVolumeMisalignment(UShort_t voluid, AliAlignObjParams *a); \r
-  AliAlignObjParams *GetSensitiveVolumeMisalignment(UShort_t voluid, Double_t *deltalocal); \r
-  void      Print(Option_t*) const; \r
-\r
-protected:\r
-  Int_t     SensVolMatrix(UShort_t volid, TGeoHMatrix *m); \r
-  Int_t     SensVolOrigGlobalMatrix(UShort_t volid, TGeoHMatrix *m); \r
-  void      AddSensitiveVolume(UShort_t volid);\r
-\r
-private:\r
-  Int_t          fNSensVol; ///\r
-  Int_t          fIndex; ///\r
-  UShort_t       fVolumeID; ///\r
-  // il symname e' il nome del TNamed...\r
-  Int_t          fSensVolIndex[ITSMILLE_NSENSVOL]; ///\r
-  UShort_t       fSensVolVolumeID[ITSMILLE_NSENSVOL]; ///\r
-  TGeoHMatrix   *fMatrix; /// ideal TGeoHMatrix of the supermodule\r
-  TGeoHMatrix   *fSensVolMatrix; ///\r
-  TGeoHMatrix   *fSensVolModifMatrix; ///\r
-  AliAlignObjParams *fTempAlignObj; ///\r
-       \r
-  ClassDef(AliITSAlignMilleModule, 0)\r
-\r
-}; \r
-\r
-#endif \r
+#ifndef ALIITSALIGNMILLEMODULE_H
+#define ALIITSALIGNMILLEMODULE_H 
+/* Copyright(c) 2007-2009 , ALICE Experiment at CERN, All rights reserved. * 
+ * See cxx source for full Copyright notice                               */  
+/// \ingroup rec 
+/// \class AliITSAlignMilleModule 
+/// \brief Class for alignment of ITS 
+// 
+// Authors: Marcello Lunardon 
+
+/* $Id$  */ 
+//#include <TString.h> 
+//#include <TObject.h> 
+#include <TNamed.h> 
+
+#define ITSMILLE_NSENSVOL    2198
+
+class AliAlignObjParams; 
+class TGeoHMatrix; 
+
+class AliITSAlignMilleModule : public TNamed 
+{ 
+public: 
+  AliITSAlignMilleModule(); 
+  AliITSAlignMilleModule(UShort_t volid); // basic single volume constructor
+  AliITSAlignMilleModule(Int_t index, UShort_t volid, char* symname, TGeoHMatrix *m, Int_t nsv=0, UShort_t *volidsv=NULL); // general constructor
+
+  AliITSAlignMilleModule(const AliITSAlignMilleModule& rhs); // copy constructor
+  AliITSAlignMilleModule& operator=(const AliITSAlignMilleModule& rhs);  
+    
+  virtual ~AliITSAlignMilleModule(); 
+   
+  // geometry methods  
+  Int_t     GetIndex() const {return fIndex;} 
+  UShort_t  GetVolumeID() const {return fVolumeID;}  
+  Int_t     GetNSensitiveVolumes() const {return fNSensVol;} 
+  TGeoHMatrix *GetMatrix() const {return fMatrix;} 
+  UShort_t *GetSensitiveVolumeVolumeID() {return fSensVolVolumeID;}
+
+  Int_t     Set(Int_t index, UShort_t volid, char* symname, TGeoHMatrix *m, Int_t nsv=0, UShort_t *volidsv=NULL); // initialize a super module
+  
+  // util
+  static Int_t GetIndexFromVolumeID(UShort_t volid);
+  static UShort_t GetVolumeIDFromSymname(const Char_t *symname);
+  static UShort_t GetVolumeIDFromIndex(Int_t index);
+
+  // methods
+  Bool_t    IsIn(UShort_t volid) const;
+  TGeoHMatrix *GetSensitiveVolumeMatrix(UShort_t voluid);
+  TGeoHMatrix *GetSensitiveVolumeOrigGlobalMatrix(UShort_t voluid);
+  TGeoHMatrix *GetSensitiveVolumeModifiedMatrix(UShort_t voluid, Double_t *deltalocal); 
+  AliAlignObjParams *GetSensitiveVolumeMisalignment(UShort_t voluid, AliAlignObjParams *a); 
+  AliAlignObjParams *GetSensitiveVolumeMisalignment(UShort_t voluid, Double_t *deltalocal); 
+  void      Print(Option_t*) const; 
+
+protected:
+  Int_t     SensVolMatrix(UShort_t volid, TGeoHMatrix *m); 
+  Int_t     SensVolOrigGlobalMatrix(UShort_t volid, TGeoHMatrix *m); 
+  void      AddSensitiveVolume(UShort_t volid);
+
+private:
+  Int_t          fNSensVol; ///
+  Int_t          fIndex; ///
+  UShort_t       fVolumeID; ///
+  // il symname e' il nome del TNamed...
+  Int_t          fSensVolIndex[ITSMILLE_NSENSVOL]; ///
+  UShort_t       fSensVolVolumeID[ITSMILLE_NSENSVOL]; ///
+  TGeoHMatrix   *fMatrix; /// ideal TGeoHMatrix of the supermodule
+  TGeoHMatrix   *fSensVolMatrix; ///
+  TGeoHMatrix   *fSensVolModifMatrix; ///
+  AliAlignObjParams *fTempAlignObj; ///
+       
+  ClassDef(AliITSAlignMilleModule, 0)
+
+}; 
+
+#endif 
index cebf4c2..f827cc2 100644 (file)
-#if !defined(__CINT__) || defined(__MAKECINT__)\r
-#include <Riostream.h>\r
-#include <TChain.h>\r
-#include <TClonesArray.h>\r
-#include <TFile.h>\r
-#include <TMath.h>\r
-#include <TStopwatch.h>\r
-#include "AliAlignObjParams.h"\r
-#include "AliTrackPointArray.h"\r
-#include "AliITSAlignMille.h"\r
-#endif\r
-//********************************************************************\r
-//  Example to run ITS alignment using Millepede\r
-//\r
-//  Read tracks from AliTrackPoints.N.root and fill Millepede.\r
-//  Millepede configuration is taken from AliITSAlignMille.conf\r
-//  Results are written as AliAlignObjParams in outfile.\r
-//\r
-//      Origin: M. Lunardon\r
-//********************************************************************\r
-\r
-Bool_t SelectLayers(AliTrackPointArray *tpa, int *nreqpts_lay) {\r
-  // selection on layers\r
-  int npts=tpa->GetNPoints();\r
-  int nlay[6]; \r
-  for (int jj=0;jj<6;jj++) nlay[jj]=0;\r
-  for (int ip=0; ip<npts; ip++) {\r
-    int lay=-1;\r
-    float r=TMath::Sqrt(tpa->GetX()[ip]*tpa->GetX()[ip] + tpa->GetY()[ip]*tpa->GetY()[ip]);\r
-    if (r<5) lay=1;\r
-    else if (r>5 && r<10) lay=2;\r
-    else if (r>10 && r<18) lay=3;\r
-    else if (r>18 && r<30) lay=4;\r
-    else if (r>30 && r<40) lay=5;\r
-    else if (r>40) lay=6;\r
-    if (lay<0) continue;\r
-    nlay[lay-1]++;\r
-  }\r
-  Bool_t isgood=1;\r
-  for (int jj=0; jj<6; jj++) {\r
-    if (nlay[jj]<nreqpts_lay[jj]) isgood=0;\r
-  }\r
-  return isgood;\r
-}\r
-//////////////////////////////////////\r
-\r
-int ITSAlignMille(int fromev=1, int toev=200, int maxentries=-1, char *outfile="ITSAlignMille.root") {\r
-\r
-  // Read tracks from AliTrackPoints.N.root and fill Millepede.\r
-  // Millepede results are written as AliAlignObjParams in outfile.\r
-  \r
-  int nreqpts=6;\r
-  int nreqpts_lay[6]={0,0,0,0,0,0};\r
-\r
-  TFile *fout=new TFile(outfile,"recreate");\r
-  if (!fout->IsOpen()) {\r
-    printf("\nCannot open output file!\n");\r
-    return -1;\r
-  }\r
-\r
-  TChain *chain=new TChain("spTree");  \r
-  char dir[100]="AliTrackPoints";\r
-  char st[200];\r
-  \r
-  for (int iev=fromev; iev<=toev; iev++) {\r
-    sprintf(st,"%s/AliTrackPoints.%d.root",dir,iev);\r
-    chain->Add(st);\r
-  }\r
-  \r
-  int nentries=chain->GetEntries();\r
-  printf("There are %d entries in chain\n",nentries);\r
-  \r
-  if (maxentries>0 && maxentries<nentries) nentries=maxentries;\r
-  \r
-  AliTrackPointArray *tpa = 0;\r
-  chain->SetBranchAddress("SP", &tpa);\r
-\r
-  ////////////////////////////////////////////\r
-  \r
-  AliITSAlignMille *alig = new AliITSAlignMille("AliITSAlignMille.conf");\r
-\r
-  Int_t nmod=alig->GetNModules();\r
-\r
-  Double_t *parameters = new Double_t[nmod*6];\r
-  Double_t *errors = new Double_t[nmod*6];\r
-  Double_t *pulls = new Double_t[nmod*6];\r
-\r
-  for(Int_t k=0;k<nmod*6;k++) {\r
-    parameters[k]=0.;\r
-    errors[k]=0.;\r
-    pulls[k]=0.;\r
-  }\r
-\r
-  Double_t trackParams[8] = {0.,0.,0.,0.,0.,0.,0.,0.};\r
-  alig->InitGlobalParameters(parameters);\r
-  alig->Print();\r
-\r
-  ////////////////////////////////////////////////////////////////////\r
-\r
-  TStopwatch stimer;\r
-  stimer.Start();\r
-\r
-  int iTrackOk=0; // number of good passed track\r
-  // loop on spTree entries\r
-  // one entry = one track\r
-  for (int i=0; i<nentries; i++) {\r
-    chain->GetEvent(i);\r
-    //////////////////////////////////////////////////////\r
-    // track preselection    \r
-    int npts=tpa->GetNPoints();\r
-    if (npts<nreqpts) continue;\r
-    if (!SelectLayers(tpa,nreqpts_lay)) continue;\r
-    //////////////////////////////////////////////////////\r
-\r
-    if (!alig->ProcessTrack(tpa)) {\r
-      if (!(iTrackOk%500)) \r
-       printf("Calling LocalFit n. %d\n",iTrackOk);\r
-      alig->LocalFit(iTrackOk++,trackParams,0);\r
-    }\r
-  }\r
-  printf("\nMillepede fed with %d tracks\n\n",iTrackOk);\r
-  \r
-  alig->GlobalFit(parameters,errors,pulls);\r
-  \r
-  cout << "Done with GlobalFit " << endl;\r
-  \r
-  ////////////////////////////////////////////////////////////\r
-  // output\r
-  \r
-\r
-  TClonesArray *array = new TClonesArray("AliAlignObjParams",4000);\r
-  TClonesArray &alobj = *array;\r
-\r
-  // first object: ITS\r
-  new(alobj[0]) AliAlignObjParams("ITS", 0, 0., 0., 0., 0., 0., 0., kTRUE);\r
-  \r
-  UShort_t volid;\r
-  const Char_t *symname;\r
-  Double_t dx,dy,dz,dpsi,dtheta,dphi;\r
-  Double_t corr[21];\r
-\r
-  // all ITS modules\r
-  for (int idx=0; idx<2198; idx++) {\r
-    volid=alig->GetModuleVolumeID(idx);\r
-    symname = AliGeomManager::SymName(volid);\r
-    for (int jj=0;jj<21;jj++) corr[jj]=0.0;\r
-\r
-    if (alig->CheckVolumeID(volid)) { // defined modules\r
-      alig->SetCurrentModule(idx);\r
-      int iidx=alig->GetCurrentModuleInternalIndex();\r
-      dx    = parameters[iidx*6+0];  corr[0] = errors[iidx*6+0]*errors[iidx*6+0];\r
-      dy    = parameters[iidx*6+1];  corr[2] = errors[iidx*6+1]*errors[iidx*6+1];\r
-      dz    = parameters[iidx*6+2];  corr[5] = errors[iidx*6+2]*errors[iidx*6+2];\r
-      dpsi  = parameters[iidx*6+3];  corr[9] = errors[iidx*6+3]*errors[iidx*6+3];\r
-      dtheta= parameters[iidx*6+4];  corr[14]= errors[iidx*6+4]*errors[iidx*6+4];\r
-      dphi  = parameters[iidx*6+5];  corr[20]= errors[iidx*6+5]*errors[iidx*6+5];\r
-    }\r
-    else { // other modules\r
-      dx=0.0; dy=0.0; dz=0.0; dpsi=0.0; dtheta=0.0; dphi=0.0;\r
-    }\r
-    \r
-    new(alobj[idx+1]) AliAlignObjParams(symname, volid, dx, dy, dz, dpsi, dtheta, dphi, kFALSE);\r
-    AliAlignObjParams* alo = (AliAlignObjParams*) array->UncheckedAt(idx+1);\r
-    alo->SetCorrMatrix(corr);\r
-  }\r
-  \r
-  fout->WriteObject(array,"ITSAlignObjs","kSingleKey");\r
-  fout->Close();\r
-\r
-  stimer.Stop();\r
-  stimer.Print();\r
-   \r
-  return 0;\r
-}\r
+#if !defined(__CINT__) || defined(__MAKECINT__)
+#include <Riostream.h>
+#include <TChain.h>
+#include <TClonesArray.h>
+#include <TFile.h>
+#include <TMath.h>
+#include <TStopwatch.h>
+#include "AliAlignObjParams.h"
+#include "AliTrackPointArray.h"
+#include "AliITSAlignMille.h"
+#endif
+
+//********************************************************************
+//  Example to run ITS alignment using Millepede
+//
+//  Read tracks from AliTrackPoints.N.root and fill Millepede.
+//  Millepede configuration is taken from AliITSAlignMille.conf
+//  Results are written as AliAlignObjParams in outfile.
+//
+//      Origin: M. Lunardon
+//********************************************************************
+
+
+int ITSAlignMille(int fromev=1, int toev=1, int fromentry=0, int nentries=-1, char *outfile="ITSAlignMille.root", char *confile="AliITSAlignMille.conf",int nreqpts=3) {
+
+  //AliLog::SetGlobalLogLevel(6);
+  
+  TFile *fout=new TFile(outfile,"recreate");
+  if (!fout->IsOpen()) {
+    printf("\nCannot open output file!\n");
+    return -1;
+  }
+
+  TChain *chain=new TChain("spTree");  
+  char dir[100]="AliTrackPoints";
+  char st[200];
+  
+  for (int iev=fromev; iev<=toev; iev++) {
+    sprintf(st,"%s/AliTrackPoints.%d.root",dir,iev);
+    chain->Add(st);
+  }
+  
+  int toentry=chain->GetEntries();
+  printf("There are %d entries in chain\n",toentry);
+  
+  if (nentries>0 && nentries<(toentry-fromentry)) toentry=fromentry+nentries;
+  
+  AliTrackPointArray *tpa = 0;
+  chain->SetBranchAddress("SP", &tpa);
+
+  ////////////////////////////////////////////
+  
+  AliITSAlignMille *alig = new AliITSAlignMille(confile);
+  if (!alig->IsConfigured()) return -3;
+
+  Int_t nmod=alig->GetNModules();
+  alig->SetMinNPtsPerTrack(nreqpts);
+
+  // require 4 points in SPD (one per layer, up and down)
+  if (nreqpts>3) {
+    alig->SetRequiredPoint("LAYER",1,1,1);
+    alig->SetRequiredPoint("LAYER",1,-1,1);
+    alig->SetRequiredPoint("LAYER",2,1,1);
+    alig->SetRequiredPoint("LAYER",2,-1,1);
+  }
+
+  // correction for SSD bug (1) : inverisione sensor 18 e 19
+  // alig->SetBug(1);
+
+  Double_t *parameters = new Double_t[nmod*6];
+  Double_t *errors = new Double_t[nmod*6];
+  Double_t *pulls = new Double_t[nmod*6];
+
+  for(Int_t k=0;k<nmod*6;k++) {
+    parameters[k]=0.;
+    errors[k]=0.;
+    pulls[k]=0.;
+  }
+
+  // need array with size fNLocal*2
+  Double_t trackParams[10] = {0.,0.,0.,0.,0.,0.,0.,0.,0.,0.};
+  alig->InitGlobalParameters(parameters);
+  alig->Print();
+
+  Double_t sigmatra=alig->GetParSigTranslations();
+  Double_t sigmarot=alig->GetParSigRotations();
+  ////////////////////////////////////////////////////////////////////
+
+  TStopwatch stimer;
+  stimer.Start();
+
+  /////////////////////
+
+  int iTrackOk=0; // number of good passed track
+  // loop on spTree entries
+  // one entry = one track
+  for (int i=fromentry; i<toentry; i++) {
+
+    chain->GetEvent(i);
+    if (!alig->ProcessTrack(tpa)) {
+      if (!(iTrackOk%500)) 
+       printf("Calling LocalFit n. %d\n",iTrackOk);
+      alig->LocalFit(iTrackOk++,trackParams,0);
+    }
+  }
+  printf("\nMillepede fed with %d tracks\n",iTrackOk);
+  printf("Total number of rejected points because of bad EqLoc : %d\n\n",alig->GetTotBadLocEqPoints());
+  
+  stimer.Print();
+  stimer.Continue(); 
+
+  // make global fit
+  alig->GlobalFit(parameters,errors,pulls);
+  
+  cout << "Done with GlobalFit " << endl;
+  
+  ////////////////////////////////////////////////////////////
+  // output
+
+  printf("\nProcessed points statistics:\n");
+  Int_t maxstat=0;
+
+  printf("\nOutput values and point statistics:\n\n");
+  for (int i=0; i<nmod; i++) {
+    Int_t statm=alig->GetProcessedPoints()[i];
+    if (statm>maxstat) maxstat=statm;
+    printf("index: %-4d   stat: %-7d   pars: %f   %f   %f   %f   %f   %f\n",alig->GetModuleIndexArray()[i], statm,
+          parameters[i*6+0],
+          parameters[i*6+1],
+          parameters[i*6+2],
+          parameters[i*6+3],
+          parameters[i*6+4],
+          parameters[i*6+5]);
+    
+  }
+  FILE *pf=fopen("ITSAlignMille.out","w");
+  if (pf) {
+    fprintf(pf,"# param     dx         dy         dz         dpsi       dtheta     dphi\n");
+    for (int i=0; i<nmod; i++) {
+      fprintf(pf,"   %-5d %-10f %-10f %-10f %-10f %-10f %-10f\n",i,
+             parameters[i*6+0],
+             parameters[i*6+1],
+             parameters[i*6+2],
+             parameters[i*6+3],
+             parameters[i*6+4],
+             parameters[i*6+5]);
+      
+    }
+    fclose(pf);
+  }
+
+  printf("Max statistics = %d\n",maxstat);
+  if (maxstat<1) {
+    printf("No points for alignment! quitting now...\n");
+    return -1;
+  }  
+
+  TClonesArray *array = new TClonesArray("AliAlignObjParams",4000);
+  TClonesArray &alobj = *array;
+
+  // first object: ITS
+  new(alobj[0]) AliAlignObjParams("ITS", 0, 0., 0., 0., 0., 0., 0., kTRUE);
+  
+  UShort_t volid;
+  Char_t *symname;
+  Double_t dx,dy,dz,dpsi,dtheta,dphi;
+  Double_t corr[21];
+  Double_t deltalocal[6];
+  Double_t t[3],r[3];
+
+  AliAlignObjParams *tmpa=NULL;
+
+  // quality factor: 0 = NOT ALIGNED or OFF
+  //                 N = ALIGNED with statistics = N  
+  UInt_t QF; 
+
+  // all ITS sensitive modules
+  for (int idx=0; idx<2198; idx++) {
+    volid=AliITSAlignMilleModule::GetVolumeIDFromIndex(idx);
+    symname = AliGeomManager::SymName(volid);
+    // default null misalignment
+    for (int jj=0;jj<21;jj++) corr[jj]=0.0;
+    for (int jj=0;jj<3;jj++) {t[jj]=0.0;r[jj]=0.0;}
+    QF=0;
+
+    if (alig->IsContained(volid)>=0) { // defined modules or inside a supermodule
+      alig->SetCurrentModule(idx); // set the supermodule that contains idx
+      int iidx=alig->GetCurrentModuleInternalIndex();
+      
+      // check if all 6 parameters have been evaluated by millepede
+      Bool_t isoff=0;
+      Double_t parsig=0;
+      for (int kk=0; kk<6; kk++) {
+       parsig=sigmatra;
+       if (kk>2) parsig=sigmarot;
+       if (pulls[iidx*6+kk]==0.0 && errors[iidx*6+kk]==parsig) isoff=1;
+      }
+
+      // check if module was fixed
+      Bool_t isfixed=1;
+      for (int kk=0; kk<6; kk++) {
+       if (parameters[iidx*6+kk]!=0.0 || pulls[iidx*6+kk]!=0.0 || errors[iidx*6+kk]!=0.0) isfixed=0;
+      }
+
+      if (!isoff && !isfixed) { // OK, has been evaluated
+       deltalocal[0] = parameters[iidx*6+0];  
+       deltalocal[1] = parameters[iidx*6+1]; 
+       deltalocal[2] = parameters[iidx*6+2]; 
+       deltalocal[3] = parameters[iidx*6+3]; 
+       deltalocal[4] = parameters[iidx*6+4];
+       deltalocal[5] = parameters[iidx*6+5]; 
+       tmpa = alig->GetCurrentModule()->GetSensitiveVolumeMisalignment(volid,deltalocal);
+       if (!tmpa) {
+         printf("error transforming millepede parameters for module %d\n",idx);
+         continue;
+       }
+       tmpa->GetPars(t,r);
+       // at the moment sigma of supermodule is given to sensitive modules. to be fixed...
+       corr[0] = errors[iidx*6+0]*errors[iidx*6+0];
+       corr[2] = errors[iidx*6+1]*errors[iidx*6+1];
+       corr[5] = errors[iidx*6+2]*errors[iidx*6+2];
+       corr[9] = errors[iidx*6+3]*errors[iidx*6+3];
+       corr[14]= errors[iidx*6+4]*errors[iidx*6+4];
+       corr[20]= errors[iidx*6+5]*errors[iidx*6+5];
+       Int_t statm=alig->GetProcessedPoints()[iidx];
+       QF=statm;
+      }
+      else {
+       if (isoff) {
+         printf("Module %d is OFF!\n",idx);
+         QF=0;
+       }
+       if (isfixed) {
+         printf("Module %d was FIXED!\n",idx);
+         if (alig->GetPreAlignmentQualityFactor(idx)>0) 
+           QF=alig->GetPreAlignmentQualityFactor(idx);
+         else 
+           QF=0;
+       }
+      }
+
+    }
+
+    new(alobj[idx+1]) AliAlignObjParams(symname,volid,t[0],t[1],t[2],r[0],r[1],r[2],kFALSE);
+    AliAlignObjParams* alo = (AliAlignObjParams*) array->UncheckedAt(idx+1);
+    alo->SetCorrMatrix(corr);
+    alo->SetUniqueID(QF);
+  }
+  
+  fout->WriteObject(array,"ITSAlignObjs","kSingleKey");
+  fout->Close();
+
+  stimer.Stop();
+  stimer.Print();
+
+  return 0;
+}
diff --git a/ITS/MakeITSMilleSuperModules.C b/ITS/MakeITSMilleSuperModules.C
new file mode 100644 (file)
index 0000000..c11ad76
--- /dev/null
@@ -0,0 +1,576 @@
+#if !defined(__CINT__) || defined(__MAKECINT__)
+#include <TError.h>
+#include <TFile.h>
+#include <TGeoManager.h>
+#include <TMath.h>
+#include <TString.h>
+#include <TSystem.h>
+#include "AliCDBPath.h"
+#include "AliCDBEntry.h"
+#include "AliCDBManager.h"
+#include "AliCDBStorage.h"
+#include "AliGeomManager.h"
+#include "AliITSMisalignMaker.h"
+#endif
+void MakeITSMilleSuperModules(char *geomfile="geometry.root") {
+//========================================================================
+//
+// Macro for building supermodules for ITS alignment
+//
+// Main author: M. Lunardon
+//
+//========================================================================
+
+  const char* macroname = "MakeITSMilleSuperModules.C";
+
+  if (!geomfile) { // look for default geometry
+    // Activate CDB storage and load geometry from CDB
+    AliCDBManager* cdb = AliCDBManager::Instance();
+    if(!cdb->IsDefaultStorageSet()) cdb->SetDefaultStorage("local://$ALICE_ROOT");
+    cdb->SetRun(0);
+    
+    AliCDBStorage* storage = NULL;
+    
+    TString compare("kTRUE");
+    if(gSystem->Getenv("TOCDB") == compare.Data()){
+      TString Storage = gSystem->Getenv("STORAGE");
+      if(!Storage.BeginsWith("local://") && !Storage.BeginsWith("alien://")) {
+       Error(macroname,"STORAGE variable set to %s is not valid. Exiting\n",Storage.Data());
+       return;
+      }
+      storage = cdb->GetStorage(Storage.Data());
+      if(!storage){
+       Error(macroname,"Unable to open storage %s\n",Storage.Data());
+       return;
+      }
+      AliCDBPath path("GRP","Geometry","Data");
+      AliCDBEntry *entry = storage->Get(path.GetPath(),cdb->GetRun());
+      if(!entry) Fatal(macroname,"Could not get the specified CDB entry!");
+      entry->SetOwner(0);
+      TGeoManager* geom = (TGeoManager*) entry->GetObject();
+      AliGeomManager::SetGeometry(geom);
+    }else{
+      AliGeomManager::LoadGeometry("geometry.root"); //load geom from default CDB storage
+    }
+  }
+  else 
+    AliGeomManager::LoadGeometry(geomfile); //load geom from file
+  //////////////////////////////////////////////////////////////////
+  
+  TClonesArray *array = new TClonesArray("AliAlignObjParams",2000);
+  TClonesArray &alobj = *array;
+  Int_t j = 0;
+  
+  // custom ITS supermodules are stored as AliAlignObjParams as follow:
+  // symname, volid = SMsymname, SMvolid
+  // matrix = TGeoHMatrix of the SM in the global c.s.
+  // symname: the list of sensitive volumes, starting with "ITSMilleModuleList:" 
+  //          keyword, is appended to the symname
+  //          example:  "ITSMilleModuleList: N1 N2 N3-N4 ..."
+  //                  where N is a ITS sensitive volume INDEX (0-2197)
+
+  Char_t symname[4096];
+  UShort_t volid;
+  Char_t modlist[4096];
+  Double_t t[3]; // global translation
+  Double_t r[9]; // global rotation
+  TGeoHMatrix m;
+
+  // virtual volids start at layer 7
+  volid=14336;
+
+  // LAYERS: volids 14336 to 14341
+  strcpy(modlist,"ITSMilleModuleList: 0-79");
+  sprintf(symname,"%s  %s","ITS/SPD0",modlist);
+  m.Clear(); // global frame
+  new(alobj[j]) AliAlignObjParams(symname, volid, m, kTRUE);
+  *(strstr(symname,"ITSMilleModuleList"))=NULL ;printf("added module %s with volid %d \n",symname,volid);
+  j++; volid++;
+
+  strcpy(modlist,"ITSMilleModuleList: 80-239");
+  sprintf(symname,"%s  %s","ITS/SPD1",modlist);
+  m.Clear(); // global frame
+  new(alobj[j]) AliAlignObjParams(symname, volid, m, kTRUE);
+  *(strstr(symname,"ITSMilleModuleList"))=NULL ;printf("added module %s with volid %d \n",symname,volid);
+  j++; volid++;
+
+  strcpy(modlist,"ITSMilleModuleList: 240-323");
+  sprintf(symname,"%s  %s","ITS/SDD2",modlist);
+  m.Clear(); // global frame
+  new(alobj[j]) AliAlignObjParams(symname, volid, m, kTRUE);
+  *(strstr(symname,"ITSMilleModuleList"))=NULL ;printf("added module %s with volid %d \n",symname,volid);
+  j++; volid++;
+
+  strcpy(modlist,"ITSMilleModuleList: 324-499");
+  sprintf(symname,"%s  %s","ITS/SDD3",modlist);
+  m.Clear(); // global frame
+  new(alobj[j]) AliAlignObjParams(symname, volid, m, kTRUE);
+  *(strstr(symname,"ITSMilleModuleList"))=NULL ;printf("added module %s with volid %d \n",symname,volid);
+  j++; volid++;
+
+  strcpy(modlist,"ITSMilleModuleList: 500-1247");
+  sprintf(symname,"%s  %s","ITS/SSD4",modlist);
+  m.Clear(); // global frame
+  new(alobj[j]) AliAlignObjParams(symname, volid, m, kTRUE);
+  *(strstr(symname,"ITSMilleModuleList"))=NULL ;printf("added module %s with volid %d \n",symname,volid);
+  j++; volid++;
+
+  strcpy(modlist,"ITSMilleModuleList: 1248-2197");
+  sprintf(symname,"%s  %s","ITS/SSD5",modlist);
+  m.Clear(); // global frame
+  new(alobj[j]) AliAlignObjParams(symname, volid, m, kTRUE);
+  *(strstr(symname,"ITSMilleModuleList"))=NULL ;printf("added module %s with volid %d \n",symname,volid);
+  j++; volid++;
+
+  // SPD BARREL: volid 14342
+  strcpy(modlist,"ITSMilleModuleList: 0-239");
+  sprintf(symname,"%s  %s","ITS/SPD/Barrel",modlist);
+  m.Clear(); // global frame
+  new(alobj[j]) AliAlignObjParams(symname, volid, m, kTRUE);
+  *(strstr(symname,"ITSMilleModuleList"))=NULL ;printf("added module %s with volid %d \n",symname,volid);
+  j++; volid++;
+  
+  // SPD HALF BARREL: volids 14343-14344
+  strcpy(modlist,"ITSMilleModuleList: 0-39 80-159");
+  sprintf(symname,"%s  %s","ITS/SPD/HalfBarrel0",modlist); // up
+  m.Clear(); // global frame
+  new(alobj[j]) AliAlignObjParams(symname, volid, m, kTRUE);
+  *(strstr(symname,"ITSMilleModuleList"))=NULL ;printf("added module %s with volid %d \n",symname,volid);
+  j++; volid++;
+
+  strcpy(modlist,"ITSMilleModuleList: 40-79 160-239");
+  sprintf(symname,"%s  %s","ITS/SPD/HalfBarrel1",modlist); // down
+  m.Clear(); // global frame
+  //m.RotateZ(180.);
+  //m.RotateY(180.); // just negY->posY
+  new(alobj[j]) AliAlignObjParams(symname, volid, m, kTRUE);
+  *(strstr(symname,"ITSMilleModuleList"))=NULL ;printf("added module %s with volid %d \n",symname,volid);
+  j++; volid++;
+
+  // SPD sectors: volids 14345 to 14354
+  for (int is=0; is<10; is++) {
+    // sect 0: 0-7  80-95
+    // sect 1: 8-15 96-111
+    // ...
+    sprintf(modlist,"ITSMilleModuleList: %d-%d %d-%d",is*8,is*8+7,is*16+80,is*16+80+15);
+    sprintf(symname,"ITS/SPD0/Sector%d",is);
+    if (AliGeomManager::GetMatrix(symname))
+      m=(*AliGeomManager::GetMatrix(symname));
+    else {
+      Error(macroname,"cannot find matrix for SPD sector\n");
+      return;
+    }
+    sprintf(symname,"%s%d  %s","ITS/SPD0/Sector",is,modlist);
+
+    new(alobj[j]) AliAlignObjParams(symname, volid, m, kTRUE);
+    *(strstr(symname,"ITSMilleModuleList"))=NULL ;printf("added module %s with volid %d \n",symname,volid);
+    j++; volid++;
+  }
+
+  // SPD staves: volids 14355 to 14414
+  for (int is=0; is<60; is++) {
+    // Stave0: 0-3
+//     // ...
+    sprintf(modlist," ITSMilleModuleList: %d-%d",is*4,is*4+3);
+    strcpy(symname,AliITSgeomTGeo::GetSymName(is*4));
+    char *clad=strstr(symname,"Ladder");
+    if (clad) *(clad-1) = NULL;
+    else  {
+      Error(macroname,"cannot find 'Ladder' in symname\n");
+      return;
+    }    
+    //printf("Symname=%s\n",symname);
+    if (AliGeomManager::GetMatrix(symname))
+      m=(*AliGeomManager::GetMatrix(symname));
+    else {
+      Error(macroname,"cannot find matrix for SPD stave\n");
+      return;
+    }
+
+    clad=strstr(symname,"HalfStave");
+    if (clad) *(clad-1) = NULL;
+    else  {
+      Error(macroname,"cannot find 'HalfStave' in symname\n");
+      return;
+    }    
+    strcat(symname,modlist);
+
+    new(alobj[j]) AliAlignObjParams(symname, volid, m, kTRUE);
+    *(strstr(symname,"ITSMilleModuleList"))=NULL ;printf("added module %s with volid %d \n",symname,volid);
+    j++; volid++;
+  }
+
+
+  // SPD HALF staves: volids 14415 to 14534
+  for (int is=0; is<120; is++) {
+    // HalfStave0: 0-1
+//     // ...
+    sprintf(modlist," ITSMilleModuleList: %d-%d ",is*2,is*2+1);
+    strcpy(symname,AliITSgeomTGeo::GetSymName(is*2));
+    char *clad=strstr(symname,"Ladder");
+    if (clad) *(clad-1) = NULL;
+    else  {
+      Error(macroname,"cannot find 'Ladder' in symname\n");
+      return;
+    }    
+    if (AliGeomManager::GetMatrix(symname))
+      m=(*AliGeomManager::GetMatrix(symname));
+    else {
+      Error(macroname,"cannot find matrix for SPD half-stave\n");
+      return;
+    }
+    strcat(symname,modlist);
+
+    new(alobj[j]) AliAlignObjParams(symname, volid, m, kTRUE);
+    *(strstr(symname,"ITSMilleModuleList"))=NULL ;printf("added module %s with volid %d \n",symname,volid);
+    j++; volid++;
+  }
+
+  // SPD HALF-HALF BARREL UP/DOWN FORWARD/BACKWARD (Y>0 and Z>0): volids 14535 to 14538
+  strcpy(modlist,"ITSMilleModuleList: ");
+  for (int ii=0; ii<40; ii++) {
+    int ij=ii/2;
+    if (!(ij%2)) sprintf(modlist,"%s %d",modlist,ii); 
+  }
+  for (int ii=80; ii<160; ii++) {
+    int ij=ii/2;
+    if (!(ij%2)) sprintf(modlist,"%s %d",modlist,ii); 
+  }
+  sprintf(symname,"%s  %s","ITS/SPD/HalfBarrel0fw",modlist); // up/fw
+  m.Clear(); // global frame
+  new(alobj[j]) AliAlignObjParams(symname, volid, m, kTRUE);
+  *(strstr(symname,"ITSMilleModuleList"))=NULL ;printf("added module %s with volid %d \n",symname,volid);
+  j++; volid++;
+  //-----
+  strcpy(modlist,"ITSMilleModuleList: ");
+  for (int ii=0; ii<40; ii++) {
+    int ij=ii/2;
+    if ((ij%2)) sprintf(modlist,"%s %d",modlist,ii); 
+  }
+  for (int ii=80; ii<160; ii++) {
+    int ij=ii/2;
+    if ((ij%2)) sprintf(modlist,"%s %d",modlist,ii); 
+  }
+  sprintf(symname,"%s  %s","ITS/SPD/HalfBarrel0bw",modlist); // up/bw
+  m.Clear(); // global frame
+  new(alobj[j]) AliAlignObjParams(symname, volid, m, kTRUE);
+  *(strstr(symname,"ITSMilleModuleList"))=NULL ;printf("added module %s with volid %d \n",symname,volid);
+  j++; volid++;
+  //-----
+  strcpy(modlist,"ITSMilleModuleList: ");
+  for (int ii=40; ii<80; ii++) {
+    int ij=ii/2;
+    if (!(ij%2)) sprintf(modlist,"%s %d",modlist,ii); 
+  }
+  for (int ii=160; ii<240; ii++) {
+    int ij=ii/2;
+    if (!(ij%2)) sprintf(modlist,"%s %d",modlist,ii); 
+  }
+  sprintf(symname,"%s  %s","ITS/SPD/HalfBarrel1fw",modlist); // down/fw
+  m.Clear(); // global frame
+  //m.RotateZ(180.);
+  //m.RotateY(180.); // just negY->posY
+  new(alobj[j]) AliAlignObjParams(symname, volid, m, kTRUE);
+  *(strstr(symname,"ITSMilleModuleList"))=NULL ;printf("added module %s with volid %d \n",symname,volid);
+  j++; volid++;
+  //-----
+  strcpy(modlist,"ITSMilleModuleList: ");
+  for (int ii=40; ii<80; ii++) {
+    int ij=ii/2;
+    if ((ij%2)) sprintf(modlist,"%s %d",modlist,ii); 
+  }
+  for (int ii=160; ii<240; ii++) {
+    int ij=ii/2;
+    if ((ij%2)) sprintf(modlist,"%s %d",modlist,ii); 
+  }
+  sprintf(symname,"%s  %s","ITS/SPD/HalfBarrel1bw",modlist); // down/bw
+  m.Clear(); // global frame
+  //m.RotateZ(180.);
+  //m.RotateY(180.); // just negY->posY
+  new(alobj[j]) AliAlignObjParams(symname, volid, m, kTRUE);
+  *(strstr(symname,"ITSMilleModuleList"))=NULL ;printf("added module %s with volid %d \n",symname,volid);
+  j++; volid++;
+  //-----
+
+  // SDD
+  // start at volid=15000
+  // - SDD2: 14 ladders da 6 elementi
+  // - SDD3: 22 ladders da 8 elementi
+  volid=15000;
+
+  // SDD2 Ladders: volids 15000 to 15013
+  for (int is=0; is<14; is++) {
+    // Ladder: 0-5
+    //     // ...
+    sprintf(modlist," ITSMilleModuleList: %d-%d ",240+is*6,240+is*6+5);
+    strcpy(symname,AliITSgeomTGeo::GetSymName(240+is*6));
+    char *clad=strstr(symname,"Sensor");
+    if (clad) *(clad-1) = NULL;
+    else  {
+      Error(macroname,"cannot find 'Sensor' in symname\n");
+      return;
+    }    
+    if (AliGeomManager::GetMatrix(symname))
+      m=(*AliGeomManager::GetMatrix(symname));
+    else {
+      Error(macroname,"cannot find matrix for SDD ladder\n");
+      return;
+    }
+    strcat(symname,modlist);
+
+    new(alobj[j]) AliAlignObjParams(symname, volid, m, kTRUE);
+    *(strstr(symname,"ITSMilleModuleList"))=NULL ;printf("added module %s with volid %d \n",symname,volid);
+    j++; volid++;
+  }
+
+  // SDD3 Ladders: volids 15014 to 15035
+  for (int is=0; is<22; is++) {
+    // Ladder: 0-7
+    //     // ...
+    sprintf(modlist," ITSMilleModuleList: %d-%d ",324+is*8,324+is*8+7);
+    strcpy(symname,AliITSgeomTGeo::GetSymName(324+is*8));
+    char *clad=strstr(symname,"Sensor");
+    if (clad) *(clad-1) = NULL;
+    else  {
+      Error(macroname,"cannot find 'Sensor' in symname\n");
+      return;
+    }    
+    if (AliGeomManager::GetMatrix(symname))
+      m=(*AliGeomManager::GetMatrix(symname));
+    else {
+      Error(macroname,"cannot find matrix for SDD ladder\n");
+      return;
+    }
+    strcat(symname,modlist);
+
+    new(alobj[j]) AliAlignObjParams(symname, volid, m, kTRUE);
+    *(strstr(symname,"ITSMilleModuleList"))=NULL ;printf("added module %s with volid %d \n",symname,volid);
+    j++; volid++;
+  }
+
+  //----------
+
+  // SSD
+  // start at volid=16000
+  // - SSD4: 34 ladders da 22 elementi
+  // - SSD5: 38 ladders da 25 elementi
+  volid=16000;
+
+  // SSD4 Ladders: volids 16000 to 16033
+  for (int is=0; is<34; is++) {
+    // Ladder: 0-5
+    //     // ...
+    sprintf(modlist," ITSMilleModuleList: %d-%d ",500+is*22,500+is*22+21);
+    strcpy(symname,AliITSgeomTGeo::GetSymName(500+is*22));
+    char *clad=strstr(symname,"Sensor");
+    if (clad) *(clad-1) = NULL;
+    else  {
+      Error(macroname,"cannot find 'Sensor' in symname\n");
+      return;
+    }    
+    if (AliGeomManager::GetMatrix(symname))
+      m=(*AliGeomManager::GetMatrix(symname));
+    else {
+      Error(macroname,"cannot find matrix for SSD ladder\n");
+      return;
+    }
+    strcat(symname,modlist);
+
+    new(alobj[j]) AliAlignObjParams(symname, volid, m, kTRUE);
+    *(strstr(symname,"ITSMilleModuleList"))=NULL ;printf("added module %s with volid %d \n",symname,volid);
+    j++; volid++;
+  }
+
+  // SSD5 Ladders: volids 16034 to 16071
+  for (int is=0; is<38; is++) {
+    // Ladder: 0-7
+    //     // ...
+    sprintf(modlist," ITSMilleModuleList: %d-%d ",1248+is*25,1248+is*25+24);
+    strcpy(symname,AliITSgeomTGeo::GetSymName(1248+is*25));
+    char *clad=strstr(symname,"Sensor");
+    if (clad) *(clad-1) = NULL;
+    else  {
+      Error(macroname,"cannot find 'Sensor' in symname\n");
+      return;
+    }    
+    if (AliGeomManager::GetMatrix(symname))
+      m=(*AliGeomManager::GetMatrix(symname));
+    else {
+      Error(macroname,"cannot find matrix for SDD ladder\n");
+      return;
+    }
+    strcat(symname,modlist);
+
+    new(alobj[j]) AliAlignObjParams(symname, volid, m, kTRUE);
+    *(strstr(symname,"ITSMilleModuleList"))=NULL ;printf("added module %s with volid %d \n",symname,volid);
+    j++; volid++;
+  }
+  
+  // SSD BARREL: volid 16072
+  strcpy(modlist,"ITSMilleModuleList: 500-2197");
+  sprintf(symname,"%s  %s","ITS/SSD/Barrel",modlist);
+  m.Clear(); // global frame
+  new(alobj[j]) AliAlignObjParams(symname, volid, m, kTRUE);
+  *(strstr(symname,"ITSMilleModuleList"))=NULL ;printf("added module %s with volid %d \n",symname,volid);
+  j++; volid++;
+  
+  
+  // SSD HALF BARREL: volids 16073-16074
+  // SSD HALF BARREL UP: volid 16073
+  strcpy(modlist,"ITSMilleModuleList: 500-873 1248-1722");
+  sprintf(symname,"%s  %s","ITS/SSD/HalfBarrel0",modlist); // up
+  m.Clear(); // global frame
+  new(alobj[j]) AliAlignObjParams(symname, volid, m, kTRUE);
+  *(strstr(symname,"ITSMilleModuleList"))=NULL ;printf("added module %s with volid %d \n",symname,volid);
+  j++; volid++;
+  
+  // SSD HALF BARREL DOWN: volid 16074
+  strcpy(modlist,"ITSMilleModuleList: 874-1246 1723-2197");
+  sprintf(symname,"%s  %s","ITS/SSD/HalfBarrel1",modlist); // down
+  m.Clear(); // global frame
+  new(alobj[j]) AliAlignObjParams(symname, volid, m, kTRUE);
+  *(strstr(symname,"ITSMilleModuleList"))=NULL ;printf("added module %s with volid %d \n",symname,volid);
+  j++; volid++;
+  
+  
+  //----------
+  // SSD HALF-LADDERS
+  // - SSD4: 34x2=68 halfladders da 12+10 elementi
+  // - SSD5: 38x2=76 halfladders da 12+13 elementi
+
+  // SSD4 Ladders: volids 16075 to 16142
+  for (int is=0; is<34; is++) {
+    // Ladder: 0-33
+    // first half
+    sprintf(modlist," ITSMilleModuleList: %d-%d ",500+is*22,500+is*22+11);
+    strcpy(symname,AliITSgeomTGeo::GetSymName(500+is*22));
+    char *clad=strstr(symname,"Sensor");
+    if (clad) *(clad-1) = NULL;
+    else  {
+      Error(macroname,"cannot find 'Sensor' in symname\n");
+      return;
+    }    
+    if (AliGeomManager::GetMatrix(symname))
+      m=(*AliGeomManager::GetMatrix(symname));
+    else {
+      Error(macroname,"cannot find matrix for SSD ladder\n");
+      return;
+    }
+    strcat(symname,"Half0");
+    strcat(symname,modlist);
+
+    new(alobj[j]) AliAlignObjParams(symname, volid, m, kTRUE);
+    *(strstr(symname,"ITSMilleModuleList"))=NULL ;printf("added module %s with volid %d \n",symname,volid);
+    j++; volid++;
+
+    // second half
+    sprintf(modlist," ITSMilleModuleList: %d-%d ",500+is*22+12,500+is*22+21);
+    strcpy(symname,AliITSgeomTGeo::GetSymName(500+is*22));
+    char *clad=strstr(symname,"Sensor");
+    if (clad) *(clad-1) = NULL;
+    else  {
+      Error(macroname,"cannot find 'Sensor' in symname\n");
+      return;
+    }    
+    if (AliGeomManager::GetMatrix(symname))
+      m=(*AliGeomManager::GetMatrix(symname));
+    else {
+      Error(macroname,"cannot find matrix for SSD ladder\n");
+      return;
+    }
+    strcat(symname,"Half1");
+    strcat(symname,modlist);
+
+    new(alobj[j]) AliAlignObjParams(symname, volid, m, kTRUE);
+    *(strstr(symname,"ITSMilleModuleList"))=NULL ;printf("added module %s with volid %d \n",symname,volid);
+    j++; volid++;
+
+  }
+
+  // SSD5 Ladders: volids 16143 to 16218
+  for (int is=0; is<38; is++) {
+    //  first half
+    sprintf(modlist," ITSMilleModuleList: %d-%d ",1248+is*25,1248+is*25+11);
+    strcpy(symname,AliITSgeomTGeo::GetSymName(1248+is*25));
+    char *clad=strstr(symname,"Sensor");
+    if (clad) *(clad-1) = NULL;
+    else  {
+      Error(macroname,"cannot find 'Sensor' in symname\n");
+      return;
+    }    
+    if (AliGeomManager::GetMatrix(symname))
+      m=(*AliGeomManager::GetMatrix(symname));
+    else {
+      Error(macroname,"cannot find matrix for SDD ladder\n");
+      return;
+    }
+    strcat(symname,"Half0");
+    strcat(symname,modlist);
+
+    new(alobj[j]) AliAlignObjParams(symname, volid, m, kTRUE);
+    *(strstr(symname,"ITSMilleModuleList"))=NULL ;printf("added module %s with volid %d \n",symname,volid);
+    j++; volid++;
+
+    // second half
+    sprintf(modlist," ITSMilleModuleList: %d-%d ",1248+is*25+12,1248+is*25+24);
+    strcpy(symname,AliITSgeomTGeo::GetSymName(1248+is*25));
+    char *clad=strstr(symname,"Sensor");
+    if (clad) *(clad-1) = NULL;
+    else  {
+      Error(macroname,"cannot find 'Sensor' in symname\n");
+      return;
+    }    
+    if (AliGeomManager::GetMatrix(symname))
+      m=(*AliGeomManager::GetMatrix(symname));
+    else {
+      Error(macroname,"cannot find matrix for SDD ladder\n");
+      return;
+    }
+    strcat(symname,"Half1");
+    strcat(symname,modlist);
+
+    new(alobj[j]) AliAlignObjParams(symname, volid, m, kTRUE);
+    *(strstr(symname,"ITSMilleModuleList"))=NULL ;printf("added module %s with volid %d \n",symname,volid);
+    j++; volid++;
+  }
+
+
+  //////////////////////////////////////////////////////////////////
+  if( TString(gSystem->Getenv("TOCDB")) != TString("kTRUE") ){
+    // save on file
+    const char* filename = "ITSMilleSuperModules.root";
+    TFile f(filename,"RECREATE");
+    if(!f){
+      Error(macroname,"cannot open file for output\n");
+      return;
+    }
+    Info(macroname,"Saving ITS SuperModules as AliAlignObjs to the file %s", filename);
+    f.cd();
+    f.WriteObject(array,"ITSMilleSuperModules","kSingleKey");
+    f.Close();
+  }else{
+    // save in CDB storage
+    TString Storage = gSystem->Getenv("STORAGE");
+    if(!Storage.BeginsWith("local://") && !Storage.BeginsWith("alien://")) {
+      Error(macroname,"STORAGE variable set to %s is not valid. Exiting\n",Storage.Data());
+      return;
+    }
+    Info(macroname,"Saving ITS SuperModules in CDB storage %s",
+        Storage.Data());
+    AliCDBManager* cdb = AliCDBManager::Instance();
+    AliCDBStorage* storage = cdb->GetStorage(Storage.Data());
+    if(!storage){
+      Error(macroname,"Unable to open storage %s\n",Storage.Data());
+      return;
+    }
+    AliCDBMetaData *md= new AliCDBMetaData();
+    md->SetResponsible("Marcello Lunardon");
+    md->SetComment("ITS super modules for ITS alignment with Millepede");
+    md->SetAliRootVersion(gSystem->Getenv("ARVERSION"));
+    AliCDBId id("ITS/Align/Data",0,AliCDBRunRange::Infinity());
+    storage->Put(array,id, md);
+  }
+  
+  array->Delete();
+  return;
+}