3 // Author: Anders Vestbo <mailto:vestbo@fi.uib.no>
4 //*-- Copyright © ALICE HLT Group
6 #include "AliL3StandardIncludes.h"
8 #include "AliL3Logging.h"
9 #include "AliL3ClusterFitter.h"
10 #include "AliL3FitUtilities.h"
11 #include "AliL3DigitData.h"
12 #include "AliL3ModelTrack.h"
13 #include "AliL3TrackArray.h"
14 #include "AliL3MemHandler.h"
15 #include "AliL3HoughTrack.h"
16 #include "AliL3SpacePointData.h"
17 #include "AliL3Compress.h"
23 /** /class AliL3ClusterFitter
25 //_____________________________________________________________
32 ClassImp(AliL3ClusterFitter)
34 Int_t AliL3ClusterFitter::fBadFitError=0;
35 Int_t AliL3ClusterFitter::fFitError=0;
36 Int_t AliL3ClusterFitter::fResultError=0;
37 Int_t AliL3ClusterFitter::fFitRangeError=0;
39 AliL3ClusterFitter::AliL3ClusterFitter()
43 fChiSqMax[0]=fChiSqMax[1]=fChiSqMax[2]=12;
60 AliL3ClusterFitter::AliL3ClusterFitter(Char_t *path)
65 fChiSqMax[0]=fChiSqMax[1]=fChiSqMax[2]=12;
82 AliL3ClusterFitter::~AliL3ClusterFitter()
90 void AliL3ClusterFitter::Init(Int_t slice,Int_t patch,Int_t *rowrange,AliL3TrackArray *tracks)
92 //Assuming tracklets found by the line transform
97 if(rowrange[0] > AliL3Transform::GetLastRow(patch) || rowrange[1] < AliL3Transform::GetFirstRow(patch))
98 cerr<<"AliL3ClusterFitter::Init : Wrong rows "<<rowrange[0]<<" "<<rowrange[1]<<endl;
104 if(fRowMax > AliL3Transform::GetLastRow(fPatch))
105 fRowMax = AliL3Transform::GetLastRow(fPatch);
109 Int_t ntimes = AliL3Transform::GetNTimeBins()+1;
110 Int_t npads = AliL3Transform::GetNPads(AliL3Transform::GetLastRow(fPatch))+1;//Max num of pads.
111 Int_t bounds = ntimes*npads;
114 fRow = new Digit[bounds];
118 fTracks = new AliL3TrackArray("AliL3ModelTrack");
120 for(Int_t i=0; i<tracks->GetNTracks(); i++)
122 AliL3HoughTrack *track = (AliL3HoughTrack*)tracks->GetCheckedTrack(i);
124 AliL3ModelTrack *mtrack = (AliL3ModelTrack*)fTracks->NextTrack();
125 mtrack->Init(slice,patch);
126 mtrack->SetTgl(track->GetTgl());
127 mtrack->SetRowRange(rowrange[0],rowrange[1]);
128 for(Int_t j=fRowMin; j<=fRowMax; j++)
131 track->GetLineCrossingPoint(j,hit);
132 hit[0] += AliL3Transform::Row2X(track->GetFirstRow());
133 Float_t R = sqrt(hit[0]*hit[0] + hit[1]*hit[1]);
134 hit[2] = R*track->GetTgl();
136 AliL3Transform::Slice2Sector(slice,j,se,ro);
137 AliL3Transform::Local2Raw(hit,se,ro);
138 if(hit[1]<0 || hit[1]>=AliL3Transform::GetNPads(j) || hit[2]<0 || hit[2]>=AliL3Transform::GetNTimeBins())
140 mtrack->SetPadHit(j,-1);
141 mtrack->SetTimeHit(j,-1);
144 mtrack->SetPadHit(j,hit[1]);
145 mtrack->SetTimeHit(j,hit[2]);
146 mtrack->SetCrossingAngleLUT(j,fabs(track->GetPsiLine() - AliL3Transform::Pi()/2));
147 //if(mtrack->GetCrossingAngleLUT(j) > AliL3Transform::Deg2Rad(20))
148 // cout<<"Angle "<<mtrack->GetCrossingAngleLUT(j)<<" psiline "<<track->GetPsiLine()*180/3.1415<<endl;
149 mtrack->CalculateClusterWidths(j);
152 // cout<<"Copied "<<fTracks->GetNTracks()<<" tracks "<<endl;
155 void AliL3ClusterFitter::Init(Int_t slice,Int_t patch)
160 fRowMin=AliL3Transform::GetFirstRow(patch);
161 fRowMax=AliL3Transform::GetLastRow(patch);
165 Int_t ntimes = AliL3Transform::GetNTimeBins()+1;
166 Int_t npads = AliL3Transform::GetNPads(AliL3Transform::GetLastRow(fPatch))+1;//Max num of pads.
167 Int_t bounds = ntimes*npads;
170 fRow = new Digit[bounds];
173 fTracks = new AliL3TrackArray("AliL3ModelTrack");
177 void AliL3ClusterFitter::LoadLocalSegments()
179 Char_t filename[1024];
180 sprintf(filename,"%s/hough/tracks_ho_%d_%d_%d.raw",fPath,fEvent,fSlice,fPatch);
182 mem.SetBinaryInput(filename);
183 mem.Binary2TrackArray(fTracks);
184 mem.CloseBinaryInput();
186 for(Int_t i=0; i<fTracks->GetNTracks(); i++)
188 AliL3ModelTrack *track = (AliL3ModelTrack*)fTracks->GetCheckedTrack(i);
191 track->CalculateHelix();
193 track->Init(fSlice,fPatch);
195 for(Int_t j=fRowMin; j<=fRowMax; j++)
197 //Calculate the crossing point between track and padrow
199 Float_t xyz_cross[3];
200 if(!track->GetCrossingPoint(j,xyz_cross))
204 AliL3Transform::Slice2Sector(fSlice,j,sector,row);
205 AliL3Transform::Local2Raw(xyz_cross,sector,row);
207 if(xyz_cross[1] < 0 || xyz_cross[1] >= AliL3Transform::GetNPads(j) ||
208 xyz_cross[2] < 0 || xyz_cross[2] >= AliL3Transform::GetNTimeBins()) //track goes out of range
211 track->SetPadHit(j,xyz_cross[1]);
212 track->SetTimeHit(j,xyz_cross[2]);
214 Float_t crossingangle = track->GetCrossingAngle(j);
215 track->SetCrossingAngleLUT(j,crossingangle);
216 track->CalculateClusterWidths(j);
217 track->GetClusterModel(j)->fSlice = fSlice;
223 void AliL3ClusterFitter::LoadSeeds(Int_t *rowrange,Bool_t offline,Int_t eventnr,Float_t zvertex)
225 //Function assumes _global_ tracks written to a single file.
226 cout<<"Loading the seeds"<<endl;
231 sprintf(fname,"%s/offline/tracks_%d.raw",fPath,fEvent);
233 sprintf(fname,"%s/hough/tracks_%d.raw",fPath,fEvent);
235 cout<<"AliL3ClusterFitter::LoadSeeds : Loading input tracks from "<<fname<<endl;
237 AliL3MemHandler tfile;
238 tfile.SetBinaryInput(fname);
242 fSeeds = new AliL3TrackArray("AliL3ModelTrack");
244 tfile.Binary2TrackArray(fSeeds);
245 tfile.CloseBinaryInput();
250 Int_t clustercount=0;
251 for(Int_t i=0; i<fSeeds->GetNTracks(); i++)
253 AliL3ModelTrack *track = (AliL3ModelTrack*)fSeeds->GetCheckedTrack(i);
258 if(i==0) cerr<<"AliL3ClusterFitter::LoadSeeds : Cutting on pt of 4 GeV!!"<<endl;
259 if(track->GetPt() > 4.)
265 clustercount += track->GetNHits();
266 track->CalculateHelix();
268 Int_t nhits = track->GetNHits();
269 UInt_t *hitids = track->GetHitNumbers();
271 Int_t origslice = (hitids[nhits-1]>>25)&0x7f;//Slice of innermost point
273 if(i==0) cerr<<"Cluster fitter only in HALF TPC!!!"<<endl;
280 track->Init(origslice,-1);
281 Int_t slice = origslice;
283 //for(Int_t j=rowrange[1]; j>=rowrange[0]; j--)
284 for(Int_t j=rowrange[0]; j<=rowrange[1]; j++)
287 //Calculate the crossing point between track and padrow
288 Float_t angle = 0; //Perpendicular to padrow in local coordinates
289 AliL3Transform::Local2GlobalAngle(&angle,slice);
290 if(!track->CalculateReferencePoint(angle,AliL3Transform::Row2X(j)))
292 //cerr<<"No crossing in slice "<<slice<<" padrow "<<j<<endl;
297 Float_t xyz_cross[3] = {track->GetPointX(),track->GetPointY(),track->GetPointZ()};
298 xyz_cross[2] += zvertex;
301 AliL3Transform::Slice2Sector(slice,j,sector,row);
302 AliL3Transform::Global2Raw(xyz_cross,sector,row);
303 //cout<<"Examining slice "<<slice<<" row "<<j<<" pad "<<xyz_cross[1]<<" time "<<xyz_cross[2]<<endl;
304 if(xyz_cross[1] < 0 || xyz_cross[1] >= AliL3Transform::GetNPads(j)) //Track leaves the slice
309 Float_t lastcross=xyz_cross[1];
328 if(slice < 0 || slice>35)
330 cerr<<"Wrong slice "<<slice<<" on row "<<j<<endl;
333 //cout<<"Track leaving, trying slice "<<slice<<endl;
335 AliL3Transform::Local2GlobalAngle(&angle,slice);
336 if(!track->CalculateReferencePoint(angle,AliL3Transform::Row2X(j)))
338 cerr<<"No crossing in slice "<<slice<<" padrow "<<j<<endl;
343 xyz_cross[0] = track->GetPointX();
344 xyz_cross[1] = track->GetPointY();
345 xyz_cross[2] = track->GetPointZ();
346 xyz_cross[2] += zvertex;
348 AliL3Transform::Slice2Sector(slice,j,sector,row);
349 AliL3Transform::Global2Raw(xyz_cross,sector,row);
350 if(xyz_cross[1] < 0 || xyz_cross[1] >= AliL3Transform::GetNPads(j)) //track is in the borderline
352 if(xyz_cross[1] > 0 && lastcross > 0 || xyz_cross[1] < 0 && lastcross < 0)
356 slice = tslice;//Track is on the border of two slices
362 if(xyz_cross[2] < 0 || xyz_cross[2] >= AliL3Transform::GetNTimeBins())//track goes out of range
365 if(xyz_cross[1] < 0 || xyz_cross[1] >= AliL3Transform::GetNPads(j))
367 cerr<<"Slice "<<slice<<" padrow "<<j<<" pad "<<xyz_cross[1]<<" time "<<xyz_cross[2]<<endl;
372 track->SetPadHit(j,xyz_cross[1]);
373 track->SetTimeHit(j,xyz_cross[2]);
375 AliL3Transform::Local2GlobalAngle(&angle,slice);
376 Float_t crossingangle = track->GetCrossingAngle(j,slice);
377 track->SetCrossingAngleLUT(j,crossingangle);
379 track->CalculateClusterWidths(j);
381 track->GetClusterModel(j)->fSlice = slice;
384 memset(track->GetHitNumbers(),0,159*sizeof(UInt_t));//Reset the hitnumbers
389 cout<<"Loaded "<<fSeeds->GetNTracks()<<" seeds and "<<clustercount<<" clusters"<<endl;
392 void AliL3ClusterFitter::FindClusters()
396 cerr<<"AliL3ClusterFitter::Process : No tracks"<<endl;
401 cerr<<"AliL3ClusterFitter::Process : No data "<<endl;
405 AliL3DigitRowData *rowPt = fRowData;
406 AliL3DigitData *digPt=0;
413 fRowMin = AliL3Transform::GetFirstRow(fPatch);
414 fRowMax = AliL3Transform::GetLastRow(fPatch);
416 for(Int_t i=AliL3Transform::GetFirstRow(fPatch); i<=AliL3Transform::GetLastRow(fPatch); i++)
418 if((Int_t)rowPt->fRow < fRowMin)
420 AliL3MemHandler::UpdateRowPointer(rowPt);
423 else if((Int_t)rowPt->fRow > fRowMax)
425 else if((Int_t)rowPt->fRow != i)
427 cerr<<"AliL3ClusterFitter::FindClusters : Mismatching row numbering "<<i<<" "<<rowPt->fRow<<endl;
431 memset((void*)fRow,0,(AliL3Transform::GetNTimeBins()+1)*(AliL3Transform::GetNPads(i)+1)*sizeof(Digit));
432 digPt = (AliL3DigitData*)rowPt->fDigitData;
434 for(UInt_t j=0; j<rowPt->fNDigit; j++)
437 time = digPt[j].fTime;
438 charge = digPt[j].fCharge;
439 fRow[(AliL3Transform::GetNTimeBins()+1)*pad+time].fCharge = charge;
440 fRow[(AliL3Transform::GetNTimeBins()+1)*pad+time].fUsed = kFALSE;
441 //cout<<"Row "<<i<<" pad "<<pad<<" time "<<time<<" charge "<<charge<<endl;
444 for(Int_t it=0; it<2; it++)
448 fProcessTracks = fSeeds;
453 fProcessTracks = fTracks;
459 for(Int_t k=0; k<fProcessTracks->GetNTracks(); k++)
461 AliL3ModelTrack *track = (AliL3ModelTrack*)fProcessTracks->GetCheckedTrack(k);
465 if(track->GetClusterModel(i)->fSlice != fSlice) continue;
467 if(track->GetPadHit(i) < 0 || track->GetPadHit(i) > AliL3Transform::GetNPads(i)-1 ||
468 track->GetTimeHit(i) < 0 || track->GetTimeHit(i) > AliL3Transform::GetNTimeBins()-1)
470 track->SetCluster(i,0,0,0,0,0,0);
474 if(CheckCluster(k) == kFALSE)
478 AliL3MemHandler::UpdateRowPointer(rowPt);
486 cout<<"Fitted "<<fFitted<<" clusters, failed "<<fFailed<<endl;
487 cout<<"Distribution:"<<endl;
488 cout<<"Bad fit "<<fBadFitError<<endl;
489 cout<<"Fit error "<<fFitError<<endl;
490 cout<<"Result error "<<fResultError<<endl;
491 cout<<"Fit range error "<<fFitRangeError<<endl;
495 Bool_t AliL3ClusterFitter::CheckCluster(Int_t trackindex)
497 //Check if this is a single or overlapping cluster
499 AliL3ModelTrack *track = (AliL3ModelTrack*)fProcessTracks->GetCheckedTrack(trackindex);
501 Int_t row = fCurrentPadRow;
503 if(track->IsSet(row)) //A fit has already be performed on this one
506 //Define the cluster region of this hit:
507 Int_t padr[2]={999,-1};
508 Int_t timer[2]={999,-1};
510 if(!SetFitRange(track,padr,timer))
512 track->SetCluster(fCurrentPadRow,0,0,0,0,0,0);
515 cout<<"Failed to fit cluster at row "<<row<<" pad "<<(Int_t)rint(track->GetPadHit(row))<<" time "
516 <<(Int_t)rint(track->GetTimeHit(row))<<" hitcharge "
517 <<fRow[(AliL3Transform::GetNTimeBins()+1)*(Int_t)rint(track->GetPadHit(row))+(Int_t)rint(track->GetTimeHit(row))].fCharge<<endl;
522 //Check if any other track contributes to this cluster:
524 for(Int_t t=trackindex+1; t<fProcessTracks->GetNTracks(); t++)
526 AliL3ModelTrack *tr = (AliL3ModelTrack*)fProcessTracks->GetCheckedTrack(t);
529 if(tr->GetClusterModel(row)->fSlice != fSlice) continue;
531 if(tr->GetPadHit(row) > padr[0] && tr->GetPadHit(row) < padr[1] &&
532 tr->GetTimeHit(row) > timer[0] && tr->GetTimeHit(row) < timer[1])
534 if(SetFitRange(tr,padr,timer))
535 track->SetOverlap(row,t);
538 Int_t xyw = (Int_t)ceil(sqrt(tr->GetParSigmaY2(row))*GetYWidthFactor());
539 Int_t zw = (Int_t)ceil(sqrt(tr->GetParSigmaZ2(row))*GetZWidthFactor());
541 (tr->GetPadHit(row) - xyw > padr[0] && tr->GetPadHit(row) - xyw < padr[1] &&
542 tr->GetTimeHit(row) - zw > timer[0] && tr->GetTimeHit(row) - zw < timer[1]) ||
544 (tr->GetPadHit(row) + xyw > padr[0] && tr->GetPadHit(row) + xyw < padr[1] &&
545 tr->GetTimeHit(row) - zw > timer[0] && tr->GetTimeHit(row) - zw < timer[1]) ||
547 (tr->GetPadHit(row) - xyw > padr[0] && tr->GetPadHit(row) - xyw < padr[1] &&
548 tr->GetTimeHit(row) + zw > timer[0] && tr->GetTimeHit(row) + zw < timer[1]) ||
550 (tr->GetPadHit(row) + xyw > padr[0] && tr->GetPadHit(row) + xyw < padr[1] &&
551 tr->GetTimeHit(row) + zw > timer[0] && tr->GetTimeHit(row) + zw < timer[1])
555 if(SetFitRange(tr,padr,timer)) //Expand the cluster fit range
557 track->SetOverlap(row,t); //Set overlap
564 cout<<"Fitting cluster with "<<track->GetNOverlaps(fCurrentPadRow)<<" overlaps"<<endl;
566 FitClusters(track,padr,timer);
567 //CalculateWeightedMean(track,padr,timer);
571 Bool_t AliL3ClusterFitter::SetFitRange(AliL3ModelTrack *track,Int_t *padrange,Int_t *timerange)
573 Int_t row = fCurrentPadRow;
574 Int_t nt = AliL3Transform::GetNTimeBins()+1;
577 if(row < AliL3Transform::GetNRowLow())
579 else if(row < AliL3Transform::GetNRowLow() + AliL3Transform::GetNRowUp1())
585 Int_t padloop[49] = {0,0,0,-1,1,-1,1,-1,1,0,0,-1,1,-1,1 ,2,-2,2,-2,2,-2,2,-2,2,-2
586 ,0,1,2,3,3,3,3,3,3,3
588 ,-3,-3,-3,-3,-3,-3,-1,-1};
589 Int_t timeloop[49] = {0,1,-1,0,0,1,1,-1,-1,2,-2,2,2,-2,-2 ,0,0,1,1,-1,-1,2,2,-2,-2
590 ,-3,-3,-3,-3,-2,-1,0,1,2,3
591 ,3,3,3,3,3,3,2,1,0,-1,-2,-3,-3,-3};
594 Int_t padloop[49] = {0,0,0,-1,1,-1,1,-1,1,0,0,-1,1,-1,1 ,2,-2,2,-2,2,-2,2,-2,2,-2
595 ,-3,3,-3,3,-3,3,-3,3,-3,3
596 ,0,0,-1,-1,1,1,-2,-2,2,2,-3,-3,3,3};
597 Int_t timeloop[49] = {0,1,-1,0,0,1,1,-1,-1,2,-2,2,2,-2,-2 ,0,0,1,1,-1,-1,2,2,-2,-2
598 ,0,0,-1,-1,1,1,-2,-2,2,2
599 ,-3,3,-3,3,-3,3,-3,3,-3,3,-3,3,-3,3};
601 Int_t padhit = (Int_t)rint(track->GetPadHit(row));
602 Int_t timehit = (Int_t)rint(track->GetTimeHit(row));
606 for(Int_t index=0; index<nsearchbins; index++)
608 if(IsMaximum(padhit + padloop[index],timehit + timeloop[index]))
610 padmax = padhit + padloop[index];
611 timemax = timehit + timeloop[index];
617 //Define the cluster region of this hit:
618 //The region we look for, is centered at the local maxima
619 //and expanded around using the parametrized cluster width
620 //according to track parameters.
625 if(padmax>=0 && timemax>=0)
627 //Set the hit to the local maxima of the cluster.
628 //Store the maxima in the cluster model structure,
629 //-only temporary, it will be overwritten when calling SetCluster.
631 track->GetClusterModel(row)->fDPad = padmax;
632 track->GetClusterModel(row)->fDTime = timemax;
634 Int_t i=padmax,j=timemax;
635 for(Int_t pdir=-1; pdir<=1; pdir+=2)
638 while(abs(padmax-i) < xyw)
640 Bool_t chargeonpad=kFALSE;
641 for(Int_t tdir=-1; tdir<=1; tdir+=2)
644 while(abs(timemax-j) < zw)
646 if(i<0 || i>=AliL3Transform::GetNPads(row) || j<0 || j>=AliL3Transform::GetNTimeBins()) break;
647 if(fRow[nt*i+j].fCharge)
649 if(i < padrange[0]) padrange[0]=i;
650 if(i > padrange[1]) padrange[1]=i;
651 if(j < timerange[0]) timerange[0]=j;
652 if(j > timerange[1]) timerange[1]=j;
666 for(Int_t i=padmax-xyw; i<=padmax+xyw; i++)
668 for(Int_t j=timemax-zw; j<=timemax+zw; j++)
670 if(i<0 || i>=AliL3Transform::GetNPads(row) || j<0 || j>=AliL3Transform::GetNTimeBins()) continue;
671 if(fRow[nt*i+j].fCharge)
673 if(i < padrange[0]) padrange[0]=i;
674 if(i > padrange[1]) padrange[1]=i;
675 if(j < timerange[0]) timerange[0]=j;
676 if(j > timerange[1]) timerange[1]=j;
683 cout<<"New padrange "<<padrange[0]<<" "<<padrange[1]<<" "<<" time "<<timerange[0]<<" "<<timerange[1]<<endl;
689 Bool_t AliL3ClusterFitter::IsMaximum(Int_t pad,Int_t time)
691 if(pad<0 || pad >= AliL3Transform::GetNPads(fCurrentPadRow) ||
692 time<0 || time >= AliL3Transform::GetNTimeBins())
694 Int_t nt = AliL3Transform::GetNTimeBins()+1;
695 if(fRow[nt*pad+time].fUsed == kTRUE) return kFALSE; //Peak has been assigned before
696 Int_t charge = fRow[nt*pad+time].fCharge;
697 if(charge == 1024 || charge==0) return kFALSE;
698 //if(charge == 0) return kFALSE;
700 //fRow[nt*pad+time].fUsed = kTRUE;
703 if(charge < fRow[nt*(pad-1)+(time-1)].fCharge) return kFALSE;
704 if(charge < fRow[nt*(pad)+(time-1)].fCharge) return kFALSE;
705 if(charge < fRow[nt*(pad+1)+(time-1)].fCharge) return kFALSE;
706 if(charge < fRow[nt*(pad-1)+(time)].fCharge) return kFALSE;
707 if(charge < fRow[nt*(pad+1)+(time)].fCharge) return kFALSE;
708 if(charge < fRow[nt*(pad-1)+(time+1)].fCharge) return kFALSE;
709 if(charge < fRow[nt*(pad)+(time+1)].fCharge) return kFALSE;
710 if(charge < fRow[nt*(pad+1)+(time+1)].fCharge) return kFALSE;
711 fRow[nt*pad+time].fUsed = kTRUE;
715 void AliL3ClusterFitter::CalculateWeightedMean(AliL3ModelTrack *track,Int_t *padrange,Int_t *timerange)
719 Float_t pad=0,time=0;
720 Int_t nt = AliL3Transform::GetNTimeBins()+1;
721 for(Int_t i=padrange[0]; i<=padrange[1]; i++)
724 for(Int_t j=timerange[0]; j<=timerange[1]; j++)
726 lsum += fRow[nt*(i-1)+(j-1)].fCharge;
727 time += j*fRow[nt*(i-1)+(j-1)].fCharge;
737 track->SetCluster(fCurrentPadRow,pad,time,sum,0,0,npads);
740 track->SetCluster(fCurrentPadRow,0,0,0,0,0,0);
743 void AliL3ClusterFitter::FitClusters(AliL3ModelTrack *track,Int_t *padrange,Int_t *timerange)
745 //Handle single and overlapping clusters
748 if( (Int_t)rint(track->GetClusterModel(fCurrentPadRow)->fDPad) <= 1 ||
749 (Int_t)rint(track->GetClusterModel(fCurrentPadRow)->fDPad) >= AliL3Transform::GetNPads(fCurrentPadRow)-2 ||
750 (Int_t)rint(track->GetClusterModel(fCurrentPadRow)->fDTime) <= 1 ||
751 (Int_t)rint(track->GetClusterModel(fCurrentPadRow)->fDTime) >= AliL3Transform::GetNTimeBins()-2)
753 CalculateWeightedMean(track,padrange,timerange);
757 Int_t size = FIT_PTS;
758 Int_t max_tracks = FIT_MAXPAR/NUM_PARS;
759 if(track->GetNOverlaps(fCurrentPadRow) > max_tracks)
761 cerr<<"AliL3ClusterFitter::FitOverlappingClusters : Too many overlapping tracks"<<endl;
764 Int_t *overlaps = track->GetOverlaps(fCurrentPadRow);
766 //Check if at least one cluster is not already fitted
767 Bool_t all_fitted=kTRUE;
770 while(k < track->GetNOverlaps(fCurrentPadRow))
772 AliL3ModelTrack *tr=0;
776 tr = (AliL3ModelTrack*)fProcessTracks->GetCheckedTrack(overlaps[k]);
779 if(!tr->IsSet(fCurrentPadRow) && !tr->IsPresent(fCurrentPadRow))//cluster has not been set and is not present
788 cout<<"But all the clusters were already fitted on row "<<fCurrentPadRow<<endl;
792 //Allocate fit parameters array; this is interface to the C code
793 plane = new DPOINT[FIT_PTS];
794 memset(plane,0,FIT_PTS*sizeof(DPOINT));
796 Double_t x[FIT_PTS],y[FIT_PTS],s[FIT_PTS];
798 //Fill the fit parameters:
799 Double_t a[FIT_MAXPAR];
800 Int_t lista[FIT_MAXPAR];
801 Double_t dev[FIT_MAXPAR],chisq_f;
808 //Fill the overlapping tracks:
809 while(k < track->GetNOverlaps(fCurrentPadRow))
811 AliL3ModelTrack *tr=0;
815 tr = (AliL3ModelTrack*)fProcessTracks->GetCheckedTrack(overlaps[k]);
819 if(tr->IsSet(fCurrentPadRow) && !tr->IsPresent(fCurrentPadRow)) continue;//Cluster fit failed before
821 //Use the local maxima as the input to the fitting routine.
822 //The local maxima is temporary stored in the cluster model:
823 Int_t hitpad = (Int_t)rint(tr->GetClusterModel(fCurrentPadRow)->fDPad);
824 Int_t hittime = (Int_t)rint(tr->GetClusterModel(fCurrentPadRow)->fDTime);
825 Int_t charge = fRow[(AliL3Transform::GetNTimeBins()+1)*hitpad + hittime].fCharge;
828 cout<<"Fitting track cluster, pad "<<tr->GetPadHit(fCurrentPadRow)<<" time "
829 <<tr->GetTimeHit(fCurrentPadRow)<<" charge "<<charge<<" at local maxima in pad "<<hitpad
830 <<" time "<<hittime<<" xywidth "<<sqrt(tr->GetParSigmaY2(fCurrentPadRow))
831 <<" zwidth "<<sqrt(tr->GetParSigmaZ2(fCurrentPadRow))<<endl;
835 cerr<<"Charge still zero!"<<endl;
839 a[n_overlaps*NUM_PARS+2] = hitpad;
840 a[n_overlaps*NUM_PARS+4] = hittime;
842 if(!tr->IsSet(fCurrentPadRow)) //Cluster is not fitted before
844 a[n_overlaps*NUM_PARS+1] = charge;
845 a[n_overlaps*NUM_PARS+3] = sqrt(tr->GetParSigmaY2(fCurrentPadRow)) * GetYWidthFactor();
846 a[n_overlaps*NUM_PARS+5] = sqrt(tr->GetParSigmaZ2(fCurrentPadRow)) * GetZWidthFactor();
847 //a[n_overlaps*NUM_PARS+6] = sqrt(tr->GetParSigmaZ2(fCurrentPadRow)) * GetZWidthFactor();
848 lista[n_overlaps*NUM_PARS + 1] = 1;
849 lista[n_overlaps*NUM_PARS + 2] = 1;
850 lista[n_overlaps*NUM_PARS + 3] = 0;
851 lista[n_overlaps*NUM_PARS + 4] = 1;
852 lista[n_overlaps*NUM_PARS + 5] = 0;
853 //lista[n_overlaps*NUM_PARS + 6] = 0;
854 fit_pars += 3; //<-------------------
856 else //Cluster was fitted before
858 if(!tr->IsPresent(fCurrentPadRow))
860 cerr<<"AliL3ClusterFitter::FindClusters : Cluster not present; there is a bug here"<<endl;
864 Float_t xywidth,zwidth,pad,time;
865 tr->GetPad(fCurrentPadRow,pad);
866 tr->GetTime(fCurrentPadRow,time);
867 tr->GetClusterCharge(fCurrentPadRow,charge);
868 xywidth = sqrt(tr->GetParSigmaY2(fCurrentPadRow));
869 zwidth = sqrt(tr->GetParSigmaZ2(fCurrentPadRow));
871 cout<<endl<<"Cluster had been fitted before, pad "<<pad<<" time "<<time<<" charge "<<charge<<" width "<<xywidth<<" "<<zwidth<<endl;
873 a[n_overlaps*NUM_PARS+2] = pad;
874 a[n_overlaps*NUM_PARS+4] = time;
875 a[n_overlaps*NUM_PARS+1] = charge;
876 a[n_overlaps*NUM_PARS+3] = xywidth * GetYWidthFactor();
877 a[n_overlaps*NUM_PARS+5] = zwidth * GetZWidthFactor();
878 //a[n_overlaps*NUM_PARS+6] = zwidth * GetZWidthFactor();
880 lista[n_overlaps*NUM_PARS + 1] = 1;
881 lista[n_overlaps*NUM_PARS + 2] = 0;
882 lista[n_overlaps*NUM_PARS + 3] = 0;
883 lista[n_overlaps*NUM_PARS + 4] = 0;
884 lista[n_overlaps*NUM_PARS + 5] = 0;
885 //lista[n_overlaps*NUM_PARS + 6] = 0;
891 if(n_overlaps==0) //No clusters here
898 Int_t time_num_max=0;
902 cout<<"Padrange "<<padrange[0]<<" "<<padrange[1]<<" timerange "<<timerange[0]<<" "<<timerange[1]<<endl;
903 for(Int_t i=padrange[0]; i<=padrange[1]; i++)
905 Int_t max_charge = 0;
907 for(Int_t j=timerange[0]; j<=timerange[1]; j++)
909 Int_t charge = fRow[(AliL3Transform::GetNTimeBins()+1)*i + j].fCharge;
911 if(charge <= 0) continue;
914 if(charge > max_charge)
920 cout<<"Filling padrow "<<fCurrentPadRow<<" pad "<<i<<" time "<<j<<" charge "<<charge<<endl;
921 tot_charge += charge;
925 cerr<<"Too many points; row "<<fCurrentPadRow<<" padrange "<<padrange[0]<<" "<<padrange[1]<<" timerange "
926 <<timerange[0]<<" "<<timerange[1]<<endl;
930 plane[ndata].u = (Double_t)i;
931 plane[ndata].v = (Double_t)j;
934 s[ndata]= 1 + sqrt((Double_t)charge);
936 if(max_charge) //there was charge on this pad
938 if(time_num_max < time_num)
939 time_num_max = time_num;
942 if(pad_num <= 1 || time_num_max <=1 || n_overlaps > fNmaxOverlaps || ndata <= fit_pars) //too few to do fit
944 SetClusterfitFalse(track);
946 cout<<"Too few digits or too many overlaps: "<<pad_num<<" "<<time_num_max<<" "<<n_overlaps<<" ndata "<<ndata<<" fit_pars "<<fit_pars<<endl;
952 Int_t npars = n_overlaps * NUM_PARS;
954 cout<<"Number of overlapping clusters "<<n_overlaps<<endl;
955 Int_t ret = lev_marq_fit( x, y, s, ndata, a, lista, dev, npars, &chisq_f, f2gauss5 );
959 SetClusterfitFalse(track);
967 chisq_f /= (ndata-fit_pars);
969 cout<<"Chisq "<<chisq_f<<endl;
971 Bool_t overlapping=kFALSE;
972 if(track->GetNOverlaps(fCurrentPadRow) > 0)//There is a overlap
977 while(k < track->GetNOverlaps(fCurrentPadRow))
979 AliL3ModelTrack *tr=0;
983 tr = (AliL3ModelTrack*)fProcessTracks->GetCheckedTrack(overlaps[k]);
986 if(!tr->IsPresent(fCurrentPadRow))
988 if(tr->IsSet(fCurrentPadRow)) continue;//This cluster has been set before
991 if(fCurrentPadRow < AliL3Transform::GetNRowLow())
993 else if(fCurrentPadRow < AliL3Transform::GetNRowLow() + AliL3Transform::GetNRowUp1())
998 //if(chisq_f < fChiSqMax[(Int_t)overlapping])//cluster fit is good enough
999 if(chisq_f < fChiSqMax[lpatch])//cluster fit is good enough
1001 tot_charge = (Int_t)(2*AliL3Transform::Pi() * a[n_overlaps*NUM_PARS+1] * a[n_overlaps*NUM_PARS+3] * a[n_overlaps*NUM_PARS+5]);
1002 Float_t fpad = a[n_overlaps*NUM_PARS+2];
1003 Float_t ftime = a[n_overlaps*NUM_PARS+4];
1004 if(tot_charge < 0 || fpad < -1 || fpad > AliL3Transform::GetNPads(fCurrentPadRow) ||
1005 ftime < -1 || ftime > AliL3Transform::GetNTimeBins())
1008 cout<<"AliL3ClusterFitter::Fatal result(s) in fit; in slice "<<fSlice<<" row "<<fCurrentPadRow
1009 <<"; pad "<<fpad<<" time "<<ftime<<" charge "<<tot_charge<<" xywidth "<<a[n_overlaps*NUM_PARS+3]
1010 <<" zwidth "<<a[n_overlaps*NUM_PARS+5]<<" peakcharge "<<a[n_overlaps*NUM_PARS+1]<<endl;
1011 tr->SetCluster(fCurrentPadRow,0,0,0,0,0,0);
1017 tr->SetCluster(fCurrentPadRow,fpad,ftime,tot_charge,0,0,pad_num);
1019 tr->SetCluster(fCurrentPadRow,fpad,ftime,tot_charge,
1020 pow(a[n_overlaps*NUM_PARS+3],2),
1021 pow(a[n_overlaps*NUM_PARS+5],2),pad_num);
1025 cout<<"Setting cluster in slice "<<fSlice<<" row "<<fCurrentPadRow<<" pad "<<a[n_overlaps*NUM_PARS+2]<<" time "<<a[n_overlaps*NUM_PARS+4]
1026 <<" padwidth "<<a[n_overlaps*NUM_PARS+3]<<" timewidth "<<a[n_overlaps*NUM_PARS+5]
1027 <<" charge "<<tot_charge<<endl;
1030 //Set the digits to used:
1031 for(Int_t i=padrange[0]; i<=padrange[1]; i++)
1032 for(Int_t j=timerange[0]; j<=timerange[1]; j++)
1033 fRow[(AliL3Transform::GetNTimeBins()+1)*i + j].fUsed = kTRUE;
1037 else //fit was too bad
1040 cout<<"Cluster fit was too bad"<<endl;
1041 tr->SetCluster(fCurrentPadRow,0,0,0,0,0,0);
1052 void AliL3ClusterFitter::SetClusterfitFalse(AliL3ModelTrack *track)
1054 //Cluster fit failed, so set the clusters to all the participating
1058 Int_t *overlaps = track->GetOverlaps(fCurrentPadRow);
1059 while(i < track->GetNOverlaps(fCurrentPadRow))
1061 AliL3ModelTrack *tr=0;
1065 tr = (AliL3ModelTrack*)fProcessTracks->GetCheckedTrack(overlaps[i]);
1069 //Set the digit data to unused, so it can be fitted to another bastard:
1070 Int_t hitpad = (Int_t)rint(tr->GetClusterModel(fCurrentPadRow)->fDPad);
1071 Int_t hittime = (Int_t)rint(tr->GetClusterModel(fCurrentPadRow)->fDTime);
1072 fRow[(AliL3Transform::GetNTimeBins()+1)*hitpad + hittime].fUsed = kFALSE;
1074 tr->SetCluster(fCurrentPadRow,0,0,0,0,0,0);
1080 void AliL3ClusterFitter::AddClusters()
1084 fClusters = new AliL3SpacePointData[fNMaxClusters];
1089 cout<<"Writing cluster in slice "<<fSlice<<" patch "<<fPatch<<endl;
1091 AliL3TrackArray *tracks=0;
1100 for(Int_t i=0; i<tracks->GetNTracks(); i++)
1102 AliL3ModelTrack *tr = (AliL3ModelTrack*)tracks->GetCheckedTrack(i);
1105 UInt_t *hitids = tr->GetHitNumbers();
1106 Int_t nhits = tr->GetNHits();
1107 for(Int_t i=fRowMax; i>=fRowMin; i--)
1110 if(tr->GetClusterModel(i)->fSlice != fSlice) continue;
1111 if(!tr->IsPresent(i)) continue;
1113 Float_t pad,time,xywidth,zwidth;
1116 tr->GetTime(i,time);
1117 tr->GetClusterCharge(i,charge);
1119 if(pad < -1 || pad >= AliL3Transform::GetNPads(i) ||
1120 time < -1 || time >= AliL3Transform::GetNTimeBins())
1123 cout<<"slice "<<fSlice<<" row "<<i<<" pad "<<pad<<" time "<<time<<endl;
1128 tr->CalculateClusterWidths(i,kTRUE); //Parametrize errors
1130 tr->GetSigmaY2(i,xywidth);
1131 tr->GetSigmaZ2(i,zwidth);
1134 AliL3Transform::Slice2Sector(fSlice,i,sector,row);
1136 AliL3Transform::Raw2Local(xyz,sector,row,pad,time);
1138 if(fNClusters >= fNMaxClusters)
1140 cerr<<"AliL3ClusterFitter::AddClusters : Too many clusters "<<fNClusters<<endl;
1144 fClusters[fNClusters].fX = xyz[0];
1145 fClusters[fNClusters].fY = xyz[1];
1146 fClusters[fNClusters].fZ = xyz[2];
1147 fClusters[fNClusters].fCharge = charge;
1148 fClusters[fNClusters].fPadRow = i;
1149 Int_t pa = AliL3Transform::GetPatch(i);
1150 if(xywidth==0 || zwidth==0)
1151 cerr<<"AliL3ClusterFitter::AddClusters : Cluster with zero width"<<endl;
1153 fClusters[fNClusters].fSigmaY2 = xywidth*pow(AliL3Transform::GetPadPitchWidth(pa),2);
1155 fClusters[fNClusters].fSigmaY2 = 1;
1157 fClusters[fNClusters].fSigmaZ2 = zwidth*pow(AliL3Transform::GetZWidth(),2);
1159 fClusters[fNClusters].fSigmaZ2 = 1;
1163 fClusters[fNClusters].fID = fNClusters + ((fSlice&0x7f)<<25)+((pat&0x7)<<22);
1165 if(nhits >= AliL3Transform::GetNRows())
1167 cerr<<"AliL3ClusterFitter::AddClusters : Cluster counter of out range "<<nhits<<endl;
1170 hitids[nhits++] = fClusters[fNClusters].fID;
1174 Int_t fpad = (Int_t)rint(pad);
1175 Int_t ftime = (Int_t)rint(time);
1178 if(fpad >= AliL3Transform::GetNPads(i))
1179 fpad = AliL3Transform::GetNPads(i)-1;
1182 if(ftime >= AliL3Transform::GetNTimeBins())
1183 ftime = AliL3Transform::GetNTimeBins()-1;
1184 GetTrackID(fpad,ftime,trackID);
1185 fClusters[fNClusters].fTrackID[0] = trackID[0];
1186 fClusters[fNClusters].fTrackID[1] = trackID[1];
1187 fClusters[fNClusters].fTrackID[2] = trackID[2];
1189 //cout<<"Setting id "<<trackID[0]<<" on pad "<<pad<<" time "<<time<<" row "<<i<<endl;
1193 //Copy back the number of assigned clusters
1194 tr->SetNHits(nhits);
1199 void AliL3ClusterFitter::WriteTracks(Int_t min_hits)
1204 AliL3TrackArray *fakes = new AliL3TrackArray();
1206 Int_t clustercount=0;
1207 for(Int_t i=0; i<fSeeds->GetNTracks(); i++)
1209 AliL3ModelTrack *tr = (AliL3ModelTrack*)fSeeds->GetCheckedTrack(i);
1211 if(tr->GetNHits() < min_hits)
1216 clustercount += tr->GetNHits();
1219 cout<<"Writing "<<clustercount<<" clusters"<<endl;
1221 AliL3MemHandler mem;
1222 Char_t filename[1024];
1223 sprintf(filename,"%s/fitter/tracks_%d.raw",fPath,fEvent);
1224 mem.SetBinaryOutput(filename);
1225 mem.TrackArray2Binary(fSeeds);
1226 mem.CloseBinaryOutput();
1228 //Write the fake tracks to its own file
1230 sprintf(filename,"%s/fitter/tracks_fakes_%d.raw",fPath,fEvent);
1231 mem.SetBinaryOutput(filename);
1232 mem.TrackArray2Binary(fakes);
1233 mem.CloseBinaryOutput();
1237 void AliL3ClusterFitter::WriteClusters(Bool_t global)
1239 AliL3MemHandler mem;
1241 cout<<"Write "<<fNClusters<<" clusters to file"<<endl;
1242 Char_t filename[1024];
1243 sprintf(filename,"%s/fitter/points_%d_%d_%d.raw",fPath,fEvent,fSlice,fPatch);
1244 mem.SetBinaryOutput(filename);
1246 mem.Transform(fNClusters,fClusters,fSlice);
1247 mem.Memory2Binary(fNClusters,fClusters);
1248 mem.CloseBinaryOutput();
1251 delete [] fClusters;