3 // Author: Anders Vestbo <mailto:vestbo@fi.uib.no>
4 //*-- Copyright © ALICE HLT Group
6 #include "AliL3StandardIncludes.h"
8 #include "AliL3Logging.h"
9 #include "AliL3HoughTransformer.h"
10 #include "AliL3MemHandler.h"
11 #include "AliL3Transform.h"
12 #include "AliL3DigitData.h"
13 #include "AliL3HistogramAdaptive.h"
19 /** \class AliL3HoughTransformer
21 //_____________________________________________________________
22 // AliL3HoughTransformer
24 // Hough transformation class
29 ClassImp(AliL3HoughTransformer)
31 AliL3HoughTransformer::AliL3HoughTransformer()
42 AliL3HoughTransformer::AliL3HoughTransformer(Int_t slice,Int_t patch,Int_t n_eta_segments,Bool_t DoEtaOverlap,Bool_t /*DoMC*/) : AliL3HoughBaseTransformer(slice,patch,n_eta_segments)
47 fEtaOverlap = DoEtaOverlap;
54 AliL3HoughTransformer::~AliL3HoughTransformer()
60 for(Int_t i=0; i<GetNEtaSegments(); i++)
62 if(!fTrackID[i]) continue;
70 void AliL3HoughTransformer::DeleteHistograms()
74 for(Int_t i=0; i<GetNEtaSegments(); i++)
76 if(!fParamSpace[i]) continue;
77 delete fParamSpace[i];
79 delete [] fParamSpace;
82 void AliL3HoughTransformer::CreateHistograms(Float_t ptmin,Float_t ptmax,Float_t ptres,
83 Int_t nybin,Float_t psi)
86 //_Only_ to be used in case of the adaptive histograms!
87 //phimax is given in radians!!
91 cerr<<"AliL3HoughTransformer::CreateHistograms: Error in ptrange "<<ptmin<<" "<<ptmax<<endl;
96 cerr<<"AliL3HoughTransformer::CreateHistograms: Wrong psi-angle "<<psi<<endl;
100 fParamSpace = new AliL3Histogram*[GetNEtaSegments()];
101 Char_t histname[256];
103 for(i=0; i<GetNEtaSegments(); i++)
105 sprintf(histname,"paramspace_%d",i);
106 fParamSpace[i] = new AliL3HistogramAdaptive(histname,ptmin,ptmax,ptres,nybin,-psi,psi);
110 void AliL3HoughTransformer::CreateHistograms(Int_t nxbin,Float_t pt_min,
111 Int_t nybin,Float_t phimin,Float_t phimax)
113 //Create the histograms (parameter space).
114 //These are 2D histograms, span by kappa (curvature of track) and phi0 (emission angle with x-axis).
115 //The arguments give the range and binning;
116 //nxbin = #bins in kappa
117 //nybin = #bins in phi0
118 //pt_min = mimium Pt of track (corresponding to maximum kappa)
119 //phi_min = mimimum phi0
120 //phi_max = maximum phi0
122 Double_t x = AliL3Transform::GetBFact()*AliL3Transform::GetBField()/pt_min;
123 //Double_t torad = AliL3Transform::Pi()/180;
125 CreateHistograms(nxbin,-1.*x,x,nybin,phimin/**torad*/,phimax/**torad*/);
128 void AliL3HoughTransformer::CreateHistograms(Int_t nxbin,Float_t xmin,Float_t xmax,
129 Int_t nybin,Float_t ymin,Float_t ymax)
132 fParamSpace = new AliL3Histogram*[GetNEtaSegments()];
134 Char_t histname[256];
135 for(Int_t i=0; i<GetNEtaSegments(); i++)
137 sprintf(histname,"paramspace_%d",i);
138 //fParamSpace[i] = new AliL3HistogramAdaptive(histname,0.5,1.5,0.05,nybin,ymin,ymax);
139 fParamSpace[i] = new AliL3Histogram(histname,"",nxbin,xmin,xmax,nybin,ymin,ymax);
145 AliL3Histogram *hist = fParamSpace[0];
146 Int_t ncells = (hist->GetNbinsX()+2)*(hist->GetNbinsY()+2);
147 cout<<"Transformer: Allocating "<<GetNEtaSegments()*ncells*sizeof(TrackIndex)<<" bytes to fTrackID"<<endl;
148 fTrackID = new TrackIndex*[GetNEtaSegments()];
149 for(Int_t i=0; i<GetNEtaSegments(); i++)
150 fTrackID[i] = new TrackIndex[ncells];
155 void AliL3HoughTransformer::Reset()
157 //Reset all the histograms
161 LOG(AliL3Log::kWarning,"AliL3HoughTransformer::Reset","Histograms")
162 <<"No histograms to reset"<<ENDLOG;
166 for(Int_t i=0; i<GetNEtaSegments(); i++)
167 fParamSpace[i]->Reset();
172 AliL3Histogram *hist = fParamSpace[0];
173 Int_t ncells = (hist->GetNbinsX()+2)*(hist->GetNbinsY()+2);
174 for(Int_t i=0; i<GetNEtaSegments(); i++)
175 memset(fTrackID[i],0,ncells*sizeof(TrackIndex));
180 Int_t AliL3HoughTransformer::GetEtaIndex(Double_t eta)
182 //Return the histogram index of the corresponding eta.
184 Double_t etaslice = (GetEtaMax() - GetEtaMin())/GetNEtaSegments();
185 Double_t index = (eta-GetEtaMin())/etaslice;
189 void AliL3HoughTransformer::GetEtaIndexes(Double_t eta,Int_t *indexes)
191 //Return histogram indexes in case of overlapping etaslices.
193 Double_t etaslice = (GetEtaMax() - GetEtaMin())/GetNEtaSegments();
194 Int_t index = (Int_t)((eta-GetEtaMin())/etaslice);
198 indexes[1] = index - 1;
202 indexes[0] = index - 1;
207 inline AliL3Histogram *AliL3HoughTransformer::GetHistogram(Int_t eta_index)
209 if(!fParamSpace || eta_index >= GetNEtaSegments() || eta_index < 0)
211 if(!fParamSpace[eta_index])
213 return fParamSpace[eta_index];
216 Double_t AliL3HoughTransformer::GetEta(Int_t eta_index,Int_t /*slice*/)
218 Double_t eta_slice = (GetEtaMax()-GetEtaMin())/GetNEtaSegments();
222 Int_t index = eta_index + 1;
223 eta=(Double_t)((index)*eta_slice);
226 eta=(Double_t)((eta_index+0.5)*eta_slice);
230 void AliL3HoughTransformer::TransformCircle()
232 //Transform the input data with a circle HT.
233 //The function loops over all the data, and transforms each pixel with the equations:
235 //kappa = 2/R*sin(phi - phi0)
237 //where R = sqrt(x*x +y*y), and phi = arctan(y/x)
239 //Each pixel then transforms into a curve in the (kappa,phi0)-space. In order to find
240 //which histogram in which the pixel should be transformed, the eta-value is calculated
241 //and the proper histogram index is found by GetEtaIndex(eta).
244 AliL3DigitRowData *tempPt = GetDataPointer();
247 LOG(AliL3Log::kError,"AliL3HoughTransformer::TransformCircle","Data")
248 <<"No input data "<<ENDLOG;
252 //Loop over the padrows:
253 for(Int_t i=AliL3Transform::GetFirstRow(GetPatch()); i<=AliL3Transform::GetLastRow(GetPatch()); i++)
255 //Get the data on this padrow:
256 AliL3DigitData *digPt = tempPt->fDigitData;
257 if(i != (Int_t)tempPt->fRow)
259 cerr<<"AliL3HoughTransform::TransformCircle : Mismatching padrow numbering "<<i<<" "<<(Int_t)tempPt->fRow<<endl;
263 //Loop over the data on this padrow:
264 for(UInt_t j=0; j<tempPt->fNDigit; j++)
266 UShort_t charge = digPt[j].fCharge;
267 UChar_t pad = digPt[j].fPad;
268 UShort_t time = digPt[j].fTime;
269 if((Int_t)charge <= GetLowerThreshold())
272 if((Int_t)charge > GetUpperThreshold())
273 charge = GetUpperThreshold();
278 //Transform data to local cartesian coordinates:
279 AliL3Transform::Slice2Sector(GetSlice(),i,sector,row);
280 AliL3Transform::Raw2Local(xyz,sector,row,(Int_t)pad,(Int_t)time);
283 Double_t eta = AliL3Transform::GetEta(xyz);
285 //Get the corresponding index, which determines which histogram to fill:
286 Int_t eta_index = GetEtaIndex(eta);
288 if(eta_index < 0 || eta_index >= GetNEtaSegments())
291 //Get the correct histogrampointer:
292 AliL3Histogram *hist = fParamSpace[eta_index];
295 cerr<<"AliL3HoughTransformer::TransformCircle : Error getting histogram in index "<<eta_index<<endl;
299 //Do the transformation:
300 Float_t R = sqrt(xyz[0]*xyz[0] + xyz[1]*xyz[1]);
301 Float_t phi = AliL3Transform::GetPhi(xyz);
304 //Fill the histogram along the phirange
305 for(Int_t b=hist->GetFirstYbin(); b<=hist->GetLastYbin(); b++)
307 Float_t phi0 = hist->GetBinCenterY(b);
308 Float_t kappa = 2*sin(phi - phi0)/R;
309 //hist->Fill(kappa,phi0,(int)rint(log((Float_t)charge)));
310 hist->Fill(kappa,phi0,charge);
311 //hist->Fill(kappa,phi0,1);
315 Int_t bin = hist->FindBin(kappa,phi0);
316 for(Int_t t=0; t<3; t++)
318 Int_t label = digPt[j].fTrackID[t];
321 for(c=0; c<MaxTrack; c++)
322 if(fTrackID[eta_index][bin].fLabel[c] == label || fTrackID[eta_index][bin].fNHits[c] == 0)
324 if(c == MaxTrack-1) cerr<<"AliL3HoughTransformer::TransformCircle : Array reached maximum!! "<<c<<endl;
325 fTrackID[eta_index][bin].fLabel[c] = label;
326 fTrackID[eta_index][bin].fNHits[c]++;
333 //Move the data pointer to the next padrow:
334 AliL3MemHandler::UpdateRowPointer(tempPt);
346 struct EtaContainer {
351 void AliL3HoughTransformer::TransformCircleC(Int_t *row_range,Int_t every)
353 //Circle transform, using combinations of every 2 points lying
354 //on different padrows and within the same etaslice.
356 AliL3DigitRowData *tempPt = GetDataPointer();
358 LOG(AliL3Log::kError,"AliL3HoughTransformer::TransformCircleC","Data")
359 <<"No input data "<<ENDLOG;
361 Int_t minrow = AliL3Transform::GetFirstRow(GetPatch());
362 Int_t maxrow = AliL3Transform::GetLastRow(GetPatch());
365 minrow = row_range[0];
366 maxrow = row_range[1];
367 if(minrow < AliL3Transform::GetFirstRow(GetPatch()) || minrow >= AliL3Transform::GetLastRow(GetPatch()))
368 minrow = AliL3Transform::GetFirstRow(GetPatch());
369 if(maxrow < AliL3Transform::GetFirstRow(GetPatch()) || maxrow >= AliL3Transform::GetLastRow(GetPatch()))
370 maxrow = AliL3Transform::GetLastRow(GetPatch());
371 if(minrow > maxrow || maxrow==minrow)
373 cerr<<"AliL3HoughTransformer::TransformCircleC : Bad row range "<<minrow<<" "<<maxrow<<endl;
379 minrow = AliL3Transform::GetFirstRow(GetPatch());
380 maxrow = AliL3Transform::GetLastRow(GetPatch());
384 for(Int_t i=AliL3Transform::GetFirstRow(GetPatch()); i<=AliL3Transform::GetLastRow(GetPatch()); i++)
386 counter += tempPt->fNDigit;
387 AliL3MemHandler::UpdateRowPointer(tempPt);
390 Int_t bound = (GetNEtaSegments()+1)*(AliL3Transform::GetNRows(GetPatch())+1);
391 EtaContainer *etaPt = new EtaContainer[bound];
392 memset(etaPt,0,bound*sizeof(EtaContainer));
394 Digit *digits = new Digit[counter];
395 cout<<"Allocating "<<counter*sizeof(Digit)<<" bytes to digitsarray"<<endl;
396 memset(digits,0,counter*sizeof(Digit));
398 Int_t sector,row,tot_charge,pad,time,charge;
399 Double_t r1,r2,phi1,phi2,eta,kappa,phi_0;
403 tempPt = GetDataPointer();
405 cout<<"Calculating digits in patch "<<GetPatch()<<endl;
406 for(Int_t i=AliL3Transform::GetFirstRow(GetPatch()); i<=AliL3Transform::GetLastRow(GetPatch()); i++)
408 AliL3DigitData *digPt = tempPt->fDigitData;
409 for(UInt_t di=0; di<tempPt->fNDigit; di++)
411 charge = digPt[di].fCharge;
412 pad = digPt[di].fPad;
413 time = digPt[di].fTime;
414 AliL3Transform::Slice2Sector(GetSlice(),i,sector,row);
415 AliL3Transform::Raw2Local(xyz,sector,row,(Int_t)pad,(Int_t)time);
416 eta = AliL3Transform::GetEta(xyz);
418 digits[counter].row = i;
419 digits[counter].r = sqrt(xyz[0]*xyz[0] + xyz[1]*xyz[1]);
420 digits[counter].phi = atan2(xyz[1],xyz[0]);
421 digits[counter].charge = charge;
425 Int_t eta_index = GetEtaIndex(eta);
427 Int_t index = (GetNEtaSegments()+1)*(i-AliL3Transform::GetFirstRow(GetPatch())) + eta_index;
429 if(index > 0 && index < bound)
431 if(etaPt[index].first == 0)
432 etaPt[index].first = &digits[counter];
434 (etaPt[index].last)->next = &digits[counter];
435 etaPt[index].last = &digits[counter];
441 GetEtaIndexes(eta,eta_index);
443 index[0] = (GetNEtaSegments()+1)*(i-AliL3Transform::GetFirstRow(GetPatch())) + eta_index[0];
444 index[1] = (GetNEtaSegments()+1)*(i-AliL3Transform::GetFirstRow(GetPatch())) + eta_index[1];
445 if(index[0] == index[1])
447 cerr<<"Same etaindexes "<<index[0]<<" "<<index[1]<<endl;
451 Int_t ind = index[0];
452 if(ind > 0 && ind < bound)
454 if(etaPt[ind].first == 0)
455 etaPt[ind].first = &digits[counter];
457 (etaPt[ind].last)->next = &digits[counter];
458 etaPt[ind].last = &digits[counter];
462 if(ind > 0 && ind < bound)
464 if(etaPt[ind].first == 0)
465 etaPt[ind].first = &digits[counter];
467 (etaPt[ind].last)->next = &digits[counter];
468 etaPt[ind].last = &digits[counter];
474 AliL3MemHandler::UpdateRowPointer(tempPt);
477 cout<<"Doing the combinatorics"<<endl;
481 for(Int_t e=0; e<GetNEtaSegments(); e++)
483 for(Int_t i=minrow; i<=maxrow; i+=every)
485 Int_t index1 = (GetNEtaSegments()+1)*(i-AliL3Transform::GetFirstRow(GetPatch())) + e;
487 for(dPt1 = (Digit*)etaPt[index1].first; dPt1 != 0; dPt1 = (Digit*)dPt1->next)
489 for(Int_t j=i+every; j<=maxrow; j+=every)
491 Int_t index2 = (GetNEtaSegments()+1)*(j-AliL3Transform::GetFirstRow(GetPatch())) + e;
493 for(dPt2 = (Digit*)etaPt[index2].first; dPt2 != 0; dPt2 = (Digit*)dPt2->next)
495 if(dPt1->row == dPt2->row)
497 cerr<<"same row; indexes "<<index1<<" "<<index2<<endl;
501 //Get the correct histogrampointer:
502 AliL3Histogram *hist = fParamSpace[e];
505 printf("AliL3HoughTransformer::TransformCircleC() : No histogram at index %d\n",i);
514 phi_0 = atan( (r2*sin(phi1)-r1*sin(phi2))/(r2*cos(phi1)-r1*cos(phi2)) );
515 kappa = 2*sin(phi2-phi_0)/r2;
516 tot_charge = dPt1->charge + dPt2->charge;
517 hist->Fill(kappa,phi_0,tot_charge);
531 void AliL3HoughTransformer::TransformLine(Int_t *row_range,Float_t *phirange)
533 //Do a line transform on the data.
536 AliL3DigitRowData *tempPt = GetDataPointer();
539 LOG(AliL3Log::kError,"AliL3HoughTransformer::TransformLine","Data")
540 <<"No input data "<<ENDLOG;
544 Int_t minrow = AliL3Transform::GetFirstRow(GetPatch());
545 Int_t maxrow = AliL3Transform::GetLastRow(GetPatch());
548 minrow = row_range[0];
549 maxrow = row_range[1];
550 if(minrow < AliL3Transform::GetFirstRow(GetPatch()) || minrow >= AliL3Transform::GetLastRow(GetPatch()))
551 minrow = AliL3Transform::GetFirstRow(GetPatch());
552 if(maxrow < AliL3Transform::GetFirstRow(GetPatch()) || maxrow >= AliL3Transform::GetLastRow(GetPatch()))
553 maxrow = AliL3Transform::GetLastRow(GetPatch());
554 if(minrow > maxrow || maxrow==minrow)
556 cerr<<"AliL3HoughTransformer::TransformCircleC : Bad row range "<<minrow<<" "<<maxrow<<endl;
561 for(Int_t i=minrow; i<=maxrow; i++)
563 AliL3DigitData *digPt = tempPt->fDigitData;
564 if(i != (Int_t)tempPt->fRow)
566 printf("AliL3HoughTransform::TransformLine : Mismatching padrow numbering\n");
569 for(UInt_t j=0; j<tempPt->fNDigit; j++)
571 UShort_t charge = digPt[j].fCharge;
572 UChar_t pad = digPt[j].fPad;
573 UShort_t time = digPt[j].fTime;
574 if(charge < GetLowerThreshold())
578 AliL3Transform::Slice2Sector(GetSlice(),i,sector,row);
579 AliL3Transform::Raw2Local(xyz,sector,row,(Int_t)pad,(Int_t)time);
583 Float_t phi = AliL3Transform::GetPhi(xyz);
584 if(phi < phirange[0] || phi > phirange[1])
587 Float_t eta = AliL3Transform::GetEta(xyz);
588 Int_t eta_index = GetEtaIndex(eta);//(Int_t)(eta/etaslice);
589 if(eta_index < 0 || eta_index >= GetNEtaSegments())
592 xyz[0] = xyz[0] - AliL3Transform::Row2X(minrow);
594 //Get the correct histogram:
595 AliL3Histogram *hist = fParamSpace[eta_index];
598 printf("AliL3HoughTransformer::TransformLine : Error getting histogram in index %d\n",eta_index);
601 for(Int_t xbin=hist->GetFirstXbin(); xbin<hist->GetLastXbin(); xbin++)
603 Double_t theta = hist->GetBinCenterX(xbin);
604 Double_t rho = xyz[0]*cos(theta) + xyz[1]*sin(theta);
605 hist->Fill(theta,rho,charge);
608 AliL3MemHandler::UpdateRowPointer(tempPt);
619 struct LEtaContainer {
623 void AliL3HoughTransformer::TransformLineC(Int_t *rowrange,Float_t *phirange)
625 AliL3DigitRowData *tempPt = GetDataPointer();
627 LOG(AliL3Log::kError,"AliL3HoughTransformer::TransformCircleC","Data")
628 <<"No input data "<<ENDLOG;
632 for(Int_t i=AliL3Transform::GetFirstRow(GetPatch()); i<=AliL3Transform::GetLastRow(GetPatch()); i++)
634 counter += tempPt->fNDigit;
635 AliL3MemHandler::UpdateRowPointer(tempPt);
638 Int_t bound = (GetNEtaSegments()+1)*(AliL3Transform::GetNRows(GetPatch())+1);
639 LEtaContainer *etaPt = new LEtaContainer[bound];
640 memset(etaPt,0,bound*sizeof(LEtaContainer));
642 LDigit *digits = new LDigit[counter];
643 cout<<"Allocating "<<counter*sizeof(LDigit)<<" bytes to digitsarray"<<endl;
644 memset(digits,0,counter*sizeof(LDigit));
650 tempPt = GetDataPointer();
652 cout<<"Calculating digits in patch "<<GetPatch()<<endl;
653 for(Int_t i=AliL3Transform::GetFirstRow(GetPatch()); i<=AliL3Transform::GetLastRow(GetPatch()); i++)
655 AliL3DigitData *digPt = tempPt->fDigitData;
656 for(UInt_t di=0; di<tempPt->fNDigit; di++)
658 Int_t charge = digPt[di].fCharge;
659 Int_t pad = digPt[di].fPad;
660 Int_t time = digPt[di].fTime;
661 AliL3Transform::Slice2Sector(GetSlice(),i,sector,row);
662 AliL3Transform::Raw2Local(xyz,sector,row,(Int_t)pad,(Int_t)time);
663 Double_t eta = AliL3Transform::GetEta(xyz);
665 Float_t phi = atan2(xyz[1],xyz[0]);
666 if(phi < phirange[0] || phi > phirange[1]) continue;
668 digits[counter].row = i;
669 digits[counter].y = xyz[1];
670 digits[counter].charge = charge;
672 Int_t eta_index = GetEtaIndex(eta);
673 Int_t index = (GetNEtaSegments()+1)*(i-AliL3Transform::GetFirstRow(GetPatch())) + eta_index;
675 if(index > 0 && index < bound)
677 if(etaPt[index].first == 0)
678 etaPt[index].first = &digits[counter];
680 (etaPt[index].last)->next = &digits[counter];
681 etaPt[index].last = &digits[counter];
685 AliL3MemHandler::UpdateRowPointer(tempPt);
688 cout<<"Doing the combinatorics"<<endl;
692 for(Int_t e=0; e<GetNEtaSegments(); e++)
694 for(Int_t i=rowrange[0]; i<=rowrange[1]; i++)
696 Int_t index1 = (GetNEtaSegments()+1)*(i-AliL3Transform::GetFirstRow(GetPatch())) + e;
698 for(dPt1 = (LDigit*)etaPt[index1].first; dPt1 != 0; dPt1 = (LDigit*)dPt1->next)
700 for(Int_t j=i+1; j<=rowrange[1]; j++)
702 Int_t index2 = (GetNEtaSegments()+1)*(j-AliL3Transform::GetFirstRow(GetPatch())) + e;
704 for(dPt2 = (LDigit*)etaPt[index2].first; dPt2 != 0; dPt2 = (LDigit*)dPt2->next)
706 if(dPt1->row == dPt2->row)
708 cerr<<"same row; indexes "<<index1<<" "<<index2<<endl;
712 //Get the correct histogrampointer:
713 AliL3Histogram *hist = fParamSpace[e];
716 printf("AliL3HoughTransformer::TransformCircleC() : No histogram at index %d\n",i);
721 float x1 = AliL3Transform::Row2X(dPt1->row) - AliL3Transform::Row2X(rowrange[0]);
722 float x2 = AliL3Transform::Row2X(dPt2->row) - AliL3Transform::Row2X(rowrange[0]);
725 float theta = atan2(x2-x1,y1-y2);
726 float rho = x1*cos(theta)+y1*sin(theta);
727 hist->Fill(theta,rho,1);//dPt1->charge+dPt2->charge);
739 Int_t AliL3HoughTransformer::GetTrackID(Int_t eta_index,Double_t kappa,Double_t psi)
743 cerr<<"AliL3HoughTransformer::GetTrackID : Flag switched off"<<endl;
748 if(eta_index < 0 || eta_index > GetNEtaSegments())
750 cerr<<"AliL3HoughTransformer::GetTrackID : Wrong etaindex "<<eta_index<<endl;
753 AliL3Histogram *hist = fParamSpace[eta_index];
754 Int_t bin = hist->FindBin(kappa,psi);
757 for(UInt_t i=0; i<MaxTrack; i++)
759 Int_t nhits=fTrackID[eta_index][bin].fNHits[i];
760 if(nhits == 0) break;
764 label = fTrackID[eta_index][bin].fLabel[i];
770 cout<<"AliL3HoughTransformer::GetTrackID : Compile with do_mc flag!"<<endl;