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 **************************************************************************/
20 ///////////////////////////////////////////////////////////////////////////////
22 // TRD cluster finder for the slow simulator.
24 ///////////////////////////////////////////////////////////////////////////////
28 #include "AliTRDclusterizerV1.h"
29 #include "AliTRDmatrix.h"
30 #include "AliTRDgeometry.h"
31 #include "AliTRDdigitizer.h"
32 #include "AliTRDrecPoint.h"
33 #include "AliTRDdataArray.h"
35 ClassImp(AliTRDclusterizerV1)
37 //_____________________________________________________________________________
38 AliTRDclusterizerV1::AliTRDclusterizerV1():AliTRDclusterizer()
41 // AliTRDclusterizerV1 default constructor
48 //_____________________________________________________________________________
49 AliTRDclusterizerV1::AliTRDclusterizerV1(const Text_t* name, const Text_t* title)
50 :AliTRDclusterizer(name,title)
53 // AliTRDclusterizerV1 default constructor
62 //_____________________________________________________________________________
63 AliTRDclusterizerV1::~AliTRDclusterizerV1()
67 fDigitsArray->Delete();
73 //_____________________________________________________________________________
74 void AliTRDclusterizerV1::Init()
77 // Initializes the cluster finder
80 // The default parameter for the clustering
87 //_____________________________________________________________________________
88 Bool_t AliTRDclusterizerV1::ReadDigits()
91 // Reads the digits arrays from the input aliroot file
95 printf("AliTRDclusterizerV1::ReadDigits -- ");
96 printf("No input file open\n");
100 // Create a new segment array for the digits
101 fDigitsArray = new AliTRDsegmentArray(kNsect*kNplan*kNcham);
103 // Read in the digit arrays
104 return (fDigitsArray->LoadArray("TRDdigits"));
108 //_____________________________________________________________________________
109 Bool_t AliTRDclusterizerV1::MakeCluster()
112 // Generates the cluster.
115 Int_t row, col, time;
117 // Get the pointer to the detector class and check for version 1
118 AliTRD *TRD = (AliTRD*) gAlice->GetDetector("TRD");
119 if (TRD->IsVersion() != 1) {
120 printf("AliTRDclusterizerV1::MakeCluster -- ");
121 printf("TRD must be version 1 (slow simulator).\n");
126 AliTRDgeometry *Geo = TRD->GetGeometry();
128 printf("AliTRDclusterizerV1::MakeCluster -- ");
129 printf("Start creating clusters.\n");
131 AliTRDdataArray *Digits;
134 Float_t maxThresh = fClusMaxThresh; // threshold value for maximum
135 Float_t signalThresh = fClusSigThresh; // threshold value for digit signal
136 Int_t clusteringMethod = fClusMethod; // clustering method option (for testing)
138 // Iteration limit for unfolding procedure
139 const Float_t epsilon = 0.01;
141 const Int_t nClus = 3;
142 const Int_t nSig = 5;
145 Int_t chamEnd = kNcham;
146 if (TRD->GetSensChamber() >= 0) {
147 chamBeg = TRD->GetSensChamber();
148 chamEnd = chamEnd + 1;
151 Int_t planEnd = kNplan;
152 if (TRD->GetSensPlane() >= 0) {
153 planBeg = TRD->GetSensPlane();
154 planEnd = planBeg + 1;
157 Int_t sectEnd = kNsect;
158 if (TRD->GetSensSector() >= 0) {
159 sectBeg = TRD->GetSensSector();
160 sectEnd = sectBeg + 1;
163 // *** Start clustering *** in every chamber
164 for (Int_t icham = chamBeg; icham < chamEnd; icham++) {
165 for (Int_t iplan = planBeg; iplan < planEnd; iplan++) {
166 for (Int_t isect = sectBeg; isect < sectEnd; isect++) {
168 Int_t idet = Geo->GetDetector(iplan,icham,isect);
171 printf("AliTRDclusterizerV1::MakeCluster -- ");
172 printf("Analyzing chamber %d, plane %d, sector %d.\n"
175 Int_t nRowMax = Geo->GetRowMax(iplan,icham,isect);
176 Int_t nColMax = Geo->GetColMax(iplan);
177 Int_t nTimeMax = Geo->GetTimeMax();
179 // Create a detector matrix to keep maxima
180 AliTRDmatrix *digitMatrix = new AliTRDmatrix(nRowMax,nColMax,nTimeMax
182 // Create a matrix to contain maximum flags
183 AliTRDmatrix *maximaMatrix = new AliTRDmatrix(nRowMax,nColMax,nTimeMax
186 // Read in the digits
187 Digits = (AliTRDdataArray *) fDigitsArray->At(idet);
189 // Loop through the detector pixel
190 for (time = 0; time < nTimeMax; time++) {
191 for ( col = 0; col < nColMax; col++) {
192 for ( row = 0; row < nRowMax; row++) {
194 Int_t signal = Digits->GetData(row,col,time);
195 Int_t index = Digits->GetIndex(row,col,time);
197 // Fill the detector matrix
198 if (signal > signalThresh) {
199 // Store the signal amplitude
200 digitMatrix->SetSignal(row,col,time,signal);
201 // Store the digits number
202 digitMatrix->AddTrack(row,col,time,index);
209 // Loop chamber and find maxima in digitMatrix
210 for ( row = 0; row < nRowMax; row++) {
211 for ( col = 1; col < nColMax; col++) {
212 for (time = 0; time < nTimeMax; time++) {
214 if (digitMatrix->GetSignal(row,col,time)
215 < digitMatrix->GetSignal(row,col - 1,time)) {
218 if (digitMatrix->GetSignal(row,col - 2,time)
219 < digitMatrix->GetSignal(row,col - 1,time)) {
220 // yes, so set maximum flag
221 maximaMatrix->SetSignal(row,col - 1,time,1);
223 else maximaMatrix->SetSignal(row,col - 1,time,0);
231 // now check maxima and calculate cluster position
232 for ( row = 0; row < nRowMax; row++) {
233 for ( col = 1; col < nColMax; col++) {
234 for (time = 0; time < nTimeMax; time++) {
236 if ((maximaMatrix->GetSignal(row,col,time) > 0)
237 && (digitMatrix->GetSignal(row,col,time) > maxThresh)) {
239 // Ratio resulting from unfolding
241 // Signals on max and neighbouring pads
242 Float_t padSignal[nSig] = {0};
243 // Signals from cluster
244 Float_t clusterSignal[nClus] = {0};
246 Float_t clusterPads[nClus] = {0};
247 // Cluster digit info
248 Int_t clusterDigit[nClus] = {0};
250 for (Int_t iPad = 0; iPad < nClus; iPad++) {
251 clusterSignal[iPad] = digitMatrix->GetSignal(row,col-1+iPad,time);
252 clusterDigit[iPad] = digitMatrix->GetTrack(row,col-1+iPad,time,0);
255 // neighbouring maximum on right side?
256 if (col < nColMax - 2) {
257 if (maximaMatrix->GetSignal(row,col + 2,time) > 0) {
259 for (Int_t iPad = 0; iPad < 5; iPad++) {
260 padSignal[iPad] = digitMatrix->GetSignal(row,col-1+iPad,time);
264 ratio = Unfold(epsilon, padSignal);
266 // set signal on overlapping pad to ratio
267 clusterSignal[2] *= ratio;
272 // Calculate the position of the cluster
273 switch (clusteringMethod) {
275 // method 1: simply center of mass
276 clusterPads[0] = row + 0.5;
277 clusterPads[1] = col - 0.5 + (clusterSignal[2] - clusterSignal[0]) /
278 (clusterSignal[1] + clusterSignal[2] + clusterSignal[3]);
279 clusterPads[2] = time + 0.5;
284 // method 2: integral gauss fit on 3 pads
285 TH1F *hPadCharges = new TH1F("hPadCharges", "Charges on center 3 pads"
287 for (Int_t iCol = -1; iCol <= 3; iCol++) {
288 if (clusterSignal[iCol] < 1) clusterSignal[iCol] = 1;
289 hPadCharges->Fill(iCol, clusterSignal[iCol]);
291 hPadCharges->Fit("gaus", "IQ", "SAME", -0.5, 2.5);
292 TF1 *fPadChargeFit = hPadCharges->GetFunction("gaus");
293 Double_t colMean = fPadChargeFit->GetParameter(1);
295 clusterPads[0] = row + 0.5;
296 clusterPads[1] = col - 1.5 + colMean;
297 clusterPads[2] = time + 0.5;
305 Float_t clusterCharge = clusterSignal[0]
309 // Add the cluster to the output array
310 TRD->AddRecPoint(clusterPads,clusterDigit,idet,clusterCharge);
317 printf("AliTRDclusterizerV1::MakeCluster -- ");
318 printf("Number of clusters found: %d\n",nClusters);
327 printf("AliTRDclusterizerV1::MakeCluster -- ");
328 printf("Total number of points found: %d\n"
329 ,TRD->RecPoints()->GetEntries());
331 // Get the pointer to the cluster branch
332 TTree *ClusterTree = gAlice->TreeR();
334 // Fill the cluster-branch
335 printf("AliTRDclusterizerV1::MakeCluster -- ");
336 printf("Fill the cluster tree.\n");
338 printf("AliTRDclusterizerV1::MakeCluster -- ");
345 //_____________________________________________________________________________
346 Float_t AliTRDclusterizerV1::Unfold(Float_t eps, Float_t* padSignal)
349 // Method to unfold neighbouring maxima.
350 // The charge ratio on the overlapping pad is calculated
351 // until there is no more change within the range given by eps.
352 // The resulting ratio is then returned to the calling method.
355 Int_t itStep = 0; // count iteration steps
357 Float_t ratio = 0.5; // start value for ratio
358 Float_t prevRatio = 0; // store previous ratio
360 Float_t newLeftSignal[3] = {0}; // array to store left cluster signal
361 Float_t newRightSignal[3] = {0}; // array to store right cluster signal
364 while ((TMath::Abs(prevRatio - ratio) > eps) && (itStep < 10)) {
369 // cluster position according to charge ratio
370 Float_t maxLeft = (ratio*padSignal[2] - padSignal[0]) /
371 (padSignal[0] + padSignal[1] + ratio*padSignal[2]);
372 Float_t maxRight = (padSignal[4] - (1-ratio)*padSignal[2]) /
373 ((1-ratio)*padSignal[2] + padSignal[3] + padSignal[4]);
375 // set cluster charge ratio
376 Float_t ampLeft = padSignal[1];
377 Float_t ampRight = padSignal[3];
379 // apply pad response to parameters
380 newLeftSignal[0] = ampLeft*PadResponse(-1 - maxLeft);
381 newLeftSignal[1] = ampLeft*PadResponse( 0 - maxLeft);
382 newLeftSignal[2] = ampLeft*PadResponse( 1 - maxLeft);
384 newRightSignal[0] = ampRight*PadResponse(-1 - maxRight);
385 newRightSignal[1] = ampRight*PadResponse( 0 - maxRight);
386 newRightSignal[2] = ampRight*PadResponse( 1 - maxRight);
388 // calculate new overlapping ratio
389 ratio = newLeftSignal[2]/(newLeftSignal[2] + newRightSignal[0]);
397 //_____________________________________________________________________________
398 Float_t AliTRDclusterizerV1::PadResponse(Float_t x)
401 // The pad response for the chevron pads.
402 // We use a simple Gaussian approximation which should be good
403 // enough for our purpose.
406 // The parameters for the response function
407 const Float_t aa = 0.8872;
408 const Float_t bb = -0.00573;
409 const Float_t cc = 0.454;
410 const Float_t cc2 = cc*cc;
412 Float_t pr = aa * (bb + TMath::Exp(-x*x / (2. * cc2)));