1 /***************************************************************************
2 * Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
4 * Author: The ALICE Off-line Project. *
5 * Contributors are mentioned in the code where appropriate. *
7 * Permission to use, copy, modify and distribute this software and its *
8 * documentation strictly for non-commercial purposes is hereby granted *
9 * without fee, provided that the above copyright notice appears in all *
10 * copies and that both the copyright notice and this permission notice *
11 * appear in the supporting documentation. The authors make no claims *
12 * about the suitability of this software for any purpose. It is *
13 * provided "as is" without express or implied warranty. *
14 **************************************************************************/
18 //-----------------------------------------------------//
20 // Source File : PMDClusteringV1.cxx, Version 00 //
22 // Date : September 26 2002 //
24 // clustering code for alice pmd //
26 //-----------------------------------------------------//
28 /* --------------------------------------------------------------------
29 Code developed by S. C. Phatak, Institute of Physics,
30 Bhubaneswar 751 005 ( phatak@iopb.res.in ) Given the energy deposited
31 ( or ADC value ) in each cell of supermodule ( pmd or cpv ), the code
32 builds up superclusters and breaks them into clusters. The input is
33 in array edepcell[kNMX] and cluster information is in a
34 TObjarray. Integer clno gives total number of clusters in the
37 fClusters is the only global ( public ) variables.
38 Others are local ( private ) to the code.
39 At the moment, the data is read for whole detector ( all supermodules
40 and pmd as well as cpv. This will have to be modify later )
41 LAST UPDATE : October 23, 2002
42 -----------------------------------------------------------------------*/
44 #include <Riostream.h>
47 #include <TObjArray.h>
51 #include "AliPMDcludata.h"
52 #include "AliPMDcluster.h"
53 #include "AliPMDisocell.h"
54 #include "AliPMDClustering.h"
55 #include "AliPMDClusteringV1.h"
59 ClassImp(AliPMDClusteringV1)
61 const Double_t AliPMDClusteringV1::fgkSqroot3by2=0.8660254; // sqrt(3.)/2.
63 AliPMDClusteringV1::AliPMDClusteringV1():
64 fPMDclucont(new TObjArray()),
67 for(Int_t i = 0; i < kNDIMX; i++)
69 for(Int_t j = 0; j < kNDIMY; j++)
71 fCoord[0][i][j] = i+j/2.;
72 fCoord[1][i][j] = fgkSqroot3by2*j;
76 // ------------------------------------------------------------------------ //
77 AliPMDClusteringV1::AliPMDClusteringV1(const AliPMDClusteringV1& pmdclv1):
78 AliPMDClustering(pmdclv1),
83 AliError("Copy constructor not allowed ");
86 // ------------------------------------------------------------------------ //
87 AliPMDClusteringV1 &AliPMDClusteringV1::operator=(const AliPMDClusteringV1& /*pmdclv1*/)
90 AliError("Assignment operator not allowed ");
93 // ------------------------------------------------------------------------ //
94 AliPMDClusteringV1::~AliPMDClusteringV1()
98 // ------------------------------------------------------------------------ //
99 void AliPMDClusteringV1::DoClust(Int_t idet, Int_t ismn,
100 Int_t celltrack[48][96],
101 Int_t cellpid[48][96],
102 Double_t celladc[48][96],
103 TObjArray *pmdisocell, TObjArray *pmdcont)
105 // main function to call other necessary functions to do clustering
108 AliPMDcluster *pmdcl = 0;
110 const float ktwobysqrt3 = 1.1547; // 2./sqrt(3.)
111 const Int_t kNmaxCell = 19; // # of cells surrounding a cluster center
113 Int_t i, j, nmx1, incr, id, jd;
114 Int_t celldataX[kNmaxCell], celldataY[kNmaxCell];
115 Int_t celldataTr[kNmaxCell], celldataPid[kNmaxCell];
116 Float_t celldataAdc[kNmaxCell];
118 Double_t cutoff, ave;
119 Double_t edepcell[kNMX];
122 Double_t *cellenergy = new Double_t [11424];
125 // call the isolated cell search method
127 FindIsoCell(idet, ismn, celladc, pmdisocell);
129 // ndimXr and ndimYr are different because of different module size
139 else if (ismn >= 12 && ismn <= 23)
145 for (i =0; i < 11424; i++)
151 for (i = 0; i < kNDIMX; i++)
153 for (j = 0; j < kNDIMY; j++)
160 for (id = 0; id < ndimXr; id++)
162 for (jd = 0; jd < ndimYr; jd++)
165 i = id+(ndimYr/2-1)-(jd/2);
167 Int_t ij = i + j*kNDIMX;
171 cellenergy[ij] = celladc[jd][id];
173 else if (ismn >= 12 && ismn <= 23)
175 cellenergy[ij] = celladc[id][jd];
180 for (i = 0; i < kNMX; i++)
182 edepcell[i] = cellenergy[i];
185 delete [] cellenergy;
188 TMath::Sort((Int_t)kNMX,edepcell,iord1);// order the data
189 cutoff = fCutoff; // cutoff to discard cells
192 for(i = 0;i < kNMX; i++)
198 if(edepcell[i] > cutoff )
204 AliDebug(1,Form("Number of cells having energy >= %f are %d",cutoff,nmx1));
206 if (nmx1 == 0) nmx1 = 1;
208 AliDebug(1,Form("Number of cells in a SuperM = %d and Average = %f",
211 incr = CrClust(ave, cutoff, nmx1,iord1, edepcell );
212 RefClust(incr,edepcell);
213 Int_t nentries1 = fPMDclucont->GetEntries();
214 AliDebug(1,Form("Detector Plane = %d Serial Module No = %d Number of clusters = %d",idet, ismn, nentries1));
215 AliDebug(1,Form("Total number of clusters/module = %d",nentries1));
217 for (Int_t ient1 = 0; ient1 < nentries1; ient1++)
219 AliPMDcludata *pmdcludata =
220 (AliPMDcludata*)fPMDclucont->UncheckedAt(ient1);
221 Float_t cluXC = pmdcludata->GetClusX();
222 Float_t cluYC = pmdcludata->GetClusY();
223 Float_t cluADC = pmdcludata->GetClusADC();
224 Float_t cluCELLS = pmdcludata->GetClusCells();
225 Float_t cluSIGX = pmdcludata->GetClusSigmaX();
226 Float_t cluSIGY = pmdcludata->GetClusSigmaY();
228 Float_t cluY0 = ktwobysqrt3*cluYC;
229 Float_t cluX0 = cluXC - cluY0/2.;
232 // Cluster X centroid is back transformed
237 clusdata[0] = cluX0 - (24-1) + cluY0/2.;
239 else if ( ismn >= 12 && ismn <= 23)
241 clusdata[0] = cluX0 - (48-1) + cluY0/2.;
245 clusdata[2] = cluADC;
246 clusdata[3] = cluCELLS;
247 clusdata[4] = cluSIGX;
248 clusdata[5] = cluSIGY;
251 // Cells associated with a cluster
254 for (Int_t ihit = 0; ihit < kNmaxCell; ihit++)
256 Int_t cellrow = pmdcludata->GetCellXY(ihit)/10000;
257 Int_t cellcol = pmdcludata->GetCellXY(ihit)%10000;
261 celldataX[ihit] = cellrow - (24-1) + int(cellcol/2.);
263 else if (ismn >= 12 && ismn <= 23)
265 celldataX[ihit] = cellrow - (48-1) + int(cellcol/2.);
268 celldataY[ihit] = cellcol;
270 Int_t irow = celldataX[ihit];
271 Int_t icol = celldataY[ihit];
275 if ((irow >= 0 && irow < 96) && (icol >= 0 && icol < 48))
277 celldataTr[ihit] = celltrack[icol][irow];
278 celldataPid[ihit] = cellpid[icol][irow];
279 celldataAdc[ihit] = (Float_t) celladc[icol][irow];
283 celldataTr[ihit] = -1;
284 celldataPid[ihit] = -1;
285 celldataAdc[ihit] = -1;
288 else if (ismn >= 12 && ismn < 24)
290 if ((irow >= 0 && irow < 48) && (icol >= 0 && icol < 96))
292 celldataTr[ihit] = celltrack[irow][icol];
293 celldataPid[ihit] = cellpid[irow][icol];
294 celldataAdc[ihit] = (Float_t) celladc[irow][icol];
299 celldataTr[ihit] = -1;
300 celldataPid[ihit] = -1;
301 celldataAdc[ihit] = -1;
307 pmdcl = new AliPMDcluster(idet, ismn, clusdata, celldataX, celldataY,
308 celldataTr, celldataPid, celldataAdc);
312 fPMDclucont->Delete();
314 // ------------------------------------------------------------------------ //
315 Int_t AliPMDClusteringV1::CrClust(Double_t ave, Double_t cutoff, Int_t nmx1,
316 Int_t iord1[], Double_t edepcell[])
318 // Does crude clustering
319 // Finds out only the big patch by just searching the
322 const Int_t kndim = 4609;
323 Int_t i,j,k,id1,id2,icl, numcell, clust[2][kndim];
324 Int_t jd1,jd2, icell, cellcount;
325 static Int_t neibx[6]={1,0,-1,-1,0,1}, neiby[6]={0,1,1,0,-1,-1};
327 AliDebug(1,Form("kNMX = %d nmx1 = %d kNDIMX = %d kNDIMY = %d ave = %f cutoff = %f",kNMX,nmx1,kNDIMX,kNDIMY,ave,cutoff));
329 for (j = 0; j < kNDIMX; j++)
331 for(k = 0; k < kNDIMY; k++)
333 fInfocl[0][j][k] = 0;
334 fInfocl[1][j][k] = 0;
337 for(i=0; i < kNMX; i++)
345 if(edepcell[j] <= cutoff)
347 fInfocl[0][id1][id2] = -1;
351 // ---------------------------------------------------------------
352 // crude clustering begins. Start with cell having largest adc
353 // count and loop over the cells in descending order of adc count
354 // ---------------------------------------------------------------
359 for(icell = 0; icell <= nmx1; icell++)
365 if(fInfocl[0][id1][id2] == 0 )
370 fInfocl[0][id1][id2] = 1;
371 fInfocl[1][id1][id2] = icl;
372 fInfcl[0][cellcount] = icl;
373 fInfcl[1][cellcount] = id1;
374 fInfcl[2][cellcount] = id2;
376 clust[0][numcell] = id1;
377 clust[1][numcell] = id2;
379 for(i = 1; i < kndim; i++)
383 // ---------------------------------------------------------------
384 // check for adc count in neib. cells. If ne 0 put it in this clust
385 // ---------------------------------------------------------------
386 for(i = 0; i < 6; i++)
388 jd1 = id1 + neibx[i];
389 jd2 = id2 + neiby[i];
390 if( (jd1 >= 0 && jd1 < kNDIMX) && (jd2 >= 0 && jd2 < kNDIMY) &&
391 fInfocl[0][jd1][jd2] == 0)
394 fInfocl[0][jd1][jd2] = 2;
395 fInfocl[1][jd1][jd2] = icl;
396 clust[0][numcell] = jd1;
397 clust[1][numcell] = jd2;
399 fInfcl[0][cellcount] = icl;
400 fInfcl[1][cellcount] = jd1;
401 fInfcl[2][cellcount] = jd2;
404 // ---------------------------------------------------------------
405 // check adc count for neighbour's neighbours recursively and
406 // if nonzero, add these to the cluster.
407 // ---------------------------------------------------------------
408 for(i = 1; i < kndim;i++)
414 for(j = 0; j < 6 ; j++)
416 jd1 = id1 + neibx[j];
417 jd2 = id2 + neiby[j];
418 if( (jd1 >= 0 && jd1 < kNDIMX) &&
419 (jd2 >= 0 && jd2 < kNDIMY) &&
420 fInfocl[0][jd1][jd2] == 0 )
422 fInfocl[0][jd1][jd2] = 2;
423 fInfocl[1][jd1][jd2] = icl;
425 clust[0][numcell] = jd1;
426 clust[1][numcell] = jd2;
428 fInfcl[0][cellcount] = icl;
429 fInfcl[1][cellcount] = jd1;
430 fInfcl[2][cellcount] = jd2;
439 // ------------------------------------------------------------------------ //
440 void AliPMDClusteringV1::RefClust(Int_t incr, Double_t edepcell[])
442 // Does the refining of clusters
443 // Takes the big patch and does gaussian fitting and
444 // finds out the more refined clusters
447 AliPMDcludata *pmdcludata = 0;
449 const Int_t kNmaxCell = 19; // # of cells surrounding a cluster center
451 Int_t ndim = incr + 1;
456 Int_t i, j, k, i1, i2, id, icl, itest,ihld, ig, nsupcl,clno, t1, t2;
458 Double_t x1, y1, z1, x2, y2, z2, rr;
460 ncl = new Int_t [ndim];
461 clxy = new Int_t [kNmaxCell];
464 for(i = 0; i<ndim; i++)
467 if (i < 6) clusdata[i] = 0.;
468 if (i < kNmaxCell) clxy[i] = 0;
471 // clno counts the final clusters
472 // nsupcl = # of superclusters; ncl[i]= # of cells in supercluster i
473 // x, y and z store (x,y) coordinates of and energy deposited in a cell
474 // xc, yc store (x,y) coordinates of the cluster center
475 // zc stores the energy deposited in a cluster
476 // rc is cluster radius
481 for(i = 0; i <= incr; i++)
483 if(fInfcl[0][i] != nsupcl)
489 AliWarning("RefClust: Too many superclusters!");
496 AliDebug(1,Form("Number of cells = %d Number of Superclusters = %d",
501 for(i = 0; i <= nsupcl; i++)
509 AliWarning("RefClust: Too many clusters! more than 4608");
516 i12 = i1 + i2*kNDIMX;
518 clusdata[0] = fCoord[0][i1][i2];
519 clusdata[1] = fCoord[1][i1][i2];
520 clusdata[2] = edepcell[i12];
525 clxy[0] = i1*10000 + i2;
527 for(Int_t icltr = 1; icltr < kNmaxCell; icltr++)
532 pmdcludata = new AliPMDcludata(clusdata,clxy);
533 fPMDclucont->Add(pmdcludata);
541 AliWarning("RefClust: Too many clusters! more than 4608");
547 i12 = i1 + i2*kNDIMX;
549 x1 = fCoord[0][i1][i2];
550 y1 = fCoord[1][i1][i2];
553 clxy[0] = i1*10000 + i2;
559 i22 = i1 + i2*kNDIMX;
560 x2 = fCoord[0][i1][i2];
561 y2 = fCoord[1][i1][i2];
564 clxy[1] = i1*10000 + i2;
567 for(Int_t icltr = 2; icltr < kNmaxCell; icltr++)
572 clusdata[0] = (x1*z1+x2*z2)/(z1+z2);
573 clusdata[1] = (y1*z1+y2*z2)/(z1+z2);
578 pmdcludata = new AliPMDcludata(clusdata,clxy);
579 fPMDclucont->Add(pmdcludata);
584 Int_t *iord, *tc, *t;
585 Double_t *x, *y, *z, *xc, *yc, *zc;
587 iord = new Int_t [ncl[i]+1];
588 tc = new Int_t [ncl[i]+1];
589 t = new Int_t [ncl[i]+1];
591 x = new Double_t [ncl[i]+1];
592 y = new Double_t [ncl[i]+1];
593 z = new Double_t [ncl[i]+1];
594 xc = new Double_t [ncl[i]+1];
595 yc = new Double_t [ncl[i]+1];
596 zc = new Double_t [ncl[i]+1];
598 for( k = 0; k < ncl[i]+1; k++)
611 // super-cluster of more than two cells - broken up into smaller
612 // clusters gaussian centers computed. (peaks separated by > 1 cell)
613 // Begin from cell having largest energy deposited This is first
617 i12 = i1 + i2*kNDIMX;
619 x[0] = fCoord[0][i1][i2];
620 y[0] = fCoord[1][i1][i2];
621 z[0] = edepcell[i12];
622 t[0] = i1*10000 + i2;
626 for(j = 1; j <= ncl[i]; j++)
631 i12 = i1 + i2*kNDIMX;
634 x[j] = fCoord[0][i1][i2];
635 y[j] = fCoord[1][i1][i2];
636 z[j] = edepcell[i12];
637 t[j] = i1*10000 + i2;
641 // arranging cells within supercluster in decreasing order
643 for(j = 1;j <= ncl[i]; j++)
647 for(i1 = 0; i1 < j; i1++)
649 if(itest == 0 && z[iord[i1]] < z[ihld])
652 for(i2 = j-1; i2 >= i1; i2--)
654 iord[i2+1] = iord[i2];
660 /* MODIFICATION PART STARTS (Tapan July 2008)
661 iord[0] is the cell with highest ADC in the crude-cluster
662 ig is the number of local maxima in the crude-cluster
663 For the higest peak we make ig=0 which means first local maximum.
664 Next we go down in terms of the ADC sequence and find out if any
665 more of the cells form local maxima. The definition of local
666 maxima is that all its neighbours are of less ADC compared to it.
673 Int_t ivalid = 0, icount = 0;
675 for(j=1;j<=ncl[i];j++)
681 rr=Distance(x1,y1,xc[ig],yc[ig]);
683 // Check the cells which are outside the neighbours (rr>1.2)
688 for(Int_t j1=1;j1<j;j1++)
691 Float_t rr1=Distance(x1,y1,x[iord[j1]],y[iord[j1]]);
692 if(rr1>1.2) ivalid++;
694 if(ivalid == icount && z1>0.5*zc[ig])
707 // We use simple Gaussian weighting. (Tapan Jan 2005)
708 // compute the number of cells belonging to each cluster.
709 // cell can be shared between several clusters
710 // in the ratio of cluster energy deposition
712 // (1) number of cells belonging to a cluster (ig) and
713 // (2) total ADC of the cluster (ig)
714 // (3) x and y positions of the cluster
721 Double_t *totaladc, *totaladc2, *ncell,*weight;
722 Double_t *xclust, *yclust, *sigxclust, *sigyclust;
723 Double_t *ax, *ay, *ax2, *ay2;
726 status = new Int_t [ncl[i]+1];
727 cellXY = new Int_t *[ncl[i]+1];
729 cellCount = new Int_t [ig+1];
730 totaladc = new Double_t [ig+1];
731 totaladc2 = new Double_t [ig+1];
732 ncell = new Double_t [ig+1];
733 weight = new Double_t [ig+1];
734 xclust = new Double_t [ig+1];
735 yclust = new Double_t [ig+1];
736 sigxclust = new Double_t [ig+1];
737 sigyclust = new Double_t [ig+1];
738 ax = new Double_t [ig+1];
739 ay = new Double_t [ig+1];
740 ax2 = new Double_t [ig+1];
741 ay2 = new Double_t [ig+1];
743 for(j = 0; j < ncl[i]+1; j++)
746 cellXY[j] = new Int_t[ig+1];
749 for(Int_t kcl = 0; kcl < ig+1; kcl++)
764 for(j = 0; j < ncl[i]+1; j++)
769 Double_t sumweight, gweight;
771 for(j = 0;j <= ncl[i]; j++)
778 for(Int_t kcl=0; kcl<=ig; kcl++)
782 rr = Distance(x1,y1,x2,y2);
789 totaladc2[kcl] = pow(z1,2);
799 for(j = 0; j <= ncl[i]; j++)
812 for(Int_t kcl = 0; kcl <= ig; kcl++)
816 rr = Distance(x1,y1,x2,y2);
817 gweight = exp(-(rr*rr)/(2*(1.2*1.2)));
818 weight[kcl] = zc[kcl] * gweight;
819 sumweight = sumweight + weight[kcl];
821 if(weight[kcl] > max)
828 cellXY[cellCount[maxweight]][maxweight] = iord[j];
830 cellCount[maxweight]++;
834 totaladc[maxweight] += z1;
835 ax[maxweight] += x1 * z1;
836 ay[maxweight] += y1 * z1;
837 totaladc2[maxweight] += pow(z1,2);
838 ax2[maxweight] += z1 * pow((x1-x2),2);
839 ay2[maxweight] += z1 * pow((y1-y2),2);
845 for(Int_t kcl = 0; kcl <= ig; kcl++)
849 if(totaladc[kcl]>0.)xclust[kcl] = (ax[kcl])/ totaladc[kcl];
850 if(totaladc[kcl]>0.)yclust[kcl] = (ay[kcl])/ totaladc[kcl];
853 if(totaladc2[kcl] >= pow(totaladc[kcl],2))
855 sigxclust[kcl] = 0.25;
856 sigyclust[kcl] = 0.25;
860 sigxclust[kcl] = (totaladc[kcl]/(pow(totaladc[kcl],2)-totaladc2[kcl]))*ax2[kcl];
861 sigyclust[kcl] = (totaladc[kcl]/(pow(totaladc[kcl],2)-totaladc2[kcl]))*ay2[kcl];
865 for(j = 0; j < cellCount[kcl]; j++) clno++;
869 AliWarning("RefClust: Too many clusters! more than 4608");
872 clusdata[0] = xclust[kcl];
873 clusdata[1] = yclust[kcl];
874 clusdata[2] = totaladc[kcl];
875 clusdata[3] = ncell[kcl];
878 if(sigxclust[kcl] > sigyclust[kcl])
880 clusdata[4] = pow(sigxclust[kcl],0.5);
881 clusdata[5] = pow(sigyclust[kcl],0.5);
885 clusdata[4] = pow(sigyclust[kcl],0.5);
886 clusdata[5] = pow(sigxclust[kcl],0.5);
892 for (Int_t ii = 0; ii < cellCount[kcl]; ii++)
896 clxy[Ncell] = t[cellXY[ii][kcl]];
901 pmdcludata = new AliPMDcludata(clusdata,clxy);
902 fPMDclucont->Add(pmdcludata);
916 for(Int_t jj = 0; jj < ncl[i]+1; jj++) delete [] cellXY[jj];
936 // ------------------------------------------------------------------------ //
937 Double_t AliPMDClusteringV1::Distance(Double_t x1, Double_t y1,
938 Double_t x2, Double_t y2)
940 return TMath::Sqrt((x1-x2)*(x1-x2) + (y1-y2)*(y1-y2));
942 // ------------------------------------------------------------------------ //
943 void AliPMDClusteringV1::FindIsoCell(Int_t idet, Int_t ismn, Double_t celladc[][96], TObjArray *pmdisocell)
945 // Does isolated cell search for offline calibration
947 AliPMDisocell *isocell = 0;
949 const Int_t kMaxRow = 48;
950 const Int_t kMaxCol = 96;
951 const Int_t kCellNeighbour = 6;
955 Int_t neibx[6] = {1,0,-1,-1,0,1};
956 Int_t neiby[6] = {0,1,1,0,-1,-1};
959 for(Int_t irow = 0; irow < kMaxRow; irow++)
961 for(Int_t icol = 0; icol < kMaxCol; icol++)
963 if(celladc[irow][icol] > 0)
966 for(Int_t ii = 0; ii < kCellNeighbour; ii++)
968 id1 = irow + neibx[ii];
969 jd1 = icol + neiby[ii];
970 Float_t adc = (Float_t) celladc[id1][jd1];
974 if(isocount == kCellNeighbour)
976 Float_t cadc = (Float_t) celladc[irow][icol];
978 isocell = new AliPMDisocell(idet,ismn,irow,icol,cadc);
979 pmdisocell->Add(isocell);
983 } // neigh cell cond.
990 // ------------------------------------------------------------------------ //
991 void AliPMDClusteringV1::SetEdepCut(Float_t decut)
995 // ------------------------------------------------------------------------ //