3 // Author: Anders Vestbo <mailto:vestbo@fi.uib.no>
4 //*-- Copyright © ALICE HLT Group
5 /** /class AliHLTClusterFitter
7 //_____________________________________________________________
15 #include "AliHLTStandardIncludes.h"
17 #include "AliHLTClusterFitter.h"
18 #include "AliHLTFitUtilities.h"
19 #include "AliHLTDigitData.h"
20 #include "AliHLTModelTrack.h"
21 #include "AliHLTTrackArray.h"
22 #include "AliHLTMemHandler.h"
23 #include "AliHLTHoughTrack.h"
24 #include "AliHLTSpacePointData.h"
30 ClassImp(AliHLTClusterFitter)
32 Int_t AliHLTClusterFitter::fgBadFitError=0;
33 Int_t AliHLTClusterFitter::fgFitError=0;
34 Int_t AliHLTClusterFitter::fgResultError=0;
35 Int_t AliHLTClusterFitter::fgFitRangeError=0;
37 AliHLTClusterFitter::AliHLTClusterFitter()
39 // default constructor
42 fChiSqMax[0]=fChiSqMax[1]=fChiSqMax[2]=12;
59 AliHLTClusterFitter::AliHLTClusterFitter(Char_t *path)
65 fChiSqMax[0]=fChiSqMax[1]=fChiSqMax[2]=12;
82 AliHLTClusterFitter::~AliHLTClusterFitter()
91 void AliHLTClusterFitter::Init(Int_t slice,Int_t patch,Int_t *rowrange,AliHLTTrackArray *tracks)
93 //Assuming tracklets found by the line transform
98 if(rowrange[0] > AliHLTTransform::GetLastRow(patch) || rowrange[1] < AliHLTTransform::GetFirstRow(patch))
99 cerr<<"AliHLTClusterFitter::Init : Wrong rows "<<rowrange[0]<<" "<<rowrange[1]<<endl;
105 if(fRowMax > AliHLTTransform::GetLastRow(fPatch))
106 fRowMax = AliHLTTransform::GetLastRow(fPatch);
110 Int_t ntimes = AliHLTTransform::GetNTimeBins()+1;
111 Int_t npads = AliHLTTransform::GetNPads(AliHLTTransform::GetLastRow(fPatch))+1;//Max num of pads.
112 Int_t bounds = ntimes*npads;
115 fRow = new Digit[bounds];
119 fTracks = new AliHLTTrackArray("AliHLTModelTrack");
121 for(Int_t i=0; i<tracks->GetNTracks(); i++)
123 AliHLTHoughTrack *track = (AliHLTHoughTrack*)tracks->GetCheckedTrack(i);
125 AliHLTModelTrack *mtrack = (AliHLTModelTrack*)fTracks->NextTrack();
126 mtrack->Init(slice,patch);
127 mtrack->SetTgl(track->GetTgl());
128 mtrack->SetRowRange(rowrange[0],rowrange[1]);
129 for(Int_t j=fRowMin; j<=fRowMax; j++)
132 track->GetLineCrossingPoint(j,hit);
133 hit[0] += AliHLTTransform::Row2X(track->GetFirstRow());
134 Float_t r = sqrt(hit[0]*hit[0] + hit[1]*hit[1]);
135 hit[2] = r*track->GetTgl();
137 AliHLTTransform::Slice2Sector(slice,j,se,ro);
138 AliHLTTransform::Local2Raw(hit,se,ro);
139 if(hit[1]<0 || hit[1]>=AliHLTTransform::GetNPads(j) || hit[2]<0 || hit[2]>=AliHLTTransform::GetNTimeBins())
141 mtrack->SetPadHit(j,-1);
142 mtrack->SetTimeHit(j,-1);
145 mtrack->SetPadHit(j,hit[1]);
146 mtrack->SetTimeHit(j,hit[2]);
147 mtrack->SetCrossingAngleLUT(j,fabs(track->GetPsiLine() - AliHLTTransform::Pi()/2));
148 //if(mtrack->GetCrossingAngleLUT(j) > AliHLTTransform::Deg2Rad(20))
149 // cout<<"Angle "<<mtrack->GetCrossingAngleLUT(j)<<" psiline "<<track->GetPsiLine()*180/3.1415<<endl;
150 mtrack->CalculateClusterWidths(j);
153 // cout<<"Copied "<<fTracks->GetNTracks()<<" tracks "<<endl;
156 void AliHLTClusterFitter::Init(Int_t slice,Int_t patch)
162 fRowMin=AliHLTTransform::GetFirstRow(patch);
163 fRowMax=AliHLTTransform::GetLastRow(patch);
167 Int_t ntimes = AliHLTTransform::GetNTimeBins()+1;
168 Int_t npads = AliHLTTransform::GetNPads(AliHLTTransform::GetLastRow(fPatch))+1;//Max num of pads.
169 Int_t bounds = ntimes*npads;
172 fRow = new Digit[bounds];
175 fTracks = new AliHLTTrackArray("AliHLTModelTrack");
179 void AliHLTClusterFitter::LoadLocalSegments()
181 // loads local segments
182 Char_t filename[1024];
183 sprintf(filename,"%s/hough/tracks_ho_%d_%d_%d.raw",fPath,fEvent,fSlice,fPatch);
184 AliHLTMemHandler mem;
185 mem.SetBinaryInput(filename);
186 mem.Binary2TrackArray(fTracks);
187 mem.CloseBinaryInput();
189 for(Int_t i=0; i<fTracks->GetNTracks(); i++)
191 AliHLTModelTrack *track = (AliHLTModelTrack*)fTracks->GetCheckedTrack(i);
194 track->CalculateHelix();
196 track->Init(fSlice,fPatch);
198 for(Int_t j=fRowMin; j<=fRowMax; j++)
200 //Calculate the crossing point between track and padrow
203 if(!track->GetCrossingPoint(j,xyzCross))
207 AliHLTTransform::Slice2Sector(fSlice,j,sector,row);
208 AliHLTTransform::Local2Raw(xyzCross,sector,row);
210 if(xyzCross[1] < 0 || xyzCross[1] >= AliHLTTransform::GetNPads(j) ||
211 xyzCross[2] < 0 || xyzCross[2] >= AliHLTTransform::GetNTimeBins()) //track goes out of range
214 track->SetPadHit(j,xyzCross[1]);
215 track->SetTimeHit(j,xyzCross[2]);
217 Float_t crossingangle = track->GetCrossingAngle(j);
218 track->SetCrossingAngleLUT(j,crossingangle);
219 track->CalculateClusterWidths(j);
220 track->GetClusterModel(j)->fSlice = fSlice;
226 void AliHLTClusterFitter::LoadSeeds(Int_t *rowrange,Bool_t offline,Int_t eventnr,Float_t zvertex)
228 //Function assumes _global_ tracks written to a single file.
229 cout<<"Loading the seeds"<<endl;
234 sprintf(fname,"%s/offline/tracks_%d.raw",fPath,fEvent);
236 sprintf(fname,"%s/hough/tracks_%d.raw",fPath,fEvent);
238 cout<<"AliHLTClusterFitter::LoadSeeds : Loading input tracks from "<<fname<<endl;
240 AliHLTMemHandler tfile;
241 tfile.SetBinaryInput(fname);
245 fSeeds = new AliHLTTrackArray("AliHLTModelTrack");
247 tfile.Binary2TrackArray(fSeeds);
248 tfile.CloseBinaryInput();
253 Int_t clustercount=0;
254 for(Int_t i=0; i<fSeeds->GetNTracks(); i++)
256 AliHLTModelTrack *track = (AliHLTModelTrack*)fSeeds->GetCheckedTrack(i);
261 if(i==0) cerr<<"AliHLTClusterFitter::LoadSeeds : Cutting on pt of 4 GeV!!"<<endl;
262 if(track->GetPt() > 4.)
268 clustercount += track->GetNHits();
269 track->CalculateHelix();
271 Int_t nhits = track->GetNHits();
272 UInt_t *hitids = track->GetHitNumbers();
274 Int_t origslice = (hitids[nhits-1]>>25)&0x7f;//Slice of innermost point
276 if(i==0) cerr<<"Cluster fitter only in HALF TPC!!!"<<endl;
283 track->Init(origslice,-1);
284 Int_t slice = origslice;
286 //for(Int_t j=rowrange[1]; j>=rowrange[0]; j--)
287 for(Int_t j=rowrange[0]; j<=rowrange[1]; j++)
290 //Calculate the crossing point between track and padrow
291 Float_t angle = 0; //Perpendicular to padrow in local coordinates
292 AliHLTTransform::Local2GlobalAngle(&angle,slice);
293 if(!track->CalculateReferencePoint(angle,AliHLTTransform::Row2X(j)))
295 //cerr<<"No crossing in slice "<<slice<<" padrow "<<j<<endl;
300 Float_t xyzCross[3] = {track->GetPointX(),track->GetPointY(),track->GetPointZ()};
301 xyzCross[2] += zvertex;
304 AliHLTTransform::Slice2Sector(slice,j,sector,row);
305 AliHLTTransform::Global2Raw(xyzCross,sector,row);
306 //cout<<"Examining slice "<<slice<<" row "<<j<<" pad "<<xyzCross[1]<<" time "<<xyzCross[2]<<endl;
307 if(xyzCross[1] < 0 || xyzCross[1] >= AliHLTTransform::GetNPads(j)) //Track leaves the slice
312 Float_t lastcross=xyzCross[1];
331 if(slice < 0 || slice>35)
333 cerr<<"Wrong slice "<<slice<<" on row "<<j<<endl;
336 //cout<<"Track leaving, trying slice "<<slice<<endl;
338 AliHLTTransform::Local2GlobalAngle(&angle,slice);
339 if(!track->CalculateReferencePoint(angle,AliHLTTransform::Row2X(j)))
341 cerr<<"No crossing in slice "<<slice<<" padrow "<<j<<endl;
346 xyzCross[0] = track->GetPointX();
347 xyzCross[1] = track->GetPointY();
348 xyzCross[2] = track->GetPointZ();
349 xyzCross[2] += zvertex;
351 AliHLTTransform::Slice2Sector(slice,j,sector,row);
352 AliHLTTransform::Global2Raw(xyzCross,sector,row);
353 if(xyzCross[1] < 0 || xyzCross[1] >= AliHLTTransform::GetNPads(j)) //track is in the borderline
355 if(xyzCross[1] > 0 && lastcross > 0 || xyzCross[1] < 0 && lastcross < 0)
359 slice = tslice;//Track is on the border of two slices
365 if(xyzCross[2] < 0 || xyzCross[2] >= AliHLTTransform::GetNTimeBins())//track goes out of range
368 if(xyzCross[1] < 0 || xyzCross[1] >= AliHLTTransform::GetNPads(j))
370 cerr<<"Slice "<<slice<<" padrow "<<j<<" pad "<<xyzCross[1]<<" time "<<xyzCross[2]<<endl;
375 track->SetPadHit(j,xyzCross[1]);
376 track->SetTimeHit(j,xyzCross[2]);
378 AliHLTTransform::Local2GlobalAngle(&angle,slice);
379 Float_t crossingangle = track->GetCrossingAngle(j,slice);
380 track->SetCrossingAngleLUT(j,crossingangle);
382 track->CalculateClusterWidths(j);
384 track->GetClusterModel(j)->fSlice = slice;
387 memset(track->GetHitNumbers(),0,159*sizeof(UInt_t));//Reset the hitnumbers
392 cout<<"Loaded "<<fSeeds->GetNTracks()<<" seeds and "<<clustercount<<" clusters"<<endl;
395 void AliHLTClusterFitter::FindClusters()
400 cerr<<"AliHLTClusterFitter::Process : No tracks"<<endl;
405 cerr<<"AliHLTClusterFitter::Process : No data "<<endl;
409 AliHLTDigitRowData *rowPt = fRowData;
410 AliHLTDigitData *digPt=0;
417 fRowMin = AliHLTTransform::GetFirstRow(fPatch);
418 fRowMax = AliHLTTransform::GetLastRow(fPatch);
420 for(Int_t i=AliHLTTransform::GetFirstRow(fPatch); i<=AliHLTTransform::GetLastRow(fPatch); i++)
422 if((Int_t)rowPt->fRow < fRowMin)
424 AliHLTMemHandler::UpdateRowPointer(rowPt);
427 else if((Int_t)rowPt->fRow > fRowMax)
429 else if((Int_t)rowPt->fRow != i)
431 cerr<<"AliHLTClusterFitter::FindClusters : Mismatching row numbering "<<i<<" "<<rowPt->fRow<<endl;
435 memset((void*)fRow,0,(AliHLTTransform::GetNTimeBins()+1)*(AliHLTTransform::GetNPads(i)+1)*sizeof(Digit));
436 digPt = (AliHLTDigitData*)rowPt->fDigitData;
438 for(UInt_t j=0; j<rowPt->fNDigit; j++)
441 time = digPt[j].fTime;
442 charge = digPt[j].fCharge;
443 fRow[(AliHLTTransform::GetNTimeBins()+1)*pad+time].fCharge = charge;
444 fRow[(AliHLTTransform::GetNTimeBins()+1)*pad+time].fUsed = kFALSE;
445 //cout<<"Row "<<i<<" pad "<<pad<<" time "<<time<<" charge "<<charge<<endl;
448 for(Int_t it=0; it<2; it++)
452 fProcessTracks = fSeeds;
457 fProcessTracks = fTracks;
463 for(Int_t k=0; k<fProcessTracks->GetNTracks(); k++)
465 AliHLTModelTrack *track = (AliHLTModelTrack*)fProcessTracks->GetCheckedTrack(k);
469 if(track->GetClusterModel(i)->fSlice != fSlice) continue;
471 if(track->GetPadHit(i) < 0 || track->GetPadHit(i) > AliHLTTransform::GetNPads(i)-1 ||
472 track->GetTimeHit(i) < 0 || track->GetTimeHit(i) > AliHLTTransform::GetNTimeBins()-1)
474 track->SetCluster(i,0,0,0,0,0,0);
478 if(CheckCluster(k) == kFALSE)
482 AliHLTMemHandler::UpdateRowPointer(rowPt);
490 cout<<"Fitted "<<fFitted<<" clusters, failed "<<fFailed<<endl;
491 cout<<"Distribution:"<<endl;
492 cout<<"Bad fit "<<fgBadFitError<<endl;
493 cout<<"Fit error "<<fgFitError<<endl;
494 cout<<"Result error "<<fgResultError<<endl;
495 cout<<"Fit range error "<<fgFitRangeError<<endl;
499 Bool_t AliHLTClusterFitter::CheckCluster(Int_t trackindex)
501 //Check if this is a single or overlapping cluster
503 AliHLTModelTrack *track = (AliHLTModelTrack*)fProcessTracks->GetCheckedTrack(trackindex);
505 Int_t row = fCurrentPadRow;
507 if(track->IsSet(row)) //A fit has already be performed on this one
510 //Define the cluster region of this hit:
511 Int_t padr[2]={999,-1};
512 Int_t timer[2]={999,-1};
514 if(!SetFitRange(track,padr,timer))
516 track->SetCluster(fCurrentPadRow,0,0,0,0,0,0);
519 cout<<"Failed to fit cluster at row "<<row<<" pad "<<(Int_t)rint(track->GetPadHit(row))<<" time "
520 <<(Int_t)rint(track->GetTimeHit(row))<<" hitcharge "
521 <<fRow[(AliHLTTransform::GetNTimeBins()+1)*(Int_t)rint(track->GetPadHit(row))+(Int_t)rint(track->GetTimeHit(row))].fCharge<<endl;
526 //Check if any other track contributes to this cluster:
528 for(Int_t t=trackindex+1; t<fProcessTracks->GetNTracks(); t++)
530 AliHLTModelTrack *tr = (AliHLTModelTrack*)fProcessTracks->GetCheckedTrack(t);
533 if(tr->GetClusterModel(row)->fSlice != fSlice) continue;
535 if(tr->GetPadHit(row) > padr[0] && tr->GetPadHit(row) < padr[1] &&
536 tr->GetTimeHit(row) > timer[0] && tr->GetTimeHit(row) < timer[1])
538 if(SetFitRange(tr,padr,timer))
539 track->SetOverlap(row,t);
542 Int_t xyw = (Int_t)ceil(sqrt(tr->GetParSigmaY2(row))*GetYWidthFactor());
543 Int_t zw = (Int_t)ceil(sqrt(tr->GetParSigmaZ2(row))*GetZWidthFactor());
545 (tr->GetPadHit(row) - xyw > padr[0] && tr->GetPadHit(row) - xyw < padr[1] &&
546 tr->GetTimeHit(row) - zw > timer[0] && tr->GetTimeHit(row) - zw < timer[1]) ||
548 (tr->GetPadHit(row) + xyw > padr[0] && tr->GetPadHit(row) + xyw < padr[1] &&
549 tr->GetTimeHit(row) - zw > timer[0] && tr->GetTimeHit(row) - zw < timer[1]) ||
551 (tr->GetPadHit(row) - xyw > padr[0] && tr->GetPadHit(row) - xyw < padr[1] &&
552 tr->GetTimeHit(row) + zw > timer[0] && tr->GetTimeHit(row) + zw < timer[1]) ||
554 (tr->GetPadHit(row) + xyw > padr[0] && tr->GetPadHit(row) + xyw < padr[1] &&
555 tr->GetTimeHit(row) + zw > timer[0] && tr->GetTimeHit(row) + zw < timer[1])
559 if(SetFitRange(tr,padr,timer)) //Expand the cluster fit range
561 track->SetOverlap(row,t); //Set overlap
568 cout<<"Fitting cluster with "<<track->GetNOverlaps(fCurrentPadRow)<<" overlaps"<<endl;
570 FitClusters(track,padr,timer);
571 //CalculateWeightedMean(track,padr,timer);
575 Bool_t AliHLTClusterFitter::SetFitRange(AliHLTModelTrack *track,Int_t *padrange,Int_t *timerange)
577 // sets the fit range
578 Int_t row = fCurrentPadRow;
579 Int_t nt = AliHLTTransform::GetNTimeBins()+1;
582 if(row < AliHLTTransform::GetNRowLow())
584 else if(row < AliHLTTransform::GetNRowLow() + AliHLTTransform::GetNRowUp1())
590 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
591 ,0,1,2,3,3,3,3,3,3,3
593 ,-3,-3,-3,-3,-3,-3,-1,-1};
594 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
595 ,-3,-3,-3,-3,-2,-1,0,1,2,3
596 ,3,3,3,3,3,3,2,1,0,-1,-2,-3,-3,-3};
599 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
600 ,-3,3,-3,3,-3,3,-3,3,-3,3
601 ,0,0,-1,-1,1,1,-2,-2,2,2,-3,-3,3,3};
602 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
603 ,0,0,-1,-1,1,1,-2,-2,2,2
604 ,-3,3,-3,3,-3,3,-3,3,-3,3,-3,3,-3,3};
606 Int_t padhit = (Int_t)rint(track->GetPadHit(row));
607 Int_t timehit = (Int_t)rint(track->GetTimeHit(row));
611 for(Int_t index=0; index<nsearchbins; index++)
613 if(IsMaximum(padhit + padloop[index],timehit + timeloop[index]))
615 padmax = padhit + padloop[index];
616 timemax = timehit + timeloop[index];
622 //Define the cluster region of this hit:
623 //The region we look for, is centered at the local maxima
624 //and expanded around using the parametrized cluster width
625 //according to track parameters.
630 if(padmax>=0 && timemax>=0)
632 //Set the hit to the local maxima of the cluster.
633 //Store the maxima in the cluster model structure,
634 //-only temporary, it will be overwritten when calling SetCluster.
636 track->GetClusterModel(row)->fDPad = padmax;
637 track->GetClusterModel(row)->fDTime = timemax;
639 Int_t i=padmax,j=timemax;
640 for(Int_t pdir=-1; pdir<=1; pdir+=2)
643 while(abs(padmax-i) < xyw)
645 Bool_t chargeonpad=kFALSE;
646 for(Int_t tdir=-1; tdir<=1; tdir+=2)
649 while(abs(timemax-j) < zw)
651 if(i<0 || i>=AliHLTTransform::GetNPads(row) || j<0 || j>=AliHLTTransform::GetNTimeBins()) break;
652 if(fRow[nt*i+j].fCharge)
654 if(i < padrange[0]) padrange[0]=i;
655 if(i > padrange[1]) padrange[1]=i;
656 if(j < timerange[0]) timerange[0]=j;
657 if(j > timerange[1]) timerange[1]=j;
671 for(Int_t i=padmax-xyw; i<=padmax+xyw; i++)
673 for(Int_t j=timemax-zw; j<=timemax+zw; j++)
675 if(i<0 || i>=AliHLTTransform::GetNPads(row) || j<0 || j>=AliHLTTransform::GetNTimeBins()) continue;
676 if(fRow[nt*i+j].fCharge)
678 if(i < padrange[0]) padrange[0]=i;
679 if(i > padrange[1]) padrange[1]=i;
680 if(j < timerange[0]) timerange[0]=j;
681 if(j > timerange[1]) timerange[1]=j;
688 cout<<"New padrange "<<padrange[0]<<" "<<padrange[1]<<" "<<" time "<<timerange[0]<<" "<<timerange[1]<<endl;
694 Bool_t AliHLTClusterFitter::IsMaximum(Int_t pad,Int_t time)
696 // checks the maximum
697 if(pad<0 || pad >= AliHLTTransform::GetNPads(fCurrentPadRow) ||
698 time<0 || time >= AliHLTTransform::GetNTimeBins())
700 Int_t nt = AliHLTTransform::GetNTimeBins()+1;
701 if(fRow[nt*pad+time].fUsed == kTRUE) return kFALSE; //Peak has been assigned before
702 Int_t charge = fRow[nt*pad+time].fCharge;
703 if(charge == 1024 || charge==0) return kFALSE;
704 //if(charge == 0) return kFALSE;
706 //fRow[nt*pad+time].fUsed = kTRUE;
709 if(charge < fRow[nt*(pad-1)+(time-1)].fCharge) return kFALSE;
710 if(charge < fRow[nt*(pad)+(time-1)].fCharge) return kFALSE;
711 if(charge < fRow[nt*(pad+1)+(time-1)].fCharge) return kFALSE;
712 if(charge < fRow[nt*(pad-1)+(time)].fCharge) return kFALSE;
713 if(charge < fRow[nt*(pad+1)+(time)].fCharge) return kFALSE;
714 if(charge < fRow[nt*(pad-1)+(time+1)].fCharge) return kFALSE;
715 if(charge < fRow[nt*(pad)+(time+1)].fCharge) return kFALSE;
716 if(charge < fRow[nt*(pad+1)+(time+1)].fCharge) return kFALSE;
717 fRow[nt*pad+time].fUsed = kTRUE;
721 void AliHLTClusterFitter::CalculateWeightedMean(AliHLTModelTrack *track,Int_t *padrange,Int_t *timerange)
723 // calculates weighted mean
726 Float_t pad=0,time=0;
727 Int_t nt = AliHLTTransform::GetNTimeBins()+1;
728 for(Int_t i=padrange[0]; i<=padrange[1]; i++)
731 for(Int_t j=timerange[0]; j<=timerange[1]; j++)
733 lsum += fRow[nt*(i-1)+(j-1)].fCharge;
734 time += j*fRow[nt*(i-1)+(j-1)].fCharge;
744 track->SetCluster(fCurrentPadRow,pad,time,sum,0,0,npads);
747 track->SetCluster(fCurrentPadRow,0,0,0,0,0,0);
750 void AliHLTClusterFitter::FitClusters(AliHLTModelTrack *track,Int_t *padrange,Int_t *timerange)
752 //Handle single and overlapping clusters
755 if( (Int_t)rint(track->GetClusterModel(fCurrentPadRow)->fDPad) <= 1 ||
756 (Int_t)rint(track->GetClusterModel(fCurrentPadRow)->fDPad) >= AliHLTTransform::GetNPads(fCurrentPadRow)-2 ||
757 (Int_t)rint(track->GetClusterModel(fCurrentPadRow)->fDTime) <= 1 ||
758 (Int_t)rint(track->GetClusterModel(fCurrentPadRow)->fDTime) >= AliHLTTransform::GetNTimeBins()-2)
760 CalculateWeightedMean(track,padrange,timerange);
764 Int_t size = FIT_PTS;
765 Int_t maxTracks = FIT_MAXPAR/NUM_PARS;
766 if(track->GetNOverlaps(fCurrentPadRow) > maxTracks)
768 cerr<<"AliHLTClusterFitter::FitOverlappingClusters : Too many overlapping tracks"<<endl;
771 Int_t *overlaps = track->GetOverlaps(fCurrentPadRow);
773 //Check if at least one cluster is not already fitted
774 Bool_t allFitted=kTRUE;
777 while(k < track->GetNOverlaps(fCurrentPadRow))
779 AliHLTModelTrack *tr=0;
783 tr = (AliHLTModelTrack*)fProcessTracks->GetCheckedTrack(overlaps[k]);
786 if(!tr->IsSet(fCurrentPadRow) && !tr->IsPresent(fCurrentPadRow))//cluster has not been set and is not present
795 cout<<"But all the clusters were already fitted on row "<<fCurrentPadRow<<endl;
799 //Allocate fit parameters array; this is interface to the C code
800 plane = new DPOINT[FIT_PTS];
801 memset(plane,0,FIT_PTS*sizeof(DPOINT));
803 Double_t x[FIT_PTS],y[FIT_PTS],s[FIT_PTS];
805 //Fill the fit parameters:
806 Double_t a[FIT_MAXPAR];
807 Int_t lista[FIT_MAXPAR];
808 Double_t dev[FIT_MAXPAR],chisqF;
815 //Fill the overlapping tracks:
816 while(k < track->GetNOverlaps(fCurrentPadRow))
818 AliHLTModelTrack *tr=0;
822 tr = (AliHLTModelTrack*)fProcessTracks->GetCheckedTrack(overlaps[k]);
826 if(tr->IsSet(fCurrentPadRow) && !tr->IsPresent(fCurrentPadRow)) continue;//Cluster fit failed before
828 //Use the local maxima as the input to the fitting routine.
829 //The local maxima is temporary stored in the cluster model:
830 Int_t hitpad = (Int_t)rint(tr->GetClusterModel(fCurrentPadRow)->fDPad);
831 Int_t hittime = (Int_t)rint(tr->GetClusterModel(fCurrentPadRow)->fDTime);
832 Int_t charge = fRow[(AliHLTTransform::GetNTimeBins()+1)*hitpad + hittime].fCharge;
835 cout<<"Fitting track cluster, pad "<<tr->GetPadHit(fCurrentPadRow)<<" time "
836 <<tr->GetTimeHit(fCurrentPadRow)<<" charge "<<charge<<" at local maxima in pad "<<hitpad
837 <<" time "<<hittime<<" xywidth "<<sqrt(tr->GetParSigmaY2(fCurrentPadRow))
838 <<" zwidth "<<sqrt(tr->GetParSigmaZ2(fCurrentPadRow))<<endl;
842 cerr<<"Charge still zero!"<<endl;
846 a[nOverlaps*NUM_PARS+2] = hitpad;
847 a[nOverlaps*NUM_PARS+4] = hittime;
849 if(!tr->IsSet(fCurrentPadRow)) //Cluster is not fitted before
851 a[nOverlaps*NUM_PARS+1] = charge;
852 a[nOverlaps*NUM_PARS+3] = sqrt(tr->GetParSigmaY2(fCurrentPadRow)) * GetYWidthFactor();
853 a[nOverlaps*NUM_PARS+5] = sqrt(tr->GetParSigmaZ2(fCurrentPadRow)) * GetZWidthFactor();
854 //a[nOverlaps*NUM_PARS+6] = sqrt(tr->GetParSigmaZ2(fCurrentPadRow)) * GetZWidthFactor();
855 lista[nOverlaps*NUM_PARS + 1] = 1;
856 lista[nOverlaps*NUM_PARS + 2] = 1;
857 lista[nOverlaps*NUM_PARS + 3] = 0;
858 lista[nOverlaps*NUM_PARS + 4] = 1;
859 lista[nOverlaps*NUM_PARS + 5] = 0;
860 //lista[nOverlaps*NUM_PARS + 6] = 0;
861 fitPars += 3; //<-------------------
863 else //Cluster was fitted before
865 if(!tr->IsPresent(fCurrentPadRow))
867 cerr<<"AliHLTClusterFitter::FindClusters : Cluster not present; there is a bug here"<<endl;
871 Float_t xywidth,zwidth,pad,time;
872 tr->GetPad(fCurrentPadRow,pad);
873 tr->GetTime(fCurrentPadRow,time);
874 tr->GetClusterCharge(fCurrentPadRow,charge);
875 xywidth = sqrt(tr->GetParSigmaY2(fCurrentPadRow));
876 zwidth = sqrt(tr->GetParSigmaZ2(fCurrentPadRow));
878 cout<<endl<<"Cluster had been fitted before, pad "<<pad<<" time "<<time<<" charge "<<charge<<" width "<<xywidth<<" "<<zwidth<<endl;
880 a[nOverlaps*NUM_PARS+2] = pad;
881 a[nOverlaps*NUM_PARS+4] = time;
882 a[nOverlaps*NUM_PARS+1] = charge;
883 a[nOverlaps*NUM_PARS+3] = xywidth * GetYWidthFactor();
884 a[nOverlaps*NUM_PARS+5] = zwidth * GetZWidthFactor();
885 //a[nOverlaps*NUM_PARS+6] = zwidth * GetZWidthFactor();
887 lista[nOverlaps*NUM_PARS + 1] = 1;
888 lista[nOverlaps*NUM_PARS + 2] = 0;
889 lista[nOverlaps*NUM_PARS + 3] = 0;
890 lista[nOverlaps*NUM_PARS + 4] = 0;
891 lista[nOverlaps*NUM_PARS + 5] = 0;
892 //lista[nOverlaps*NUM_PARS + 6] = 0;
898 if(nOverlaps==0) //No clusters here
909 cout<<"Padrange "<<padrange[0]<<" "<<padrange[1]<<" timerange "<<timerange[0]<<" "<<timerange[1]<<endl;
910 for(Int_t i=padrange[0]; i<=padrange[1]; i++)
914 for(Int_t j=timerange[0]; j<=timerange[1]; j++)
916 Int_t charge = fRow[(AliHLTTransform::GetNTimeBins()+1)*i + j].fCharge;
918 if(charge <= 0) continue;
921 if(charge > maxCharge)
927 cout<<"Filling padrow "<<fCurrentPadRow<<" pad "<<i<<" time "<<j<<" charge "<<charge<<endl;
932 cerr<<"Too many points; row "<<fCurrentPadRow<<" padrange "<<padrange[0]<<" "<<padrange[1]<<" timerange "
933 <<timerange[0]<<" "<<timerange[1]<<endl;
937 plane[ndata].u = (Double_t)i;
938 plane[ndata].v = (Double_t)j;
941 s[ndata]= 1 + sqrt((Double_t)charge);
943 if(maxCharge) //there was charge on this pad
945 if(timeNumMax < timeNum)
946 timeNumMax = timeNum;
949 if(padNum <= 1 || timeNumMax <=1 || nOverlaps > fNmaxOverlaps || ndata <= fitPars) //too few to do fit
951 SetClusterfitFalse(track);
953 cout<<"Too few digits or too many overlaps: "<<padNum<<" "<<timeNumMax<<" "<<nOverlaps<<" ndata "<<ndata<<" fitPars "<<fitPars<<endl;
959 Int_t npars = nOverlaps * NUM_PARS;
961 cout<<"Number of overlapping clusters "<<nOverlaps<<endl;
962 Int_t ret = lev_marq_fit( x, y, s, ndata, a, lista, dev, npars, &chisqF, f2gauss5 );
966 SetClusterfitFalse(track);
974 chisqF /= (ndata-fitPars);
976 cout<<"Chisq "<<chisqF<<endl;
978 Bool_t overlapping=kFALSE;
979 if(track->GetNOverlaps(fCurrentPadRow) > 0)//There is a overlap
984 while(k < track->GetNOverlaps(fCurrentPadRow))
986 AliHLTModelTrack *tr=0;
990 tr = (AliHLTModelTrack*)fProcessTracks->GetCheckedTrack(overlaps[k]);
993 if(!tr->IsPresent(fCurrentPadRow))
995 if(tr->IsSet(fCurrentPadRow)) continue;//This cluster has been set before
998 if(fCurrentPadRow < AliHLTTransform::GetNRowLow())
1000 else if(fCurrentPadRow < AliHLTTransform::GetNRowLow() + AliHLTTransform::GetNRowUp1())
1005 //if(chisqF < fChiSqMax[(Int_t)overlapping])//cluster fit is good enough
1006 if(chisqF < fChiSqMax[lpatch])//cluster fit is good enough
1008 totCharge = (Int_t)(2*AliHLTTransform::Pi() * a[nOverlaps*NUM_PARS+1] * a[nOverlaps*NUM_PARS+3] * a[nOverlaps*NUM_PARS+5]);
1009 Float_t fpad = a[nOverlaps*NUM_PARS+2];
1010 Float_t ftime = a[nOverlaps*NUM_PARS+4];
1011 if(totCharge < 0 || fpad < -1 || fpad > AliHLTTransform::GetNPads(fCurrentPadRow) ||
1012 ftime < -1 || ftime > AliHLTTransform::GetNTimeBins())
1015 cout<<"AliHLTClusterFitter::Fatal result(s) in fit; in slice "<<fSlice<<" row "<<fCurrentPadRow
1016 <<"; pad "<<fpad<<" time "<<ftime<<" charge "<<totCharge<<" xywidth "<<a[nOverlaps*NUM_PARS+3]
1017 <<" zwidth "<<a[nOverlaps*NUM_PARS+5]<<" peakcharge "<<a[nOverlaps*NUM_PARS+1]<<endl;
1018 tr->SetCluster(fCurrentPadRow,0,0,0,0,0,0);
1024 tr->SetCluster(fCurrentPadRow,fpad,ftime,totCharge,0,0,padNum);
1026 tr->SetCluster(fCurrentPadRow,fpad,ftime,totCharge,
1027 pow(a[nOverlaps*NUM_PARS+3],2),
1028 pow(a[nOverlaps*NUM_PARS+5],2),padNum);
1032 cout<<"Setting cluster in slice "<<fSlice<<" row "<<fCurrentPadRow<<" pad "<<a[nOverlaps*NUM_PARS+2]<<" time "<<a[nOverlaps*NUM_PARS+4]
1033 <<" padwidth "<<a[nOverlaps*NUM_PARS+3]<<" timewidth "<<a[nOverlaps*NUM_PARS+5]
1034 <<" charge "<<totCharge<<endl;
1037 //Set the digits to used:
1038 for(Int_t i=padrange[0]; i<=padrange[1]; i++)
1039 for(Int_t j=timerange[0]; j<=timerange[1]; j++)
1040 fRow[(AliHLTTransform::GetNTimeBins()+1)*i + j].fUsed = kTRUE;
1044 else //fit was too bad
1047 cout<<"Cluster fit was too bad"<<endl;
1048 tr->SetCluster(fCurrentPadRow,0,0,0,0,0,0);
1059 void AliHLTClusterFitter::SetClusterfitFalse(AliHLTModelTrack *track)
1061 //Cluster fit failed, so set the clusters to all the participating
1065 Int_t *overlaps = track->GetOverlaps(fCurrentPadRow);
1066 while(i < track->GetNOverlaps(fCurrentPadRow))
1068 AliHLTModelTrack *tr=0;
1072 tr = (AliHLTModelTrack*)fProcessTracks->GetCheckedTrack(overlaps[i]);
1076 //Set the digit data to unused, so it can be fitted to another bastard:
1077 Int_t hitpad = (Int_t)rint(tr->GetClusterModel(fCurrentPadRow)->fDPad);
1078 Int_t hittime = (Int_t)rint(tr->GetClusterModel(fCurrentPadRow)->fDTime);
1079 fRow[(AliHLTTransform::GetNTimeBins()+1)*hitpad + hittime].fUsed = kFALSE;
1081 tr->SetCluster(fCurrentPadRow,0,0,0,0,0,0);
1087 void AliHLTClusterFitter::AddClusters()
1092 fClusters = new AliHLTSpacePointData[fNMaxClusters];
1097 cout<<"Writing cluster in slice "<<fSlice<<" patch "<<fPatch<<endl;
1099 AliHLTTrackArray *tracks=0;
1108 for(Int_t i=0; i<tracks->GetNTracks(); i++)
1110 AliHLTModelTrack *tr = (AliHLTModelTrack*)tracks->GetCheckedTrack(i);
1113 UInt_t *hitids = tr->GetHitNumbers();
1114 Int_t nhits = tr->GetNHits();
1115 for(Int_t i=fRowMax; i>=fRowMin; i--)
1118 if(tr->GetClusterModel(i)->fSlice != fSlice) continue;
1119 if(!tr->IsPresent(i)) continue;
1121 Float_t pad,time,xywidth,zwidth;
1124 tr->GetTime(i,time);
1125 tr->GetClusterCharge(i,charge);
1127 if(pad < -1 || pad >= AliHLTTransform::GetNPads(i) ||
1128 time < -1 || time >= AliHLTTransform::GetNTimeBins())
1131 // cout<<"slice "<<fSlice<<" row "<<i<<" pad "<<pad<<" time "<<time<<endl;
1136 tr->CalculateClusterWidths(i,kTRUE); //Parametrize errors
1138 tr->GetSigmaY2(i,xywidth);
1139 tr->GetSigmaZ2(i,zwidth);
1142 AliHLTTransform::Slice2Sector(fSlice,i,sector,row);
1144 AliHLTTransform::Raw2Local(xyz,sector,row,pad,time);
1146 if(fNClusters >= fNMaxClusters)
1148 cerr<<"AliHLTClusterFitter::AddClusters : Too many clusters "<<fNClusters<<endl;
1152 fClusters[fNClusters].fX = xyz[0];
1153 fClusters[fNClusters].fY = xyz[1];
1154 fClusters[fNClusters].fZ = xyz[2];
1155 fClusters[fNClusters].fCharge = charge;
1156 fClusters[fNClusters].fPadRow = i;
1157 Int_t pa = AliHLTTransform::GetPatch(i);
1158 if(xywidth==0 || zwidth==0)
1159 cerr<<"AliHLTClusterFitter::AddClusters : Cluster with zero width"<<endl;
1161 fClusters[fNClusters].fSigmaY2 = xywidth*pow(AliHLTTransform::GetPadPitchWidth(pa),2);
1163 fClusters[fNClusters].fSigmaY2 = 1;
1165 fClusters[fNClusters].fSigmaZ2 = zwidth*pow(AliHLTTransform::GetZWidth(),2);
1167 fClusters[fNClusters].fSigmaZ2 = 1;
1171 fClusters[fNClusters].fID = fNClusters + ((fSlice&0x7f)<<25)+((pat&0x7)<<22);
1173 if(nhits >= AliHLTTransform::GetNRows())
1175 cerr<<"AliHLTClusterFitter::AddClusters : Cluster counter of out range "<<nhits<<endl;
1178 hitids[nhits++] = fClusters[fNClusters].fID;
1182 Int_t fpad = (Int_t)rint(pad);
1183 Int_t ftime = (Int_t)rint(time);
1186 if(fpad >= AliHLTTransform::GetNPads(i))
1187 fpad = AliHLTTransform::GetNPads(i)-1;
1190 if(ftime >= AliHLTTransform::GetNTimeBins())
1191 ftime = AliHLTTransform::GetNTimeBins()-1;
1192 GetTrackID(fpad,ftime,trackID);
1193 fClusters[fNClusters].fTrackID[0] = trackID[0];
1194 fClusters[fNClusters].fTrackID[1] = trackID[1];
1195 fClusters[fNClusters].fTrackID[2] = trackID[2];
1197 //cout<<"Setting id "<<trackID[0]<<" on pad "<<pad<<" time "<<time<<" row "<<i<<endl;
1201 //Copy back the number of assigned clusters
1202 tr->SetNHits(nhits);
1207 void AliHLTClusterFitter::WriteTracks(Int_t minHits)
1213 AliHLTTrackArray *fakes = new AliHLTTrackArray();
1215 Int_t clustercount=0;
1216 for(Int_t i=0; i<fSeeds->GetNTracks(); i++)
1218 AliHLTModelTrack *tr = (AliHLTModelTrack*)fSeeds->GetCheckedTrack(i);
1220 if(tr->GetNHits() < minHits)
1225 clustercount += tr->GetNHits();
1228 cout<<"Writing "<<clustercount<<" clusters"<<endl;
1230 AliHLTMemHandler mem;
1231 Char_t filename[1024];
1232 sprintf(filename,"%s/fitter/tracks_%d.raw",fPath,fEvent);
1233 mem.SetBinaryOutput(filename);
1234 mem.TrackArray2Binary(fSeeds);
1235 mem.CloseBinaryOutput();
1237 //Write the fake tracks to its own file
1239 sprintf(filename,"%s/fitter/tracks_fakes_%d.raw",fPath,fEvent);
1240 mem.SetBinaryOutput(filename);
1241 mem.TrackArray2Binary(fakes);
1242 mem.CloseBinaryOutput();
1246 void AliHLTClusterFitter::WriteClusters(Bool_t global)
1249 AliHLTMemHandler mem;
1251 cout<<"Write "<<fNClusters<<" clusters to file"<<endl;
1252 Char_t filename[1024];
1253 sprintf(filename,"%s/fitter/points_%d_%d_%d.raw",fPath,fEvent,fSlice,fPatch);
1254 mem.SetBinaryOutput(filename);
1256 mem.Transform(fNClusters,fClusters,fSlice);
1257 mem.Memory2Binary(fNClusters,fClusters);
1258 mem.CloseBinaryOutput();
1261 delete [] fClusters;