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 Revision 1.11 2001/05/21 16:45:47 hristov
19 Last minute changes (C.Blume)
21 Revision 1.10 2001/05/07 08:06:44 cblume
22 Speedup of the code. Create only AliTRDcluster
24 Revision 1.9 2000/11/01 14:53:20 cblume
25 Merge with TRD-develop
27 Revision 1.1.4.5 2000/10/15 23:40:01 cblume
30 Revision 1.1.4.4 2000/10/06 16:49:46 cblume
33 Revision 1.1.4.3 2000/10/04 16:34:58 cblume
34 Replace include files by forward declarations
36 Revision 1.1.4.2 2000/09/22 14:49:49 cblume
37 Adapted to tracking code
39 Revision 1.8 2000/10/02 21:28:19 fca
40 Removal of useless dependecies via forward declarations
42 Revision 1.7 2000/06/27 13:08:50 cblume
43 Changed to Copy(TObject &A) to appease the HP-compiler
45 Revision 1.6 2000/06/09 11:10:07 cblume
46 Compiler warnings and coding conventions, next round
48 Revision 1.5 2000/06/08 18:32:58 cblume
49 Make code compliant to coding conventions
51 Revision 1.4 2000/06/07 16:27:01 cblume
52 Try to remove compiler warnings on Sun and HP
54 Revision 1.3 2000/05/08 16:17:27 cblume
57 Revision 1.1.4.1 2000/05/08 15:09:01 cblume
58 Introduce AliTRDdigitsManager
60 Revision 1.1 2000/02/28 18:58:54 cblume
65 ///////////////////////////////////////////////////////////////////////////////
67 // TRD cluster finder for the slow simulator.
69 ///////////////////////////////////////////////////////////////////////////////
78 #include "AliTRDclusterizerV1.h"
79 #include "AliTRDmatrix.h"
80 #include "AliTRDgeometry.h"
81 #include "AliTRDdigitizer.h"
82 #include "AliTRDdataArrayF.h"
83 #include "AliTRDdataArrayI.h"
84 #include "AliTRDdigitsManager.h"
86 ClassImp(AliTRDclusterizerV1)
88 //_____________________________________________________________________________
89 AliTRDclusterizerV1::AliTRDclusterizerV1():AliTRDclusterizer()
92 // AliTRDclusterizerV1 default constructor
95 fDigitsManager = NULL;
104 //_____________________________________________________________________________
105 AliTRDclusterizerV1::AliTRDclusterizerV1(const Text_t* name, const Text_t* title)
106 :AliTRDclusterizer(name,title)
109 // AliTRDclusterizerV1 default constructor
112 fDigitsManager = new AliTRDdigitsManager();
118 //_____________________________________________________________________________
119 AliTRDclusterizerV1::AliTRDclusterizerV1(const AliTRDclusterizerV1 &c)
122 // AliTRDclusterizerV1 copy constructor
125 ((AliTRDclusterizerV1 &) c).Copy(*this);
129 //_____________________________________________________________________________
130 AliTRDclusterizerV1::~AliTRDclusterizerV1()
133 // AliTRDclusterizerV1 destructor
136 if (fDigitsManager) {
137 delete fDigitsManager;
142 //_____________________________________________________________________________
143 AliTRDclusterizerV1 &AliTRDclusterizerV1::operator=(const AliTRDclusterizerV1 &c)
146 // Assignment operator
149 if (this != &c) ((AliTRDclusterizerV1 &) c).Copy(*this);
154 //_____________________________________________________________________________
155 void AliTRDclusterizerV1::Copy(TObject &c)
161 ((AliTRDclusterizerV1 &) c).fUseLUT = fUseLUT;
162 ((AliTRDclusterizerV1 &) c).fClusMaxThresh = fClusMaxThresh;
163 ((AliTRDclusterizerV1 &) c).fClusSigThresh = fClusSigThresh;
164 ((AliTRDclusterizerV1 &) c).fDigitsManager = NULL;
165 for (Int_t ilut = 0; ilut < kNlut; ilut++) {
166 ((AliTRDclusterizerV1 &) c).fLUT[ilut] = fLUT[ilut];
169 AliTRDclusterizer::Copy(c);
173 //_____________________________________________________________________________
174 void AliTRDclusterizerV1::Init()
177 // Initializes the cluster finder
180 // The default parameter for the clustering
184 // Use the lookup table for the position determination
187 // The lookup table from Bogdan
189 0.0068, 0.0198, 0.0318, 0.0432, 0.0538, 0.0642, 0.0742, 0.0838,
190 0.0932, 0.1023, 0.1107, 0.1187, 0.1268, 0.1347, 0.1423, 0.1493,
191 0.1562, 0.1632, 0.1698, 0.1762, 0.1828, 0.1887, 0.1947, 0.2002,
192 0.2062, 0.2118, 0.2173, 0.2222, 0.2278, 0.2327, 0.2377, 0.2428,
193 0.2473, 0.2522, 0.2567, 0.2612, 0.2657, 0.2697, 0.2743, 0.2783,
194 0.2822, 0.2862, 0.2903, 0.2943, 0.2982, 0.3018, 0.3058, 0.3092,
195 0.3128, 0.3167, 0.3203, 0.3237, 0.3268, 0.3302, 0.3338, 0.3368,
196 0.3402, 0.3433, 0.3462, 0.3492, 0.3528, 0.3557, 0.3587, 0.3613,
197 0.3643, 0.3672, 0.3702, 0.3728, 0.3758, 0.3783, 0.3812, 0.3837,
198 0.3862, 0.3887, 0.3918, 0.3943, 0.3968, 0.3993, 0.4017, 0.4042,
199 0.4067, 0.4087, 0.4112, 0.4137, 0.4157, 0.4182, 0.4207, 0.4227,
200 0.4252, 0.4272, 0.4293, 0.4317, 0.4338, 0.4358, 0.4383, 0.4403,
201 0.4423, 0.4442, 0.4462, 0.4482, 0.4502, 0.4523, 0.4543, 0.4563,
202 0.4582, 0.4602, 0.4622, 0.4638, 0.4658, 0.4678, 0.4697, 0.4712,
203 0.4733, 0.4753, 0.4767, 0.4787, 0.4803, 0.4823, 0.4837, 0.4857,
204 0.4873, 0.4888, 0.4908, 0.4922, 0.4942, 0.4958, 0.4972, 0.4988
206 for (Int_t ilut = 0; ilut < kNlut; ilut++) {
207 fLUT[ilut] = lut[ilut];
212 //_____________________________________________________________________________
213 Bool_t AliTRDclusterizerV1::ReadDigits()
216 // Reads the digits arrays from the input aliroot file
220 printf("AliTRDclusterizerV1::ReadDigits -- ");
221 printf("No input file open\n");
225 // Read in the digit arrays
226 return (fDigitsManager->ReadDigits());
230 //_____________________________________________________________________________
231 Bool_t AliTRDclusterizerV1::MakeClusters()
234 // Generates the cluster.
237 Int_t row, col, time;
239 if (fTRD->IsVersion() != 1) {
240 printf("AliTRDclusterizerV1::MakeCluster -- ");
241 printf("TRD must be version 1 (slow simulator).\n");
246 AliTRDgeometry *geo = fTRD->GetGeometry();
248 printf("AliTRDclusterizerV1::MakeCluster -- ");
249 printf("Start creating clusters.\n");
251 AliTRDdataArrayI *digits;
252 AliTRDdataArrayI *track0;
253 AliTRDdataArrayI *track1;
254 AliTRDdataArrayI *track2;
256 // Threshold value for the maximum
257 Int_t maxThresh = fClusMaxThresh;
258 // Threshold value for the digit signal
259 Int_t sigThresh = fClusSigThresh;
261 // Iteration limit for unfolding procedure
262 const Float_t kEpsilon = 0.01;
264 const Int_t kNclus = 3;
265 const Int_t kNsig = 5;
266 const Int_t kNtrack = 3 * kNclus;
269 const Float_t kLUTmin = 0.106113;
270 const Float_t kLUTmax = 0.995415;
275 Float_t ratioLeft = 1.0;
276 Float_t ratioRight = 1.0;
278 Float_t padSignal[kNsig];
279 Float_t clusterSignal[kNclus];
280 Float_t clusterPads[kNclus];
281 Int_t clusterDigit[kNclus];
282 Int_t clusterTracks[kNtrack];
285 Int_t chamEnd = AliTRDgeometry::Ncham();
286 if (fTRD->GetSensChamber() >= 0) {
287 chamBeg = fTRD->GetSensChamber();
288 chamEnd = chamBeg + 1;
291 Int_t planEnd = AliTRDgeometry::Nplan();
292 if (fTRD->GetSensPlane() >= 0) {
293 planBeg = fTRD->GetSensPlane();
294 planEnd = planBeg + 1;
297 Int_t sectEnd = AliTRDgeometry::Nsect();
299 // Start clustering in every chamber
300 for (Int_t icham = chamBeg; icham < chamEnd; icham++) {
301 for (Int_t iplan = planBeg; iplan < planEnd; iplan++) {
302 for (Int_t isect = sectBeg; isect < sectEnd; isect++) {
304 if (fTRD->GetSensSector() >= 0) {
305 Int_t sens1 = fTRD->GetSensSector();
306 Int_t sens2 = sens1 + fTRD->GetSensSectorRange();
307 sens2 -= ((Int_t) (sens2 / AliTRDgeometry::Nsect()))
308 * AliTRDgeometry::Nsect();
310 if ((isect < sens1) || (isect >= sens2)) continue;
313 if ((isect < sens1) && (isect >= sens2)) continue;
317 Int_t idet = geo->GetDetector(iplan,icham,isect);
320 Int_t nClusters2pad = 0;
321 Int_t nClusters3pad = 0;
322 Int_t nClusters4pad = 0;
323 Int_t nClusters5pad = 0;
324 Int_t nClustersLarge = 0;
326 printf("AliTRDclusterizerV1::MakeCluster -- ");
327 printf("Analyzing chamber %d, plane %d, sector %d.\n"
330 Int_t nRowMax = geo->GetRowMax(iplan,icham,isect);
331 Int_t nColMax = geo->GetColMax(iplan);
332 Int_t nTimeBefore = geo->GetTimeBefore();
333 Int_t nTimeTotal = geo->GetTimeTotal();
336 digits = fDigitsManager->GetDigits(idet);
338 track0 = fDigitsManager->GetDictionary(idet,0);
340 track1 = fDigitsManager->GetDictionary(idet,1);
342 track2 = fDigitsManager->GetDictionary(idet,2);
345 // Loop through the chamber and find the maxima
346 for ( row = 0; row < nRowMax; row++) {
347 for ( col = 2; col < nColMax; col++) {
348 for (time = 0; time < nTimeTotal; time++) {
350 Int_t signalL = digits->GetDataUnchecked(row,col ,time);
351 Int_t signalM = digits->GetDataUnchecked(row,col-1,time);
352 Int_t signalR = digits->GetDataUnchecked(row,col-2,time);
354 // Look for the maximum
355 if (signalM >= maxThresh) {
356 if (((signalL >= sigThresh) &&
357 (signalL < signalM)) ||
358 ((signalR >= sigThresh) &&
359 (signalR < signalM))) {
360 // Maximum found, mark the position by a negative signal
361 digits->SetDataUnchecked(row,col-1,time,-signalM);
369 // Now check the maxima and calculate the cluster position
370 for ( row = 0; row < nRowMax ; row++) {
371 for (time = 0; time < nTimeTotal; time++) {
372 for ( col = 1; col < nColMax-1; col++) {
375 if (digits->GetDataUnchecked(row,col,time) < 0) {
378 for (iPad = 0; iPad < kNclus; iPad++) {
379 Int_t iPadCol = col - 1 + iPad;
380 clusterSignal[iPad] = TMath::Abs(digits->GetDataUnchecked(row
383 clusterDigit[iPad] = digits->GetIndexUnchecked(row,iPadCol,time);
384 clusterTracks[3*iPad ] = track0->GetDataUnchecked(row,iPadCol,time) - 1;
385 clusterTracks[3*iPad+1] = track1->GetDataUnchecked(row,iPadCol,time) - 1;
386 clusterTracks[3*iPad+2] = track2->GetDataUnchecked(row,iPadCol,time) - 1;
389 // Count the number of pads in the cluster
392 while (TMath::Abs(digits->GetDataUnchecked(row,col-ii ,time))
396 if (col-ii < 0) break;
399 while (TMath::Abs(digits->GetDataUnchecked(row,col+ii+1,time))
403 if (col+ii+1 >= nColMax) break;
430 // Don't analyze large clusters
431 //if (iType == 4) continue;
433 // Look for 5 pad cluster with minimum in the middle
434 Bool_t fivePadCluster = kFALSE;
435 if (col < nColMax-3) {
436 if (digits->GetDataUnchecked(row,col+2,time) < 0) {
437 fivePadCluster = kTRUE;
439 if ((fivePadCluster) && (col < nColMax-5)) {
440 if (digits->GetDataUnchecked(row,col+4,time) >= sigThresh) {
441 fivePadCluster = kFALSE;
444 if ((fivePadCluster) && (col > 1)) {
445 if (digits->GetDataUnchecked(row,col-2,time) >= sigThresh) {
446 fivePadCluster = kFALSE;
452 // Modify the signal of the overlapping pad for the left part
453 // of the cluster which remains from a previous unfolding
455 clusterSignal[0] *= ratioLeft;
460 // Unfold the 5 pad cluster
461 if (fivePadCluster) {
462 for (iPad = 0; iPad < kNsig; iPad++) {
463 padSignal[iPad] = TMath::Abs(digits->GetDataUnchecked(row
467 // Unfold the two maxima and set the signal on
468 // the overlapping pad to the ratio
469 ratioRight = Unfold(kEpsilon,padSignal);
470 ratioLeft = 1.0 - ratioRight;
471 clusterSignal[2] *= ratioRight;
476 Float_t clusterCharge = clusterSignal[0]
480 // The position of the cluster
481 clusterPads[0] = row + 0.5;
482 // Take the shift of the additional time bins into account
483 clusterPads[2] = time - nTimeBefore + 0.5;
487 // Calculate the position of the cluster by using the
488 // lookup table method
492 if (clusterSignal[0] > clusterSignal[2]) {
493 ratioLUT = clusterSignal[0] / clusterSignal[1];
497 ratioLUT = clusterSignal[2] / clusterSignal[1];
500 if (ratioLUT < kLUTmin) {
503 else if (ratioLUT > kLUTmax) {
507 Int_t indexLUT = TMath::Nint ((kNlut-1) * (ratioLUT - kLUTmin)
508 / (kLUTmax - kLUTmin));
509 lut = fLUT[indexLUT];
511 clusterPads[1] = col + 0.5 + signLUT * lut;
516 // Calculate the position of the cluster by using the
517 // center of gravity method
518 clusterPads[1] = col + 0.5
519 + (clusterSignal[2] - clusterSignal[0])
525 printf("-----------------------------------------------------------\n");
526 printf("Create cluster no. %d\n",nClusters);
527 printf("Position: row = %f, col = %f, time = %f\n",clusterPads[0]
530 printf("Indices: %d, %d, %d\n",clusterDigit[0]
533 printf("Total charge = %f\n",clusterCharge);
534 printf("Tracks: pad0 %d, %d, %d\n",clusterTracks[0]
537 printf(" pad1 %d, %d, %d\n",clusterTracks[3]
540 printf(" pad2 %d, %d, %d\n",clusterTracks[6]
543 printf("Type = %d, Number of pads = %d\n",iType,nPadCount);
546 // Add the cluster to the output array
547 fTRD->AddCluster(clusterPads
559 // Compress the arrays
560 digits->Compress(1,0);
561 track0->Compress(1,0);
562 track1->Compress(1,0);
563 track2->Compress(1,0);
565 // Write the cluster and reset the array
567 fTRD->ResetRecPoints();
569 printf("AliTRDclusterizerV1::MakeCluster -- ");
570 printf("Found %d clusters in total.\n"
572 printf(" 2pad: %d\n",nClusters2pad);
573 printf(" 3pad: %d\n",nClusters3pad);
574 printf(" 4pad: %d\n",nClusters4pad);
575 printf(" 5pad: %d\n",nClusters5pad);
576 printf(" Large: %d\n",nClustersLarge);
582 printf("AliTRDclusterizerV1::MakeCluster -- ");
589 //_____________________________________________________________________________
590 Float_t AliTRDclusterizerV1::Unfold(Float_t eps, Float_t* padSignal)
593 // Method to unfold neighbouring maxima.
594 // The charge ratio on the overlapping pad is calculated
595 // until there is no more change within the range given by eps.
596 // The resulting ratio is then returned to the calling method.
599 Int_t itStep = 0; // Count iteration steps
601 Float_t ratio = 0.5; // Start value for ratio
602 Float_t prevRatio = 0; // Store previous ratio
604 Float_t newLeftSignal[3] = {0}; // Array to store left cluster signal
605 Float_t newRightSignal[3] = {0}; // Array to store right cluster signal
607 // Start the iteration
608 while ((TMath::Abs(prevRatio - ratio) > eps) && (itStep < 10)) {
613 // Cluster position according to charge ratio
614 Float_t maxLeft = (ratio*padSignal[2] - padSignal[0])
615 / (padSignal[0] + padSignal[1] + ratio*padSignal[2]);
616 Float_t maxRight = (padSignal[4] - (1-ratio)*padSignal[2])
617 / ((1-ratio)*padSignal[2] + padSignal[3] + padSignal[4]);
619 // Set cluster charge ratio
620 Float_t ampLeft = padSignal[1];
621 Float_t ampRight = padSignal[3];
623 // Apply pad response to parameters
624 newLeftSignal[0] = ampLeft * PadResponse(-1 - maxLeft);
625 newLeftSignal[1] = ampLeft * PadResponse( 0 - maxLeft);
626 newLeftSignal[2] = ampLeft * PadResponse( 1 - maxLeft);
628 newRightSignal[0] = ampRight * PadResponse(-1 - maxRight);
629 newRightSignal[1] = ampRight * PadResponse( 0 - maxRight);
630 newRightSignal[2] = ampRight * PadResponse( 1 - maxRight);
632 // Calculate new overlapping ratio
633 ratio = TMath::Min((Float_t)1.0,newLeftSignal[2] /
634 (newLeftSignal[2] + newRightSignal[0]));
642 //_____________________________________________________________________________
643 Float_t AliTRDclusterizerV1::PadResponse(Float_t x)
646 // The pad response for the chevron pads.
647 // We use a simple Gaussian approximation which should be good
648 // enough for our purpose.
649 // Updated for new PRF 1/5/01.
652 // The parameters for the response function
653 const Float_t kA = 0.8303;
654 const Float_t kB = -0.00392;
655 const Float_t kC = 0.472 * 0.472;
656 const Float_t kD = 2.19;
658 Float_t pr = kA * (kB + TMath::Exp(-TMath::Power(x*x,kD) / (2.*kC)));