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.13 2001/05/28 17:07:58 hristov
19 Last minute changes; ExB correction in AliTRDclusterizerV1; taking into account of material in G10 TEC frames and material between TEC planes (C.Blume,S.Sedykh)
21 Revision 1.12 2001/05/21 17:42:58 hristov
22 Constant casted to avoid the ambiguity
24 Revision 1.11 2001/05/21 16:45:47 hristov
25 Last minute changes (C.Blume)
27 Revision 1.10 2001/05/07 08:06:44 cblume
28 Speedup of the code. Create only AliTRDcluster
30 Revision 1.9 2000/11/01 14:53:20 cblume
31 Merge with TRD-develop
33 Revision 1.1.4.5 2000/10/15 23:40:01 cblume
36 Revision 1.1.4.4 2000/10/06 16:49:46 cblume
39 Revision 1.1.4.3 2000/10/04 16:34:58 cblume
40 Replace include files by forward declarations
42 Revision 1.1.4.2 2000/09/22 14:49:49 cblume
43 Adapted to tracking code
45 Revision 1.8 2000/10/02 21:28:19 fca
46 Removal of useless dependecies via forward declarations
48 Revision 1.7 2000/06/27 13:08:50 cblume
49 Changed to Copy(TObject &A) to appease the HP-compiler
51 Revision 1.6 2000/06/09 11:10:07 cblume
52 Compiler warnings and coding conventions, next round
54 Revision 1.5 2000/06/08 18:32:58 cblume
55 Make code compliant to coding conventions
57 Revision 1.4 2000/06/07 16:27:01 cblume
58 Try to remove compiler warnings on Sun and HP
60 Revision 1.3 2000/05/08 16:17:27 cblume
63 Revision 1.1.4.1 2000/05/08 15:09:01 cblume
64 Introduce AliTRDdigitsManager
66 Revision 1.1 2000/02/28 18:58:54 cblume
71 ///////////////////////////////////////////////////////////////////////////////
73 // TRD cluster finder for the slow simulator.
75 ///////////////////////////////////////////////////////////////////////////////
85 #include "AliTRDclusterizerV1.h"
86 #include "AliTRDmatrix.h"
87 #include "AliTRDgeometry.h"
88 #include "AliTRDdigitizer.h"
89 #include "AliTRDdataArrayF.h"
90 #include "AliTRDdataArrayI.h"
91 #include "AliTRDdigitsManager.h"
93 ClassImp(AliTRDclusterizerV1)
95 //_____________________________________________________________________________
96 AliTRDclusterizerV1::AliTRDclusterizerV1():AliTRDclusterizer()
99 // AliTRDclusterizerV1 default constructor
102 fDigitsManager = NULL;
111 //_____________________________________________________________________________
112 AliTRDclusterizerV1::AliTRDclusterizerV1(const Text_t* name, const Text_t* title)
113 :AliTRDclusterizer(name,title)
116 // AliTRDclusterizerV1 default constructor
119 fDigitsManager = new AliTRDdigitsManager();
125 //_____________________________________________________________________________
126 AliTRDclusterizerV1::AliTRDclusterizerV1(const AliTRDclusterizerV1 &c)
129 // AliTRDclusterizerV1 copy constructor
132 ((AliTRDclusterizerV1 &) c).Copy(*this);
136 //_____________________________________________________________________________
137 AliTRDclusterizerV1::~AliTRDclusterizerV1()
140 // AliTRDclusterizerV1 destructor
143 if (fDigitsManager) {
144 delete fDigitsManager;
145 fDigitsManager = NULL;
150 //_____________________________________________________________________________
151 AliTRDclusterizerV1 &AliTRDclusterizerV1::operator=(const AliTRDclusterizerV1 &c)
154 // Assignment operator
157 if (this != &c) ((AliTRDclusterizerV1 &) c).Copy(*this);
162 //_____________________________________________________________________________
163 void AliTRDclusterizerV1::Copy(TObject &c)
169 ((AliTRDclusterizerV1 &) c).fUseLUT = fUseLUT;
170 ((AliTRDclusterizerV1 &) c).fClusMaxThresh = fClusMaxThresh;
171 ((AliTRDclusterizerV1 &) c).fClusSigThresh = fClusSigThresh;
172 ((AliTRDclusterizerV1 &) c).fDigitsManager = NULL;
173 for (Int_t ilut = 0; ilut < kNlut; ilut++) {
174 ((AliTRDclusterizerV1 &) c).fLUT[ilut] = fLUT[ilut];
177 AliTRDclusterizer::Copy(c);
181 //_____________________________________________________________________________
182 void AliTRDclusterizerV1::Init()
185 // Initializes the cluster finder
188 // The default parameter for the clustering
192 // Use the lookup table for the position determination
195 // The lookup table from Bogdan
197 0.0068, 0.0198, 0.0318, 0.0432, 0.0538, 0.0642, 0.0742, 0.0838,
198 0.0932, 0.1023, 0.1107, 0.1187, 0.1268, 0.1347, 0.1423, 0.1493,
199 0.1562, 0.1632, 0.1698, 0.1762, 0.1828, 0.1887, 0.1947, 0.2002,
200 0.2062, 0.2118, 0.2173, 0.2222, 0.2278, 0.2327, 0.2377, 0.2428,
201 0.2473, 0.2522, 0.2567, 0.2612, 0.2657, 0.2697, 0.2743, 0.2783,
202 0.2822, 0.2862, 0.2903, 0.2943, 0.2982, 0.3018, 0.3058, 0.3092,
203 0.3128, 0.3167, 0.3203, 0.3237, 0.3268, 0.3302, 0.3338, 0.3368,
204 0.3402, 0.3433, 0.3462, 0.3492, 0.3528, 0.3557, 0.3587, 0.3613,
205 0.3643, 0.3672, 0.3702, 0.3728, 0.3758, 0.3783, 0.3812, 0.3837,
206 0.3862, 0.3887, 0.3918, 0.3943, 0.3968, 0.3993, 0.4017, 0.4042,
207 0.4067, 0.4087, 0.4112, 0.4137, 0.4157, 0.4182, 0.4207, 0.4227,
208 0.4252, 0.4272, 0.4293, 0.4317, 0.4338, 0.4358, 0.4383, 0.4403,
209 0.4423, 0.4442, 0.4462, 0.4482, 0.4502, 0.4523, 0.4543, 0.4563,
210 0.4582, 0.4602, 0.4622, 0.4638, 0.4658, 0.4678, 0.4697, 0.4712,
211 0.4733, 0.4753, 0.4767, 0.4787, 0.4803, 0.4823, 0.4837, 0.4857,
212 0.4873, 0.4888, 0.4908, 0.4922, 0.4942, 0.4958, 0.4972, 0.4988
214 for (Int_t ilut = 0; ilut < kNlut; ilut++) {
215 fLUT[ilut] = lut[ilut];
218 fDigitsManager->CreateArrays();
222 //_____________________________________________________________________________
223 Bool_t AliTRDclusterizerV1::ReadDigits()
226 // Reads the digits arrays from the input aliroot file
230 printf("AliTRDclusterizerV1::ReadDigits -- ");
231 printf("No input file open\n");
235 fDigitsManager->Open(fInputFile->GetName());
237 // Read in the digit arrays
238 return (fDigitsManager->ReadDigits());
242 //_____________________________________________________________________________
243 Bool_t AliTRDclusterizerV1::MakeClusters()
246 // Generates the cluster.
249 Int_t row, col, time;
251 if (fTRD->IsVersion() != 1) {
252 printf("AliTRDclusterizerV1::MakeCluster -- ");
253 printf("TRD must be version 1 (slow simulator).\n");
258 AliTRDgeometry *geo = fTRD->GetGeometry();
260 Float_t timeBinSize = geo->GetTimeBinSize();
261 // Half of ampl.region
262 const Float_t kAmWidth = AliTRDgeometry::AmThick()/2.;
264 AliTRDdigitizer *digitizer = (AliTRDdigitizer*) fInputFile->Get("digitizer");
265 printf("AliTRDclusterizerV1::MakeCluster -- ");
266 printf("Got digitizer\n");
267 Float_t omegaTau = digitizer->GetOmegaTau();
268 printf("AliTRDclusterizerV1::MakeCluster -- ");
269 printf("OmegaTau = %f \n",omegaTau);
271 printf("AliTRDclusterizerV1::MakeCluster -- ");
272 printf("Start creating clusters.\n");
274 AliTRDdataArrayI *digits;
275 AliTRDdataArrayI *track0;
276 AliTRDdataArrayI *track1;
277 AliTRDdataArrayI *track2;
279 // Threshold value for the maximum
280 Int_t maxThresh = fClusMaxThresh;
281 // Threshold value for the digit signal
282 Int_t sigThresh = fClusSigThresh;
284 // Iteration limit for unfolding procedure
285 const Float_t kEpsilon = 0.01;
287 const Int_t kNclus = 3;
288 const Int_t kNsig = 5;
289 const Int_t kNtrack = 3 * kNclus;
292 const Float_t kLUTmin = 0.106113;
293 const Float_t kLUTmax = 0.995415;
298 Float_t ratioLeft = 1.0;
299 Float_t ratioRight = 1.0;
301 Float_t padSignal[kNsig];
302 Float_t clusterSignal[kNclus];
303 Float_t clusterPads[kNclus];
304 Int_t clusterDigit[kNclus];
305 Int_t clusterTracks[kNtrack];
308 Int_t chamEnd = AliTRDgeometry::Ncham();
309 if (fTRD->GetSensChamber() >= 0) {
310 chamBeg = fTRD->GetSensChamber();
311 chamEnd = chamBeg + 1;
314 Int_t planEnd = AliTRDgeometry::Nplan();
315 if (fTRD->GetSensPlane() >= 0) {
316 planBeg = fTRD->GetSensPlane();
317 planEnd = planBeg + 1;
320 Int_t sectEnd = AliTRDgeometry::Nsect();
322 // Start clustering in every chamber
323 for (Int_t icham = chamBeg; icham < chamEnd; icham++) {
324 for (Int_t iplan = planBeg; iplan < planEnd; iplan++) {
325 for (Int_t isect = sectBeg; isect < sectEnd; isect++) {
327 if (fTRD->GetSensSector() >= 0) {
328 Int_t sens1 = fTRD->GetSensSector();
329 Int_t sens2 = sens1 + fTRD->GetSensSectorRange();
330 sens2 -= ((Int_t) (sens2 / AliTRDgeometry::Nsect()))
331 * AliTRDgeometry::Nsect();
333 if ((isect < sens1) || (isect >= sens2)) continue;
336 if ((isect < sens1) && (isect >= sens2)) continue;
340 Int_t idet = geo->GetDetector(iplan,icham,isect);
343 Int_t nClusters2pad = 0;
344 Int_t nClusters3pad = 0;
345 Int_t nClusters4pad = 0;
346 Int_t nClusters5pad = 0;
347 Int_t nClustersLarge = 0;
349 printf("AliTRDclusterizerV1::MakeCluster -- ");
350 printf("Analyzing chamber %d, plane %d, sector %d.\n"
353 Int_t nRowMax = geo->GetRowMax(iplan,icham,isect);
354 Int_t nColMax = geo->GetColMax(iplan);
355 Int_t nTimeBefore = geo->GetTimeBefore();
356 Int_t nTimeTotal = geo->GetTimeTotal();
359 digits = fDigitsManager->GetDigits(idet);
361 track0 = fDigitsManager->GetDictionary(idet,0);
363 track1 = fDigitsManager->GetDictionary(idet,1);
365 track2 = fDigitsManager->GetDictionary(idet,2);
368 // Loop through the chamber and find the maxima
369 for ( row = 0; row < nRowMax; row++) {
370 for ( col = 2; col < nColMax; col++) {
371 for (time = 0; time < nTimeTotal; time++) {
373 Int_t signalL = TMath::Abs(digits->GetDataUnchecked(row,col ,time));
374 Int_t signalM = TMath::Abs(digits->GetDataUnchecked(row,col-1,time));
375 Int_t signalR = TMath::Abs(digits->GetDataUnchecked(row,col-2,time));
377 // Look for the maximum
378 if (signalM >= maxThresh) {
379 if (((signalL >= sigThresh) &&
380 (signalL < signalM)) ||
381 ((signalR >= sigThresh) &&
382 (signalR < signalM))) {
383 // Maximum found, mark the position by a negative signal
384 digits->SetDataUnchecked(row,col-1,time,-signalM);
392 // Now check the maxima and calculate the cluster position
393 for ( row = 0; row < nRowMax ; row++) {
394 for (time = 0; time < nTimeTotal; time++) {
395 for ( col = 1; col < nColMax-1; col++) {
398 if (digits->GetDataUnchecked(row,col,time) < 0) {
401 for (iPad = 0; iPad < kNclus; iPad++) {
402 Int_t iPadCol = col - 1 + iPad;
403 clusterSignal[iPad] = TMath::Abs(digits->GetDataUnchecked(row
406 clusterDigit[iPad] = digits->GetIndexUnchecked(row,iPadCol,time);
407 clusterTracks[3*iPad ] = track0->GetDataUnchecked(row,iPadCol,time) - 1;
408 clusterTracks[3*iPad+1] = track1->GetDataUnchecked(row,iPadCol,time) - 1;
409 clusterTracks[3*iPad+2] = track2->GetDataUnchecked(row,iPadCol,time) - 1;
412 // Count the number of pads in the cluster
415 while (TMath::Abs(digits->GetDataUnchecked(row,col-ii ,time))
419 if (col-ii < 0) break;
422 while (TMath::Abs(digits->GetDataUnchecked(row,col+ii+1,time))
426 if (col+ii+1 >= nColMax) break;
453 // Don't analyze large clusters
454 //if (iType == 4) continue;
456 // Look for 5 pad cluster with minimum in the middle
457 Bool_t fivePadCluster = kFALSE;
458 if (col < nColMax-3) {
459 if (digits->GetDataUnchecked(row,col+2,time) < 0) {
460 fivePadCluster = kTRUE;
462 if ((fivePadCluster) && (col < nColMax-5)) {
463 if (digits->GetDataUnchecked(row,col+4,time) >= sigThresh) {
464 fivePadCluster = kFALSE;
467 if ((fivePadCluster) && (col > 1)) {
468 if (digits->GetDataUnchecked(row,col-2,time) >= sigThresh) {
469 fivePadCluster = kFALSE;
475 // Modify the signal of the overlapping pad for the left part
476 // of the cluster which remains from a previous unfolding
478 clusterSignal[0] *= ratioLeft;
483 // Unfold the 5 pad cluster
484 if (fivePadCluster) {
485 for (iPad = 0; iPad < kNsig; iPad++) {
486 padSignal[iPad] = TMath::Abs(digits->GetDataUnchecked(row
490 // Unfold the two maxima and set the signal on
491 // the overlapping pad to the ratio
492 ratioRight = Unfold(kEpsilon,padSignal);
493 ratioLeft = 1.0 - ratioRight;
494 clusterSignal[2] *= ratioRight;
499 Float_t clusterCharge = clusterSignal[0]
503 // The position of the cluster
504 clusterPads[0] = row + 0.5;
505 // Take the shift of the additional time bins into account
506 clusterPads[2] = time - nTimeBefore + 0.5;
510 // Calculate the position of the cluster by using the
511 // lookup table method
515 if (clusterSignal[0] > clusterSignal[2]) {
516 ratioLUT = clusterSignal[0] / clusterSignal[1];
520 ratioLUT = clusterSignal[2] / clusterSignal[1];
523 if (ratioLUT < kLUTmin) {
526 else if (ratioLUT > kLUTmax) {
530 Int_t indexLUT = TMath::Nint ((kNlut-1) * (ratioLUT - kLUTmin)
531 / (kLUTmax - kLUTmin));
532 lut = fLUT[indexLUT];
534 clusterPads[1] = col + 0.5 + signLUT * lut;
539 // Calculate the position of the cluster by using the
540 // center of gravity method
541 clusterPads[1] = col + 0.5
542 + (clusterSignal[2] - clusterSignal[0])
547 Float_t clusterSigmaY2 = (clusterSignal[2] + clusterSignal[0]) / clusterCharge
548 - (clusterPads[1]-col-0.5) * (clusterPads[1]-col-0.5);
550 // Correct for ExB displacement
551 if (digitizer->GetExB()) {
552 Int_t local_time_bin = (Int_t) clusterPads[2];
553 Float_t driftLength = local_time_bin * timeBinSize + kAmWidth;
554 Float_t colSize = geo->GetColPadSize(iplan);
555 Float_t deltaY = omegaTau*driftLength/colSize;
556 clusterPads[1] = clusterPads[1] - deltaY;
560 printf("-----------------------------------------------------------\n");
561 printf("Create cluster no. %d\n",nClusters);
562 printf("Position: row = %f, col = %f, time = %f\n",clusterPads[0]
565 printf("Indices: %d, %d, %d\n",clusterDigit[0]
568 printf("Total charge = %f\n",clusterCharge);
569 printf("Tracks: pad0 %d, %d, %d\n",clusterTracks[0]
572 printf(" pad1 %d, %d, %d\n",clusterTracks[3]
575 printf(" pad2 %d, %d, %d\n",clusterTracks[6]
578 printf("Type = %d, Number of pads = %d\n",iType,nPadCount);
581 // Add the cluster to the output array
582 fTRD->AddCluster(clusterPads
595 // Compress the arrays
596 digits->Compress(1,0);
597 track0->Compress(1,0);
598 track1->Compress(1,0);
599 track2->Compress(1,0);
601 // Write the cluster and reset the array
603 fTRD->ResetRecPoints();
605 printf("AliTRDclusterizerV1::MakeCluster -- ");
606 printf("Found %d clusters in total.\n"
608 printf(" 2pad: %d\n",nClusters2pad);
609 printf(" 3pad: %d\n",nClusters3pad);
610 printf(" 4pad: %d\n",nClusters4pad);
611 printf(" 5pad: %d\n",nClusters5pad);
612 printf(" Large: %d\n",nClustersLarge);
618 printf("AliTRDclusterizerV1::MakeCluster -- ");
625 //_____________________________________________________________________________
626 Float_t AliTRDclusterizerV1::Unfold(Float_t eps, Float_t* padSignal)
629 // Method to unfold neighbouring maxima.
630 // The charge ratio on the overlapping pad is calculated
631 // until there is no more change within the range given by eps.
632 // The resulting ratio is then returned to the calling method.
635 Int_t itStep = 0; // Count iteration steps
637 Float_t ratio = 0.5; // Start value for ratio
638 Float_t prevRatio = 0; // Store previous ratio
640 Float_t newLeftSignal[3] = {0}; // Array to store left cluster signal
641 Float_t newRightSignal[3] = {0}; // Array to store right cluster signal
643 // Start the iteration
644 while ((TMath::Abs(prevRatio - ratio) > eps) && (itStep < 10)) {
649 // Cluster position according to charge ratio
650 Float_t maxLeft = (ratio*padSignal[2] - padSignal[0])
651 / (padSignal[0] + padSignal[1] + ratio*padSignal[2]);
652 Float_t maxRight = (padSignal[4] - (1-ratio)*padSignal[2])
653 / ((1-ratio)*padSignal[2] + padSignal[3] + padSignal[4]);
655 // Set cluster charge ratio
656 Float_t ampLeft = padSignal[1] / PadResponse(0 - maxLeft );
657 Float_t ampRight = padSignal[3] / PadResponse(0 - maxRight);
659 // Apply pad response to parameters
660 newLeftSignal[0] = ampLeft * PadResponse(-1 - maxLeft);
661 newLeftSignal[1] = ampLeft * PadResponse( 0 - maxLeft);
662 newLeftSignal[2] = ampLeft * PadResponse( 1 - maxLeft);
664 newRightSignal[0] = ampRight * PadResponse(-1 - maxRight);
665 newRightSignal[1] = ampRight * PadResponse( 0 - maxRight);
666 newRightSignal[2] = ampRight * PadResponse( 1 - maxRight);
668 // Calculate new overlapping ratio
669 ratio = TMath::Min((Float_t)1.0,newLeftSignal[2] /
670 (newLeftSignal[2] + newRightSignal[0]));
678 //_____________________________________________________________________________
679 Float_t AliTRDclusterizerV1::PadResponse(Float_t x)
682 // The pad response for the chevron pads.
683 // We use a simple Gaussian approximation which should be good
684 // enough for our purpose.
685 // Updated for new PRF 1/5/01.
688 // The parameters for the response function
689 const Float_t kA = 0.8303;
690 const Float_t kB = -0.00392;
691 const Float_t kC = 0.472 * 0.472;
692 const Float_t kD = 2.19;
694 Float_t pr = kA * (kB + TMath::Exp(-TMath::Power(x*x,kD) / (2.*kC)));