2 // origin: hough/AliL3HoughMaxFinder.cxx,v 1.13 Tue Mar 28 18:05:12 2006 UTC by alibrary
4 // Author: Anders Vestbo <mailto:vestbo@fi.uib.no>
5 //*-- Copyright © ALICE HLT Group
12 #include "AliHLTTPCLogging.h"
13 #include "AliHLTTPCHoughMaxFinder.h"
14 #include "AliHLTTPCHistogram.h"
15 #include "AliHLTTPCTrackArray.h"
16 #include "AliHLTTPCHoughTrack.h"
17 #include "AliHLTTPCTransform.h"
18 #include "AliHLTTPCHoughTransformerRow.h"
24 /** \class AliHLTTPCHoughMaxFinder
26 //_____________________________________________________________
27 // AliHLTTPCHoughMaxFinder
34 ClassImp(AliHLTTPCHoughMaxFinder)
37 AliHLTTPCHoughMaxFinder::AliHLTTPCHoughMaxFinder()
41 fCurrentEtaSlice = -1;
47 fN1PeaksPrevEtaSlice=0;
48 fN2PeaksPrevEtaSlice=0;
63 AliHLTTPCHoughMaxFinder::AliHLTTPCHoughMaxFinder(Char_t *histotype,Int_t nmax,AliHLTTPCHistogram *hist)
67 //fTracks = new AliHLTTPCTrackArray("AliHLTTPCHoughTrack");
68 if(strcmp(histotype,"KappaPhi")==0) fHistoType='c';
69 if(strcmp(histotype,"DPsi")==0) fHistoType='l';
71 fCurrentEtaSlice = -1;
79 fXPeaks = new Float_t[fNMax];
80 fYPeaks = new Float_t[fNMax];
81 fWeight = new Int_t[fNMax];
82 fSTARTXPeaks = new Int_t[fNMax];
83 fSTARTYPeaks = new Int_t[fNMax];
84 fENDXPeaks = new Int_t[fNMax];
85 fENDYPeaks = new Int_t[fNMax];
86 fSTARTETAPeaks = new Int_t[fNMax];
87 fENDETAPeaks = new Int_t[fNMax];
94 AliHLTTPCHoughMaxFinder::~AliHLTTPCHoughMaxFinder()
104 delete [] fSTARTXPeaks;
106 delete [] fSTARTYPeaks;
108 delete [] fENDXPeaks;
110 delete [] fENDYPeaks;
112 delete [] fSTARTETAPeaks;
114 delete [] fENDETAPeaks;
121 void AliHLTTPCHoughMaxFinder::Reset()
123 // Method to reinit the Peak Finder
124 for(Int_t i=0; i<fNMax; i++)
137 fN1PeaksPrevEtaSlice=0;
138 fN2PeaksPrevEtaSlice=0;
141 void AliHLTTPCHoughMaxFinder::CreateNtuppel()
143 // Fill a NTuple with the peak parameters
145 //content#; neighbouring bins of the peak.
146 fNtuppel = new TNtuple("ntuppel","Peak charateristics","kappa:phi0:weigth:content3:content5:content1:content7");
147 fNtuppel->SetDirectory(0);
151 void AliHLTTPCHoughMaxFinder::WriteNtuppel(Char_t *filename)
153 // Write the NTuple with the peak parameters
155 TFile *file = TFile::Open(filename,"RECREATE");
158 cerr<<"AliHLTTPCHoughMaxFinder::WriteNtuppel : Error opening file "<<filename<<endl;
166 void AliHLTTPCHoughMaxFinder::FindAbsMaxima()
168 // Simple Peak Finder in the Hough space
171 cerr<<"AliHLTTPCHoughMaxFinder::FindAbsMaxima : No histogram"<<endl;
174 AliHLTTPCHistogram *hist = fCurrentHisto;
176 if(hist->GetNEntries() == 0)
179 Int_t xmin = hist->GetFirstXbin();
180 Int_t xmax = hist->GetLastXbin();
181 Int_t ymin = hist->GetFirstYbin();
182 Int_t ymax = hist->GetLastYbin();
184 Double_t value,maxvalue=0;
186 Int_t maxxbin=0,maxybin=0;
187 for(Int_t xbin=xmin; xbin<=xmax; xbin++)
189 for(Int_t ybin=ymin; ybin<=ymax; ybin++)
191 bin = hist->GetBin(xbin,ybin);
192 value = hist->GetBinContent(bin);
207 cerr<<"AliHLTTPCHoughMaxFinder::FindAbsMaxima : Array out of range : "<<fNPeaks<<endl;
211 Double_t maxx = hist->GetBinCenterX(maxxbin);
212 Double_t maxy = hist->GetBinCenterY(maxybin);
213 fXPeaks[fNPeaks] = maxx;
214 fYPeaks[fNPeaks] = maxy;
215 fWeight[fNPeaks] = (Int_t)maxvalue;
221 Int_t bin3 = hist->GetBin(maxxbin-1,maxybin);
222 Int_t bin5 = hist->GetBin(maxxbin+1,maxybin);
223 Int_t bin1 = hist->GetBin(maxxbin,maxybin-1);
224 Int_t bin7 = hist->GetBin(maxxbin,maxybin+1);
226 fNtuppel->Fill(maxx,maxy,maxvalue,hist->GetBinContent(bin3),hist->GetBinContent(bin5),hist->GetBinContent(bin1),hist->GetBinContent(bin7));
231 void AliHLTTPCHoughMaxFinder::FindBigMaxima()
233 // Another Peak finder
234 AliHLTTPCHistogram *hist = fCurrentHisto;
236 if(hist->GetNEntries() == 0)
239 Int_t xmin = hist->GetFirstXbin();
240 Int_t xmax = hist->GetLastXbin();
241 Int_t ymin = hist->GetFirstYbin();
242 Int_t ymax = hist->GetLastYbin();
243 Int_t bin[25],binindex;
246 for(Int_t xbin=xmin+2; xbin<xmax-3; xbin++)
248 for(Int_t ybin=ymin+2; ybin<ymax-3; ybin++)
251 for(Int_t xb=xbin-2; xb<=xbin+2; xb++)
253 for(Int_t yb=ybin-2; yb<=ybin+2; yb++)
255 bin[binindex]=hist->GetBin(xb,yb);
256 value[binindex]=hist->GetBinContent(bin[binindex]);
260 if(value[12]==0) continue;
264 if(value[b] > value[12] || b==binindex) break;
266 //printf("b %d\n",b);
273 cerr<<"AliHLTTPCHoughMaxFinder::FindBigMaxima : Array out of range "<<fNPeaks<<endl;
277 Double_t maxx = hist->GetBinCenterX(xbin);
278 Double_t maxy = hist->GetBinCenterY(ybin);
279 fXPeaks[fNPeaks] = maxx;
280 fYPeaks[fNPeaks] = maxy;
287 void AliHLTTPCHoughMaxFinder::FindMaxima(Int_t threshold)
289 //Locate all the maxima in input histogram.
290 //Maxima is defined as bins with more entries than the
291 //immediately neighbouring bins.
293 if(fCurrentHisto->GetNEntries() == 0)
296 Int_t xmin = fCurrentHisto->GetFirstXbin();
297 Int_t xmax = fCurrentHisto->GetLastXbin();
298 Int_t ymin = fCurrentHisto->GetFirstYbin();
299 Int_t ymax = fCurrentHisto->GetLastYbin();
303 //Float_t max_kappa = 0.001;
304 //Float_t max_phi0 = 0.08;
306 for(Int_t xbin=xmin+1; xbin<=xmax-1; xbin++)
308 for(Int_t ybin=ymin+1; ybin<=ymax-1; ybin++)
310 bin[0] = fCurrentHisto->GetBin(xbin-1,ybin-1);
311 bin[1] = fCurrentHisto->GetBin(xbin,ybin-1);
312 bin[2] = fCurrentHisto->GetBin(xbin+1,ybin-1);
313 bin[3] = fCurrentHisto->GetBin(xbin-1,ybin);
314 bin[4] = fCurrentHisto->GetBin(xbin,ybin);
315 bin[5] = fCurrentHisto->GetBin(xbin+1,ybin);
316 bin[6] = fCurrentHisto->GetBin(xbin-1,ybin+1);
317 bin[7] = fCurrentHisto->GetBin(xbin,ybin+1);
318 bin[8] = fCurrentHisto->GetBin(xbin+1,ybin+1);
319 value[0] = fCurrentHisto->GetBinContent(bin[0]);
320 value[1] = fCurrentHisto->GetBinContent(bin[1]);
321 value[2] = fCurrentHisto->GetBinContent(bin[2]);
322 value[3] = fCurrentHisto->GetBinContent(bin[3]);
323 value[4] = fCurrentHisto->GetBinContent(bin[4]);
324 value[5] = fCurrentHisto->GetBinContent(bin[5]);
325 value[6] = fCurrentHisto->GetBinContent(bin[6]);
326 value[7] = fCurrentHisto->GetBinContent(bin[7]);
327 value[8] = fCurrentHisto->GetBinContent(bin[8]);
330 if(value[4]>value[0] && value[4]>value[1] && value[4]>value[2]
331 && value[4]>value[3] && value[4]>value[5] && value[4]>value[6]
332 && value[4]>value[7] && value[4]>value[8])
334 //Found a local maxima
335 Float_t maxx = fCurrentHisto->GetBinCenterX(xbin);
336 Float_t maxy = fCurrentHisto->GetBinCenterY(ybin);
338 if((Int_t)value[4] <= threshold) continue;//central bin below threshold
341 cout<<"AliHLTTPCHoughMaxFinder::FindMaxima : Array out of range "<<fNPeaks<<endl;
345 //Check the gradient:
346 if(value[3]/value[4] > fGradX && value[5]/value[4] > fGradX)
349 if(value[1]/value[4] > fGradY && value[7]/value[4] > fGradY)
352 fXPeaks[fNPeaks] = maxx;
353 fYPeaks[fNPeaks] = maxy;
354 fWeight[fNPeaks] = (Int_t)value[4];
358 //Check if the peak is overlapping with a previous:
359 Bool_t bigger = kFALSE;
360 for(Int_t p=0; p<fNPeaks; p++)
362 if(fabs(maxx - fXPeaks[p]) < max_kappa && fabs(maxy - fYPeaks[p]) < max_phi0)
365 if(value[4] > fWeight[p]) //this peak is bigger.
369 fWeight[p] = (Int_t)value[4];
372 continue; //previous peak is bigger.
375 if(!bigger) //there were no overlapping peaks.
377 fXPeaks[fNPeaks] = maxx;
378 fYPeaks[fNPeaks] = maxy;
379 fWeight[fNPeaks] = (Int_t)value[4];
389 struct AliHLTTPCWindow
391 Int_t fStart; // Start
395 void AliHLTTPCHoughMaxFinder::FindAdaptedPeaks(Int_t kappawindow,Float_t cutratio)
397 //Peak finder which looks for peaks with a certain shape.
398 //The first step involves a pre-peak finder, which looks for peaks
399 //in windows (size controlled by kappawindow) summing over each psi-bin.
400 //These pre-preaks are then matched between neighbouring kappa-bins to
401 //look for real 2D peaks exhbiting the typical cross-shape in the Hough circle transform.
402 //The maximum bin within this region is marked as the peak itself, and
403 //a few checks is performed to avoid the clear fake peaks (asymmetry check etc.)
406 AliHLTTPCHistogram *hist = fCurrentHisto;
410 cerr<<"AliHLTTPCHoughMaxFinder : No histogram!"<<endl;
414 if(hist->GetNEntries() == 0)
417 Int_t xmin = hist->GetFirstXbin();
418 Int_t xmax = hist->GetLastXbin();
419 Int_t ymin = hist->GetFirstYbin();
420 Int_t ymax = hist->GetLastYbin();
423 //Start by looking for pre-peaks:
425 AliHLTTPCWindow **localmaxima = new AliHLTTPCWindow*[hist->GetNbinsY()];
427 Short_t *nmaxs = new Short_t[hist->GetNbinsY()];
430 for(Int_t ybin=ymin; ybin<=ymax; ybin++)
432 localmaxima[ybin-ymin] = new AliHLTTPCWindow[hist->GetNbinsX()];
433 nmaxs[ybin-ymin] = 0;
437 for(Int_t xbin=xmin; xbin<=xmax-kappawindow; xbin++)
440 for(Int_t lbin=xbin; lbin<xbin+kappawindow; lbin++)
441 sum += hist->GetBinContent(hist->GetBin(lbin,ybin));
446 if(sumwasrising)//Previous sum was a local maxima
448 localmaxima[ybin-ymin][nmaxs[ybin-ymin]].fStart = xbin-1;
449 localmaxima[ybin-ymin][nmaxs[ybin-ymin]].fSum = lastsum;
462 Int_t *starts = new Int_t[hist->GetNbinsY()+1];
463 Int_t *maxs = new Int_t[hist->GetNbinsY()+1];
465 for(Int_t ybin=ymax; ybin >= ymin+1; ybin--)
467 for(Int_t i=0; i<nmaxs[ybin-ymin]; i++)
469 Int_t lw = localmaxima[ybin-ymin][i].fSum;
472 continue; //already used
474 Int_t maxvalue=0,maxybin=0,maxxbin=0,maxwindow=0;
475 for(Int_t k=localmaxima[ybin-ymin][i].fStart; k<localmaxima[ybin-ymin][i].fStart + kappawindow; k++)
476 if(hist->GetBinContent(hist->GetBin(k,ybin)) > maxvalue)
478 maxvalue = hist->GetBinContent(hist->GetBin(k,ybin));
483 //start expanding in the psi-direction:
485 Int_t lb = localmaxima[ybin-ymin][i].fStart;
487 starts[ybin] = localmaxima[ybin-ymin][i].fStart;
488 maxs[ybin] = maxxbin;
489 Int_t yl=ybin-1,nybins=1;
491 //cout<<"Starting search at ybin "<<ybin<<" start "<<lb<<" with sum "<<localmaxima[ybin-ymin][i].sum<<endl;
495 for(Int_t j=0; j<nmaxs[yl-ymin]; j++)
497 if( localmaxima[yl-ymin][j].fStart - lb < 0) continue;
498 if( localmaxima[yl-ymin][j].fStart < lb + kappawindow + match &&
499 localmaxima[yl-ymin][j].fStart >= lb && localmaxima[yl-ymin][j].fSum > 0)
502 //cout<<"match at ybin "<<yl<<" yvalue "<<hist->GetBinCenterY(yl)<<" start "<<localmaxima[yl-ymin][j].start<<" sum "<<localmaxima[yl-ymin][j].sum<<endl;
504 Int_t lmaxvalue=0,lmaxxbin=0;
505 for(Int_t k=localmaxima[yl-ymin][j].fStart; k<localmaxima[yl-ymin][j].fStart + kappawindow; k++)
507 if(hist->GetBinContent(hist->GetBin(k,yl)) > maxvalue)
509 maxvalue = hist->GetBinContent(hist->GetBin(k,yl));
514 if(hist->GetBinContent(hist->GetBin(k,yl)) > lmaxvalue)//local maxima value
516 lmaxvalue=hist->GetBinContent(hist->GetBin(k,yl));
521 starts[yl] = localmaxima[yl-ymin][j].fStart;
523 localmaxima[yl-ymin][j].fSum=-1; //Mark as used
525 lb = localmaxima[yl-ymin][j].fStart;
526 break;//Since we found a match in this bin, we dont have to search it anymore, goto next bin.
529 if(!found || yl == ymin)//no more local maximas to be matched, so write the final peak and break the expansion:
533 //cout<<"ystart "<<ystart<<" and nybins "<<nybins<<endl;
535 Bool_t truepeak=kTRUE;
537 //cout<<"Maxima found at xbin "<<maxxbin<<" ybin "<<maxybin<<" value "<<maxvalue<<endl;
538 //cout<<"Starting to sum at xbin "<<starts[maxybin-ymin]<<endl;
541 //Look in a window on both sides to probe the asymmetry
542 Float_t right=0,left=0;
543 for(Int_t w=maxxbin+1; w<=maxxbin+3; w++)
545 for(Int_t r=maxybin+1; r<=maxybin+3; r++)
547 right += (Float_t)hist->GetBinContent(hist->GetBin(w,r));
551 for(Int_t w=maxxbin-1; w>=maxxbin-3; w--)
553 for(Int_t r=maxybin+1; r<=maxybin+3; r++)
555 left += (Float_t)hist->GetBinContent(hist->GetBin(w,r));
559 //cout<<"ratio "<<right/left<<endl;
561 Float_t upperratio=1,lowerratio=1;
563 upperratio = right/left;
566 for(Int_t w=maxxbin+1; w<=maxxbin+3; w++)
568 for(Int_t r=maxybin-1; r>=maxybin-3; r--)
570 right += (Float_t)hist->GetBinContent(hist->GetBin(w,r));
574 for(Int_t w=maxxbin-1; w>=maxxbin-3; w--)
576 for(Int_t r=maxybin-1; r>=maxybin-3; r--)
578 left += (Float_t)hist->GetBinContent(hist->GetBin(w,r));
582 //cout<<"ratio "<<left/right<<endl;
585 lowerratio = left/right;
587 if(upperratio > cutratio || lowerratio > cutratio)
593 fXPeaks[fNPeaks] = hist->GetBinCenterX(maxxbin);
594 fYPeaks[fNPeaks] = hist->GetBinCenterY(maxybin);
595 fWeight[fNPeaks] = maxvalue;
599 //Calculate the peak using weigthed means:
602 for(Int_t k=maxybin-1; k<=maxybin+1; k++)
605 for(Int_t l=starts[k]; l<starts[k]+kappawindow; l++)
607 lsum += (Float_t)hist->GetBinContent(hist->GetBin(l,k));
608 sum += (Float_t)hist->GetBinContent(hist->GetBin(l,k));
610 fYPeaks[fNPeaks] += lsum*hist->GetBinCenterY(k);
612 fYPeaks[fNPeaks] /= sum;
614 if(fYPeaks[fNPeaks] < hist->GetBinCenterY(hist->FindYbin(fYPeaks[fNPeaks])))
616 ybin1 = hist->FindYbin(fYPeaks[fNPeaks])-1;
621 ybin1 = hist->FindYbin(fYPeaks[fNPeaks]);
625 Float_t kappa1=0,kappa2=0;
627 for(Int_t k=starts[ybin1]; k<starts[ybin1] + kappawindow; k++)
629 kappa1 += hist->GetBinCenterX(k)*hist->GetBinContent(hist->GetBin(k,ybin1));
630 sum += (Float_t)hist->GetBinContent(hist->GetBin(k,ybin1));
634 for(Int_t k=starts[ybin2]; k<starts[ybin2] + kappawindow; k++)
636 kappa2 += hist->GetBinCenterX(k)*hist->GetBinContent(hist->GetBin(k,ybin2));
637 sum += (Float_t)hist->GetBinContent(hist->GetBin(k,ybin2));
641 fXPeaks[fNPeaks] = ( kappa1*( hist->GetBinCenterY(ybin2) - fYPeaks[fNPeaks] ) +
642 kappa2*( fYPeaks[fNPeaks] - hist->GetBinCenterY(ybin1) ) ) /
643 (hist->GetBinCenterY(ybin2) - hist->GetBinCenterY(ybin1));
652 yl--;//Search continues...
657 for(Int_t i=0; i<hist->GetNbinsY(); i++)
658 delete localmaxima[i];
660 delete [] localmaxima;
666 struct AliHLTTPCPreYPeak
668 Int_t fStartPosition; // Start position in X
669 Int_t fEndPosition; // End position in X
670 Int_t fMinValue; // Minimum value inside the prepeak
671 Int_t fMaxValue; // Maximum value inside the prepeak
672 Int_t fPrevValue; // Neighbour values
673 Int_t fLeftValue; // Neighbour values
674 Int_t fRightValue; // Neighbour values
677 void AliHLTTPCHoughMaxFinder::FindAdaptedRowPeaks(Int_t kappawindow,Int_t xsize,Int_t ysize)
679 // Peak finder which is working over the Hough Space provided by the AliHLTTPCHoughTransformerRow class
680 AliHLTTPCHistogram *hist = fCurrentHisto;
684 cerr<<"AliHLTTPCHoughMaxFinder : No histogram!"<<endl;
688 if(hist->GetNEntries() == 0)
691 Int_t xmin = hist->GetFirstXbin();
692 Int_t xmax = hist->GetLastXbin();
693 Int_t ymin = hist->GetFirstYbin();
694 Int_t ymax = hist->GetLastYbin();
695 Int_t nxbins = hist->GetNbinsX()+2;
696 Int_t *content = hist->GetContentArray();
698 //Start by looking for pre-peaks:
700 AliHLTTPCPreYPeak **localmaxima = new AliHLTTPCPreYPeak*[hist->GetNbinsY()];
702 Short_t *nmaxs = new Short_t[hist->GetNbinsY()];
703 memset(nmaxs,0,hist->GetNbinsY()*sizeof(Short_t));
704 Int_t lastvalue=0,value=0;
705 for(Int_t ybin=fNextRow[ymin]; ybin<=ymax; ybin = fNextRow[ybin+1])
707 localmaxima[ybin-ymin] = new AliHLTTPCPreYPeak[nxbins-2];
710 for(Int_t xbin=xmin; xbin<=xmax; xbin++)
712 value = content[xbin + nxbins*ybin]; //value = hist->GetBinContent(xbin + nxbins*ybin); //value = hist->GetBinContent(hist->GetBin(xbin,ybin));
715 if((value - lastvalue) > 1)
717 localmaxima[ybin-ymin][nmaxs[ybin-ymin]].fStartPosition = xbin;
718 localmaxima[ybin-ymin][nmaxs[ybin-ymin]].fEndPosition = xbin;
719 localmaxima[ybin-ymin][nmaxs[ybin-ymin]].fMinValue = value;
720 localmaxima[ybin-ymin][nmaxs[ybin-ymin]].fMaxValue = value;
721 localmaxima[ybin-ymin][nmaxs[ybin-ymin]].fPrevValue = 0;
722 localmaxima[ybin-ymin][nmaxs[ybin-ymin]].fLeftValue = lastvalue;
725 if(abs(value - lastvalue) <= 1)
728 localmaxima[ybin-ymin][nmaxs[ybin-ymin]].fEndPosition = xbin;
729 if(value>localmaxima[ybin-ymin][nmaxs[ybin-ymin]].fMaxValue)
730 localmaxima[ybin-ymin][nmaxs[ybin-ymin]].fMaxValue = value;
731 if(value<localmaxima[ybin-ymin][nmaxs[ybin-ymin]].fMinValue)
732 localmaxima[ybin-ymin][nmaxs[ybin-ymin]].fMinValue = value;
735 if((value - lastvalue) < -1)
738 localmaxima[ybin-ymin][nmaxs[ybin-ymin]].fRightValue = value;
747 localmaxima[ybin-ymin][nmaxs[ybin-ymin]].fRightValue = value;
756 localmaxima[ybin-ymin][nmaxs[ybin-ymin]].fRightValue = 0;
761 AliHLTTPCPre2DPeak maxima[500];
764 for(Int_t ybin=ymax; ybin >= ymin; ybin--)
766 for(Int_t i=0; i<nmaxs[ybin-ymin]; i++)
768 Int_t localminvalue = localmaxima[ybin-ymin][i].fMinValue;
769 Int_t localmaxvalue = localmaxima[ybin-ymin][i].fMaxValue;
770 Int_t localprevvalue = localmaxima[ybin-ymin][i].fPrevValue;
771 Int_t localnextvalue = 0;
772 Int_t localleftvalue = localmaxima[ybin-ymin][i].fLeftValue;
773 Int_t localrightvalue = localmaxima[ybin-ymin][i].fRightValue;
776 continue; //already used
778 //start expanding in the psi-direction:
780 Int_t localxstart = localmaxima[ybin-ymin][i].fStartPosition;
781 Int_t localxend = localmaxima[ybin-ymin][i].fEndPosition;
782 Int_t tempxstart = localmaxima[ybin-ymin][i].fStartPosition;
783 Int_t tempxend = localmaxima[ybin-ymin][i].fEndPosition;
785 Int_t localy=ybin-1,nybins=1;
787 while(localy >= ymin)
790 for(Int_t j=0; j<nmaxs[localy-ymin]; j++)
792 if( (localmaxima[localy-ymin][j].fStartPosition <= (tempxend + kappawindow)) && (localmaxima[localy-ymin][j].fEndPosition >= (tempxstart - kappawindow)))
794 if((localmaxima[localy-ymin][j].fMinValue <= localmaxvalue) && (localmaxima[localy-ymin][j].fMaxValue >= localminvalue))
796 if(localmaxima[localy-ymin][j].fEndPosition > localxend)
797 localxend = localmaxima[localy-ymin][j].fEndPosition;
798 if(localmaxima[localy-ymin][j].fStartPosition < localxstart)
799 localxstart = localmaxima[localy-ymin][j].fStartPosition;
800 tempxstart = localmaxima[localy-ymin][j].fStartPosition;
801 tempxend = localmaxima[localy-ymin][j].fEndPosition;
802 if(localmaxima[localy-ymin][j].fMinValue < localminvalue)
803 localminvalue = localmaxima[localy-ymin][j].fMinValue;
804 if(localmaxima[localy-ymin][j].fMaxValue > localmaxvalue)
805 localmaxvalue = localmaxima[localy-ymin][j].fMaxValue;
806 if(localmaxima[localy-ymin][j].fRightValue > localrightvalue)
807 localrightvalue = localmaxima[localy-ymin][j].fRightValue;
808 if(localmaxima[localy-ymin][j].fLeftValue > localleftvalue)
809 localleftvalue = localmaxima[localy-ymin][j].fLeftValue;
810 localmaxima[localy-ymin][j].fMinValue = -1;
817 if(localmaxvalue > localmaxima[localy-ymin][j].fPrevValue)
818 localmaxima[localy-ymin][j].fPrevValue = localmaxvalue;
819 if(localmaxima[localy-ymin][j].fMaxValue > localnextvalue)
820 localnextvalue = localmaxima[localy-ymin][j].fMaxValue;
824 if(!found || localy == ymin)//no more local maximas to be matched, so write the final peak and break the expansion:
826 if((nybins > ysize) && ((localxend-localxstart+1) > xsize) && (localmaxvalue > localprevvalue) && (localmaxvalue > localnextvalue) && (localmaxvalue > localleftvalue) && (localmaxvalue > localrightvalue))
827 // if((nybins > ysize) && ((localxend-localxstart+1) > xsize))
829 maxima[nmaxima].fX = ((Float_t)localxstart+(Float_t)localxend)/2.0;
830 maxima[nmaxima].fY = ((Float_t)ybin+(Float_t)(localy+1))/2.0;
831 maxima[nmaxima].fSizeX = localxend-localxstart+1;
832 maxima[nmaxima].fSizeY = nybins;
833 maxima[nmaxima].fWeight = (localminvalue+localmaxvalue)/2;
834 maxima[nmaxima].fStartX = localxstart;
835 maxima[nmaxima].fEndX = localxend;
836 maxima[nmaxima].fStartY = localy +1;
837 maxima[nmaxima].fEndY = ybin;
839 // cout<<"Peak found at: "<<((Float_t)localxstart+(Float_t)localxend)/2.0<<" "<<((Float_t)ybin+(Float_t)(localy+1))/2.0<<" "<<localminvalue<<" "<<localmaxvalue<<" "<<" with weight "<<(localminvalue+localmaxvalue)/2<<" and size "<<localxend-localxstart+1<<" by "<<nybins<<endl;
846 localy--;//Search continues...
853 for(Int_t i = 0; i < (nmaxima - 1); i++)
855 // if(maxima[i].fWeight < 0) continue;
856 for(Int_t j = i + 1; j < nmaxima; j++)
858 // if(maxima[j].fWeight < 0) continue;
859 MergeRowPeaks(&maxima[i],&maxima[j],5.0);
863 //merge tracks in neighbour eta slices
864 Int_t currentnpeaks = fNPeaks;
865 for(Int_t i = 0; i < nmaxima; i++) {
866 if(maxima[i].fWeight < 0) continue;
867 Bool_t merged = kFALSE;
868 for(Int_t j = fN1PeaksPrevEtaSlice; j < fN2PeaksPrevEtaSlice; j++) {
869 // if(fWeight[j] < 0) continue;
870 // Merge only peaks with limited size in eta
871 if((fENDETAPeaks[j]-fSTARTETAPeaks[j]) >= 2) continue;
872 if((maxima[i].fStartX <= fENDXPeaks[j]+1) && (maxima[i].fEndX >= fSTARTXPeaks[j]-1) && (maxima[i].fStartY <= fENDYPeaks[j]+1) && (maxima[i].fEndY >= fSTARTYPeaks[j]-1)){
876 fXPeaks[fNPeaks] = (hist->GetPreciseBinCenterX(maxima[i].fX)+(fENDETAPeaks[j]-fSTARTETAPeaks[j]+1)*fXPeaks[j])/(fENDETAPeaks[j]-fSTARTETAPeaks[j]+2);
877 fYPeaks[fNPeaks] = (hist->GetPreciseBinCenterY(maxima[i].fY)+(fENDETAPeaks[j]-fSTARTETAPeaks[j]+1)*fYPeaks[j])/(fENDETAPeaks[j]-fSTARTETAPeaks[j]+2);
878 fSTARTXPeaks[fNPeaks] = maxima[i].fStartX;
879 fSTARTYPeaks[fNPeaks] = maxima[i].fStartY;
880 fENDXPeaks[fNPeaks] = maxima[i].fEndX;
881 fENDYPeaks[fNPeaks] = maxima[i].fEndY;
883 fWeight[fNPeaks] = abs((Int_t)maxima[i].fWeight) + abs(fWeight[j]);
884 fSTARTETAPeaks[fNPeaks] = fSTARTETAPeaks[j];
885 fENDETAPeaks[fNPeaks] = fCurrentEtaSlice;
888 fWeight[j] = -abs(fWeight[j]);
891 fXPeaks[fNPeaks] = hist->GetPreciseBinCenterX(maxima[i].fX);
892 fYPeaks[fNPeaks] = hist->GetPreciseBinCenterY(maxima[i].fY);
894 fWeight[fNPeaks] = abs((Int_t)maxima[i].fWeight);
896 fWeight[fNPeaks] = -abs((Int_t)maxima[i].fWeight);
897 fSTARTXPeaks[fNPeaks] = maxima[i].fStartX;
898 fSTARTYPeaks[fNPeaks] = maxima[i].fStartY;
899 fENDXPeaks[fNPeaks] = maxima[i].fEndX;
900 fENDYPeaks[fNPeaks] = maxima[i].fEndY;
901 fSTARTETAPeaks[fNPeaks] = fCurrentEtaSlice;
902 fENDETAPeaks[fNPeaks] = fCurrentEtaSlice;
906 fN1PeaksPrevEtaSlice = currentnpeaks;
907 fN2PeaksPrevEtaSlice = fNPeaks;
909 for(Int_t ybin=fNextRow[ymin]; ybin<=ymax; ybin = fNextRow[ybin+1])
910 delete [] localmaxima[ybin-ymin];
912 delete [] localmaxima;
916 void AliHLTTPCHoughMaxFinder::FindPeak1(Int_t ywindow,Int_t xbinsides)
918 //Testing mutliple peakfinding.
919 //The algorithm searches the histogram for prepreaks by looking in windows
920 //for each bin on the xaxis. The size of these windows is controlled by ywindow.
921 //Then the prepreaks are sorted according to their weight (sum inside window),
922 //and the peak positions are calculated by taking the weighted mean in both
923 //x and y direction. The size of the peak in x-direction is controlled by xbinsides.
927 printf("AliHLTTPCHoughMaxFinder::FindPeak1 : No input histogram\n");
930 if(fCurrentHisto->GetNEntries()==0)
936 //Float_t max_kappa = 0.001;
937 //Float_t max_phi0 = 0.08;
941 Int_t xmin = fCurrentHisto->GetFirstXbin();
942 Int_t xmax = fCurrentHisto->GetLastXbin();
943 Int_t ymin = fCurrentHisto->GetFirstYbin();
944 Int_t ymax = fCurrentHisto->GetLastYbin();
945 Int_t nbinsx = fCurrentHisto->GetNbinsX()+1;
947 AliHLTTPCAxisWindow **windowPt = new AliHLTTPCAxisWindow*[nbinsx];
948 AliHLTTPCAxisWindow **anotherPt = new AliHLTTPCAxisWindow*[nbinsx];
950 for(Int_t i=0; i<nbinsx; i++)
952 windowPt[i] = new AliHLTTPCAxisWindow;
953 #if defined(__DECCXX)
954 bzero((char *)windowPt[i],sizeof(AliHLTTPCAxisWindow));
956 bzero((void*)windowPt[i],sizeof(AliHLTTPCAxisWindow));
958 anotherPt[i] = windowPt[i];
961 for(Int_t xbin=xmin; xbin<=xmax; xbin++)
964 for(Int_t ybin=ymin; ybin<=ymax-ywindow; ybin++)
967 for(Int_t b=ybin; b<ybin+ywindow; b++)
970 Int_t bin = fCurrentHisto->GetBin(xbin,b);
971 suminwindow += (Int_t)fCurrentHisto->GetBinContent(bin);
974 if(suminwindow > maxsum)
976 maxsum = suminwindow;
977 windowPt[xbin]->fYmin = ybin;
978 windowPt[xbin]->fYmax = ybin + ywindow;
979 windowPt[xbin]->fWeight = suminwindow;
980 windowPt[xbin]->fXbin = xbin;
985 //Sort the windows according to the weight
986 SortPeaks(windowPt,0,nbinsx);
989 for(Int_t i=0; i<nbinsx; i++)
992 Int_t xbin = windowPt[i]->fXbin;
994 if(xbin<xmin || xbin > xmax-1) continue;
996 //Check if this is really a local maxima
997 if(anotherPt[xbin-1]->fWeight > anotherPt[xbin]->fWeight ||
998 anotherPt[xbin+1]->fWeight > anotherPt[xbin]->fWeight)
1001 for(Int_t j=windowPt[i]->fYmin; j<windowPt[i]->fYmax; j++)
1003 //Calculate the mean in y direction:
1004 Int_t bin = fCurrentHisto->GetBin(windowPt[i]->fXbin,j);
1005 top += (fCurrentHisto->GetBinCenterY(j))*(fCurrentHisto->GetBinContent(bin));
1006 butt += fCurrentHisto->GetBinContent(bin);
1009 if(butt < fThreshold)
1012 fXPeaks[fNPeaks] = fCurrentHisto->GetBinCenterX(windowPt[i]->fXbin);
1013 fYPeaks[fNPeaks] = top/butt;
1014 fWeight[fNPeaks] = (Int_t)butt;
1015 //cout<<"mean in y "<<ypeaks[n]<<" on x "<<windowPt[i]->xbin<<" content "<<butt<<endl;
1019 cerr<<"AliHLTTPCHoughMaxFinder::FindPeak1 : Peak array out of range!!!"<<endl;
1025 //Improve the peaks by including the region around in x.
1029 for(Int_t i=0; i<fNPeaks; i++)
1031 Int_t xbin = fCurrentHisto->FindXbin(fXPeaks[i]);
1032 if(xbin - xbinsides < xmin || xbin + xbinsides > xmax) continue;
1036 prev = xbin - xbinsides+1;
1037 for(Int_t j=xbin-xbinsides; j<=xbin+xbinsides; j++)
1040 //Check if the windows are overlapping:
1041 if(anotherPt[j]->ymin > anotherPt[prev]->ymax) {prev=j; continue;}
1042 if(anotherPt[j]->ymax < anotherPt[prev]->ymin) {prev=j; continue;}
1046 top += fCurrentHisto->GetBinCenterX(j)*anotherPt[j]->fWeight;
1047 butt += anotherPt[j]->fWeight;
1049 for(Int_t k=anotherPt[j]->fYmin; k<anotherPt[j]->fYmax; k++)
1051 Int_t bin = fCurrentHisto->GetBin(j,k);
1052 ytop += (fCurrentHisto->GetBinCenterY(k))*(fCurrentHisto->GetBinContent(bin));
1053 ybutt += fCurrentHisto->GetBinContent(bin);
1054 w+=(Int_t)fCurrentHisto->GetBinContent(bin);
1058 fXPeaks[i] = top/butt;
1059 fYPeaks[i] = ytop/ybutt;
1061 //cout<<"Setting weight "<<w<<" kappa "<<fXPeaks[i]<<" phi0 "<<fYPeaks[i]<<endl;
1064 //Check if this peak is overlapping with a previous:
1065 for(Int_t p=0; p<i; p++)
1067 //cout<<fabs(fXPeaks[p] - fXPeaks[i])<<" "<<fabs(fYPeaks[p] - fYPeaks[i])<<endl;
1068 if(fabs(fXPeaks[p] - fXPeaks[i]) < max_kappa &&
1069 fabs(fYPeaks[p] - fYPeaks[i]) < max_phi0)
1078 for(Int_t i=0; i<nbinsx; i++)
1081 delete [] anotherPt;
1084 void AliHLTTPCHoughMaxFinder::SortPeaks(struct AliHLTTPCAxisWindow **a,Int_t first,Int_t last)
1086 //General sorting routine
1087 //Sort according to PeakCompare()
1089 static struct AliHLTTPCAxisWindow *tmp;
1090 static int i; // "static" to save stack space
1093 while (last - first > 1) {
1097 while (++i < last && PeakCompare(a[i], a[first]) < 0)
1099 while (--j > first && PeakCompare(a[j], a[first]) > 0)
1115 if (j - first < last - (j + 1)) {
1116 SortPeaks(a, first, j);
1117 first = j + 1; // QSort(j + 1, last);
1119 SortPeaks(a, j + 1, last);
1120 last = j; // QSort(first, j);
1126 Int_t AliHLTTPCHoughMaxFinder::PeakCompare(struct AliHLTTPCAxisWindow *a,struct AliHLTTPCAxisWindow *b) const
1128 // Peak comparison based on peaks weight
1129 if(a->fWeight < b->fWeight) return 1;
1130 if(a->fWeight > b->fWeight) return -1;
1134 void AliHLTTPCHoughMaxFinder::FindPeak(Int_t t1,Double_t t2,Int_t t3)
1136 //Attempt of a more sophisticated peak finder.
1137 //Finds the best peak in the histogram, and returns the corresponding
1142 printf("AliHLTTPCHoughMaxFinder::FindPeak : No histogram!!\n");
1145 AliHLTTPCHistogram *hist = fCurrentHisto;
1146 if(hist->GetNEntries()==0)
1149 Int_t xmin = hist->GetFirstXbin();
1150 Int_t xmax = hist->GetLastXbin();
1151 Int_t ymin = hist->GetFirstYbin();
1152 Int_t ymax = hist->GetLastYbin();
1153 Int_t nbinsx = hist->GetNbinsX()+1;
1155 Int_t *m = new Int_t[nbinsx];
1156 Int_t *mlow = new Int_t[nbinsx];
1157 Int_t *mup = new Int_t[nbinsx];
1160 recompute: //this is a goto.
1162 for(Int_t i=0; i<nbinsx; i++)
1169 Int_t maxx=0,sum=0,maxxbin=0,bin=0;
1171 for(Int_t xbin=xmin; xbin<=xmax; xbin++)
1173 for(Int_t ybin=ymin; ybin <= ymax - t1; ybin++)
1176 for(Int_t y=ybin; y <= ybin+t1; y++)
1180 bin = hist->GetBin(xbin,y);
1181 sum += (Int_t)hist->GetBinContent(bin);
1184 if(sum > m[xbin]) //Max value locally in this xbin
1188 mup[xbin]=ybin + t1;
1193 if(m[xbin] > maxx) //Max value globally in x-direction
1196 maxx = m[xbin];//sum;
1199 //printf("maxxbin %d maxx %d mlow %d mup %d\n",maxxbin,maxx,mlow[maxxbin],mup[maxxbin]);
1200 //printf("ylow %f yup %f\n",hist->GetBinCenterY(mlow[maxxbin]),hist->GetBinCenterY(mup[maxxbin]));
1202 //Determine a width in the x-direction
1205 for(Int_t xbin=maxxbin-1; xbin >= xmin; xbin--)
1207 if(m[xbin] < maxx*t2)
1213 for(Int_t xbin = maxxbin+1; xbin <=xmax; xbin++)
1215 if(m[xbin] < maxx*t2)
1222 Double_t top=0,butt=0,value,xpeak;
1223 if(xup - xlow + 1 > t3)
1226 printf("\nxrange out if limit xup %d xlow %d t1 %d\n\n",xlow,xup,t1);
1231 xpeak = hist->GetBinCenterX(maxxbin);
1236 //printf("xlow %f xup %f\n",hist->GetBinCenterX(xlow),hist->GetBinCenterX(xup));
1237 //printf("Spread in x %d\n",xup-xlow +1);
1239 //Now, calculate the center of mass in x-direction
1240 for(Int_t xbin=xlow; xbin <= xup; xbin++)
1242 value = hist->GetBinCenterX(xbin);
1243 top += value*m[xbin];
1250 //Find the peak in y direction:
1251 Int_t xl = hist->FindXbin(xpeak);
1252 if(hist->GetBinCenterX(xl) > xpeak)
1257 if(hist->GetBinCenterX(xl) > xpeak || hist->GetBinCenterX(xu) <= xpeak)
1258 printf("\nAliHLTTPCHoughMaxFinder::FindPeak : Wrong xrange %f %f %f\n\n",hist->GetBinCenterX(xl),xpeak,hist->GetBinCenterX(xu));
1260 //printf("\nxlow %f xup %f\n",hist->GetBinCenterX(xl),hist->GetBinCenterX(xu));
1264 //printf("ylow %f yup %f\n",hist->GetBinCenterY(mlow[xl]),hist->GetBinCenterY(mup[xl]));
1265 //printf("ylow %f yup %f\n",hist->GetBinCenterY(mlow[xu]),hist->GetBinCenterY(mup[xu]));
1267 for(Int_t ybin=mlow[xl]; ybin <= mup[xl]; ybin++)
1269 value = hist->GetBinCenterY(ybin);
1270 bin = hist->GetBin(xl,ybin);
1271 top += value*hist->GetBinContent(bin);
1272 butt += hist->GetBinContent(bin);
1274 Double_t ypeaklow = top/butt;
1276 //printf("ypeaklow %f\n",ypeaklow);
1279 for(Int_t ybin=mlow[xu]; ybin <= mup[xu]; ybin++)
1281 value = hist->GetBinCenterY(ybin);
1282 bin = hist->GetBin(xu,ybin);
1283 top += value*hist->GetBinContent(bin);
1284 butt += hist->GetBinContent(bin);
1286 Double_t ypeakup = top/butt;
1288 //printf("ypeakup %f\n",ypeakup);
1290 Double_t xvalueup = hist->GetBinCenterX(xu);
1291 Double_t xvaluelow = hist->GetBinCenterX(xl);
1293 Double_t ypeak = (ypeaklow*(xvalueup - xpeak) + ypeakup*(xpeak - xvaluelow))/(xvalueup - xvaluelow);
1297 //bin = hist->FindBin(xpeak,ypeak);
1298 //Int_t weight = (Int_t)hist->GetBinContent(bin);
1300 //AliHLTTPCHoughTrack *track = new AliHLTTPCHoughTrack();
1301 //track->SetTrackParameters(xpeak,ypeak,weight);
1302 fXPeaks[fNPeaks]=xpeak;
1303 fYPeaks[fNPeaks]=ypeak;
1304 fWeight[fNPeaks]=(Int_t)hist->GetBinContent(bin);
1314 Float_t AliHLTTPCHoughMaxFinder::GetXPeakSize(Int_t i) const
1316 // Get X size of a peak
1319 STDCERR<<"AliHLTTPCHoughMaxFinder::GetXPeakSize : Invalid index "<<i<<STDENDL;
1322 Float_t binwidth = fCurrentHisto->GetBinWidthX();
1323 return binwidth*(fENDXPeaks[i]-fSTARTXPeaks[i]+1);
1326 Float_t AliHLTTPCHoughMaxFinder::GetYPeakSize(Int_t i) const
1328 // Get Y size of a peak
1331 STDCERR<<"AliHLTTPCHoughMaxFinder::GetYPeak : Invalid index "<<i<<STDENDL;
1334 Float_t binwidth = fCurrentHisto->GetBinWidthY();
1335 return binwidth*(fENDYPeaks[i]-fSTARTYPeaks[i]+1);
1338 Bool_t AliHLTTPCHoughMaxFinder::MergeRowPeaks(AliHLTTPCPre2DPeak *maxima1, AliHLTTPCPre2DPeak *maxima2, Float_t distance)
1340 // Check the distance between tracks corresponding to given Hough space peaks and if the
1341 // distance is smaller than some threshold value marks the smaller peak as fake
1342 AliHLTTPCHistogram *hist = fCurrentHisto;
1343 Int_t nxbins = hist->GetNbinsX()+2;
1345 Int_t xtrack1=0,xtrack2=0,ytrack1=0,ytrack2=0;
1346 Int_t deltax = 9999;
1347 for(Int_t ix1 = maxima1->fStartX; ix1 <= maxima1->fEndX; ix1++) {
1348 for(Int_t ix2 = maxima2->fStartX; ix2 <= maxima2->fEndX; ix2++) {
1349 if(abs(ix1 - ix2) < deltax) {
1350 deltax = abs(ix1 - ix2);
1356 Int_t deltay = 9999;
1357 for(Int_t iy1 = maxima1->fStartY; iy1 <= maxima1->fEndY; iy1++) {
1358 for(Int_t iy2 = maxima2->fStartY; iy2 <= maxima2->fEndY; iy2++) {
1359 if(abs(iy1 - iy2) < deltay) {
1360 deltay = abs(iy1 - iy2);
1366 Int_t firstrow1 = fTrackFirstRow[xtrack1 + nxbins*ytrack1];
1367 Int_t lastrow1 = fTrackLastRow[xtrack1 + nxbins*ytrack1];
1368 Int_t firstrow2 = fTrackFirstRow[xtrack1 + nxbins*ytrack1];
1369 Int_t lastrow2 = fTrackLastRow[xtrack1 + nxbins*ytrack1];
1370 Int_t firstrow,lastrow;
1371 if(firstrow1 < firstrow2)
1372 firstrow = firstrow2;
1374 firstrow = firstrow1;
1376 if(lastrow1 > lastrow2)
1381 AliHLTTPCHoughTrack track1;
1382 Float_t x1 = hist->GetPreciseBinCenterX(xtrack1);
1383 Float_t y1 = hist->GetPreciseBinCenterY(ytrack1);
1384 Float_t psi1 = atan((x1-y1)/(AliHLTTPCHoughTransformerRow::GetBeta1()-AliHLTTPCHoughTransformerRow::GetBeta2()));
1385 Float_t kappa1 = 2.0*(x1*cos(psi1)-AliHLTTPCHoughTransformerRow::GetBeta1()*sin(psi1));
1386 track1.SetTrackParameters(kappa1,psi1,1);
1387 Float_t firsthit1[3];
1388 if(!track1.GetCrossingPoint(firstrow,firsthit1)) return kFALSE;
1389 Float_t lasthit1[3];
1390 if(!track1.GetCrossingPoint(lastrow,lasthit1)) return kFALSE;
1392 AliHLTTPCHoughTrack track2;
1393 Float_t x2 = hist->GetPreciseBinCenterX(xtrack2);
1394 Float_t y2 = hist->GetPreciseBinCenterY(ytrack2);
1395 Float_t psi2 = atan((x2-y2)/(AliHLTTPCHoughTransformerRow::GetBeta1()-AliHLTTPCHoughTransformerRow::GetBeta2()));
1396 Float_t kappa2 = 2.0*(x2*cos(psi2)-AliHLTTPCHoughTransformerRow::GetBeta1()*sin(psi2));
1397 track2.SetTrackParameters(kappa2,psi2,1);
1398 Float_t firsthit2[3];
1399 if(!track2.GetCrossingPoint(firstrow,firsthit2)) return kFALSE;
1400 Float_t lasthit2[3];
1401 if(!track2.GetCrossingPoint(lastrow,lasthit2)) return kFALSE;
1403 Float_t padpitchlow = AliHLTTPCTransform::GetPadPitchWidth(AliHLTTPCTransform::GetPatch(firstrow));
1404 Float_t padpitchup = AliHLTTPCTransform::GetPadPitchWidth(AliHLTTPCTransform::GetPatch(lastrow));
1405 // check the distance between tracks at the edges
1406 // cout<<"Check "<<firsthit1[1]<<" "<<firsthit2[1]<<" "<<padpitchlow<<" "<<lasthit1[1]<<" "<<lasthit2[1]<<" "<<padpitchup<<" "<<xtrack1<<" "<<ytrack1<<" "<<xtrack2<<" "<<ytrack2<<endl;
1407 if((fabs(firsthit1[1]-firsthit2[1])/padpitchlow + fabs(lasthit1[1]-lasthit2[1])/padpitchup) < distance) {
1408 if(maxima1->fSizeX*maxima1->fSizeY > maxima2->fSizeX*maxima2->fSizeY)
1409 maxima2->fWeight = -fabs(maxima2->fWeight);
1410 if(maxima1->fSizeX*maxima1->fSizeY < maxima2->fSizeX*maxima2->fSizeY)
1411 maxima1->fWeight = -fabs(maxima1->fWeight);
1412 if(maxima1->fSizeX*maxima1->fSizeY == maxima2->fSizeX*maxima2->fSizeY) {
1413 if(maxima1->fStartX > maxima2->fStartX)
1414 maxima1->fStartX = maxima2->fStartX;
1415 if(maxima1->fStartY > maxima2->fStartY)
1416 maxima1->fStartY = maxima2->fStartY;
1417 if(maxima1->fEndX < maxima2->fEndX)
1418 maxima1->fEndX = maxima2->fEndX;
1419 if(maxima1->fEndY < maxima2->fEndY)
1420 maxima1->fEndY = maxima2->fEndY;
1421 maxima1->fX = ((Float_t)maxima1->fStartX + (Float_t)maxima1->fEndX)/2.0;
1422 maxima1->fY = ((Float_t)maxima1->fStartY + (Float_t)maxima1->fEndY)/2.0;
1423 maxima1->fSizeX = (maxima1->fEndX - maxima1->fStartX + 1);
1424 maxima1->fSizeY = (maxima1->fEndY - maxima1->fStartY + 1);
1425 maxima2->fWeight = -fabs(maxima2->fWeight);