40 #include "AliRunLoader.h"
43 #include <Riostream.h>
86 fkSegmentation[1] = fkSegmentation[0] = 0x0;
88 if (fPlot) fDebug = 1;
97 AliInfo(Form(
"Total clusters %d AddVirtualPad needed %d",
110 for ( Int_t i = 0; i < 2; ++i )
119 AliRunLoader *runLoader = AliRunLoader::Instance();
120 fEventNumber = runLoader ? runLoader->GetEventNumber() : 0;
171 for ( Int_t i = 0; i < mult; ++i )
197 printf(
" bbb %3d %1d %8.4f %8.4f %8.4f %8.4f %6.1f %3d %3d %2d %1d %1d \n",
204 if (!cluster)
return kFALSE;
210 AliDebug(1,
"No pixel for the above cluster");
215 Int_t nMax = 1, localMax[100], maxPos[100] = {0};
216 Double_t maxVal[100];
220 if (nMax > 1) TMath::Sort(nMax, maxVal, maxPos, kTRUE);
222 for (Int_t i = 0; i < nMax; ++i)
267 AliDebug(2,
"Start of CheckPreCluster=");
290 Int_t* flags =
new Int_t[npad];
291 for (Int_t j = 0; j < npad; ++j) flags[j] = 0;
294 for ( Int_t i = 0; i < npad; ++i)
297 if ( padi->
Cathode() != 0 )
continue;
298 for (Int_t j = i+1; j < npad; ++j)
301 if ( padj->
Cathode() != 1 )
continue;
303 flags[i] = flags[j] = 1;
309 for (Int_t i = 0; i < npad; ++i)
311 if (!flags[i]) ++nFlags;
317 if (
fDebug) cout <<
" nFlags: " << nFlags << endl;
319 for (Int_t i = 0; i < npad; ++i)
322 if (flags[i])
continue;
324 Int_t cath1 = TMath::Even(cath);
328 if (!mpPad.
IsValid())
continue;
330 if (nFlags == 1 && pad->
Charge() < 3.05)
continue;
331 AliDebug(2,Form(
"Releasing the following pad : de,cath,ix,iy %d,%d,%d,%d charge %e",
333 toBeRemoved.AddLast(pad);
336 Int_t nRemove = toBeRemoved.GetEntriesFast();
337 for ( Int_t i = 0; i < nRemove; ++i )
339 cluster->
RemovePad(static_cast<AliMUONPad*>(toBeRemoved.UncheckedAt(i)));
357 for ( Int_t i = 0; i < mult; ++i )
366 if ( pad->
Charge() < cmin )
375 else if ( pad->
Charge() > cmax )
381 AliDebug(2,Form(
"Pad imin,imax %d,%d cmin,cmax %e,%e",
382 imin,imax,cmin,cmax));
386 Double_t* dist =
new Double_t[mult];
393 for ( Int_t i = 0; i < mult; ++i )
396 if ( i == imax)
continue;
399 Double_t dx = (pad->
X()-padmax->
X())/padmax->
DX()/2.0;
400 Double_t dy = (pad->
Y()-padmax->
Y())/padmax->
DY()/2.0;
401 dist[i] = TMath::Sqrt(dx*dx+dy*dy);
404 dmin = dist[i] + 1E-3;
410 TMath::Sort(mult,dist,flags,kFALSE);
411 Double_t xmax(-1), distPrev(999);
414 for ( Int_t i = 0; i < mult; ++i )
416 Int_t indx = flags[i];
419 if ( dist[indx] > dmin )
422 Double_t dx = (pad->
X()-padmax->
X())/padmax->
DX()/2.0;
423 Double_t dy = (pad->
Y()-padmax->
Y())/padmax->
DY()/2.0;
426 if (dx >= 0 && dy >= 0)
continue;
427 if (TMath::Abs(dx) > TMath::Abs(dy) && dx >= 0)
continue;
428 if (TMath::Abs(dy) > TMath::Abs(dx) && dy >= 0)
continue;
430 if (dist[indx] > distPrev + 1)
break;
431 if ( pad->
Charge() <= cmax || TMath::Abs(dist[indx]-xmax) < 1E-3 )
434 if (TMath::Abs(dist[indx]-xmax) < 1.e-3)
436 cmax = TMath::Max(pad->
Charge(),cmax);
443 distPrev = dist[indx];
444 AliDebug(2,Form(
"Releasing the following pad : de,cath,ix,iy %d,%d,%d,%d charge %e",
448 toBeRemoved.AddLast(pad);
452 Int_t nRemove = toBeRemoved.GetEntriesFast();
453 for ( Int_t i = 0; i < nRemove; ++i )
455 cluster->
RemovePad(static_cast<AliMUONPad*>(toBeRemoved.UncheckedAt(i)));
462 AliDebug(2,
"End of CheckPreClusterTwoCathodes=");
477 for ( Int_t i = 0; i < nPix; ++i )
482 pixelI->
Size(0),pixelI->
Size(1),0.0);
484 for ( Int_t j = i+1; j < nPix; ++j )
489 pixelJ->
Size(0),pixelJ->
Size(1),0.0);
494 AliInfo(Form(
"The following 2 pixels (%d and %d) overlap !",i,j));
517 AliWarning(
"Got no pad at all ?!");
536 Double_t width[2] = {dim.X(), dim.Y()}, xy0[2] = { 0.0, 0.0 };
539 for ( Int_t i = 0; i < mult; ++i) {
541 for (Int_t j = 0; j < 2; ++j) {
543 xy0[j] = pad->
Coord(j);
547 if (found[0] && found[1])
break;
550 Double_t min[2], max[2];
551 Int_t cath0 = 0, cath1 = 1;
555 Double_t leftDownX, leftDownY;
557 Double_t rightUpX, rightUpY;
563 if (cath1 != cath0) {
566 min[0] = TMath::Max (min[0], leftDownX);
567 min[1] = TMath::Max (min[1], leftDownY);
568 max[0] = TMath::Min (max[0], rightUpX);
569 max[1] = TMath::Min (max[1], rightUpY);
575 for (Int_t i = 0; i < 2; ++i) {
576 Double_t dist = (min[i] - xy0[i]) / width[i] / 2;
577 if (TMath::Abs(dist) < 1.e-6) dist = -1.e-6;
578 min[i] = xy0[i] + (TMath::Nint(dist-TMath::Sign(1.e-6,dist))
579 + TMath::Sign(0.5,dist)) * width[i] * 2;
580 nbins[i] = TMath::Nint ((max[i] - min[i]) / width[i] / 2);
581 if (nbins[i] == 0) ++nbins[i];
582 max[i] = min[i] + nbins[i] * width[i] * 2;
587 TH2D *hist1 =
new TH2D (
"Grid",
"", nbins[0], min[0], max[0], nbins[1], min[1], max[1]);
588 TH2D *hist2 =
new TH2D (
"Entries",
"", nbins[0], min[0], max[0], nbins[1], min[1], max[1]);
589 TAxis *xaxis = hist1->GetXaxis();
590 TAxis *yaxis = hist1->GetYaxis();
593 for ( Int_t i = 0; i < mult; ++i) {
595 Int_t ix0 = xaxis->FindBin(pad->
X());
596 Int_t iy0 = yaxis->FindBin(pad->
Y());
601 for (Int_t i = 1; i <= nbins[0]; ++i) {
602 Double_t x = xaxis->GetBinCenter(i);
603 for (Int_t j = 1; j <= nbins[1]; ++j) {
604 if (hist2->GetBinContent(hist2->GetBin(i,j)) < 0.01525)
continue;
605 if (cath0 != cath1) {
607 Double_t cont = hist2->GetBinContent(hist2->GetBin(i,j));
608 if (cont < 999.)
continue;
609 if (cont-Int_t(cont/1000.)*1000. < 0.07625)
continue;
613 Double_t y = yaxis->GetBinCenter(j);
614 Double_t charge = hist1->GetBinContent(hist1->GetBin(i,j));
636 TH2D *hist1, TH2D *hist2)
640 TAxis *axis = idir == 0 ? hist1->GetXaxis() : hist1->GetYaxis();
641 Int_t nbins = axis->GetNbins(), cath = pad->
Cathode();
642 Double_t bin = axis->GetBinWidth(1), amask = TMath::Power(1000.,cath*1.);
646 for (Int_t i = 0; i < nbinPad; ++i) {
647 Int_t ixy = idir == 0 ? ix0 + i : iy0 + i;
648 if (ixy > nbins)
break;
649 Double_t lowEdge = axis->GetBinLowEdge(ixy);
651 if (idir == 0)
PadOverHist(1, ixy, iy0, pad, hist1, hist2);
654 Double_t cont = pad->
Charge();
655 if (hist2->GetBinContent(hist2->GetBin(ix0, ixy)) > 0.01525)
656 cont = TMath::Min (hist1->GetBinContent(hist1->GetBin(ix0, ixy)), cont)
657 + TMath::Min (TMath::Max(hist1->GetBinContent(hist1->GetBin(ix0, ixy)),cont)*0.1, 1.525);
658 hist1->SetBinContent(hist1->GetBin(ix0, ixy), cont);
659 hist2->SetBinContent(hist2->GetBin(ix0, ixy), hist2->GetBinContent(hist2->GetBin(ix0, ixy))+amask);
663 for (Int_t i = -1; i > -nbinPad; --i) {
664 Int_t ixy = idir == 0 ? ix0 + i : iy0 + i;
666 Double_t upEdge = axis->GetBinUpEdge(ixy);
667 if (upEdge - fgkDistancePrecision < pad->Coord(idir) - pad->
Size(idir))
break;
668 if (idir == 0)
PadOverHist(1, ixy, iy0, pad, hist1, hist2);
671 Double_t cont = pad->
Charge();
672 if (hist2->GetBinContent(hist2->GetBin(ix0, ixy)) > 0.01525)
673 cont = TMath::Min (hist1->GetBinContent(hist1->GetBin(ix0, ixy)), cont)
674 + TMath::Min (TMath::Max(hist1->GetBinContent(hist1->GetBin(ix0, ixy)),cont)*0.1,1.525);
675 hist1->SetBinContent(hist1->GetBin(ix0, ixy), cont);
676 hist2->SetBinContent( hist2->GetBin(ix0, ixy), hist2->GetBinContent(hist2->GetBin(ix0, ixy))+amask);
686 AliDebug(1,Form(
"nPix=%d",pixArray->GetLast()+1));
695 Double_t xylim[4] = {999, 999, 999, 999};
697 Int_t nPix = pixArray->GetEntriesFast();
699 if ( nPix <= 0 )
return 0;
702 for (Int_t ipix = 0; ipix < nPix; ++ipix) {
703 pixPtr = (
AliMUONPad*) pixArray->UncheckedAt(ipix);
704 for (Int_t i = 0; i < 4; ++i)
705 xylim[i] = TMath::Min (xylim[i], (i%2 ? -1 : 1)*pixPtr->
Coord(i/2));
707 for (Int_t i = 0; i < 4; ++i) xylim[i] -= pixPtr->
Size(i/2);
709 Int_t nx = TMath::Nint ((-xylim[1]-xylim[0])/pixPtr->
Size(0)/2);
710 Int_t ny = TMath::Nint ((-xylim[3]-xylim[2])/pixPtr->
Size(1)/2);
711 if (pixArray ==
fPixArray)
fHistAnode =
new TH2D(
"anode",
"anode",nx,xylim[0],-xylim[1],ny,xylim[2],-xylim[3]);
712 else fHistAnode =
new TH2D(
"anode1",
"anode1",nx,xylim[0],-xylim[1],ny,xylim[2],-xylim[3]);
713 for (Int_t ipix = 0; ipix < nPix; ++ipix) {
714 pixPtr = (
AliMUONPad*) pixArray->UncheckedAt(ipix);
719 Int_t nMax = 0, indx, nxy = ny * nx;
720 Int_t *isLocalMax =
new Int_t[nxy];
721 for (Int_t i = 0; i < nxy; ++i) isLocalMax[i] = 0;
723 for (Int_t i = 1; i <= ny; ++i) {
725 for (Int_t j = 1; j <= nx; ++j) {
728 if (isLocalMax[indx+j-1] != 0)
continue;
733 for (Int_t i = 1; i <= ny; ++i) {
735 for (Int_t j = 1; j <= nx; ++j) {
736 if (isLocalMax[indx+j-1] > 0) {
737 localMax[nMax] = indx + j - 1;
739 if (nMax > 99)
break;
743 AliError(
" Too many local maxima !!!");
747 if (
fDebug) cout <<
" Local max: " << nMax << endl;
748 delete [] isLocalMax;
757 Int_t nx = hist->GetNbinsX();
758 Int_t ny = hist->GetNbinsY();
759 Int_t cont = TMath::Nint (hist->GetBinContent(hist->GetBin(j,i)));
760 Int_t cont1 = 0, indx = (i-1)*nx+j-1, indx1 = 0, indx2 = 0;
762 Int_t ie = i + 2, je = j + 2;
763 for (Int_t i1 = i-1; i1 < ie; ++i1) {
764 if (i1 < 1 || i1 > ny)
continue;
765 indx1 = (i1 - 1) * nx;
766 for (Int_t j1 = j-1; j1 < je; ++j1) {
767 if (j1 < 1 || j1 > nx)
continue;
768 if (i == i1 && j == j1)
continue;
769 indx2 = indx1 + j1 - 1;
770 cont1 = TMath::Nint (hist->GetBinContent(hist->GetBin(j1,i1)));
771 if (cont < cont1) { isLocalMax[indx] = -1;
return; }
772 else if (cont > cont1) isLocalMax[indx2] = -1;
774 isLocalMax[indx] = 1;
775 if (isLocalMax[indx2] == 0) {
777 if (isLocalMax[indx2] < 0) { isLocalMax[indx] = -1;
return; }
778 else isLocalMax[indx2] = -1;
783 isLocalMax[indx] = 1;
788 const Int_t *localMax, Int_t iMax)
804 Int_t ic = localMax[iMax] / nx + 1;
805 Int_t jc = localMax[iMax] % nx + 1;
813 Int_t nonb[2] = {1, 0};
822 Double_t wx =
fHistAnode->GetXaxis()->GetBinWidth(1)/2;
823 Double_t wy =
fHistAnode->GetYaxis()->GetBinWidth(1)/2;
824 Double_t yc =
fHistAnode->GetYaxis()->GetBinCenter(ic);
825 Double_t xc =
fHistAnode->GetXaxis()->GetBinCenter(jc);
833 Double_t qMax[2] = {0};
834 AliMUONPad *matrix[2][3] = {{0x0,0x0,0x0},{0x0,0x0,0x0}};
835 for (Int_t j = 0; j < npad; ++j)
840 if (
fDebug) { cout << j <<
" "; pad->
Print(
"full"); }
843 matrix[pad->
Cathode()][1] = pad;
844 if (nSides == 1) matrix[!pad->
Cathode()][1] = pad;
851 for (Int_t j = 0; j < npad; ++j)
855 if (pad == matrix[cath][1])
continue;
856 Int_t nLoops = 3 - nSides;
858 for (Int_t k = 0; k < nLoops; ++k) {
860 if (k) cath1 = !cath;
863 Double_t dist = pad->
Coord(nonb[cath1]) - matrix[cath][1]->
Coord(nonb[cath1]);
864 Double_t dir = TMath::Sign (1., dist);
865 dist = TMath::Abs(dist) - pad->
Size(nonb[cath1]) - matrix[cath][1]->
Size(nonb[cath1]);
869 dist = pad->
Coord(!nonb[cath1]) - matrix[cath1][1]->
Coord(!nonb[cath1]);
870 if (TMath::Abs(dist) >
872 Int_t idir = TMath::Nint (dir);
873 if (matrix[cath1][1+idir] == 0x0) matrix[cath1][1+idir] = pad;
874 else if (pad->
Charge() > matrix[cath1][1+idir]->
Charge()) matrix[cath1][1+idir] = pad;
881 Double_t coord[2] = {0.}, qAver = 0.;
882 for (Int_t i = 0; i < 2; ++i) {
884 Double_t coordQ = 0.;
885 Int_t cath = matrix[i][1]->
Cathode();
886 if (i && nSides == 1) cath = !cath;
887 for (Int_t j = 0; j < 3; ++j) {
888 if (matrix[i][j] == 0x0)
continue;
889 Double_t dq = matrix[i][j]->
Charge();
891 coordQ += dq * matrix[i][j]->
Coord(nonb[cath]);
894 coord[cath] = coordQ / q;
895 qAver = TMath::Max (qAver, q);
899 if ( qAver >= 2.135 )
906 cluster1->
SetPosition(TVector2(coord[1],coord[0]),TVector2(0.,0.));
908 cluster1->
SetPosition(TVector2(coord[0],coord[1]),TVector2(0.,0.));
915 AliDebug(2,Form(
"Adding RawCluster detElemId %4d mult %2d charge %5d (xl,yl)=(%9.6g,%9.6g)",
929 if (
this == &rhs)
return *
this;
931 AliFatal(
"Not implemented.");
938 Int_t &nInX, Int_t &nInY)
const
947 if ( nInX < 0 ) statusToTest =
fgkZero;
949 Bool_t mustMatch(kTRUE);
951 Long_t cn = cluster.
NofPads(statusToTest,mustMatch);
981 if ( swhat.Contains(
"precluster") )
static Bool_t AreOverlapping(const AliMUONPad &d1, const AliMUONPad &d2, const TVector2 &precision, AliMpArea &overlapArea)
printf("Chi2/npoints = %f\n", TMath::Sqrt(chi2/npoints))
void FindCluster(AliMUONCluster &cluster, const Int_t *localMax, Int_t iMax)
virtual Bool_t Prepare(Int_t detElemId, TObjArray *pads[2], const AliMpArea &area, const AliMpVSegmentation *seg[2])
Bool_t IsReal() const
Return info whether this is a real pad or a virtual one.
Interface of a cluster finder.
AliMUONCluster * CheckPreclusterTwoCathodes(AliMUONCluster *cluster)
static const Int_t fgkUseForFit
should be used for fit
Bool_t IsSaturated() const
Return info whether this pad is saturated or not.
static const Double_t fgkDistancePrecision
used to check overlaps and so on
const AliMpVSegmentation * fkSegmentation[2]
! new segmentation
Bool_t fPlot
! whether we should plot thing (for debug only, quite slow!)
A group of adjacent pads.
void RemovePixel(Int_t i)
void BuildPixArrayOneCathode(AliMUONCluster &cluster)
Int_t fDebug
! debug level
Int_t fEventNumber
! current event being processed
TObjArray fClusterList
! clusters corresponding to the current pre-cluster
virtual void Print(Option_t *opt="") const
void BuildPixArray(AliMUONCluster &cluster)
build array of pixels
AliMUONClusterFinderPeakCOG & operator=(const AliMUONClusterFinderPeakCOG &rhs)
Not implemented.
A rectangle area positioned in plane..
TH2D * fHistAnode
! histo for peak search
Double_t DY() const
Return half dimensions in y (cm)
Int_t Multiplicity() const
virtual Bool_t Prepare(Int_t detElemId, TObjArray *pads[2], const AliMpArea &area)
virtual Bool_t NeedSegmentation() const
Int_t FindLocalMaxima(TObjArray *pixArray, Int_t *localMax, Double_t *maxVal)
void SetPosition(const TVector2 &pos, const TVector2 &errorOnPos)
Set (x,y) of that cluster and errors.
virtual Bool_t UsePad(const AliMUONPad &pad)
Double_t Y() const
Return position in y (cm)
Int_t fClusterNumber
! current cluster number
Int_t Iy() const
Return y-index.
void Release()
Detach this pad from a cluster.
AliMUONPad * Pixel(Int_t i) const
static const Int_t fgkZero
pad "basic" state
void LeftDownCorner(Double_t &x, Double_t &y) const
Double_t X() const
Return position in x (cm)
Int_t fNAddVirtualPads
! number of clusters for which we added virtual pads
virtual AliMUONCluster * NextCluster()
Int_t Cathode() const
Return cathode number.
void PadOverHist(Int_t idir, Int_t ix0, Int_t iy0, AliMUONPad *pad, TH2D *h1, TH2D *h2)
Bool_t IsUsed() const
Return true if is used.
void SetCharge(Float_t chargeCath0, Float_t chargeCath1)
Set cathode (re)computed charges.
Double_t Size(Int_t ixy) const
void plot(const std::vector< TH1 * > &v, Double_t min, Double_t max, Double_t factor)
void RemovePad(AliMUONPad *pad)
Int_t fDetElemId
! current DE being processed
TVector2 Position() const
Return (x,y) of that cluster.
void FlagLocalMax(TH2D *hist, Int_t i, Int_t j, Int_t *isLocalMax)
void SetChi2(Float_t chi2)
Set chi2 of the RawCharge fit.
Bool_t IsValid() const
Return validity.
TVector2 Position() const
Return positions in x and y (cm)
AliMUONVClusterFinder * fPreClusterFinder
! the pre-clustering worker
virtual AliMpPad PadByPosition(Double_t x, Double_t y, Bool_t warning=true) const =0
Find pad by position.
void RightUpCorner(Double_t &x, Double_t &y) const
virtual AliMUONCluster * NextCluster()=0
Long_t NofPads(Int_t cathode, Int_t statusMask, Bool_t matchMask) const
Compute number of pads in X and Y direction for a given cathode.
Bool_t WorkOnPreCluster()
The abstract base class for the segmentation.
Int_t Ix() const
Return x-index.
AliMpArea Area() const
Area that contains all the pads (whatever the cathode)
Int_t PairFirst(MpPair_t pair)
Decode the first integer from encoded pair.
void Print(Option_t *opt="") const
Double_t Charge() const
Return pad charge.
Double_t Coord(Int_t ixy) const
Class which encapsuate all information about a pad.
Bool_t IsSaturated(Int_t cathode) const
Whether we have at least one saturated pad in a given cathode.
Int_t DetElemId() const
Return detection element id.
Float_t ChargeAsymmetry() const
Return the cathode's charges asymmetry.
AliMUONCluster * CheckPrecluster(const AliMUONCluster &cluster)
Check precluster to simplify it (if possible), and return the simplified cluster. ...
static const TVector2 fgkDecreaseSize
idem
Int_t PairSecond(MpPair_t pair)
Decode the second integer from encoded pair.
AliMUONCluster * fPreCluster
! current pre-cluster
virtual void Print(Option_t *opt="") const
void PadsInXandY(AliMUONCluster &cluster, Int_t &nInX, Int_t &nInY) const
TVector2 MinPadDimensions(Int_t cathode, Int_t statusMask, Bool_t matchMask) const
Return the smallest pad dimensions for a given cathode.
Int_t Status() const
Return status word.
Bool_t Overlap(const AliMUONPad &pad, const AliMUONPad &pixel)
Checks whether a pad and a pixel have an overlapping area.
Int_t MaxRawChargeCathode() const
Return the max raw charge on the chathod.
AliMUONPad * Pad(Int_t index) const
virtual ~AliMUONClusterFinderPeakCOG()
Int_t fNClusters
! total number of clusters
TObjArray * fPixArray
! collection of pixels
Cluster finder in MUON arm of ALICE.
Combination of digit and mppad informations.
Double_t DX() const
Return half dimensions in x (cm)