// @(#) $Id$ // Author: Anders Vestbo //*-- Copyright © ALICE HLT Group #include "AliL3StandardIncludes.h" #include "AliL3Logging.h" #include "AliL3ClusterFitter.h" #include "AliL3FitUtilities.h" #include "AliL3DigitData.h" #include "AliL3ModelTrack.h" #include "AliL3TrackArray.h" #include "AliL3MemHandler.h" #include "AliL3HoughTrack.h" #include "AliL3SpacePointData.h" #include "AliL3Compress.h" #if GCCVERSION == 3 using namespace std; #endif //_____________________________________________________________ // // AliL3ClusterFitter // ClassImp(AliL3ClusterFitter) Int_t AliL3ClusterFitter::fBadFitError=0; Int_t AliL3ClusterFitter::fFitError=0; Int_t AliL3ClusterFitter::fResultError=0; Int_t AliL3ClusterFitter::fFitRangeError=0; AliL3ClusterFitter::AliL3ClusterFitter() { plane=0; fNmaxOverlaps = 3; fChiSqMax=12; fRowMin=-1; fRowMax=-1; fFitted=0; fFailed=0; fYInnerWidthFactor=1; fZInnerWidthFactor=1; fYOuterWidthFactor=1; fZOuterWidthFactor=1; fSeeds=0; fProcessTracks=0; fClusters=0; fNMaxClusters=0; fNClusters=0; } AliL3ClusterFitter::AliL3ClusterFitter(Char_t *path) { strcpy(fPath,path); plane=0; fNmaxOverlaps = 3; fChiSqMax=12; fRowMin=-1; fRowMax=-1; fFitted=0; fFailed=0; fYInnerWidthFactor=1; fZInnerWidthFactor=1; fYOuterWidthFactor=1; fZOuterWidthFactor=1; fSeeds=0; fProcessTracks=0; fNMaxClusters=100000; fClusters=0; fNClusters=0; } AliL3ClusterFitter::~AliL3ClusterFitter() { if(fSeeds) delete fSeeds; if(fClusters) delete [] fClusters; } void AliL3ClusterFitter::Init(Int_t slice,Int_t patch,Int_t *rowrange,AliL3TrackArray *tracks) { //Assuming tracklets found by the line transform fSlice=slice; fPatch=patch; if(rowrange[0] > AliL3Transform::GetLastRow(patch) || rowrange[1] < AliL3Transform::GetFirstRow(patch)) cerr<<"AliL3ClusterFitter::Init : Wrong rows "< AliL3Transform::GetLastRow(fPatch)) fRowMax = AliL3Transform::GetLastRow(fPatch); fFitted=fFailed=0; Int_t ntimes = AliL3Transform::GetNTimeBins()+1; Int_t npads = AliL3Transform::GetNPads(AliL3Transform::GetLastRow(fPatch))+1;//Max num of pads. Int_t bounds = ntimes*npads; if(fRow) delete [] fRow; fRow = new Digit[bounds]; if(fTracks) delete fTracks; fTracks = new AliL3TrackArray("AliL3ModelTrack"); for(Int_t i=0; iGetNTracks(); i++) { AliL3HoughTrack *track = (AliL3HoughTrack*)tracks->GetCheckedTrack(i); if(!track) continue; AliL3ModelTrack *mtrack = (AliL3ModelTrack*)fTracks->NextTrack(); mtrack->Init(slice,patch); mtrack->SetTgl(track->GetTgl()); mtrack->SetRowRange(rowrange[0],rowrange[1]); for(Int_t j=fRowMin; j<=fRowMax; j++) { Float_t hit[3]; track->GetLineCrossingPoint(j,hit); hit[0] += AliL3Transform::Row2X(track->GetFirstRow()); Float_t R = sqrt(hit[0]*hit[0] + hit[1]*hit[1]); hit[2] = R*track->GetTgl(); Int_t se,ro; AliL3Transform::Slice2Sector(slice,j,se,ro); AliL3Transform::Local2Raw(hit,se,ro); if(hit[1]<0 || hit[1]>=AliL3Transform::GetNPads(j) || hit[2]<0 || hit[2]>=AliL3Transform::GetNTimeBins()) { mtrack->SetPadHit(j,-1); mtrack->SetTimeHit(j,-1); continue; } mtrack->SetPadHit(j,hit[1]); mtrack->SetTimeHit(j,hit[2]); mtrack->SetCrossingAngleLUT(j,fabs(track->GetPsiLine() - AliL3Transform::Pi()/2)); //if(mtrack->GetCrossingAngleLUT(j) > AliL3Transform::Deg2Rad(20)) // cout<<"Angle "<GetCrossingAngleLUT(j)<<" psiline "<GetPsiLine()*180/3.1415<CalculateClusterWidths(j); } } // cout<<"Copied "<GetNTracks()<<" tracks "<QSort(); Int_t clustercount=0; for(Int_t i=0; iGetNTracks(); i++) { AliL3ModelTrack *track = (AliL3ModelTrack*)fSeeds->GetCheckedTrack(i); if(!track) continue; if(!offline) { /* if(track->GetNHits() < 10 || track->GetPt() < 0.08) { fSeeds->Remove(i); continue; } */ } clustercount += track->GetNHits(); track->CalculateHelix(); Int_t nhits = track->GetNHits(); UInt_t *hitids = track->GetHitNumbers(); Int_t origslice = (hitids[nhits-1]>>25)&0x7f;//Slice of innermost point track->Init(origslice,-1); Int_t slice = origslice; //for(Int_t j=rowrange[1]; j>=rowrange[0]; j--) for(Int_t j=rowrange[0]; j<=rowrange[1]; j++) { //Calculate the crossing point between track and padrow Float_t angle = 0; //Perpendicular to padrow in local coordinates AliL3Transform::Local2GlobalAngle(&angle,slice); if(!track->CalculateReferencePoint(angle,AliL3Transform::Row2X(j))) { cerr<<"No crossing in slice "<Print(); //exit(5); } Float_t xyz_cross[3] = {track->GetPointX(),track->GetPointY(),track->GetPointZ()}; Int_t sector,row; AliL3Transform::Slice2Sector(slice,j,sector,row); AliL3Transform::Global2Raw(xyz_cross,sector,row); //cout<<"Examining slice "<= AliL3Transform::GetNPads(j)) //Track leaves the slice { newslice: Int_t tslice=slice; Float_t lastcross=xyz_cross[1]; if(xyz_cross[1] > 0) { if(slice == 17) slice=0; else if(slice == 35) slice = 18; else slice += 1; } else { if(slice == 0) slice = 17; else if(slice==18) slice = 35; else slice -= 1; } if(slice < 0 || slice>35) { cerr<<"Wrong slice "<CalculateReferencePoint(angle,AliL3Transform::Row2X(j))) { cerr<<"No crossing in slice "<Print(); //exit(5); } xyz_cross[0] = track->GetPointX(); xyz_cross[1] = track->GetPointY(); xyz_cross[2] = track->GetPointZ(); Int_t sector,row; AliL3Transform::Slice2Sector(slice,j,sector,row); AliL3Transform::Global2Raw(xyz_cross,sector,row); if(xyz_cross[1] < 0 || xyz_cross[1] >= AliL3Transform::GetNPads(j)) //track is in the borderline { if(xyz_cross[1] > 0 && lastcross > 0 || xyz_cross[1] < 0 && lastcross < 0) goto newslice; else { slice = tslice;//Track is on the border of two slices continue; } } } if(xyz_cross[2] < 0 || xyz_cross[2] >= AliL3Transform::GetNTimeBins())//track goes out of range continue; if(xyz_cross[1] < 0 || xyz_cross[1] >= AliL3Transform::GetNPads(j)) { cerr<<"Slice "<Print(); exit(5); } track->SetPadHit(j,xyz_cross[1]); track->SetTimeHit(j,xyz_cross[2]); angle=0; AliL3Transform::Local2GlobalAngle(&angle,slice); Float_t crossingangle = track->GetCrossingAngle(j,slice); track->SetCrossingAngleLUT(j,crossingangle); track->CalculateClusterWidths(j); track->GetClusterModel(j)->fSlice = slice; } memset(track->GetHitNumbers(),0,159*sizeof(UInt_t)); track->SetNHits(0); } fSeeds->Compress(); AliL3Compress *c = new AliL3Compress(-1,-1,fPath); c->WriteFile(fSeeds,"tracks_before.raw"); delete c; cout<<"Loaded "<GetNTracks()<<" seeds and "<fRow < fRowMin) { AliL3MemHandler::UpdateRowPointer(rowPt); continue; } else if((Int_t)rowPt->fRow > fRowMax) break; else if((Int_t)rowPt->fRow != i) { cerr<<"AliL3ClusterFitter::FindClusters : Mismatching row numbering "<fRow<fDigitData; for(UInt_t j=0; jfNDigit; j++) { pad = digPt[j].fPad; time = digPt[j].fTime; charge = digPt[j].fCharge; if(charge > 1024) charge -= 1024; fRow[(AliL3Transform::GetNTimeBins()+1)*pad+time].fCharge = charge; fRow[(AliL3Transform::GetNTimeBins()+1)*pad+time].fUsed = kFALSE; //cout<<"Row "<GetNTracks(); k++) { AliL3ModelTrack *track = (AliL3ModelTrack*)fProcessTracks->GetCheckedTrack(k); if(!track) continue; if(fSeeding) if(track->GetClusterModel(i)->fSlice != fSlice) continue; if(track->GetPadHit(i) < 0 || track->GetPadHit(i) > AliL3Transform::GetNPads(i)-1 || track->GetTimeHit(i) < 0 || track->GetTimeHit(i) > AliL3Transform::GetNTimeBins()-1) { track->SetCluster(i,0,0,0,0,0,0); continue; } if(CheckCluster(k) == kFALSE) fFailed++; } } //FillZeros(rowPt); AliL3MemHandler::UpdateRowPointer(rowPt); } fSeeding = kTRUE; AddClusters(); fSeeding = kFALSE; AddClusters(); cout<<"Fitted "<GetCheckedTrack(trackindex); Int_t row = fCurrentPadRow; if(track->IsSet(row)) //A fit has already be performed on this one return kTRUE; //Define the cluster region of this hit: Int_t padr[2]={999,-1}; Int_t timer[2]={999,-1}; if(!SetFitRange(track,padr,timer)) { track->SetCluster(fCurrentPadRow,0,0,0,0,0,0); if(fDebug) cout<<"Failed to fit cluster at row "<GetPadHit(row))<<" time " <<(Int_t)rint(track->GetTimeHit(row))<<" hitcharge " <GetPadHit(row))+(Int_t)rint(track->GetTimeHit(row))].fCharge<GetNTracks(); t++) { AliL3ModelTrack *tr = (AliL3ModelTrack*)fProcessTracks->GetCheckedTrack(t); if(!tr) continue; if(fSeeding) if(tr->GetClusterModel(row)->fSlice != fSlice) continue; Int_t xyw = (Int_t)ceil(sqrt(tr->GetParSigmaY2(row))) + 1; Int_t zw = (Int_t)ceil(sqrt(tr->GetParSigmaZ2(row))) + 1; if( (tr->GetPadHit(row) - xyw > padr[0] && tr->GetPadHit(row) - xyw < padr[1] && tr->GetTimeHit(row) - zw > timer[0] && tr->GetTimeHit(row) - zw < timer[1]) || (tr->GetPadHit(row) + xyw > padr[0] && tr->GetPadHit(row) + xyw < padr[1] && tr->GetTimeHit(row) - zw > timer[0] && tr->GetTimeHit(row) - zw < timer[1]) || (tr->GetPadHit(row) - xyw > padr[0] && tr->GetPadHit(row) - xyw < padr[1] && tr->GetTimeHit(row) + zw > timer[0] && tr->GetTimeHit(row) + zw < timer[1]) || (tr->GetPadHit(row) + xyw > padr[0] && tr->GetPadHit(row) + xyw < padr[1] && tr->GetTimeHit(row) + zw > timer[0] && tr->GetTimeHit(row) + zw < timer[1]) ) { if(SetFitRange(tr,padr,timer)) //Expand the cluster fit range track->SetOverlap(row,t); //Set overlap } } if(fDebug) cout<<"Fitting cluster with "<GetNOverlaps(fCurrentPadRow)<<" overlaps"<GetPadHit(row)); Int_t timehit = (Int_t)rint(track->GetTimeHit(row)); Int_t padmax=-1; Int_t timemax=-1; for(Int_t index=0; indexGetParSigmaY2(row)))+1; Int_t zw = (Int_t)ceil(sqrt(track->GetParSigmaZ2(row)))+1; if(padmax>=0 && timemax>=0) { if(fDebug) { cout<<"Expanding cluster range using expected cluster widths: "< 10 || zw > 10) track->Print(); } //Set the hit to the local maxima of the cluster. //Store the maxima in the cluster model structure, //-only temporary, it will be overwritten when calling SetCluster. track->GetClusterModel(row)->fDPad = padmax; track->GetClusterModel(row)->fDTime = timemax; for(Int_t i=padmax-xyw; i<=padmax+xyw; i++) { for(Int_t j=timemax-zw; j<=timemax+zw; j++) { if(i<0 || i>=AliL3Transform::GetNPads(row) || j<0 || j>=AliL3Transform::GetNTimeBins()) continue; if(fRow[nt*i+j].fCharge) { if(i < padrange[0]) padrange[0]=i; if(i > padrange[1]) padrange[1]=i; if(j < timerange[0]) timerange[0]=j; if(j > timerange[1]) timerange[1]=j; } } } if(fDebug) cout<<"New padrange "<= AliL3Transform::GetNPads(fCurrentPadRow) || time<0 || time >= AliL3Transform::GetNTimeBins()) return kFALSE; Int_t nt = AliL3Transform::GetNTimeBins()+1; if(fRow[nt*pad+time].fUsed == kTRUE) return kFALSE; //Peak has been assigned before Int_t charge = fRow[nt*pad+time].fCharge; if(charge == 1023 || charge==0) return kFALSE; fRow[nt*pad+time].fUsed = kTRUE; return kTRUE; //if(charge < fRow[nt*(pad-1)+(time-1)].fCharge) return kFALSE; if(charge < fRow[nt*(pad)+(time-1)].fCharge) return kFALSE; //if(charge < fRow[nt*(pad+1)+(time-1)].fCharge) return kFALSE; if(charge < fRow[nt*(pad-1)+(time)].fCharge) return kFALSE; if(charge < fRow[nt*(pad+1)+(time)].fCharge) return kFALSE; //if(charge < fRow[nt*(pad-1)+(time+1)].fCharge) return kFALSE; if(charge < fRow[nt*(pad)+(time+1)].fCharge) return kFALSE; //if(charge < fRow[nt*(pad+1)+(time+1)].fCharge) return kFALSE; fRow[nt*pad+time].fUsed = kTRUE; return kTRUE; } void AliL3ClusterFitter::FitClusters(AliL3ModelTrack *track,Int_t *padrange,Int_t *timerange) { //Handle single and overlapping clusters //Check whether this cluster has been set before: Int_t size = FIT_PTS; Int_t max_tracks = FIT_MAXPAR/NUM_PARS; if(track->GetNOverlaps(fCurrentPadRow) > max_tracks) { cerr<<"AliL3ClusterFitter::FitOverlappingClusters : Too many overlapping tracks"<GetOverlaps(fCurrentPadRow); //Check if at least one cluster is not already fitted Bool_t all_fitted=kTRUE; Int_t k=-1; while(k < track->GetNOverlaps(fCurrentPadRow)) { AliL3ModelTrack *tr=0; if(k==-1) tr = track; else tr = (AliL3ModelTrack*)fProcessTracks->GetCheckedTrack(overlaps[k]); k++; if(!tr) continue; if(!tr->IsSet(fCurrentPadRow) && !tr->IsPresent(fCurrentPadRow))//cluster has not been set and is not present { all_fitted = kFALSE; break; } } if(all_fitted) { if(fDebug) cout<<"But all the clusters were already fitted on row "<GetNOverlaps(fCurrentPadRow)) { AliL3ModelTrack *tr=0; if(k==-1) tr = track; else tr = (AliL3ModelTrack*)fProcessTracks->GetCheckedTrack(overlaps[k]); k++; if(!tr) continue; if(tr->IsSet(fCurrentPadRow) && !tr->IsPresent(fCurrentPadRow)) continue;//Cluster fit failed before //Use the local maxima as the input to the fitting routine. //The local maxima is temporary stored in the cluster model: Int_t hitpad = (Int_t)rint(tr->GetClusterModel(fCurrentPadRow)->fDPad); //rint(tr->GetPadHit(fCurrentPadRow)); Int_t hittime = (Int_t)rint(tr->GetClusterModel(fCurrentPadRow)->fDTime); //rint(tr->GetTimeHit(fCurrentPadRow)); Int_t charge = fRow[(AliL3Transform::GetNTimeBins()+1)*hitpad + hittime].fCharge; if(fDebug) cout<<"Fitting track cluster, pad "<GetPadHit(fCurrentPadRow)<<" time " <GetTimeHit(fCurrentPadRow)<<" charge "<GetParSigmaY2(fCurrentPadRow)) <<" zwidth "<GetParSigmaZ2(fCurrentPadRow))<IsSet(fCurrentPadRow)) //Cluster is not fitted before { a[n_overlaps*NUM_PARS+1] = charge; a[n_overlaps*NUM_PARS+3] = sqrt(tr->GetParSigmaY2(fCurrentPadRow)) * GetYWidthFactor(); a[n_overlaps*NUM_PARS+5] = sqrt(tr->GetParSigmaZ2(fCurrentPadRow)) * GetZWidthFactor(); a[n_overlaps*NUM_PARS+6] = sqrt(tr->GetParSigmaZ2(fCurrentPadRow)) * GetZWidthFactor(); lista[n_overlaps*NUM_PARS + 1] = 1; lista[n_overlaps*NUM_PARS + 2] = 1; lista[n_overlaps*NUM_PARS + 3] = 0; lista[n_overlaps*NUM_PARS + 4] = 1; lista[n_overlaps*NUM_PARS + 5] = 0; lista[n_overlaps*NUM_PARS + 6] = 0; fit_pars += 3; } else //Cluster was fitted before { if(!tr->IsPresent(fCurrentPadRow)) { cerr<<"AliL3ClusterFitter::FindClusters : Cluster not present; there is a bug here"<GetPad(fCurrentPadRow,pad); tr->GetTime(fCurrentPadRow,time); tr->GetClusterCharge(fCurrentPadRow,charge); xywidth = sqrt(tr->GetParSigmaY2(fCurrentPadRow)); zwidth = sqrt(tr->GetParSigmaZ2(fCurrentPadRow)); if(fDebug) cout<<"Cluster had been fitted before, pad "< max_charge) { max_charge = charge; //time_num++; } if(fDebug) cout<<"Filling padrow "<= size) { cerr<<"Too many points; row "< fNmaxOverlaps || ndata <= fit_pars) //too few to do fit { SetClusterfitFalse(track); if(fDebug) cout<<"Too few digits or too many overlaps: "<GetNOverlaps(fCurrentPadRow)) { AliL3ModelTrack *tr=0; if(k==-1) tr = track; else tr = (AliL3ModelTrack*)fProcessTracks->GetCheckedTrack(overlaps[k]); k++; if(!tr) continue; if(!tr->IsPresent(fCurrentPadRow)) { if(tr->IsSet(fCurrentPadRow)) continue;//This cluster has been set before if(chisq_f < fChiSqMax)//cluster fit is good enough { tot_charge = (Int_t)(a[n_overlaps*NUM_PARS+1] * a[n_overlaps*NUM_PARS+3] * a[n_overlaps*NUM_PARS+5]); Float_t fpad = a[n_overlaps*NUM_PARS+2]; Float_t ftime = a[n_overlaps*NUM_PARS+4]; if(tot_charge < 0 || fpad < -1 || fpad > AliL3Transform::GetNPads(fCurrentPadRow) || ftime < -1 || ftime > AliL3Transform::GetNTimeBins()) { if(fDebug) cout<<"AliL3ClusterFitter::Fatal result(s) in fit; in slice "<SetCluster(fCurrentPadRow,0,0,0,0,0,0); fFailed++; fResultError++; continue; } tr->SetCluster(fCurrentPadRow,fpad,ftime,tot_charge,0,0,pad_num); if(fDebug) cout<<"Setting cluster in pad "<SetCluster(fCurrentPadRow,0,0,0,0,0,0); fBadFitError++; fFailed++; } } n_overlaps++; } delete [] plane; } void AliL3ClusterFitter::SetClusterfitFalse(AliL3ModelTrack *track) { //Cluster fit failed, so set the clusters to all the participating //tracks to zero. Int_t i=-1; Int_t *overlaps = track->GetOverlaps(fCurrentPadRow); while(i < track->GetNOverlaps(fCurrentPadRow)) { AliL3ModelTrack *tr=0; if(i==-1) tr = track; else tr = (AliL3ModelTrack*)fProcessTracks->GetCheckedTrack(overlaps[i]); i++; if(!tr) continue; tr->SetCluster(fCurrentPadRow,0,0,0,0,0,0); } } void AliL3ClusterFitter::AddClusters() { if(!fClusters) { fClusters = new AliL3SpacePointData[fNMaxClusters]; fNClusters=0; } if(fDebug) cout<<"Writing cluster in slice "<GetNTracks(); i++) { AliL3ModelTrack *tr = (AliL3ModelTrack*)tracks->GetCheckedTrack(i); if(!tr) continue; UInt_t *hitids = tr->GetHitNumbers(); Int_t nhits = tr->GetNHits(); for(Int_t i=fRowMax; i>=fRowMin; i--) { if(fSeeding) if(tr->GetClusterModel(i)->fSlice != fSlice) continue; if(!tr->IsPresent(i)) continue; fCurrentPadRow = i; Float_t pad,time,xywidth,zwidth; Int_t charge; tr->GetPad(i,pad); tr->GetTime(i,time); tr->GetClusterCharge(i,charge); if(pad < -1 || pad >= AliL3Transform::GetNPads(i) || time < -1 || time >= AliL3Transform::GetNTimeBins()) { continue; cout<<"slice "<Print(); exit(5); } tr->CalculateClusterWidths(i,kTRUE); //Parametrize errors tr->GetXYWidth(i,xywidth); tr->GetZWidth(i,zwidth); Float_t xyz[3]; Int_t sector,row; AliL3Transform::Slice2Sector(fSlice,i,sector,row); AliL3Transform::Raw2Global(xyz,sector,row,pad,time); if(fNClusters >= fNMaxClusters) { cerr<<"AliL3ClusterFitter::AddClusters : Too many clusters "<0) fClusters[fNClusters].fSigmaY2 = xywidth*pow(AliL3Transform::GetPadPitchWidth(pa),2); else fClusters[fNClusters].fSigmaY2 = 1; if(zwidth>0) fClusters[fNClusters].fSigmaZ2 = zwidth*pow(AliL3Transform::GetZWidth(),2); else fClusters[fNClusters].fSigmaZ2 = 1; Int_t pat=fPatch; if(fPatch==-1) pat=0; fClusters[fNClusters].fID = fNClusters + ((fSlice&0x7f)<<25)+((pat&0x7)<<22); if(nhits >= 159) { cerr<<"AliL3ClusterFitter::AddClusters : Cluster counter of out range "<= AliL3Transform::GetNPads(i)) fpad = AliL3Transform::GetNPads(i)-1; if(ftime<0) ftime=0; if(ftime >= AliL3Transform::GetNTimeBins()) ftime = AliL3Transform::GetNTimeBins()-1; GetTrackID(fpad,ftime,trackID); fClusters[fNClusters].fTrackID[0] = trackID[0]; fClusters[fNClusters].fTrackID[1] = trackID[1]; fClusters[fNClusters].fTrackID[2] = trackID[2]; #endif //cout<<"Setting id "<SetNHits(nhits); } } void AliL3ClusterFitter::WriteTracks() { if(!fSeeds) return; AliL3Compress *c = new AliL3Compress(-1,-1,fPath); c->WriteFile(fSeeds,"tracks_after.raw"); delete c; Int_t clustercount=0; for(Int_t i=0; iGetNTracks(); i++) { AliL3ModelTrack *tr = (AliL3ModelTrack*)fSeeds->GetCheckedTrack(i); if(!tr) continue; if(tr->GetNHits()==0) fSeeds->Remove(i); clustercount += tr->GetNHits(); /* if(tr->GetPt() > 1 && tr->GetNPresentClusters() < 150) tr->Print(); */ } cout<<"Writing "<Compress(); AliL3MemHandler mem; Char_t filename[1024]; sprintf(filename,"%s/fitter/tracks_0.raw",fPath); mem.SetBinaryOutput(filename); mem.TrackArray2Binary(fSeeds); mem.CloseBinaryOutput(); } void AliL3ClusterFitter::WriteClusters() { AliL3MemHandler mem; if(fDebug) cout<<"Write "<