+
+ // exclude tracks at boundary between detectors
+ //Double_t boundaryWidth=AliITSRecoParam::GetBoundaryWidthPlaneEff();
+ Double_t boundaryWidth=0; // for the time being hard-wired, later on from AliITSRecoParam
+ AliDebug(2,Form("Tracking: track impact x=%f, y=%f, z=%f",tmp.GetX(), tmp.GetY(), tmp.GetZ()));
+ AliDebug(2,Form("Local: track impact x=%f, z=%f",locx,locz));
+ AliDebug(2,Form("Search Road. Tracking: dy=%f , dz=%f",dx,dz));
+ if ( (locx-dx < blockXmn+boundaryWidth) ||
+ (locx+dx > blockXmx-boundaryWidth) ||
+ (locz-dz < blockZmn+boundaryWidth) ||
+ (locz+dz > blockZmx-boundaryWidth) ) return kFALSE;
+
+ if(ilayer==0){
+ const AliESDEvent *myesd = ((AliESDtrack*)tmp.GetESDtrack())->GetESDEvent();
+ //The beam pipe
+ if (CorrectForPipeMaterial(&tmp,"inward")) {
+ const AliESDVertex* vtx = myesd->GetVertex();
+ if(!vtx) return kFALSE;
+ Double_t ddz[2],cov[3];
+ Double_t maxD=3.;
+ if(!tmp.PropagateToDCA(vtx,AliTracker::GetBz(),maxD,ddz,cov)) return kFALSE;
+ if(TMath::Abs(ddz[0])>=AliITSReconstructor::GetRecoParam()->GetDCACutPlaneEff()) return kFALSE;
+
+ Double_t covar[6]; vtx->GetCovMatrix(covar);
+ Double_t p[2]={tmp.GetParameter()[0]-ddz[0],tmp.GetParameter()[1]-ddz[1]};
+ Double_t c[3]={covar[2],0.,covar[5]};
+ Double_t chi2= ((AliESDtrack*)tmp.GetESDtrack())->GetPredictedChi2(p,c);
+ if (chi2>AliITSReconstructor::GetRecoParam()->GetVertexChi2CutPlaneEff()) return kFALSE; // Use this to cut on chi^2
+
+ } else return kFALSE;
+ }
+
+
+ return kTRUE;
+}
+//------------------------------------------------------------------------
+void AliITStrackerMI::UseTrackForPlaneEff(const AliITStrackMI* track, Int_t ilayer) {
+//
+// This Method has to be optimized! For the time-being it uses the same criteria
+// as those used in the search of extra clusters for overlapping modules.
+//
+// Method Purpose: estabilish whether a track has produced a recpoint or not
+// in the layer under study (For Plane efficiency)
+//
+// inputs: AliITStrackMI* track (pointer to a usable track)
+// outputs: none
+// side effects: update (by 1 count) the Plane Efficiency statistics of the basic block
+// traversed by this very track. In details:
+// - if a cluster can be associated to the track then call
+// AliITSPlaneEff::UpDatePlaneEff(key,kTRUE);
+// - if not, the AliITSPlaneEff::UpDatePlaneEff(key,kFALSE) is called
+//
+ if(!fPlaneEff)
+ {AliWarning("UseTrackForPlaneEff: null pointer to AliITSPlaneEff"); return;}
+ AliITSlayer &layer=fgLayers[ilayer];
+ Double_t r=layer.GetR();
+ AliITStrackMI tmp(*track);
+
+// detector number
+ Double_t phi,z;
+ if (!tmp.GetPhiZat(r,phi,z)) return;
+ Int_t idet=layer.FindDetectorIndex(phi,z);
+
+ if(idet<0) { AliInfo(Form("cannot find detector"));
+ return;}
+
+
+//propagate to the intersection with the detector plane
+ const AliITSdetector &det=layer.GetDetector(idet);
+ if (!tmp.Propagate(det.GetPhi(),det.GetR())) return;
+
+
+//***************
+// DEFINITION OF SEARCH ROAD FOR CLUSTERS SELECTION
+//
+ Double_t dz=AliITSReconstructor::GetRecoParam()->GetNSigmaRoadZ()*
+ TMath::Sqrt(tmp.GetSigmaZ2() +
+ AliITSReconstructor::GetRecoParam()->GetNSigmaZLayerForRoadZ()*
+ AliITSReconstructor::GetRecoParam()->GetNSigmaZLayerForRoadZ()*
+ AliITSReconstructor::GetRecoParam()->GetSigmaZ2(ilayer));
+ Double_t dy=AliITSReconstructor::GetRecoParam()->GetNSigmaRoadY()*
+ TMath::Sqrt(tmp.GetSigmaY2() +
+ AliITSReconstructor::GetRecoParam()->GetNSigmaYLayerForRoadY()*
+ AliITSReconstructor::GetRecoParam()->GetNSigmaYLayerForRoadY()*
+ AliITSReconstructor::GetRecoParam()->GetSigmaY2(ilayer));
+
+// road in global (rphi,z) [i.e. in tracking ref. system]
+ Double_t zmin = tmp.GetZ() - dz;
+ Double_t zmax = tmp.GetZ() + dz;
+ Double_t ymin = tmp.GetY() + r*det.GetPhi() - dy;
+ Double_t ymax = tmp.GetY() + r*det.GetPhi() + dy;
+
+// select clusters in road
+ layer.SelectClusters(zmin,zmax,ymin,ymax);
+
+// Define criteria for track-cluster association
+ Double_t msz = tmp.GetSigmaZ2() +
+ AliITSReconstructor::GetRecoParam()->GetNSigmaZLayerForRoadZ()*
+ AliITSReconstructor::GetRecoParam()->GetNSigmaZLayerForRoadZ()*
+ AliITSReconstructor::GetRecoParam()->GetSigmaZ2(ilayer);
+ Double_t msy = tmp.GetSigmaY2() +
+ AliITSReconstructor::GetRecoParam()->GetNSigmaYLayerForRoadY()*
+ AliITSReconstructor::GetRecoParam()->GetNSigmaYLayerForRoadY()*
+ AliITSReconstructor::GetRecoParam()->GetSigmaY2(ilayer);
+ if (tmp.GetConstrain()) {
+ msz *= AliITSReconstructor::GetRecoParam()->GetNSigma2RoadZC();
+ msy *= AliITSReconstructor::GetRecoParam()->GetNSigma2RoadYC();
+ } else {
+ msz *= AliITSReconstructor::GetRecoParam()->GetNSigma2RoadZNonC();
+ msy *= AliITSReconstructor::GetRecoParam()->GetNSigma2RoadYNonC();
+ }
+
+ if(AliITSReconstructor::GetRecoParam()->GetSwitchOffStdSearchClusPlaneEff()){
+ Double_t nsigx=AliITSReconstructor::GetRecoParam()->GetNSigXSearchClusterPlaneEff();
+ Double_t nsigz=AliITSReconstructor::GetRecoParam()->GetNSigZSearchClusterPlaneEff();
+ Double_t distx=AliITSReconstructor::GetRecoParam()->GetDistXSearchClusterPlaneEff();
+ Double_t distz=AliITSReconstructor::GetRecoParam()->GetDistZSearchClusterPlaneEff();
+ msy = nsigx*TMath::Sqrt(tmp.GetSigmaY2()) + distx;
+ msz = nsigz*TMath::Sqrt(tmp.GetSigmaZ2()) + distz;
+
+ if(AliITSReconstructor::GetRecoParam()->GetSwitchOnMaxDistNSigSrhClusPlaneEff()){
+ if(nsigx*TMath::Sqrt(tmp.GetSigmaY2())<=distx) msy -= nsigx*TMath::Sqrt(tmp.GetSigmaY2());
+ else msy -= distx;
+
+ if(nsigz*TMath::Sqrt(tmp.GetSigmaZ2())<=distz) msz -= nsigz*TMath::Sqrt(tmp.GetSigmaZ2());
+ else msz -= distz;
+ }
+
+ msy *= msy;
+ msz *= msz;
+
+ }
+
+ if(msz==0 || msy==0){AliWarning("UseTrackForPlaneEff: null search frame"); return;}
+
+ msz = 1./msz; // 1/RoadZ^2
+ msy = 1./msy; // 1/RoadY^2
+
+ const AliITSRecPoint *cl=0; Int_t clidx=-1, ci=-1;
+ Int_t idetc=-1;
+ Double_t chi2trkcl=1000.*AliITSReconstructor::GetRecoParam()->GetMaxChi2();
+ //Double_t tolerance=0.2;
+ /*while ((cl=layer.GetNextCluster(clidx))!=0) {
+ idetc = cl->GetDetectorIndex();
+ if(idet!=idetc) continue;
+ //Int_t ilay = cl->GetLayer();
+
+ if (TMath::Abs(tmp.GetZ() - cl->GetZ()) > tolerance) continue;
+ if (TMath::Abs(tmp.GetY() - cl->GetY()) > tolerance) continue;
+
+ Double_t chi2=tmp.GetPredictedChi2(cl);
+ if (chi2<chi2trkcl) { chi2trkcl=chi2; ci=clidx; }
+ }*/
+ Float_t locx; //
+ Float_t locz; //
+ if(!LocalModuleCoord(ilayer,idet,&tmp,locx,locz)) return;
+//
+ AliDebug(2,Form("ilayer= %d, idet=%d, x= %f, z=%f",ilayer,idet,locx,locz));
+ UInt_t key=fPlaneEff->GetKeyFromDetLocCoord(ilayer,idet,locx,locz);
+ if(key>fPlaneEff->Nblock()) return;
+ Bool_t found=kFALSE;
+ //if (ci>=0) {
+ Double_t chi2;
+ while ((cl=layer.GetNextCluster(clidx))!=0) {
+ idetc = cl->GetDetectorIndex();
+ if(idet!=idetc) continue;
+ // here real control to see whether the cluster can be associated to the track.
+ // cluster not associated to track
+ if ( (tmp.GetZ()-cl->GetZ())*(tmp.GetZ()-cl->GetZ())*msz +
+ (tmp.GetY()-cl->GetY())*(tmp.GetY()-cl->GetY())*msy > 1. ) continue;
+ // calculate track-clusters chi2
+ chi2 = GetPredictedChi2MI(&tmp,cl,ilayer); // note that this method change track tmp
+ // in particular, the error associated to the cluster
+ //Double_t chi2 = tmp.GetPredictedChi(cl); // this method does not change track tmp
+ // chi2 cut
+ if (chi2 > AliITSReconstructor::GetRecoParam()->GetMaxChi2s(ilayer)) continue;
+ found=kTRUE;
+ if (chi2<chi2trkcl) { chi2trkcl=chi2; ci=clidx; } // this just to trace which cluster is selected
+ // track->SetExtraCluster(ilayer,(ilayer<<28)+ci);
+ // track->SetExtraModule(ilayer,idetExtra);
+ }
+ if(!fPlaneEff->UpDatePlaneEff(found,key))
+ AliWarning(Form("UseTrackForPlaneEff: cannot UpDate PlaneEff for key=%d",key));
+
+// this for FO efficiency studies (only for SPD) //
+ UInt_t keyFO=999999;
+ Bool_t foundFO=kFALSE;
+ if(ilayer<2){ //ONLY SPD layers for FastOr studies
+ TBits mapFO = fkDetTypeRec->GetFastOrFiredMap();
+ Int_t phase = (fEsd->GetBunchCrossNumber())%4;
+ if(!fSPDChipIntPlaneEff[key]){
+ AliITSPlaneEffSPD spd;
+ keyFO = spd.SwitchChipKeyNumbering(key);
+ if(mapFO.TestBitNumber(keyFO))foundFO=kTRUE;
+ keyFO = key + (AliITSPlaneEffSPD::kNModule*AliITSPlaneEffSPD::kNChip)*(phase+1);
+ if(keyFO<AliITSPlaneEffSPD::kNModule*AliITSPlaneEffSPD::kNChip) {
+ AliWarning(Form("UseTrackForPlaneEff: too small keyF0 (= %d), setting it to 999999",keyFO));
+ keyFO=999999;
+ }
+ if(!fPlaneEff->UpDatePlaneEff(foundFO,keyFO))
+ AliWarning(Form("UseTrackForPlaneEff: cannot UpDate PlaneEff for FastOR for key=%d",keyFO));
+ }