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 //_____________________________________________________________
20 // AliL3HoughTransformer
22 // Hough transformation class
25 ClassImp(AliL3HoughTransformer)
27 AliL3HoughTransformer::AliL3HoughTransformer()
38 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)
43 fEtaOverlap = DoEtaOverlap;
60 AliL3HoughTransformer::~AliL3HoughTransformer()
66 for(Int_t i=0; i<GetNEtaSegments(); i++)
68 if(!fTrackID[i]) continue;
76 void AliL3HoughTransformer::DeleteHistograms()
80 for(Int_t i=0; i<GetNEtaSegments(); i++)
82 if(!fParamSpace[i]) continue;
83 delete fParamSpace[i];
85 delete [] fParamSpace;
88 void AliL3HoughTransformer::CreateHistograms(Float_t ptmin,Float_t ptmax,Float_t ptres,
89 Int_t nybin,Float_t psi)
92 //_Only_ to be used in case of the adaptive histograms!
93 //phimax is given in radians!!
97 cerr<<"AliL3HoughTransformer.:CreateHistograms: Error in ptrange "<<ptmin<<" "<<ptmax<<endl;
102 cerr<<"AliL3HoughTransformer::CreateHistograms: Wrong psi-angle "<<psi<<endl;
106 fParamSpace = new AliL3Histogram*[GetNEtaSegments()];
107 Char_t histname[256];
109 for(i=0; i<GetNEtaSegments(); i++)
111 sprintf(histname,"paramspace_%d",i);
112 fParamSpace[i] = new AliL3HistogramAdaptive(histname,ptmin,ptmax,ptres,nybin,-psi,psi);
117 void AliL3HoughTransformer::CreateHistograms(Int_t nxbin,Float_t pt_min,
118 Int_t nybin,Float_t phimin,Float_t phimax)
120 //Create the histograms (parameter space).
121 //These are 2D histograms, span by kappa (curvature of track) and phi0 (emission angle with x-axis).
122 //The arguments give the range and binning;
123 //nxbin = #bins in kappa
124 //nybin = #bins in phi0
125 //pt_min = mimium Pt of track (corresponding to maximum kappa)
126 //phi_min = mimimum phi0
127 //phi_max = maximum phi0
129 Double_t x = AliL3Transform::GetBFact()*AliL3Transform::GetBField()/pt_min;
130 //Double_t torad = AliL3Transform::Pi()/180;
132 CreateHistograms(nxbin,-1.*x,x,nybin,phimin/**torad*/,phimax/**torad*/);
135 void AliL3HoughTransformer::CreateHistograms(Int_t nxbin,Float_t xmin,Float_t xmax,
136 Int_t nybin,Float_t ymin,Float_t ymax)
139 fParamSpace = new AliL3Histogram*[GetNEtaSegments()];
141 Char_t histname[256];
142 for(Int_t i=0; i<GetNEtaSegments(); i++)
144 sprintf(histname,"paramspace_%d",i);
145 //fParamSpace[i] = new AliL3HistogramAdaptive(histname,0.5,1.5,0.05,nybin,ymin,ymax);
146 fParamSpace[i] = new AliL3Histogram(histname,"",nxbin,xmin,xmax,nybin,ymin,ymax);
152 AliL3Histogram *hist = fParamSpace[0];
153 Int_t ncells = (hist->GetNbinsX()+2)*(hist->GetNbinsY()+2);
154 cout<<"Transformer: Allocating "<<GetNEtaSegments()*ncells*sizeof(TrackIndex)<<" bytes to fTrackID"<<endl;
155 fTrackID = new TrackIndex*[GetNEtaSegments()];
156 for(Int_t i=0; i<GetNEtaSegments(); i++)
157 fTrackID[i] = new TrackIndex[ncells];
162 void AliL3HoughTransformer::Reset()
164 //Reset all the histograms
168 LOG(AliL3Log::kWarning,"AliL3HoughTransformer::Reset","Histograms")
169 <<"No histograms to reset"<<ENDLOG;
173 for(Int_t i=0; i<GetNEtaSegments(); i++)
174 fParamSpace[i]->Reset();
179 AliL3Histogram *hist = fParamSpace[0];
180 Int_t ncells = (hist->GetNbinsX()+2)*(hist->GetNbinsY()+2);
181 for(Int_t i=0; i<GetNEtaSegments(); i++)
182 memset(fTrackID[i],0,ncells*sizeof(TrackIndex));
187 Int_t AliL3HoughTransformer::GetEtaIndex(Double_t eta)
189 //Return the histogram index of the corresponding eta.
191 Double_t etaslice = (GetEtaMax() - GetEtaMin())/GetNEtaSegments();
192 Double_t index = (eta-GetEtaMin())/etaslice;
196 void AliL3HoughTransformer::GetEtaIndexes(Double_t eta,Int_t *indexes)
198 //Return histogram indexes in case of overlapping etaslices.
200 Double_t etaslice = (GetEtaMax() - GetEtaMin())/GetNEtaSegments();
201 Int_t index = (Int_t)((eta-GetEtaMin())/etaslice);
205 indexes[1] = index - 1;
209 indexes[0] = index - 1;
214 inline AliL3Histogram *AliL3HoughTransformer::GetHistogram(Int_t eta_index)
216 if(!fParamSpace || eta_index >= GetNEtaSegments() || eta_index < 0)
218 if(!fParamSpace[eta_index])
220 return fParamSpace[eta_index];
223 Double_t AliL3HoughTransformer::GetEta(Int_t eta_index,Int_t slice)
225 Double_t eta_slice = (GetEtaMax()-GetEtaMin())/GetNEtaSegments();
229 Int_t index = eta_index + 1;
230 eta=(Double_t)((index)*eta_slice);
233 eta=(Double_t)((eta_index+0.5)*eta_slice);
238 void AliL3HoughTransformer::TransformCircle()
240 //Transform the input data with a circle HT.
241 //The function loops over all the data, and transforms each pixel with the equations:
243 //kappa = 2/R*sin(phi - phi0)
245 //where R = sqrt(x*x +y*y), and phi = arctan(y/x)
247 //Each pixel then transforms into a curve in the (kappa,phi0)-space. In order to find
248 //which histogram in which the pixel should be transformed, the eta-value is calculated
249 //and the proper histogram index is found by GetEtaIndex(eta).
252 AliL3DigitRowData *tempPt = GetDataPointer();
255 LOG(AliL3Log::kError,"AliL3HoughTransformer::TransformCircle","Data")
256 <<"No input data "<<ENDLOG;
260 //Loop over the padrows:
261 for(Int_t i=AliL3Transform::GetFirstRow(GetPatch()); i<=AliL3Transform::GetLastRow(GetPatch()); i++)
263 //Get the data on this padrow:
264 AliL3DigitData *digPt = tempPt->fDigitData;
265 if(i != (Int_t)tempPt->fRow)
267 cerr<<"AliL3HoughTransform::TransformCircle : Mismatching padrow numbering "<<i<<" "<<(Int_t)tempPt->fRow<<endl;
271 //Loop over the data on this padrow:
272 for(UInt_t j=0; j<tempPt->fNDigit; j++)
274 UShort_t charge = digPt[j].fCharge;
275 UChar_t pad = digPt[j].fPad;
276 UShort_t time = digPt[j].fTime;
277 if((Int_t)charge <= GetLowerThreshold())
280 if((Int_t)charge > GetUpperThreshold())
281 charge = GetUpperThreshold();
286 //Transform data to local cartesian coordinates:
287 AliL3Transform::Slice2Sector(GetSlice(),i,sector,row);
288 AliL3Transform::Raw2Local(xyz,sector,row,(Int_t)pad,(Int_t)time);
291 Double_t eta = AliL3Transform::GetEta(xyz);
293 //Get the corresponding index, which determines which histogram to fill:
294 Int_t eta_index = GetEtaIndex(eta);
296 if(eta_index < 0 || eta_index >= GetNEtaSegments())
299 //Get the correct histogrampointer:
300 AliL3Histogram *hist = fParamSpace[eta_index];
303 cerr<<"AliL3HoughTransformer::TransformCircle : Error getting histogram in index "<<eta_index<<endl;
307 //Do the transformation:
308 Float_t R = sqrt(xyz[0]*xyz[0] + xyz[1]*xyz[1]);
309 Float_t phi = AliL3Transform::GetPhi(xyz);
312 //Fill the histogram along the phirange
313 for(Int_t b=hist->GetFirstYbin(); b<=hist->GetLastYbin(); b++)
315 Float_t phi0 = hist->GetBinCenterY(b);
316 Float_t kappa = 2*sin(phi - phi0)/R;
317 //hist->Fill(kappa,phi0,(int)rint(log((Float_t)charge)));
318 hist->Fill(kappa,phi0,charge);
319 //hist->Fill(kappa,phi0,1);
323 Int_t bin = hist->FindBin(kappa,phi0);
324 for(Int_t t=0; t<3; t++)
326 Int_t label = digPt[j].fTrackID[t];
329 for(c=0; c<MaxTrack; c++)
330 if(fTrackID[eta_index][bin].fLabel[c] == label || fTrackID[eta_index][bin].fNHits[c] == 0)
332 if(c == MaxTrack-1) cerr<<"AliL3HoughTransformer::TransformCircle : Array reached maximum!! "<<c<<endl;
333 fTrackID[eta_index][bin].fLabel[c] = label;
334 fTrackID[eta_index][bin].fNHits[c]++;
341 //Move the data pointer to the next padrow:
342 AliL3MemHandler::UpdateRowPointer(tempPt);
354 struct EtaContainer {
358 void AliL3HoughTransformer::TransformCircleC(Int_t *row_range,Int_t every)
360 //Circle transform, using combinations of every 2 points lying
361 //on different padrows and within the same etaslice.
363 AliL3DigitRowData *tempPt = GetDataPointer();
365 LOG(AliL3Log::kError,"AliL3HoughTransformer::TransformCircleC","Data")
366 <<"No input data "<<ENDLOG;
368 Int_t minrow = AliL3Transform::GetFirstRow(GetPatch());
369 Int_t maxrow = AliL3Transform::GetLastRow(GetPatch());
372 minrow = row_range[0];
373 maxrow = row_range[1];
374 if(minrow < AliL3Transform::GetFirstRow(GetPatch()) || minrow >= AliL3Transform::GetLastRow(GetPatch()))
375 minrow = AliL3Transform::GetFirstRow(GetPatch());
376 if(maxrow < AliL3Transform::GetFirstRow(GetPatch()) || maxrow >= AliL3Transform::GetLastRow(GetPatch()))
377 maxrow = AliL3Transform::GetLastRow(GetPatch());
378 if(minrow > maxrow || maxrow==minrow)
380 cerr<<"AliL3HoughTransformer::TransformCircleC : Bad row range "<<minrow<<" "<<maxrow<<endl;
386 minrow = AliL3Transform::GetFirstRow(GetPatch());
387 maxrow = AliL3Transform::GetLastRow(GetPatch());
391 for(Int_t i=AliL3Transform::GetFirstRow(GetPatch()); i<=AliL3Transform::GetLastRow(GetPatch()); i++)
393 counter += tempPt->fNDigit;
394 AliL3MemHandler::UpdateRowPointer(tempPt);
397 Int_t bound = (GetNEtaSegments()+1)*(AliL3Transform::GetNRows(GetPatch())+1);
398 EtaContainer *etaPt = new EtaContainer[bound];
399 memset(etaPt,0,bound*sizeof(EtaContainer));
401 Digit *digits = new Digit[counter];
402 cout<<"Allocating "<<counter*sizeof(Digit)<<" bytes to digitsarray"<<endl;
403 memset(digits,0,counter*sizeof(Digit));
405 Int_t sector,row,tot_charge,pad,time,charge;
406 Double_t r1,r2,phi1,phi2,eta,kappa,phi_0;
410 tempPt = GetDataPointer();
412 cout<<"Calculating digits in patch "<<GetPatch()<<endl;
413 for(Int_t i=AliL3Transform::GetFirstRow(GetPatch()); i<=AliL3Transform::GetLastRow(GetPatch()); i++)
415 AliL3DigitData *digPt = tempPt->fDigitData;
416 for(UInt_t di=0; di<tempPt->fNDigit; di++)
418 charge = digPt[di].fCharge;
419 pad = digPt[di].fPad;
420 time = digPt[di].fTime;
421 AliL3Transform::Slice2Sector(GetSlice(),i,sector,row);
422 AliL3Transform::Raw2Local(xyz,sector,row,(Int_t)pad,(Int_t)time);
423 eta = AliL3Transform::GetEta(xyz);
425 digits[counter].row = i;
426 digits[counter].r = sqrt(xyz[0]*xyz[0] + xyz[1]*xyz[1]);
427 digits[counter].phi = atan2(xyz[1],xyz[0]);
428 digits[counter].charge = charge;
432 Int_t eta_index = GetEtaIndex(eta);
434 Int_t index = (GetNEtaSegments()+1)*(i-AliL3Transform::GetFirstRow(GetPatch())) + eta_index;
436 if(index > 0 && index < bound)
438 if(etaPt[index].first == 0)
439 etaPt[index].first = &digits[counter];
441 (etaPt[index].last)->next = &digits[counter];
442 etaPt[index].last = &digits[counter];
448 GetEtaIndexes(eta,eta_index);
450 index[0] = (GetNEtaSegments()+1)*(i-AliL3Transform::GetFirstRow(GetPatch())) + eta_index[0];
451 index[1] = (GetNEtaSegments()+1)*(i-AliL3Transform::GetFirstRow(GetPatch())) + eta_index[1];
452 if(index[0] == index[1])
454 cerr<<"Same etaindexes "<<index[0]<<" "<<index[1]<<endl;
458 Int_t ind = index[0];
459 if(ind > 0 && ind < bound)
461 if(etaPt[ind].first == 0)
462 etaPt[ind].first = &digits[counter];
464 (etaPt[ind].last)->next = &digits[counter];
465 etaPt[ind].last = &digits[counter];
469 if(ind > 0 && ind < bound)
471 if(etaPt[ind].first == 0)
472 etaPt[ind].first = &digits[counter];
474 (etaPt[ind].last)->next = &digits[counter];
475 etaPt[ind].last = &digits[counter];
481 AliL3MemHandler::UpdateRowPointer(tempPt);
484 cout<<"Doing the combinatorics"<<endl;
488 for(Int_t e=0; e<GetNEtaSegments(); e++)
490 for(Int_t i=minrow; i<=maxrow; i+=every)
492 Int_t index1 = (GetNEtaSegments()+1)*(i-AliL3Transform::GetFirstRow(GetPatch())) + e;
494 for(dPt1 = (Digit*)etaPt[index1].first; dPt1 != 0; dPt1 = (Digit*)dPt1->next)
496 for(Int_t j=i+every; j<=maxrow; j+=every)
498 Int_t index2 = (GetNEtaSegments()+1)*(j-AliL3Transform::GetFirstRow(GetPatch())) + e;
500 for(dPt2 = (Digit*)etaPt[index2].first; dPt2 != 0; dPt2 = (Digit*)dPt2->next)
502 if(dPt1->row == dPt2->row)
504 cerr<<"same row; indexes "<<index1<<" "<<index2<<endl;
508 //Get the correct histogrampointer:
509 AliL3Histogram *hist = fParamSpace[e];
512 printf("AliL3HoughTransformer::TransformCircleC() : No histogram at index %d\n",i);
521 phi_0 = atan( (r2*sin(phi1)-r1*sin(phi2))/(r2*cos(phi1)-r1*cos(phi2)) );
522 kappa = 2*sin(phi2-phi_0)/r2;
523 tot_charge = dPt1->charge + dPt2->charge;
524 hist->Fill(kappa,phi_0,tot_charge);
538 void AliL3HoughTransformer::TransformLine(Int_t *row_range,Float_t *phirange)
540 //Do a line transform on the data.
543 AliL3DigitRowData *tempPt = GetDataPointer();
546 LOG(AliL3Log::kError,"AliL3HoughTransformer::TransformLine","Data")
547 <<"No input data "<<ENDLOG;
551 Int_t minrow = AliL3Transform::GetFirstRow(GetPatch());
552 Int_t maxrow = AliL3Transform::GetLastRow(GetPatch());
555 minrow = row_range[0];
556 maxrow = row_range[1];
557 if(minrow < AliL3Transform::GetFirstRow(GetPatch()) || minrow >= AliL3Transform::GetLastRow(GetPatch()))
558 minrow = AliL3Transform::GetFirstRow(GetPatch());
559 if(maxrow < AliL3Transform::GetFirstRow(GetPatch()) || maxrow >= AliL3Transform::GetLastRow(GetPatch()))
560 maxrow = AliL3Transform::GetLastRow(GetPatch());
561 if(minrow > maxrow || maxrow==minrow)
563 cerr<<"AliL3HoughTransformer::TransformCircleC : Bad row range "<<minrow<<" "<<maxrow<<endl;
568 for(Int_t i=minrow; i<=maxrow; i++)
570 AliL3DigitData *digPt = tempPt->fDigitData;
571 if(i != (Int_t)tempPt->fRow)
573 printf("AliL3HoughTransform::TransformLine : Mismatching padrow numbering\n");
576 for(UInt_t j=0; j<tempPt->fNDigit; j++)
578 UShort_t charge = digPt[j].fCharge;
579 UChar_t pad = digPt[j].fPad;
580 UShort_t time = digPt[j].fTime;
581 if(charge < GetLowerThreshold())
585 AliL3Transform::Slice2Sector(GetSlice(),i,sector,row);
586 AliL3Transform::Raw2Local(xyz,sector,row,(Int_t)pad,(Int_t)time);
590 Float_t phi = AliL3Transform::GetPhi(xyz);
591 if(phi < phirange[0] || phi > phirange[1])
594 Float_t eta = AliL3Transform::GetEta(xyz);
595 Int_t eta_index = GetEtaIndex(eta);//(Int_t)(eta/etaslice);
596 if(eta_index < 0 || eta_index >= GetNEtaSegments())
599 xyz[0] = xyz[0] - AliL3Transform::Row2X(minrow);
601 //Get the correct histogram:
602 AliL3Histogram *hist = fParamSpace[eta_index];
605 printf("AliL3HoughTransformer::TransformLine : Error getting histogram in index %d\n",eta_index);
608 for(Int_t xbin=hist->GetFirstXbin(); xbin<hist->GetLastXbin(); xbin++)
610 Double_t theta = hist->GetBinCenterX(xbin);
611 Double_t rho = xyz[0]*cos(theta) + xyz[1]*sin(theta);
612 hist->Fill(theta,rho,charge);
615 AliL3MemHandler::UpdateRowPointer(tempPt);
626 struct LEtaContainer {
630 void AliL3HoughTransformer::TransformLineC(Int_t *rowrange,Float_t *phirange)
632 AliL3DigitRowData *tempPt = GetDataPointer();
634 LOG(AliL3Log::kError,"AliL3HoughTransformer::TransformCircleC","Data")
635 <<"No input data "<<ENDLOG;
639 for(Int_t i=AliL3Transform::GetFirstRow(GetPatch()); i<=AliL3Transform::GetLastRow(GetPatch()); i++)
641 counter += tempPt->fNDigit;
642 AliL3MemHandler::UpdateRowPointer(tempPt);
645 Int_t bound = (GetNEtaSegments()+1)*(AliL3Transform::GetNRows(GetPatch())+1);
646 LEtaContainer *etaPt = new LEtaContainer[bound];
647 memset(etaPt,0,bound*sizeof(LEtaContainer));
649 LDigit *digits = new LDigit[counter];
650 cout<<"Allocating "<<counter*sizeof(LDigit)<<" bytes to digitsarray"<<endl;
651 memset(digits,0,counter*sizeof(LDigit));
657 tempPt = GetDataPointer();
659 cout<<"Calculating digits in patch "<<GetPatch()<<endl;
660 for(Int_t i=AliL3Transform::GetFirstRow(GetPatch()); i<=AliL3Transform::GetLastRow(GetPatch()); i++)
662 AliL3DigitData *digPt = tempPt->fDigitData;
663 for(UInt_t di=0; di<tempPt->fNDigit; di++)
665 Int_t charge = digPt[di].fCharge;
666 Int_t pad = digPt[di].fPad;
667 Int_t time = digPt[di].fTime;
668 AliL3Transform::Slice2Sector(GetSlice(),i,sector,row);
669 AliL3Transform::Raw2Local(xyz,sector,row,(Int_t)pad,(Int_t)time);
670 Double_t eta = AliL3Transform::GetEta(xyz);
672 Float_t phi = atan2(xyz[1],xyz[0]);
673 if(phi < phirange[0] || phi > phirange[1]) continue;
675 digits[counter].row = i;
676 digits[counter].y = xyz[1];
677 digits[counter].charge = charge;
679 Int_t eta_index = GetEtaIndex(eta);
680 Int_t index = (GetNEtaSegments()+1)*(i-AliL3Transform::GetFirstRow(GetPatch())) + eta_index;
682 if(index > 0 && index < bound)
684 if(etaPt[index].first == 0)
685 etaPt[index].first = &digits[counter];
687 (etaPt[index].last)->next = &digits[counter];
688 etaPt[index].last = &digits[counter];
692 AliL3MemHandler::UpdateRowPointer(tempPt);
695 cout<<"Doing the combinatorics"<<endl;
699 for(Int_t e=0; e<GetNEtaSegments(); e++)
701 for(Int_t i=rowrange[0]; i<=rowrange[1]; i++)
703 Int_t index1 = (GetNEtaSegments()+1)*(i-AliL3Transform::GetFirstRow(GetPatch())) + e;
705 for(dPt1 = (LDigit*)etaPt[index1].first; dPt1 != 0; dPt1 = (LDigit*)dPt1->next)
707 for(Int_t j=i+1; j<=rowrange[1]; j++)
709 Int_t index2 = (GetNEtaSegments()+1)*(j-AliL3Transform::GetFirstRow(GetPatch())) + e;
711 for(dPt2 = (LDigit*)etaPt[index2].first; dPt2 != 0; dPt2 = (LDigit*)dPt2->next)
713 if(dPt1->row == dPt2->row)
715 cerr<<"same row; indexes "<<index1<<" "<<index2<<endl;
719 //Get the correct histogrampointer:
720 AliL3Histogram *hist = fParamSpace[e];
723 printf("AliL3HoughTransformer::TransformCircleC() : No histogram at index %d\n",i);
728 float x1 = AliL3Transform::Row2X(dPt1->row) - AliL3Transform::Row2X(rowrange[0]);
729 float x2 = AliL3Transform::Row2X(dPt2->row) - AliL3Transform::Row2X(rowrange[0]);
732 float theta = atan2(x2-x1,y1-y2);
733 float rho = x1*cos(theta)+y1*sin(theta);
734 hist->Fill(theta,rho,1);//dPt1->charge+dPt2->charge);
746 Int_t AliL3HoughTransformer::GetTrackID(Int_t eta_index,Double_t kappa,Double_t psi)
750 cerr<<"AliL3HoughTransformer::GetTrackID : Flag switched off"<<endl;
755 if(eta_index < 0 || eta_index > GetNEtaSegments())
757 cerr<<"AliL3HoughTransformer::GetTrackID : Wrong etaindex "<<eta_index<<endl;
760 AliL3Histogram *hist = fParamSpace[eta_index];
761 Int_t bin = hist->FindBin(kappa,psi);
764 for(UInt_t i=0; i<MaxTrack; i++)
766 Int_t nhits=fTrackID[eta_index][bin].fNHits[i];
767 if(nhits == 0) break;
771 label = fTrackID[eta_index][bin].fLabel[i];
777 cout<<"AliL3HoughTransformer::GetTrackID : Compile with do_mc flag!"<<endl;