+//________________________________________________________________________________________________________
+void AliITSAlignMille2::SetBField(Double_t b)
+{
+ // set Bz value
+ if (IsZero(b,1e-5)) {
+ fBField = 0.0;
+ fBOn = kFALSE;
+ fNLocal = 4;
+ }
+ else {
+ fBField = b;
+ fBOn = kTRUE;
+ fNLocal = 5; // helices
+ }
+}
+
+//________________________________________________________________________________________________________
+Int_t AliITSAlignMille2::ProcessUserInfo(TList* userInfo)
+{
+ // extract calibration information used for TrackPointArray creation from run info
+ //
+ if (!userInfo) { AliInfo("No UserInfo is provided"); return 0;}
+ //
+ TMap *cdbMap=0;
+ TList* cdbList=0;
+ TObjString *objStr,*objStr1,*keyStr;
+ TString cdbStr;
+ AliCDBManager* man = AliCDBManager::Instance();
+ man->SetCacheFlag(kFALSE);
+ //
+ int run = userInfo->GetUniqueID();
+ if (run>0) SetRunID(run);
+ AliInfo(Form("UserInfo corresponds to run#%d",run));
+ cdbMap = (TMap*)userInfo->FindObject("cdbMap");
+ const TMap *curMap = man->GetStorageMap();
+ if (!cdbMap) {AliInfo("No CDB Map found in UserInfo");}
+ else {
+ if ((objStr=(TObjString*)cdbMap->GetValue("default"))) { // first set default CDB path
+ if ((objStr1=(TObjString*)curMap->GetValue("default")) && objStr1->GetUniqueID()) {
+ AliInfo(Form("OCDB default path from UserInfo: %s is overriden by user setting %s",objStr->GetName(),objStr1->GetName()));
+ }
+ else {
+ cdbStr = objStr->GetString();
+ man->UnsetDefaultStorage();
+ if (man->GetRaw()) man->SetRaw(kFALSE);
+ if (cdbStr.BeginsWith("raw://")) cdbStr = "raw://";
+ AliInfo(Form("Default CDB Storage from UserInfo: %s",cdbStr.Data()));
+ man->SetDefaultStorage( cdbStr.Data() ); // this may be overriden later by configuration file
+ }
+ }
+ if (man->GetRaw() && run>0) man->SetRun(run);
+ //
+ // set specific paths relevant for alignment
+ TIter itMap(cdbMap);
+ while( (keyStr=(TObjString*)itMap.Next()) ) {
+ TString keyS = keyStr->GetString();
+ if ( keyS == "default" ) continue;
+ //
+ TObjString* curPath = (TObjString*)curMap->GetValue(keyStr->GetName());
+ if (curPath && curPath->GetUniqueID()) {
+ AliInfo(Form("Storage for %s from UserInfo\n is overriden by user setting %s",keyS.Data(),curPath->GetName()));
+ continue;
+ }
+ man->SetSpecificStorage( keyS.Data(), cdbMap->GetValue(keyS)->GetName() );
+ }
+ }
+ //
+ cdbList = (TList*)userInfo->FindObject("cdbList");
+ if (!cdbList) {AliInfo("No CDB List found in UserInfo");}
+ else {
+ // Objects used for TrackPointArray production
+ GetPathFromUserInfo(cdbList,"GRP/Geometry/Data",fIniGeomPath ,kSameInitGeomBit);
+ GetPathFromUserInfo(cdbList,"ITS/Align/Data" ,fIniDeltaPath,kSameInitDeltasBit);
+ GetPathFromUserInfo(cdbList,"ITS/Calib/RespSDD",fIniSDDRespPath,kSameInitSDDRespBit);
+ GetPathFromUserInfo(cdbList,"ITS/Calib/DriftSpeedSDD",fIniSDDVDriftPath,kSameInitSDDVDriftBit);
+ GetPathFromUserInfo(cdbList,"ITS/Calib/MapsTimeSDD",fIniSDDCorrMapPath,kSameInitSDDCorrMapBit);
+ GetPathFromUserInfo(cdbList,"GRP/Calib/MeanVertexSPD",fDiamondPath,kSameDiamondBit);
+ }
+ //
+ TList *bzlst = (TList*)userInfo->FindObject("BzkGauss");
+ if (bzlst && bzlst->At(0)) {
+ objStr = (TObjString*)bzlst->At(0);
+ SetBField( objStr->GetString().Atof() );
+ AliInfo(Form("Magnetic field from UserInfo: %+.2e",GetBField()));
+ }
+ return 0;
+}
+
+//________________________________________________________________________________________________________
+Int_t AliITSAlignMille2::GetPathFromUserInfo(const TList* cdbList,const char* calib,TString& path, Int_t useBit)
+{
+ // extract the path for specific CDB path from user info. If it is the same as already loaded, set corresponing bit
+ TIter itList(cdbList);
+ if (useBit>=0) ResetBit(useBit);
+ TObjString* objStr;
+ while( (objStr=(TObjString*)itList.Next()) )
+ if (objStr->GetString().Contains(calib)) {
+ TString newpath = objStr->GetString();
+ AliInfo(Form("Found path in UserInfo: %s",newpath.Data()));
+ if ( useBit>=0 && (fUserProvided&useBit) ) {
+ AliInfo(Form("Will use the one provided in config: %s",path.Data()));
+ SetBit(useBit);
+ }
+ else if ( useBit>=0 && (newpath == path) ) {
+ AliInfo(Form("Path %s is the same as already loaded",path.Data()));
+ SetBit(useBit);
+ }
+ else path = newpath;
+ //
+ return 0;
+ }
+ AliInfo(Form("Did not find path for %s in UserInfo",calib));
+ path = "";
+ return -1;
+}
+
+//________________________________________________________________________________________________________
+Int_t AliITSAlignMille2::LoadSDDResponse(TString& path, AliITSresponseSDD *&resp)
+{
+ // load SDD response
+ if (path.IsNull()) return 0;
+ AliInfo(Form("Loading SDD response from %s",path.Data()));
+ //
+ AliCDBEntry *entry = 0;
+ delete resp;
+ resp = 0;
+ //
+ while(1) {
+ if (path.BeginsWith("path: ")) { // must load from OCDB
+ entry = GetCDBEntry(path.Data());
+ if (!entry) break;
+ resp = (AliITSresponseSDD*) entry->GetObject();
+ entry->SetObject(NULL);
+ entry->SetOwner(kTRUE);
+ // AliCDBManager::Instance()->UnloadFromCache(path); // don't want cached object, read new copy
+ // delete cdbId;
+ // delete entry;
+ break;
+ }
+ //
+ if (gSystem->AccessPathName(path.Data())) break;
+ TFile* precf = TFile::Open(path.Data());
+ if (precf->FindKey("AliITSresponseSDD")) resp = (AliITSresponseSDD*)precf->Get("AliITSresponseSDD");
+ else if (precf->FindKey("AliCDBEntry") && (entry=(AliCDBEntry*)precf->Get("AliCDBEntry"))) {
+ resp = (AliITSresponseSDD*) entry->GetObject();
+ if (resp && resp->InheritsFrom(AliITSresponseSDD::Class())) entry->SetObject(NULL);
+ else resp = 0;
+ entry->SetObject(NULL);
+ entry->SetOwner(kTRUE);
+ delete entry;
+ }
+ //
+ precf->Close();
+ delete precf;
+ break;
+ }
+ //
+ if (!resp) {AliError(Form("Failed to load SDD response from %s",path.Data())); return -1;}
+ return 0;
+}
+
+//________________________________________________________________________________________________________
+Int_t AliITSAlignMille2::LoadSDDVDrift(TString& path, TObjArray *&arr)
+{
+ // load VDrift object
+ if (path.IsNull()) return 0;
+ AliInfo(Form("Loading SDD VDrift from %s",path.Data()));
+ //
+ AliCDBEntry *entry = 0;
+ delete arr;
+ arr = 0;
+ while(1) {
+ if (path.BeginsWith("path: ")) { // must load from OCDB
+ entry = GetCDBEntry(path.Data());
+ if (!entry) break;
+ arr = (TObjArray*) entry->GetObject();
+ entry->SetObject(NULL);
+ entry->SetOwner(kTRUE);
+ // AliCDBManager::Instance()->UnloadFromCache(path); // don't want cached object, read new copy
+ // delete cdbId;
+ // delete entry;
+ break;
+ }
+ //
+ if (gSystem->AccessPathName(path.Data())) break;
+ TFile* precf = TFile::Open(path.Data());
+ if (precf->FindKey("TObjArray")) arr = (TObjArray*)precf->Get("TObjArray");
+ else if (precf->FindKey("AliCDBEntry") && (entry=(AliCDBEntry*)precf->Get("AliCDBEntry"))) {
+ arr = (TObjArray*) entry->GetObject();
+ if (arr && arr->InheritsFrom(TObjArray::Class())) entry->SetObject(NULL);
+ else arr = 0;
+ entry->SetObject(NULL);
+ entry->SetOwner(kTRUE);
+ delete entry;
+ }
+ //
+ precf->Close();
+ delete precf;
+ break;
+ }
+ //
+ if (!arr) {AliError(Form("Failed to load SDD vdrift from %s",path.Data())); return -1;}
+ arr->SetOwner(kTRUE);
+ return 0;
+}
+
+//________________________________________________________________________________________________________
+Int_t AliITSAlignMille2::LoadSDDCorrMap(TString& path, AliITSCorrectSDDPoints *&map)
+{
+ // Load SDD correction map
+ //
+ if (path.IsNull()) return 0;
+ AliInfo(Form("Loading SDD Correction Maps from %s",path.Data()));
+ //
+ AliCDBEntry *entry = 0;
+ delete map;
+ map = 0;
+ TObjArray* arr = 0;
+ while(1) {
+ if (path.BeginsWith("path: ")) { // must load from OCDB
+ entry = GetCDBEntry(path.Data());
+ if (!entry) break;
+ arr = (TObjArray*) entry->GetObject();
+ entry->SetObject(NULL);
+ entry->SetOwner(kTRUE);
+ // AliCDBManager::Instance()->UnloadFromCache(path); // don't want cached object, read new copy
+ // delete cdbId;
+ // delete entry;
+ break;
+ }
+ //
+ if (gSystem->AccessPathName(path.Data())) break;
+ TFile* precf = TFile::Open(path.Data());
+ if (precf->FindKey("TObjArray")) arr = (TObjArray*)precf->Get("TObjArray");
+ else if (precf->FindKey("AliCDBEntry") && (entry=(AliCDBEntry*)precf->Get("AliCDBEntry"))) {
+ arr = (TObjArray*) entry->GetObject();
+ if (arr && arr->InheritsFrom(TObjArray::Class())) entry->SetObject(NULL);
+ else arr = 0;
+ entry->SetObject(NULL);
+ entry->SetOwner(kTRUE);
+ delete entry;
+ }
+ //
+ precf->Close();
+ delete precf;
+ break;
+ }
+ //
+ if (!arr) {AliError(Form("Failed to load SDD Correction Map from %s",path.Data())); return -1;}
+ arr->SetOwner(kTRUE);
+ map = new AliITSCorrectSDDPoints(arr);
+
+ return 0;
+}
+
+//________________________________________________________________________________________________________
+Int_t AliITSAlignMille2::LoadPreSDDCalib()
+{
+ // Load SDD correction map for prealignment from current CDB
+ //
+ AliInfo(Form("Loading SDD Calibration set for run %d",fRunID));
+ AliCDBManager* man = AliCDBManager::Instance();
+ man->SetRun(fRunID);
+ AliCDBEntry *entry = man->Get("ITS/Calib/MapsTimeSDD");
+ if(!entry){
+ AliError("Error accessing OCDB: SDD maps not found");
+ return -1;
+ }
+ delete fPreCorrMapSDD;
+ TObjArray* arr = (TObjArray*) entry->GetObject();
+ entry->SetObject(NULL);
+ entry->SetOwner(kTRUE);
+ arr->SetOwner(kTRUE);
+ fPreCorrMapSDD = new AliITSCorrectSDDPoints(arr);
+ //
+ entry = man->Get("ITS/Calib/RespSDD");
+ if(!entry){
+ AliError("Error accessing OCDB: SDD response not found");
+ return -1;
+ }
+ delete fPreRespSDD;
+ fPreRespSDD = (AliITSresponseSDD*) entry->GetObject();
+ entry->SetObject(NULL);
+ entry->SetOwner(kTRUE);
+ //
+ entry = man->Get("ITS/Calib/DriftSpeedSDD");
+ if(!entry){
+ AliError("Error accessing OCDB: SDD Drift speed not found");
+ return -1;
+ }
+ delete fPreVDriftSDD;
+ fPreVDriftSDD = (TObjArray*) entry->GetObject();
+ entry->SetObject(NULL);
+ entry->SetOwner(kTRUE);
+ delete entry;
+ //
+ return 0;
+}
+
+//________________________________________________________________________________________________________
+Int_t AliITSAlignMille2::LoadDiamond(TString& path)
+{
+ // load vertex constraint
+ if (path.IsNull()) return 0;
+ AliInfo(Form("Loading Diamond Constraint from %s",path.Data()));
+ //
+ AliCDBEntry *entry = 0;
+ AliESDVertex *vtx = 0;
+ while(1) {
+ if (path.BeginsWith("path: ")) { // must load from OCDB
+ entry = GetCDBEntry(path.Data());
+ if (!entry) break;
+ vtx = (AliESDVertex*) entry->GetObject();
+ entry->SetObject(NULL);
+ entry->SetOwner(kTRUE);
+ // AliCDBManager::Instance()->UnloadFromCache(path); // don't want cached object, read new copy
+ // delete cdbId;
+ // delete entry;
+ break;
+ }
+ //
+ if (gSystem->AccessPathName(path.Data())) break;
+ TFile* precf = TFile::Open(path.Data());
+ if (precf->FindKey("AliESDVertex")) vtx = (AliESDVertex*)precf->Get("AliESDVertex");
+ else if (precf->FindKey("AliCDBEntry") && (entry=(AliCDBEntry*)precf->Get("AliCDBEntry"))) {
+ vtx = (AliESDVertex*) entry->GetObject();
+ if (vtx && vtx->InheritsFrom(AliESDVertex::Class())) entry->SetObject(NULL);
+ else vtx = 0;
+ entry->SetObject(NULL);
+ entry->SetOwner(kTRUE);
+ delete entry;
+ }
+ //
+ precf->Close();
+ delete precf;
+ break;
+ }
+ //
+ if (!vtx) {AliError(Form("Failed to load Diamond constraint from %s",path.Data())); return -1;}
+ //
+ double vtxXYZ[3];
+ vtx->GetXYZ(vtxXYZ);
+ for (int i=3;i--;) vtxXYZ[i] -= fCorrDiamond[i];
+ vtx->SetXYZ(vtxXYZ);
+ SetVertexConstraint(vtx);
+ AliInfo("Will use following Diamond Constraint (errors inverted):");
+ fDiamondI.Print("");
+ delete vtx;
+ return 0;
+}
+
+//________________________________________________________________________________________________________
+Int_t AliITSAlignMille2::LoadDeltas(TString& path, TClonesArray *&arr)
+{
+ // load ITS geom deltas
+ if (path.IsNull()) return 0;
+ AliInfo(Form("Loading Alignment Deltas from %s",path.Data()));
+ //
+ AliCDBEntry *entry = 0;
+ delete arr;
+ arr = 0;
+ while(1) {
+ if (path.BeginsWith("path: ")) { // must load from OCDB
+ entry = GetCDBEntry(path.Data());
+ if (!entry) break;
+ arr = (TClonesArray*) entry->GetObject();
+ entry->SetObject(NULL);
+ entry->SetOwner(kTRUE);
+ // AliCDBManager::Instance()->UnloadFromCache(path); // don't want cached object, read new copy
+ // delete cdbId;
+ // delete entry;
+ break;
+ }
+ //
+ if (gSystem->AccessPathName(path.Data())) break;
+ TFile* precf = TFile::Open(path.Data());
+ if (precf->FindKey("ITSAlignObjs")) arr = (TClonesArray*)precf->Get("ITSAlignObjs");
+ else if (precf->FindKey("AliCDBEntry") && (entry=(AliCDBEntry*)precf->Get("AliCDBEntry"))) {
+ arr = (TClonesArray*) entry->GetObject();
+ if (arr && arr->InheritsFrom(TClonesArray::Class())) entry->SetObject(NULL);
+ else arr = 0;
+ entry->SetObject(NULL);
+ entry->SetOwner(kTRUE);
+ delete entry;
+ }
+ precf->Close();
+ delete precf;
+ break;
+ }
+ //
+ if (!arr) {AliError(Form("Failed to load Deltas from %s",path.Data())); return -1;}
+ //
+ return 0;
+}
+
+//________________________________________________________________________________________________________
+Int_t AliITSAlignMille2::CacheMatricesCurr()
+{
+ // build arrays for the fast access to sensor matrices from their sensor ID
+ //
+ TGeoHMatrix mdel;
+ AliInfo("Building sensors current matrices cache");
+ //
+ fCacheMatrixCurr.Delete();
+ for (int idx=0;idx<=kMaxITSSensID;idx++) {
+ int volID = AliITSAlignMille2Module::GetVolumeIDFromIndex(idx);
+ TGeoHMatrix *mcurr = new TGeoHMatrix();
+ AliITSAlignMille2Module::SensVolMatrix(volID, mcurr);
+ fCacheMatrixCurr.AddAtAndExpand(mcurr,idx);
+ //
+ }
+ //
+ TGeoHMatrix *mcurr = new TGeoHMatrix();
+ fCacheMatrixCurr.AddAtAndExpand(mcurr,kVtxSensID); // special unit matrix for diamond constraint
+ //
+ fCacheMatrixCurr.SetOwner(kTRUE);
+ return 0;
+}
+
+//________________________________________________________________________________________________________
+Int_t AliITSAlignMille2::CacheMatricesOrig()
+{
+ // build arrays for the fast access to sensor original matrices (used for production)
+ //
+ TGeoHMatrix mdel;
+ AliInfo(Form("Building sensors original matrices cache. InitDeltaPath: %s",fIniDeltaPath.Data()));
+ //
+ /*if (fIniGeomPath!=fGeometryPath)*/ if (LoadGeometry(fIniGeomPath)) {AliInfo("Failed to re-load ideal geometry");exit(1);}
+ //
+ fCacheMatrixOrig.Delete();
+ if (!fIniDeltaPath.IsNull()) {
+ TClonesArray* prealSav = fPrealignment;
+ fPrealignment = 0;
+ if (LoadDeltas(fIniDeltaPath,fPrealignment) || ApplyToGeometry())
+ { AliError("Failed to load/apply initial deltas used to produce points"); return -1;}
+ delete fPrealignment;
+ fPrealignment = prealSav;
+ }
+ //
+ for (int idx=0;idx<=kMaxITSSensID;idx++) {
+ int volID = AliITSAlignMille2Module::GetVolumeIDFromIndex(idx);
+ TGeoHMatrix *morig = new TGeoHMatrix();
+ AliITSAlignMille2Module::SensVolMatrix(volID,morig);
+ fCacheMatrixOrig.AddAtAndExpand(morig,idx);
+ }
+ //
+ if (fConvertPreDeltas) {
+ // in order to convert deltas from old to new geometry we need the final matrices for all alignable objects
+ int nmat = fGeoManager->GetNAlignable();
+ fConvAlgMatOld.Delete();
+ int nmatSel = 0;
+ for (int i=0;i<nmat;i++) {
+ TString nm = fGeoManager->GetAlignableEntry(i)->GetName();
+ if (!nm.BeginsWith("ITS")) continue;
+ TGeoHMatrix *mo = new TGeoHMatrix();
+ (*mo) = *(AliGeomManager::GetMatrix(nm));
+ fConvAlgMatOld.AddAtAndExpand(mo,nmatSel++);
+ mo->SetTitle(nm);
+ mo->SetName(nm);
+ }
+ ConvSortHierarchically(fConvAlgMatOld);
+ }
+ //
+ TGeoHMatrix *mcurr = new TGeoHMatrix();
+ fCacheMatrixOrig.AddAtAndExpand(mcurr,kVtxSensID); // special unit matrix for diamond constraint
+ //
+ fCacheMatrixOrig.SetOwner(kTRUE);
+
+ fUsePreAlignment = 0;
+ LoadGeometry(fGeometryPath); // reload target geometry
+ //
+ return 0;
+}
+
+//________________________________________________________________________________________________________
+void AliITSAlignMille2::RemoveHelixFitConstraint()
+{
+ // suppress constraint
+ fConstrCharge = 0;
+ fConstrPT = fConstrPTErr = -1;
+}
+
+//________________________________________________________________________________________________________
+void AliITSAlignMille2::ConstrainHelixFitPT(Int_t q,Double_t pt,Double_t pterr)
+{
+ // constrain q and pT of the helical fit of the track (should be set before process.track)
+ //
+ fConstrCharge = q==0 ? q:TMath::Sign(1,q);
+ fConstrPT = pt;
+ fConstrPTErr = pterr;
+ fCurvFitWasConstrained = kTRUE;
+}
+
+//________________________________________________________________________________________________________
+void AliITSAlignMille2::ConstrainHelixFitCurv(Int_t q,Double_t crv,Double_t crverr)
+{
+ // constrain charge and curvature of the helical fit of the track (should be set before process.track)
+ //
+ const double kCQConv = 0.299792458e-3;// R = PT/Bz/fgkCQConv with GeV,kGauss,cm
+
+ fConstrCharge = q==0 ? q:TMath::Sign(1,q);
+ if (crv<0 || IsZero(crv)) {
+ fConstrPT = -1;
+ fConstrPTErr = -1;
+ fCurvFitWasConstrained = kFALSE;
+ }
+ else {
+ fConstrPT = TMath::Abs(1./crv*fBField*kCQConv);
+ fConstrPTErr = crverr>1e-10 ? TMath::Abs(fConstrPT/crv*crverr) : 0.;
+ fCurvFitWasConstrained = kTRUE;
+ }
+}
+
+//________________________________________________________________________________________________________
+TClonesArray* AliITSAlignMille2::CreateDeltas()
+{
+ // Create \Deltas for every explicitly or implicitly (via non-alignable volumes) varied
+ // or prealigned module.
+ // If the module has inded J in the hierarchy of alignable volumes (0 - the top, most
+ // coarse level), then its Delta is expressed via MP2 \deltas (in global frame) and
+ // prealignment \DeltaP's as:
+ // \Delta_J = Y X Y^-1
+ // where X = \delta_J * \DeltaP_J
+ // Y = Prod_{K=0,J-1} \delta_K
+ // Note that \delta_L accounts not only for its own correction but also of all non-alignable
+ // modules in the hierarchy chain from L up to the closest alignable:
+ // while (parent && !parent->IsAlignable()) {
+ // \delta_L->MultiplyLeft( \delta_parent );
+ // parent = parent->GetParent();
+ // }
+ //
+ Bool_t convLoc = kFALSE;
+ if (!GetUseGlobalDelta()) {
+ ConvertParamsToGlobal();
+ convLoc = kTRUE;
+ }
+ //
+ AliAlignObjParams tempAlignObj;
+ TGeoHMatrix tempMatX,tempMatY,tempMat1;
+ //
+ TClonesArray *array = new TClonesArray("AliAlignObjParams",10);
+ TClonesArray &alobj = *array;
+ int idx = 0;
+ //
+ TGeoManager* geoManager = AliGeomManager::GetGeometry();
+ int nalgtot = geoManager->GetNAlignable();
+ //
+ for (int ialg=0;ialg<nalgtot;ialg++) { // loop over all alignable entries
+ //
+ const char* algname = geoManager->GetAlignableEntry(ialg)->GetName();
+ //
+ AliITSAlignMille2Module* md = GetMilleModuleBySymName(algname); // explicitly varied?
+ AliITSAlignMille2Module* parent = md ? md->GetParent(): GetMilleModuleIfContained(algname);
+ if (md && parent) {
+ TString mdName = md->GetName();
+ TString prName = parent->GetName();
+ // SPD Sector -> Layer parentship is fake, need special treatment
+ if ( mdName.CountChar('/')==2 && mdName.BeginsWith("ITS/SPD") && // SPD sector
+ prName.CountChar('/')==1 && mdName.BeginsWith("ITS/SPD") ) // SPD Layer
+ parent = parent->GetParent();//: GetMilleModuleIfContained(prName.Data());
+ }
+ //
+ AliAlignObjParams* preob = GetPrealignedObject(algname); // was it prealigned ?
+ //
+ if (!preob && !md && (!parent || parent->IsAlignable())) continue; // noting to do
+ //
+ // create matrix X (see comment) ------------------------------------------------->>>
+ // start from unity matrix
+ tempMatX.Clear();
+ if (preob) { // account prealigngment
+ preob->GetMatrix(tempMat1);
+ tempMatX.MultiplyLeft(&tempMat1);
+ }
+ //
+ if (md) {
+ tempAlignObj.SetTranslation( md->GetParVal(0),md->GetParVal(1),md->GetParVal(2));
+ tempAlignObj.SetRotation( md->GetParVal(3),md->GetParVal(4),md->GetParVal(5));
+ tempAlignObj.GetMatrix(tempMat1);
+ tempMatX.MultiplyLeft(&tempMat1); // acount correction to varied module
+ }
+ //
+ // the corrections to all non-alignable modules from current on
+ // till first alignable should add up to its matrix
+ while (parent && !parent->IsAlignable()) {
+ tempAlignObj.SetTranslation( parent->GetParVal(0),parent->GetParVal(1),parent->GetParVal(2));
+ tempAlignObj.SetRotation( parent->GetParVal(3),parent->GetParVal(4),parent->GetParVal(5));
+ tempAlignObj.GetMatrix(tempMat1);
+ tempMatX.MultiplyLeft(&tempMat1); // add matrix of non-alignable module
+ parent = parent->GetParent();
+ }
+ // create matrix X (see comment) ------------------------------------------------<<<
+ //
+ // create matrix Y (see comment) ------------------------------------------------>>>
+ // start from unity matrix
+ tempMatY.Clear();
+ while ( parent ) {
+ tempAlignObj.SetTranslation( parent->GetParVal(0),parent->GetParVal(1),parent->GetParVal(2));
+ tempAlignObj.SetRotation( parent->GetParVal(3),parent->GetParVal(4),parent->GetParVal(5));
+ tempAlignObj.GetMatrix(tempMat1);
+ tempMatY.MultiplyLeft(&tempMat1);
+ parent = parent->GetParent();
+ }
+ // create matrix Y (see comment) ------------------------------------------------<<<
+ //
+ tempMatX.MultiplyLeft(&tempMatY);
+ tempMatX.Multiply(&tempMatY.Inverse());
+ //
+ if (tempMatX.IsIdentity()) continue; // do not store dummy matrices
+ UShort_t vid = AliITSAlignMille2Module::GetVolumeIDFromSymname(algname);
+ new(alobj[idx++]) AliAlignObjParams(algname,vid,tempMatX,kTRUE);
+ //
+ }
+ //
+ if (convLoc) ConvertParamsToLocal();
+ //
+ return array;
+ //
+}
+
+//_______________________________________________________________________________________
+AliITSresponseSDD* AliITSAlignMille2::CreateSDDResponse()
+{
+ // create object with SDD repsonse (t0 and vdrift corrections) accounting for
+ // eventual precalibration
+ //
+ // if there was a precalibration provided, copy it to new arrray
+ AliITSresponseSDD *precal = GetSDDPrecalResp();
+ if (!precal && fIniVDriftSDD) precal = GetSDDInitResp(); // InitResp is used only when IniVDrift is provided
+ Bool_t isPreCalMult = precal&&precal->IsVDCorrMult() ? kTRUE : kFALSE;
+ AliITSresponseSDD *calibSDD = new AliITSresponseSDD();
+ calibSDD->SetVDCorrMult(fIsSDDVDriftMult);
+ //
+ // copy initial values to the new object
+ if (precal) {
+ calibSDD->SetTimeOffset(precal->GetTimeOffset());
+ calibSDD->SetADC2keV(precal->GetADC2keV());
+ calibSDD->SetChargevsTime(precal->GetChargevsTime());
+ for (int ind=kSDDoffsID;ind<kSDDoffsID+kNSDDmod;ind++) {
+ calibSDD->SetModuleTimeZero(ind, precal->GetTimeZero(ind));
+ calibSDD->SetDeltaVDrift(ind, precal->GetDeltaVDrift(ind,kFALSE),kFALSE); // left
+ calibSDD->SetDeltaVDrift(ind, precal->GetDeltaVDrift(ind,kTRUE ),kTRUE); // right
+ calibSDD->SetADCtokeV(ind,precal->GetADCtokeV(ind));
+ }
+ }
+ else for (int ind=kSDDoffsID;ind<kSDDoffsID+kNSDDmod;ind++) calibSDD->SetModuleTimeZero(ind,0);
+ //
+ Bool_t save = kFALSE;
+ for (int imd=GetNModules();imd--;) {
+ AliITSAlignMille2Module* md = GetMilleModule(imd);
+ if (!md->IsSDD()) continue;
+ if (md->IsFreeDOF(AliITSAlignMille2Module::kDOFT0) ||
+ md->IsFreeDOF(AliITSAlignMille2Module::kDOFDVL) ||
+ md->IsFreeDOF(AliITSAlignMille2Module::kDOFDVR)) save = kTRUE;
+ //
+ for (int is=0;is<md->GetNSensitiveVolumes();is++) {
+ int ind = md->GetSensVolIndex(is);
+ float t0 = calibSDD->GetTimeZero(ind) + md->GetParVal(AliITSAlignMille2Module::kDOFT0);
+ double dvL = md->GetParVal(AliITSAlignMille2Module::kDOFDVL);
+ double dvR = md->GetParVal(AliITSAlignMille2Module::kDOFDVR);
+ if (!calibSDD->IsVDCorrMult()) { // save as additive correction
+ dvL *= 1e4;
+ dvR *= 1e4;
+ //
+ double conv = 1;
+ if (isPreCalMult) conv = 6.4; // convert multiplicative precal correction to additive
+ dvL += calibSDD->GetDeltaVDrift(ind,kFALSE)*conv;
+ dvR += calibSDD->GetDeltaVDrift(ind,kTRUE)*conv;
+ }
+ else { // save as multipicative correction
+ double conv = 1;
+ if (!isPreCalMult) conv = 1./6.4; // convert additive precal correction to multiplicative
+ dvL += calibSDD->GetDeltaVDrift(ind,kFALSE)*conv;
+ dvR += calibSDD->GetDeltaVDrift(ind,kTRUE)*conv;
+ }
+ //
+ calibSDD->SetModuleTimeZero(ind, t0);
+ calibSDD->SetDeltaVDrift(ind, dvL, kFALSE); // left side correction
+ calibSDD->SetDeltaVDrift(ind, dvR, kTRUE); // right side correction
+ }
+ }
+ //
+ if (!save) {
+ AliInfo("No free parameters for SDD calibration, nothing to save");
+ delete calibSDD;
+ calibSDD = 0;
+ }
+ //
+ return calibSDD;
+}
+
+//_______________________________________________________________________________________
+Int_t AliITSAlignMille2::ReloadInitCalib(TList *userInfo)
+{
+ // Use provided UserInfo to
+ // load the initial calib parameters (geometry, SDD response...)
+ // Can be used if set of data was processed with different calibration
+ //
+ if (!userInfo) {
+ AliInfo("Reloading of the Calibration parameters was called with empty userInfo");
+ return 1;
+ }
+ if (ProcessUserInfo(userInfo)) {
+ AliInfo("Error in processing user info");
+ userInfo->Print();
+ exit(1);
+ }
+ return ReloadInitCalib();
+}
+
+//_______________________________________________________________________________________
+Int_t AliITSAlignMille2::ReloadInitCalib()
+{
+ // Load the initial calib parameters (geometry, SDD response...)
+ // Can be used if set of data was processed with different calibration
+ //
+ AliInfo(Form("SameInitDelta: %d | SameInitGeom: %d",TestBit(kSameInitDeltasBit), TestBit(kSameInitGeomBit)));
+ // 1st cache original matrices
+ if (!(TestBit(kSameInitDeltasBit) && TestBit(kSameInitGeomBit))) { // need to reload geometry
+ //
+ if (CacheMatricesOrig()) {
+ AliInfo("Failed to cache new initial geometry");
+ exit(1);
+ }
+ // RS : commented because we don't need to reload prealignment deltas, they are already loaded
+ // then reload the prealignment geometry
+ // if (LoadDeltas(fPreDeltaPath,fPrealignment)) {
+ // AliInfo(Form("Failed to reload the prealigned geometry %s",fPreDeltaPath.Data()));
+ // exit(1);
+ // }
+ //
+ if (fPrealignment && ApplyToGeometry()) {
+ AliInfo(Form("Failed re-apply prealigned geometry %s",fPreDeltaPath.Data()));
+ exit(1);
+ }
+ //
+ // usually no need to re-cache the prealignment geometry, it was not changed
+ if (fCacheMatrixCurr.GetEntriesFast() != fCacheMatrixOrig.GetEntriesFast()) {
+ // CacheMatricesCurr();
+ AliInfo(Form("Failed to cache the prealigned geometry %s",fPreDeltaPath.Data()));
+ exit(1);
+ }
+ }
+ else ResetBit(kSameInitDeltasBit);
+ //
+ // reload initial SDD response
+ if (!TestBit(kSameInitSDDRespBit)) {
+ if (LoadSDDResponse(fIniSDDRespPath, fIniRespSDD) ) {
+ AliInfo(Form("Failed to load new SDD response %s",fIniSDDRespPath.Data()));
+ exit(1);
+ }
+ }
+ else ResetBit(kSameInitSDDRespBit);
+ //
+ // reload initial SDD vdrift
+ if (!TestBit(kSameInitSDDVDriftBit)) {
+ if (LoadSDDVDrift(fIniSDDVDriftPath, fIniVDriftSDD) ) {
+ AliInfo(Form("Failed to load new SDD VDrift %s",fIniSDDVDriftPath.Data()));
+ exit(1);
+ }
+ }
+ else ResetBit(kSameInitSDDRespBit);
+ //
+ // reload SDD corr.map
+ if (!TestBit(kSameInitSDDCorrMapBit)) {
+ if (LoadSDDCorrMap(fIniSDDCorrMapPath, fIniCorrMapSDD) ) {
+ AliInfo(Form("Failed to load new SDD Correction Map %s",fIniSDDCorrMapPath.Data()));
+ exit(1);
+ }
+ }
+ else ResetBit(kSameInitSDDRespBit);
+ //
+ // reload diamond info
+ if (!TestBit(kSameDiamondBit)) {
+ if (LoadDiamond(fDiamondPath) ) {
+ AliInfo(Form("Failed to load new Diamond constraint %s",fDiamondPath.Data()));
+ exit(1);
+ }
+ }
+ else ResetBit(kSameInitSDDRespBit);
+ //
+ return 0;
+}
+
+//_______________________________________________________________________________________
+void AliITSAlignMille2::JacobianPosGloLoc(int locid,double* jacobian)
+{
+ // calculate the locid row of the jacobian for transformation of the local coordinate to global at current point
+ TGeoHMatrix* mat = GetSensorCurrMatrixSID(fCurrentSensID);
+ const Double_t dpar = 1e-2;
+ double sav = fMeasLoc[locid];
+ fMeasLoc[locid] += dpar;
+ mat->LocalToMaster(fMeasLoc,jacobian);
+ fMeasLoc[locid] = sav; // recover original value
+ for (int i=3;i--;) jacobian[i] = (jacobian[i]-fMeasGlo[i])/dpar; // the transformation is linear!!!
+}
+
+//_______________________________________________________________________________________
+void AliITSAlignMille2::TieSDDVDriftsLR(AliITSAlignMille2Module* mod)
+{
+ // impose equality of Left/Right sides VDrift correction for SDD
+ ResetLocalEquation();
+ if ( (mod->IsFreeDOF(AliITSAlignMille2Module::kDOFDVL) + mod->IsFreeDOF(AliITSAlignMille2Module::kDOFDVR))==1) {
+ AliError("Left/Right VDrift equality is requested for SDD module with only one side VDrift free");
+ mod->Print();
+ return;
+ }
+ if (mod->GetParOffset(AliITSAlignMille2Module::kDOFDVL)>=0) SetGlobalDerivative(mod->GetParOffset(AliITSAlignMille2Module::kDOFDVL), 1.);
+ if (mod->GetParOffset(AliITSAlignMille2Module::kDOFDVR)>=0) SetGlobalDerivative(mod->GetParOffset(AliITSAlignMille2Module::kDOFDVR), -1.);
+ AddConstraint(fGlobalDerivatives, 0, 1e-12);
+ //
+}
+
+//_______________________________________________________________________________________
+void AliITSAlignMille2::ProcessSDDPointInfo(const AliTrackPoint* pnt,Int_t sID, Int_t pntID)
+{
+ // extract the drift information from SDD track point
+ //
+ fDriftTime0[pntID] = fIniRespSDD ? fIniRespSDD->GetTimeZero(sID) : 0.;
+ double tdif = pnt->GetDriftTime() - fDriftTime0[pntID];
+ if (tdif<0) tdif = 1;
+ //
+ // VDrift extraction
+ double vdrift=0,vdrift0=0;
+ Bool_t sddSide = kFALSE;
+ int sID0 = 2*(sID-kSDDoffsID);
+ double zanode = -999;
+ //
+ if (fIniVDriftSDD) { // SDD VDrift object is provided, use the vdrift from it
+ AliITSDriftSpeedArraySDD* drarr;
+ double vdR,vdL,xlR,xlL;
+ // sometimes xlocal on right side is negative due to the wrong calibration, need to test both hypothesis
+ double xlabs = TMath::Abs(fMeasLoc[kX]);
+ drarr = (AliITSDriftSpeedArraySDD*)fIniVDriftSDD->At(sID0); // left side, xloc>0
+ zanode = fSegmentationSDD->GetAnodeFromLocal(xlabs,fMeasLoc[kZ]);
+ vdL = drarr->GetDriftSpeed(0, zanode);
+ if (fIniRespSDD) {
+ double corr = fIniRespSDD->GetDeltaVDrift(sID, kFALSE);
+ if (fIniRespSDD->IsVDCorrMult()) vdL *= (1+corr);
+ else vdL += corr;
+ }
+ xlL = (fSegmentationSDD->Dx() - vdL*tdif)*1e-4;
+ //
+ drarr = (AliITSDriftSpeedArraySDD*)fIniVDriftSDD->At(sID0+1); // right side, xloc<0
+ zanode = fSegmentationSDD->GetAnodeFromLocal(-xlabs,fMeasLoc[kZ]) - 256;
+ vdR = drarr->GetDriftSpeed(0, zanode);
+ if (fIniRespSDD) {
+ double corr = fIniRespSDD->GetDeltaVDrift(sID, kTRUE);
+ if (fIniRespSDD->IsVDCorrMult()) vdR *= (1+corr);
+ else vdR += corr;
+ }
+ xlR = -(fSegmentationSDD->Dx() - vdR*tdif)*1e-4;
+ //
+ if (TMath::Abs(xlL-fMeasLoc[kX])<TMath::Abs(xlR-fMeasLoc[kX])) {
+ sddSide = 0; // left side
+ vdrift = vdL*1e-4;
+ }
+ else { // right side
+ sddSide = 1;
+ vdrift = vdR*1e-4;
+ }
+ //
+ }
+ else { // try to determine the vdrift from the xloc
+ vdrift = (fSegmentationSDD->Dx()*1e-4 - TMath::Abs(fMeasLoc[kX]))/tdif;
+ sddSide = fMeasLoc[kX]<0; // 0 = left (xloc>0) ; 1 = right (xloc<1)
+ }
+ //
+ if (fPreVDriftSDD) { // use imposed vdrift as a starting point
+ zanode = fSegmentationSDD->GetAnodeFromLocal(0.5-sddSide,fMeasLoc[kZ]);
+ if (sddSide) zanode -= 256;
+ vdrift = ((AliITSDriftSpeedArraySDD*)fPreVDriftSDD->At(sID0+sddSide))->GetDriftSpeed(0, zanode)*1e-4;
+ }
+ //
+ if (vdrift<0) vdrift = 0;
+ vdrift0 = vdrift;
+ // at this point we have vdrift and t0 used to create the original point.
+ // see if precalibration was provided
+ if (fPreRespSDD) {
+ float t0Upd = fPreRespSDD->GetTimeZero(sID);
+ double corr = fPreRespSDD->GetDeltaVDrift(sID, sddSide);
+ if (fPreRespSDD->IsVDCorrMult()) vdrift *= 1+corr; // right side (xloc<0) may have different correction
+ else vdrift += corr*1e-4;
+ //
+ // if IniRespSDD was used, it should be subtracted back, since it is accounted in the PreResp
+ if (fIniVDriftSDD&&fIniRespSDD && (fPreVDriftSDD==0)) {
+ double corr1 = fIniRespSDD->GetDeltaVDrift(sID, sddSide);
+ if (fIniRespSDD->IsVDCorrMult()) vdrift *= (1-corr1);
+ else vdrift -= corr1*1e-4;
+ }
+ tdif = pnt->GetDriftTime() - t0Upd;
+ // correct Xlocal
+ fMeasLoc[0] = fSegmentationSDD->Dx()*1e-4 - vdrift*tdif;
+ if (sddSide) fMeasLoc[0] = -fMeasLoc[0];
+ fDriftTime0[pntID] = t0Upd;
+ }
+ //
+ if (fPreCorrMapSDD) { // apply correction map
+ fMeasLoc[0] += fPreCorrMapSDD->GetCorrection(sID,fMeasLoc[2],fMeasLoc[0]);
+ }
+
+ // TEMPORARY CORRECTION (if provided) --------------<<<
+ fDriftSpeed[pntID] = sddSide ? -vdrift : vdrift;
+ fDriftSpeed0[pntID] = sddSide ? -vdrift0 : vdrift0;
+ //
+ // printf("#%d: t:%+e x:%+e v:%+e: side:%d\n",pntID,fDriftTime0[pntID],fMeasLoc[0],fDriftSpeed[pntID],sddSide);
+}
+
+//_______________________________________________________________________________________
+AliITSAlignMille2Module* AliITSAlignMille2::CreateVertexModule()
+{
+ // creates dummy module for vertex constraint
+ TGeoHMatrix mt;
+ AliITSAlignMille2Module* mod = new AliITSAlignMille2Module(kVtxSensID,kVtxSensVID,"VTX",&mt,0,0);
+ fMilleModule.AddAtAndExpand(mod,fNModules);
+ mod->SetGeomParamsGlobal(fUseGlobalDelta);
+ fDiamondModID = fNModules;
+ mod->SetUniqueID(fNModules++);
+ mod->SetNotInConf(kTRUE);
+ return mod;
+ //
+}
+
+//_______________________________________________________________________________________
+AliCDBEntry* AliITSAlignMille2::GetCDBEntry(const char* path)
+{
+ // return object from the OCDB
+ AliCDBEntry *entry = 0;
+ AliInfo(Form("Loading object %s",path));
+ AliCDBManager* man = AliCDBManager::Instance();
+ AliCDBId* cdbId = AliCDBId::MakeFromString(path);
+ if (!cdbId) {
+ AliError("Failed to create cdbId");
+ return 0;
+ }
+ //
+ AliCDBStorage* stor = man->GetDefaultStorage();
+ if (!stor && !man->GetRaw()) man->SetDefaultStorage("raw://");
+ if (man->GetRaw()) man->SetRun(fRunID>0 ? fRunID : cdbId->GetFirstRun());
+ if (stor) {
+ TString tp = stor->GetType();
+ if (tp.Contains("alien",TString::kIgnoreCase) && !gGrid) TGrid::Connect("alien:");
+ }
+ entry = man->Get(cdbId->GetPath(),cdbId->GetFirstRun(),cdbId->GetVersion(),cdbId->GetSubVersion());
+ // entry = man->Get( *cdbId );
+ man->ClearCache();
+ //
+ delete cdbId;
+ return entry;
+ //
+}