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.10 2001/05/07 08:06:44 cblume
19 Speedup of the code. Create only AliTRDcluster
21 Revision 1.9 2000/11/01 14:53:20 cblume
22 Merge with TRD-develop
24 Revision 1.1.4.5 2000/10/15 23:40:01 cblume
27 Revision 1.1.4.4 2000/10/06 16:49:46 cblume
30 Revision 1.1.4.3 2000/10/04 16:34:58 cblume
31 Replace include files by forward declarations
33 Revision 1.1.4.2 2000/09/22 14:49:49 cblume
34 Adapted to tracking code
36 Revision 1.8 2000/10/02 21:28:19 fca
37 Removal of useless dependecies via forward declarations
39 Revision 1.7 2000/06/27 13:08:50 cblume
40 Changed to Copy(TObject &A) to appease the HP-compiler
42 Revision 1.6 2000/06/09 11:10:07 cblume
43 Compiler warnings and coding conventions, next round
45 Revision 1.5 2000/06/08 18:32:58 cblume
46 Make code compliant to coding conventions
48 Revision 1.4 2000/06/07 16:27:01 cblume
49 Try to remove compiler warnings on Sun and HP
51 Revision 1.3 2000/05/08 16:17:27 cblume
54 Revision 1.1.4.1 2000/05/08 15:09:01 cblume
55 Introduce AliTRDdigitsManager
57 Revision 1.1 2000/02/28 18:58:54 cblume
62 ///////////////////////////////////////////////////////////////////////////////
64 // TRD cluster finder for the slow simulator.
66 ///////////////////////////////////////////////////////////////////////////////
75 #include "AliTRDclusterizerV1.h"
76 #include "AliTRDmatrix.h"
77 #include "AliTRDgeometry.h"
78 #include "AliTRDdigitizer.h"
79 #include "AliTRDdataArrayF.h"
80 #include "AliTRDdataArrayI.h"
81 #include "AliTRDdigitsManager.h"
83 ClassImp(AliTRDclusterizerV1)
85 //_____________________________________________________________________________
86 AliTRDclusterizerV1::AliTRDclusterizerV1():AliTRDclusterizer()
89 // AliTRDclusterizerV1 default constructor
92 fDigitsManager = NULL;
101 //_____________________________________________________________________________
102 AliTRDclusterizerV1::AliTRDclusterizerV1(const Text_t* name, const Text_t* title)
103 :AliTRDclusterizer(name,title)
106 // AliTRDclusterizerV1 default constructor
109 fDigitsManager = new AliTRDdigitsManager();
115 //_____________________________________________________________________________
116 AliTRDclusterizerV1::AliTRDclusterizerV1(const AliTRDclusterizerV1 &c)
119 // AliTRDclusterizerV1 copy constructor
122 ((AliTRDclusterizerV1 &) c).Copy(*this);
126 //_____________________________________________________________________________
127 AliTRDclusterizerV1::~AliTRDclusterizerV1()
130 // AliTRDclusterizerV1 destructor
133 if (fDigitsManager) {
134 delete fDigitsManager;
139 //_____________________________________________________________________________
140 AliTRDclusterizerV1 &AliTRDclusterizerV1::operator=(const AliTRDclusterizerV1 &c)
143 // Assignment operator
146 if (this != &c) ((AliTRDclusterizerV1 &) c).Copy(*this);
151 //_____________________________________________________________________________
152 void AliTRDclusterizerV1::Copy(TObject &c)
158 ((AliTRDclusterizerV1 &) c).fUseLUT = fUseLUT;
159 ((AliTRDclusterizerV1 &) c).fClusMaxThresh = fClusMaxThresh;
160 ((AliTRDclusterizerV1 &) c).fClusSigThresh = fClusSigThresh;
161 ((AliTRDclusterizerV1 &) c).fDigitsManager = NULL;
162 for (Int_t ilut = 0; ilut < kNlut; ilut++) {
163 ((AliTRDclusterizerV1 &) c).fLUT[ilut] = fLUT[ilut];
166 AliTRDclusterizer::Copy(c);
170 //_____________________________________________________________________________
171 void AliTRDclusterizerV1::Init()
174 // Initializes the cluster finder
177 // The default parameter for the clustering
181 // Use the lookup table for the position determination
184 // The lookup table from Bogdan
186 0.0068, 0.0198, 0.0318, 0.0432, 0.0538, 0.0642, 0.0742, 0.0838,
187 0.0932, 0.1023, 0.1107, 0.1187, 0.1268, 0.1347, 0.1423, 0.1493,
188 0.1562, 0.1632, 0.1698, 0.1762, 0.1828, 0.1887, 0.1947, 0.2002,
189 0.2062, 0.2118, 0.2173, 0.2222, 0.2278, 0.2327, 0.2377, 0.2428,
190 0.2473, 0.2522, 0.2567, 0.2612, 0.2657, 0.2697, 0.2743, 0.2783,
191 0.2822, 0.2862, 0.2903, 0.2943, 0.2982, 0.3018, 0.3058, 0.3092,
192 0.3128, 0.3167, 0.3203, 0.3237, 0.3268, 0.3302, 0.3338, 0.3368,
193 0.3402, 0.3433, 0.3462, 0.3492, 0.3528, 0.3557, 0.3587, 0.3613,
194 0.3643, 0.3672, 0.3702, 0.3728, 0.3758, 0.3783, 0.3812, 0.3837,
195 0.3862, 0.3887, 0.3918, 0.3943, 0.3968, 0.3993, 0.4017, 0.4042,
196 0.4067, 0.4087, 0.4112, 0.4137, 0.4157, 0.4182, 0.4207, 0.4227,
197 0.4252, 0.4272, 0.4293, 0.4317, 0.4338, 0.4358, 0.4383, 0.4403,
198 0.4423, 0.4442, 0.4462, 0.4482, 0.4502, 0.4523, 0.4543, 0.4563,
199 0.4582, 0.4602, 0.4622, 0.4638, 0.4658, 0.4678, 0.4697, 0.4712,
200 0.4733, 0.4753, 0.4767, 0.4787, 0.4803, 0.4823, 0.4837, 0.4857,
201 0.4873, 0.4888, 0.4908, 0.4922, 0.4942, 0.4958, 0.4972, 0.4988
203 for (Int_t ilut = 0; ilut < kNlut; ilut++) {
204 fLUT[ilut] = lut[ilut];
209 //_____________________________________________________________________________
210 Bool_t AliTRDclusterizerV1::ReadDigits()
213 // Reads the digits arrays from the input aliroot file
217 printf("AliTRDclusterizerV1::ReadDigits -- ");
218 printf("No input file open\n");
222 // Read in the digit arrays
223 return (fDigitsManager->ReadDigits());
227 //_____________________________________________________________________________
228 Bool_t AliTRDclusterizerV1::MakeClusters()
231 // Generates the cluster.
234 Int_t row, col, time;
236 if (fTRD->IsVersion() != 1) {
237 printf("AliTRDclusterizerV1::MakeCluster -- ");
238 printf("TRD must be version 1 (slow simulator).\n");
243 AliTRDgeometry *geo = fTRD->GetGeometry();
245 printf("AliTRDclusterizerV1::MakeCluster -- ");
246 printf("Start creating clusters.\n");
248 AliTRDdataArrayI *digits;
249 AliTRDdataArrayI *track0;
250 AliTRDdataArrayI *track1;
251 AliTRDdataArrayI *track2;
253 // Threshold value for the maximum
254 Int_t maxThresh = fClusMaxThresh;
255 // Threshold value for the digit signal
256 Int_t sigThresh = fClusSigThresh;
258 // Iteration limit for unfolding procedure
259 const Float_t kEpsilon = 0.01;
261 const Int_t kNclus = 3;
262 const Int_t kNsig = 5;
263 const Int_t kNtrack = 3 * kNclus;
266 const Float_t kLUTmin = 0.106113;
267 const Float_t kLUTmax = 0.995415;
272 Float_t ratioLeft = 1.0;
273 Float_t ratioRight = 1.0;
275 Float_t padSignal[kNsig];
276 Float_t clusterSignal[kNclus];
277 Float_t clusterPads[kNclus];
278 Int_t clusterDigit[kNclus];
279 Int_t clusterTracks[kNtrack];
282 Int_t chamEnd = AliTRDgeometry::Ncham();
283 if (fTRD->GetSensChamber() >= 0) {
284 chamBeg = fTRD->GetSensChamber();
285 chamEnd = chamBeg + 1;
288 Int_t planEnd = AliTRDgeometry::Nplan();
289 if (fTRD->GetSensPlane() >= 0) {
290 planBeg = fTRD->GetSensPlane();
291 planEnd = planBeg + 1;
294 Int_t sectEnd = AliTRDgeometry::Nsect();
296 // Start clustering in every chamber
297 for (Int_t icham = chamBeg; icham < chamEnd; icham++) {
298 for (Int_t iplan = planBeg; iplan < planEnd; iplan++) {
299 for (Int_t isect = sectBeg; isect < sectEnd; isect++) {
301 if (fTRD->GetSensSector() >= 0) {
302 Int_t sens1 = fTRD->GetSensSector();
303 Int_t sens2 = sens1 + fTRD->GetSensSectorRange();
304 sens2 -= ((Int_t) (sens2 / AliTRDgeometry::Nsect()))
305 * AliTRDgeometry::Nsect();
307 if ((isect < sens1) || (isect >= sens2)) continue;
310 if ((isect < sens1) && (isect >= sens2)) continue;
314 Int_t idet = geo->GetDetector(iplan,icham,isect);
317 Int_t nClusters2pad = 0;
318 Int_t nClusters3pad = 0;
319 Int_t nClusters4pad = 0;
320 Int_t nClusters5pad = 0;
321 Int_t nClustersLarge = 0;
323 printf("AliTRDclusterizerV1::MakeCluster -- ");
324 printf("Analyzing chamber %d, plane %d, sector %d.\n"
327 Int_t nRowMax = geo->GetRowMax(iplan,icham,isect);
328 Int_t nColMax = geo->GetColMax(iplan);
329 Int_t nTimeBefore = geo->GetTimeBefore();
330 Int_t nTimeTotal = geo->GetTimeTotal();
333 digits = fDigitsManager->GetDigits(idet);
335 track0 = fDigitsManager->GetDictionary(idet,0);
337 track1 = fDigitsManager->GetDictionary(idet,1);
339 track2 = fDigitsManager->GetDictionary(idet,2);
342 // Loop through the chamber and find the maxima
343 for ( row = 0; row < nRowMax; row++) {
344 for ( col = 2; col < nColMax; col++) {
345 for (time = 0; time < nTimeTotal; time++) {
347 Int_t signalL = digits->GetDataUnchecked(row,col ,time);
348 Int_t signalM = digits->GetDataUnchecked(row,col-1,time);
349 Int_t signalR = digits->GetDataUnchecked(row,col-2,time);
351 // Look for the maximum
352 if (signalM >= maxThresh) {
353 if (((signalL >= sigThresh) &&
354 (signalL < signalM)) ||
355 ((signalR >= sigThresh) &&
356 (signalR < signalM))) {
357 // Maximum found, mark the position by a negative signal
358 digits->SetDataUnchecked(row,col-1,time,-signalM);
366 // Now check the maxima and calculate the cluster position
367 for ( row = 0; row < nRowMax ; row++) {
368 for (time = 0; time < nTimeTotal; time++) {
369 for ( col = 1; col < nColMax-1; col++) {
372 if (digits->GetDataUnchecked(row,col,time) < 0) {
375 for (iPad = 0; iPad < kNclus; iPad++) {
376 Int_t iPadCol = col - 1 + iPad;
377 clusterSignal[iPad] = TMath::Abs(digits->GetDataUnchecked(row
380 clusterDigit[iPad] = digits->GetIndexUnchecked(row,iPadCol,time);
381 clusterTracks[3*iPad ] = track0->GetDataUnchecked(row,iPadCol,time) - 1;
382 clusterTracks[3*iPad+1] = track1->GetDataUnchecked(row,iPadCol,time) - 1;
383 clusterTracks[3*iPad+2] = track2->GetDataUnchecked(row,iPadCol,time) - 1;
386 // Count the number of pads in the cluster
389 while (TMath::Abs(digits->GetDataUnchecked(row,col-ii ,time))
393 if (col-ii < 0) break;
396 while (TMath::Abs(digits->GetDataUnchecked(row,col+ii+1,time))
400 if (col+ii+1 >= nColMax) break;
427 // Don't analyze large clusters
428 //if (iType == 4) continue;
430 // Look for 5 pad cluster with minimum in the middle
431 Bool_t fivePadCluster = kFALSE;
432 if (col < nColMax-3) {
433 if (digits->GetDataUnchecked(row,col+2,time) < 0) {
434 fivePadCluster = kTRUE;
436 if ((fivePadCluster) && (col < nColMax-5)) {
437 if (digits->GetDataUnchecked(row,col+4,time) >= sigThresh) {
438 fivePadCluster = kFALSE;
441 if ((fivePadCluster) && (col > 1)) {
442 if (digits->GetDataUnchecked(row,col-2,time) >= sigThresh) {
443 fivePadCluster = kFALSE;
449 // Modify the signal of the overlapping pad for the left part
450 // of the cluster which remains from a previous unfolding
452 clusterSignal[0] *= ratioLeft;
457 // Unfold the 5 pad cluster
458 if (fivePadCluster) {
459 for (iPad = 0; iPad < kNsig; iPad++) {
460 padSignal[iPad] = TMath::Abs(digits->GetDataUnchecked(row
464 // Unfold the two maxima and set the signal on
465 // the overlapping pad to the ratio
466 ratioRight = Unfold(kEpsilon,padSignal);
467 ratioLeft = 1.0 - ratioRight;
468 clusterSignal[2] *= ratioRight;
473 Float_t clusterCharge = clusterSignal[0]
477 // The position of the cluster
478 clusterPads[0] = row + 0.5;
479 // Take the shift of the additional time bins into account
480 clusterPads[2] = time - nTimeBefore + 0.5;
484 // Calculate the position of the cluster by using the
485 // lookup table method
489 if (clusterSignal[0] > clusterSignal[2]) {
490 ratioLUT = clusterSignal[0] / clusterSignal[1];
494 ratioLUT = clusterSignal[2] / clusterSignal[1];
497 if (ratioLUT < kLUTmin) {
500 else if (ratioLUT > kLUTmax) {
504 Int_t indexLUT = TMath::Nint ((kNlut-1) * (ratioLUT - kLUTmin)
505 / (kLUTmax - kLUTmin));
506 lut = fLUT[indexLUT];
508 clusterPads[1] = col + 0.5 + signLUT * lut;
513 // Calculate the position of the cluster by using the
514 // center of gravity method
515 clusterPads[1] = col + 0.5
516 + (clusterSignal[2] - clusterSignal[0])
522 printf("-----------------------------------------------------------\n");
523 printf("Create cluster no. %d\n",nClusters);
524 printf("Position: row = %f, col = %f, time = %f\n",clusterPads[0]
527 printf("Indices: %d, %d, %d\n",clusterDigit[0]
530 printf("Total charge = %f\n",clusterCharge);
531 printf("Tracks: pad0 %d, %d, %d\n",clusterTracks[0]
534 printf(" pad1 %d, %d, %d\n",clusterTracks[3]
537 printf(" pad2 %d, %d, %d\n",clusterTracks[6]
540 printf("Type = %d, Number of pads = %d\n",iType,nPadCount);
543 // Add the cluster to the output array
544 fTRD->AddCluster(clusterPads
556 // Compress the arrays
557 digits->Compress(1,0);
558 track0->Compress(1,0);
559 track1->Compress(1,0);
560 track2->Compress(1,0);
562 // Write the cluster and reset the array
564 fTRD->ResetRecPoints();
566 printf("AliTRDclusterizerV1::MakeCluster -- ");
567 printf("Found %d clusters in total.\n"
569 printf(" 2pad: %d\n",nClusters2pad);
570 printf(" 3pad: %d\n",nClusters3pad);
571 printf(" 4pad: %d\n",nClusters4pad);
572 printf(" 5pad: %d\n",nClusters5pad);
573 printf(" Large: %d\n",nClustersLarge);
579 printf("AliTRDclusterizerV1::MakeCluster -- ");
586 //_____________________________________________________________________________
587 Float_t AliTRDclusterizerV1::Unfold(Float_t eps, Float_t* padSignal)
590 // Method to unfold neighbouring maxima.
591 // The charge ratio on the overlapping pad is calculated
592 // until there is no more change within the range given by eps.
593 // The resulting ratio is then returned to the calling method.
596 Int_t itStep = 0; // Count iteration steps
598 Float_t ratio = 0.5; // Start value for ratio
599 Float_t prevRatio = 0; // Store previous ratio
601 Float_t newLeftSignal[3] = {0}; // Array to store left cluster signal
602 Float_t newRightSignal[3] = {0}; // Array to store right cluster signal
604 // Start the iteration
605 while ((TMath::Abs(prevRatio - ratio) > eps) && (itStep < 10)) {
610 // Cluster position according to charge ratio
611 Float_t maxLeft = (ratio*padSignal[2] - padSignal[0])
612 / (padSignal[0] + padSignal[1] + ratio*padSignal[2]);
613 Float_t maxRight = (padSignal[4] - (1-ratio)*padSignal[2])
614 / ((1-ratio)*padSignal[2] + padSignal[3] + padSignal[4]);
616 // Set cluster charge ratio
617 Float_t ampLeft = padSignal[1];
618 Float_t ampRight = padSignal[3];
620 // Apply pad response to parameters
621 newLeftSignal[0] = ampLeft * PadResponse(-1 - maxLeft);
622 newLeftSignal[1] = ampLeft * PadResponse( 0 - maxLeft);
623 newLeftSignal[2] = ampLeft * PadResponse( 1 - maxLeft);
625 newRightSignal[0] = ampRight * PadResponse(-1 - maxRight);
626 newRightSignal[1] = ampRight * PadResponse( 0 - maxRight);
627 newRightSignal[2] = ampRight * PadResponse( 1 - maxRight);
629 // Calculate new overlapping ratio
630 ratio = TMath::Min(1.0,newLeftSignal[2] /
631 (newLeftSignal[2] + newRightSignal[0]));
639 //_____________________________________________________________________________
640 Float_t AliTRDclusterizerV1::PadResponse(Float_t x)
643 // The pad response for the chevron pads.
644 // We use a simple Gaussian approximation which should be good
645 // enough for our purpose.
646 // Updated for new PRF 1/5/01.
649 // The parameters for the response function
650 const Float_t kA = 0.8303;
651 const Float_t kB = -0.00392;
652 const Float_t kC = 0.472 * 0.472;
653 const Float_t kD = 2.19;
655 Float_t pr = kA * (kB + TMath::Exp(-TMath::Power(x*x,kD) / (2.*kC)));