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 "AliPMDClustering.h"
54 #include "AliPMDClusteringV1.h"
58 ClassImp(AliPMDClusteringV1)
60 const Double_t AliPMDClusteringV1::fgkSqroot3by2=0.8660254; // sqrt(3.)/2.
62 AliPMDClusteringV1::AliPMDClusteringV1():
63 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),
84 AliError("Copy constructor not allowed ");
87 // ------------------------------------------------------------------------ //
88 AliPMDClusteringV1 &AliPMDClusteringV1::operator=(const AliPMDClusteringV1& /*pmdclv1*/)
91 AliError("Assignment operator not allowed ");
94 // ------------------------------------------------------------------------ //
95 AliPMDClusteringV1::~AliPMDClusteringV1()
99 // ------------------------------------------------------------------------ //
100 void AliPMDClusteringV1::DoClust(Int_t idet, Int_t ismn,
101 Int_t celltrack[48][96],
102 Int_t cellpid[48][96],
103 Double_t celladc[48][96],
106 // main function to call other necessary functions to do clustering
109 AliPMDcluster *pmdcl = 0;
111 const float ktwobysqrt3 = 1.1547; // 2./sqrt(3.)
112 const Int_t kNmaxCell = 19; // # of cells surrounding a cluster center
114 Int_t i = 0, j = 0, nmx1 = 0;
115 Int_t incr = 0, id = 0, jd = 0;
116 Int_t celldataX[kNmaxCell], celldataY[kNmaxCell];
117 Int_t celldataTr[kNmaxCell], celldataPid[kNmaxCell];
118 Float_t celldataAdc[kNmaxCell];
119 Float_t clusdata[6] = {0.,0.,0.,0.,0.,0.};
120 Double_t cutoff, ave;
121 Double_t edepcell[kNMX];
122 Double_t cellenergy[kNMX];
124 // ndimXr and ndimYr are different because of different module size
134 else if (ismn >= 12 && ismn <= 23)
140 for (i = 0; i < kNMX; i++)
146 for (i = 0; i < kNDIMX; i++)
148 for (j = 0; j < kNDIMY; j++)
155 for (id = 0; id < ndimXr; id++)
157 for (jd = 0; jd < ndimYr; jd++)
160 i = id+(ndimYr/2-1)-(jd/2);
162 Int_t ij = i + j*kNDIMX;
166 cellenergy[ij] = celladc[jd][id];
168 else if (ismn >= 12 && ismn <= 23)
170 cellenergy[ij] = celladc[id][jd];
175 for (i = 0; i < kNMX; i++)
177 edepcell[i] = cellenergy[i];
182 TMath::Sort((Int_t)kNMX,edepcell,iord1,jsort);// order the data
183 cutoff = fCutoff; // cutoff to discard cells
186 for(i = 0;i < kNMX; i++)
192 if(edepcell[i] > cutoff )
198 AliDebug(1,Form("Number of cells having energy >= %f are %d",cutoff,nmx1));
200 if (nmx1 == 0) nmx1 = 1;
202 AliDebug(1,Form("Number of cells in a SuperM = %d and Average = %f",
205 incr = CrClust(ave, cutoff, nmx1,iord1, edepcell );
206 RefClust(incr,edepcell);
207 Int_t nentries1 = fPMDclucont->GetEntries();
208 AliDebug(1,Form("Detector Plane = %d Serial Module No = %d Number of clusters = %d",idet, ismn, nentries1));
209 AliDebug(1,Form("Total number of clusters/module = %d",nentries1));
211 for (Int_t ient1 = 0; ient1 < nentries1; ient1++)
213 AliPMDcludata *pmdcludata =
214 (AliPMDcludata*)fPMDclucont->UncheckedAt(ient1);
215 Float_t cluXC = pmdcludata->GetClusX();
216 Float_t cluYC = pmdcludata->GetClusY();
217 Float_t cluADC = pmdcludata->GetClusADC();
218 Float_t cluCELLS = pmdcludata->GetClusCells();
219 Float_t cluSIGX = pmdcludata->GetClusSigmaX();
220 Float_t cluSIGY = pmdcludata->GetClusSigmaY();
222 Float_t cluY0 = ktwobysqrt3*cluYC;
223 Float_t cluX0 = cluXC - cluY0/2.;
226 // Cluster X centroid is back transformed
231 clusdata[0] = cluX0 - (24-1) + cluY0/2.;
233 else if ( ismn >= 12 && ismn <= 23)
235 clusdata[0] = cluX0 - (48-1) + cluY0/2.;
239 clusdata[2] = cluADC;
240 clusdata[3] = cluCELLS;
241 clusdata[4] = cluSIGX;
242 clusdata[5] = cluSIGY;
245 // Cells associated with a cluster
248 for (Int_t ihit = 0; ihit < kNmaxCell; ihit++)
250 Int_t cellrow = pmdcludata->GetCellXY(ihit)/10000;
251 Int_t cellcol = pmdcludata->GetCellXY(ihit)%10000;
255 celldataX[ihit] = cellrow - (24-1) + int(cellcol/2.);
257 else if (ismn >= 12 && ismn <= 23)
259 celldataX[ihit] = cellrow - (48-1) + int(cellcol/2.);
262 celldataY[ihit] = cellcol;
264 Int_t irow = celldataX[ihit];
265 Int_t icol = celldataY[ihit];
269 if ((irow >= 0 && irow < 96) && (icol >= 0 && icol < 48))
271 celldataTr[ihit] = celltrack[icol][irow];
272 celldataPid[ihit] = cellpid[icol][irow];
273 celldataAdc[ihit] = (Float_t) celladc[icol][irow];
277 celldataTr[ihit] = -1;
278 celldataPid[ihit] = -1;
279 celldataAdc[ihit] = -1;
282 else if (ismn >= 12 && ismn < 24)
284 if ((irow >= 0 && irow < 48) && (icol >= 0 && icol < 96))
286 celldataTr[ihit] = celltrack[irow][icol];
287 celldataPid[ihit] = cellpid[irow][icol];
288 celldataAdc[ihit] = (Float_t) celladc[irow][icol];
293 celldataTr[ihit] = -1;
294 celldataPid[ihit] = -1;
295 celldataAdc[ihit] = -1;
301 pmdcl = new AliPMDcluster(idet, ismn, clusdata, celldataX, celldataY,
302 celldataTr, celldataPid, celldataAdc);
306 fPMDclucont->Delete();
308 // ------------------------------------------------------------------------ //
309 Int_t AliPMDClusteringV1::CrClust(Double_t ave, Double_t cutoff, Int_t nmx1,
310 Int_t iord1[], Double_t edepcell[])
312 // Does crude clustering
313 // Finds out only the big patch by just searching the
316 const Int_t kndim = 4609;
317 Int_t i=0,j=0,k=0,id1=0,id2=0,icl=0, numcell=0;
318 Int_t jd1=0,jd2=0, icell=0, cellcount=0;
319 Int_t clust[2][kndim];
320 static Int_t neibx[6]={1,0,-1,-1,0,1}, neiby[6]={0,1,1,0,-1,-1};
322 AliDebug(1,Form("kNMX = %d nmx1 = %d kNDIMX = %d kNDIMY = %d ave = %f cutoff = %f",kNMX,nmx1,kNDIMX,kNDIMY,ave,cutoff));
324 for (j = 0; j < kNDIMX; j++)
326 for(k = 0; k < kNDIMY; k++)
328 fInfocl[0][j][k] = 0;
329 fInfocl[1][j][k] = 0;
332 for(i=0; i < kNMX; i++)
340 if(edepcell[j] <= cutoff)
342 fInfocl[0][id1][id2] = -1;
346 // ---------------------------------------------------------------
347 // crude clustering begins. Start with cell having largest adc
348 // count and loop over the cells in descending order of adc count
349 // ---------------------------------------------------------------
354 for(icell = 0; icell <= nmx1; icell++)
360 if(fInfocl[0][id1][id2] == 0 )
365 fInfocl[0][id1][id2] = 1;
366 fInfocl[1][id1][id2] = icl;
367 fInfcl[0][cellcount] = icl;
368 fInfcl[1][cellcount] = id1;
369 fInfcl[2][cellcount] = id2;
371 clust[0][numcell] = id1;
372 clust[1][numcell] = id2;
374 for(i = 1; i < kndim; i++)
378 // ---------------------------------------------------------------
379 // check for adc count in neib. cells. If ne 0 put it in this clust
380 // ---------------------------------------------------------------
381 for(i = 0; i < 6; i++)
383 jd1 = id1 + neibx[i];
384 jd2 = id2 + neiby[i];
385 if( (jd1 >= 0 && jd1 < kNDIMX) && (jd2 >= 0 && jd2 < kNDIMY) &&
386 fInfocl[0][jd1][jd2] == 0)
389 fInfocl[0][jd1][jd2] = 2;
390 fInfocl[1][jd1][jd2] = icl;
391 clust[0][numcell] = jd1;
392 clust[1][numcell] = jd2;
394 fInfcl[0][cellcount] = icl;
395 fInfcl[1][cellcount] = jd1;
396 fInfcl[2][cellcount] = jd2;
399 // ---------------------------------------------------------------
400 // check adc count for neighbour's neighbours recursively and
401 // if nonzero, add these to the cluster.
402 // ---------------------------------------------------------------
403 for(i = 1; i < kndim;i++)
409 for(j = 0; j < 6 ; j++)
411 jd1 = id1 + neibx[j];
412 jd2 = id2 + neiby[j];
413 if( (jd1 >= 0 && jd1 < kNDIMX) &&
414 (jd2 >= 0 && jd2 < kNDIMY) &&
415 fInfocl[0][jd1][jd2] == 0 )
417 fInfocl[0][jd1][jd2] = 2;
418 fInfocl[1][jd1][jd2] = icl;
420 clust[0][numcell] = jd1;
421 clust[1][numcell] = jd2;
423 fInfcl[0][cellcount] = icl;
424 fInfcl[1][cellcount] = jd1;
425 fInfcl[2][cellcount] = jd2;
434 // ------------------------------------------------------------------------ //
435 void AliPMDClusteringV1::RefClust(Int_t incr, Double_t edepcell[])
437 // Does the refining of clusters
438 // Takes the big patch and does gaussian fitting and
439 // finds out the more refined clusters
442 AliPMDcludata *pmdcludata = 0;
444 const Int_t kNmaxCell = 19; // # of cells surrounding a cluster center
446 Int_t ndim = incr + 1;
450 Int_t i12 = 0, i22 = 0;
451 Int_t i = 0, j = 0, k = 0;
452 Int_t i1 = 0, i2 = 0, id = 0, icl = 0;
453 Int_t itest = 0, ihld = 0, ig = 0;
454 Int_t nsupcl = 0, clno = 0, t1 = 0, t2 = 0;
456 Double_t x1 = 0, y1 = 0, z1 = 0, x2 = 0, y2 = 0, z2 = 0, rr = 0;
458 ncl = new Int_t [ndim];
459 clxy = new Int_t [kNmaxCell];
462 for(i = 0; i<ndim; i++)
470 for(i = 0; i<19; i++)
475 // clno counts the final clusters
476 // nsupcl = # of superclusters; ncl[i]= # of cells in supercluster i
477 // x, y and z store (x,y) coordinates of and energy deposited in a cell
478 // xc, yc store (x,y) coordinates of the cluster center
479 // zc stores the energy deposited in a cluster
480 // rc is cluster radius
485 for(i = 0; i <= incr; i++)
487 if(fInfcl[0][i] != nsupcl)
493 AliWarning("RefClust: Too many superclusters!");
500 AliDebug(1,Form("Number of cells = %d Number of Superclusters = %d",
505 for(i = 0; i <= nsupcl; i++)
513 AliWarning("RefClust: Too many clusters! more than 4608");
520 i12 = i1 + i2*kNDIMX;
522 clusdata[0] = fCoord[0][i1][i2];
523 clusdata[1] = fCoord[1][i1][i2];
524 clusdata[2] = edepcell[i12];
529 clxy[0] = i1*10000 + i2;
531 for(Int_t icltr = 1; icltr < kNmaxCell; icltr++)
536 pmdcludata = new AliPMDcludata(clusdata,clxy);
537 fPMDclucont->Add(pmdcludata);
545 AliWarning("RefClust: Too many clusters! more than 4608");
551 i12 = i1 + i2*kNDIMX;
553 x1 = fCoord[0][i1][i2];
554 y1 = fCoord[1][i1][i2];
557 clxy[0] = i1*10000 + i2;
563 i22 = i1 + i2*kNDIMX;
564 x2 = fCoord[0][i1][i2];
565 y2 = fCoord[1][i1][i2];
568 clxy[1] = i1*10000 + i2;
571 for(Int_t icltr = 2; icltr < kNmaxCell; icltr++)
576 clusdata[0] = (x1*z1+x2*z2)/(z1+z2);
577 clusdata[1] = (y1*z1+y2*z2)/(z1+z2);
582 pmdcludata = new AliPMDcludata(clusdata,clxy);
583 fPMDclucont->Add(pmdcludata);
588 Int_t *iord, *tc, *t;
589 Double_t *x, *y, *z, *xc, *yc, *zc;
591 iord = new Int_t [ncl[i]+1];
592 tc = new Int_t [ncl[i]+1];
593 t = new Int_t [ncl[i]+1];
595 x = new Double_t [ncl[i]+1];
596 y = new Double_t [ncl[i]+1];
597 z = new Double_t [ncl[i]+1];
598 xc = new Double_t [ncl[i]+1];
599 yc = new Double_t [ncl[i]+1];
600 zc = new Double_t [ncl[i]+1];
602 for( k = 0; k < ncl[i]+1; k++)
615 // super-cluster of more than two cells - broken up into smaller
616 // clusters gaussian centers computed. (peaks separated by > 1 cell)
617 // Begin from cell having largest energy deposited This is first
621 i12 = i1 + i2*kNDIMX;
623 x[0] = fCoord[0][i1][i2];
624 y[0] = fCoord[1][i1][i2];
625 z[0] = edepcell[i12];
626 t[0] = i1*10000 + i2;
630 for(j = 1; j <= ncl[i]; j++)
635 i12 = i1 + i2*kNDIMX;
638 x[j] = fCoord[0][i1][i2];
639 y[j] = fCoord[1][i1][i2];
640 z[j] = edepcell[i12];
641 t[j] = i1*10000 + i2;
645 // arranging cells within supercluster in decreasing order
647 for(j = 1;j <= ncl[i]; j++)
651 for(i1 = 0; i1 < j; i1++)
653 if(itest == 0 && z[iord[i1]] < z[ihld])
656 for(i2 = j-1; i2 >= i1; i2--)
658 iord[i2+1] = iord[i2];
667 // Clustering algorithm returns from here for PP collisions
668 // for pp, only the output of crude clusterng is taken
669 // sigx and sigy are not calculated at this moment
671 Double_t supx=0., supy=0., supz=0.;
673 for(j = 0;j <= ncl[i]; j++)
675 supx += x[iord[j]]*z[iord[j]];
676 supy += y[iord[j]]*z[iord[j]];
680 clxy[j] = t[iord[j]];
686 for(Int_t ncel = ncl[i] + 1; ncel < kNmaxCell; ncel ++ )
691 clusdata[0] = supx/supz;
692 clusdata[1] = supy/supz;
694 clusdata[3] = ncl[i]+1;
697 pmdcludata = new AliPMDcludata(clusdata,clxy);
698 fPMDclucont->Add(pmdcludata);
701 /* MODIFICATION PART STARTS (Tapan July 2008)
702 iord[0] is the cell with highest ADC in the crude-cluster
703 ig is the number of local maxima in the crude-cluster
704 For the higest peak we make ig=0 which means first local maximum.
705 Next we go down in terms of the ADC sequence and find out if any
706 more of the cells form local maxima. The definition of local
707 maxima is that all its neighbours are of less ADC compared to it.
712 // This part is to split the supercluster
719 Int_t ivalid = 0, icount = 0;
721 for(j=1;j<=ncl[i];j++)
727 rr=Distance(x1,y1,xc[ig],yc[ig]);
729 // Check the cells which are outside the neighbours (rr>1.2)
734 for(Int_t j1=1;j1<j;j1++)
737 Float_t rr1=Distance(x1,y1,x[iord[j1]],y[iord[j1]]);
738 if(rr1>1.2) ivalid++;
740 if(ivalid == icount && z1>0.5*zc[ig])
753 // We use simple Gaussian weighting. (Tapan Jan 2005)
754 // compute the number of cells belonging to each cluster.
755 // cell can be shared between several clusters
756 // in the ratio of cluster energy deposition
758 // (1) number of cells belonging to a cluster (ig) and
759 // (2) total ADC of the cluster (ig)
760 // (3) x and y positions of the cluster
767 Double_t *totaladc, *totaladc2, *ncell,*weight;
768 Double_t *xclust, *yclust, *sigxclust, *sigyclust;
769 Double_t *ax, *ay, *ax2, *ay2;
772 status = new Int_t [ncl[i]+1];
773 cellXY = new Int_t *[ncl[i]+1];
775 cellCount = new Int_t [ig+1];
776 totaladc = new Double_t [ig+1];
777 totaladc2 = new Double_t [ig+1];
778 ncell = new Double_t [ig+1];
779 weight = new Double_t [ig+1];
780 xclust = new Double_t [ig+1];
781 yclust = new Double_t [ig+1];
782 sigxclust = new Double_t [ig+1];
783 sigyclust = new Double_t [ig+1];
784 ax = new Double_t [ig+1];
785 ay = new Double_t [ig+1];
786 ax2 = new Double_t [ig+1];
787 ay2 = new Double_t [ig+1];
789 for(j = 0; j < ncl[i]+1; j++)
792 cellXY[j] = new Int_t[ig+1];
795 for(Int_t kcl = 0; kcl < ig+1; kcl++)
810 for(j = 0; j < ncl[i]+1; j++)
815 Double_t sumweight, gweight;
817 for(j = 0;j <= ncl[i]; j++)
824 for(Int_t kcl=0; kcl<=ig; kcl++)
828 rr = Distance(x1,y1,x2,y2);
835 totaladc2[kcl] = z1*z1;
845 for(j = 0; j <= ncl[i]; j++)
858 for(Int_t kcl = 0; kcl <= ig; kcl++)
862 rr = Distance(x1,y1,x2,y2);
863 gweight = exp(-(rr*rr)/(2*(1.2*1.2)));
864 weight[kcl] = zc[kcl] * gweight;
865 sumweight = sumweight + weight[kcl];
867 if(weight[kcl] > max)
874 cellXY[cellCount[maxweight]][maxweight] = iord[j];
876 cellCount[maxweight]++;
880 totaladc[maxweight] += z1;
881 ax[maxweight] += x1*z1;
882 ay[maxweight] += y1*z1;
883 totaladc2[maxweight] += z1*z1;
884 ax2[maxweight] += z1*(x1-x2)*(x1-x2);
885 ay2[maxweight] += z1*(y1-y2)*(y1-y2);
891 for(Int_t kcl = 0; kcl <= ig; kcl++)
893 if(totaladc[kcl] > 0.)
895 xclust[kcl] = (ax[kcl])/ totaladc[kcl];
896 yclust[kcl] = (ay[kcl])/ totaladc[kcl];
899 Float_t sqtotadc = totaladc[kcl]*totaladc[kcl];
900 if(totaladc2[kcl] >= sqtotadc)
902 sigxclust[kcl] = 0.25;
903 sigyclust[kcl] = 0.25;
907 sigxclust[kcl] = (totaladc[kcl]/(sqtotadc-totaladc2[kcl]))*ax2[kcl];
908 sigyclust[kcl] = (totaladc[kcl]/(sqtotadc-totaladc2[kcl]))*ay2[kcl];
912 for(j = 0; j < cellCount[kcl]; j++) clno++;
916 AliWarning("RefClust: Too many clusters! more than 4608");
919 clusdata[0] = xclust[kcl];
920 clusdata[1] = yclust[kcl];
921 clusdata[2] = totaladc[kcl];
922 clusdata[3] = ncell[kcl];
924 if(sigxclust[kcl] > sigyclust[kcl])
926 clusdata[4] = TMath::Sqrt(sigxclust[kcl]);
927 clusdata[5] = TMath::Sqrt(sigyclust[kcl]);
931 clusdata[4] = TMath::Sqrt(sigyclust[kcl]);
932 clusdata[5] = TMath::Sqrt(sigxclust[kcl]);
938 for (Int_t ii = 0; ii < cellCount[kcl]; ii++)
942 clxy[Ncell] = t[cellXY[ii][kcl]];
947 pmdcludata = new AliPMDcludata(clusdata,clxy);
948 fPMDclucont->Add(pmdcludata);
951 for(Int_t jj = 0; jj < ncl[i]+1; jj++) delete [] cellXY[jj];
985 // ------------------------------------------------------------------------ //
986 Double_t AliPMDClusteringV1::Distance(Double_t x1, Double_t y1,
987 Double_t x2, Double_t y2)
989 return TMath::Sqrt((x1-x2)*(x1-x2) + (y1-y2)*(y1-y2));
991 // ------------------------------------------------------------------------ //
992 void AliPMDClusteringV1::SetEdepCut(Float_t decut)
996 // ------------------------------------------------------------------------ //
997 void AliPMDClusteringV1::SetClusteringParam(Int_t cluspar)
999 fClusParam = cluspar;
1001 // ------------------------------------------------------------------------ //