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 // TRD cluster finder for the slow simulator.
22 ///////////////////////////////////////////////////////////////////////////////
30 #include "AliRunLoader.h"
31 #include "AliLoader.h"
33 #include "AliTRDclusterizerMI.h"
34 #include "AliTRDmatrix.h"
35 #include "AliTRDgeometry.h"
36 #include "AliTRDdataArrayF.h"
37 #include "AliTRDdataArrayI.h"
38 #include "AliTRDdigitsManager.h"
39 #include "AliTRDparameter.h"
40 #include "AliTRDclusterMI.h"
42 ClassImp(AliTRDclusterizerMI)
44 //_____________________________________________________________________________
45 AliTRDclusterizerMI::AliTRDclusterizerMI():AliTRDclusterizerV1()
48 // AliTRDclusterizerMI default constructor
52 //_____________________________________________________________________________
53 AliTRDclusterizerMI::AliTRDclusterizerMI(const Text_t* name, const Text_t* title)
54 :AliTRDclusterizerV1(name,title)
57 // AliTRDclusterizerMI default constructor
61 //_____________________________________________________________________________
62 AliTRDclusterizerMI::~AliTRDclusterizerMI()
65 // AliTRDclusterizerMI destructor
70 AliTRDclusterMI * AliTRDclusterizerMI::AddCluster()
72 AliTRDclusterMI *c = new AliTRDclusterMI();
73 fClusterContainer->Add(c);
77 void AliTRDclusterizerMI::SetCluster(AliTRDclusterMI * cl,Float_t *pos, Int_t det, Float_t amp
78 ,Int_t *tracks, Float_t *sig, Int_t iType, Float_t sigmay, Float_t relpad)
84 cl->AddTrackIndex(tracks);
88 cl->SetSigmaY2(sig[0]);
89 cl->SetSigmaZ2(sig[1]);
90 cl->SetLocalTimeBin(((Int_t) pos[2]));
92 cl->SetRelPos(relpad);
96 void AliTRDclusterizerMI::MakeCluster(Float_t * padSignal, Float_t * pos, Float_t &sigma, Float_t & relpad)
103 Float_t signal[3]={padSignal[0],padSignal[1],padSignal[2]};
105 signal[0] = 0.015*(signal[1]*signal[1])/(signal[2]+0.5);
106 if (signal[0]>2) signal[0]=2;
109 signal[2] = 0.015*(signal[1]*signal[1])/(signal[0]+0.5);
110 if (signal[2]>2) signal[2]=2;
113 for (Int_t i=-1;i<=1;i++){
115 sumx +=signal[i+1]*float(i);
116 sumx2 +=signal[i+1]*float(i)*float(i);
120 sigma = sumx2/sum-pos[0]*pos[0];
124 //_____________________________________________________________________________
125 Bool_t AliTRDclusterizerMI::MakeClusters()
128 // Generates the cluster.
131 //////////////////////
132 //STUPIDITY to be fixed later
133 fClusterContainer = RecPoints();
135 Int_t row, col, time;
138 if (fTRD->IsVersion() != 1) {
139 printf("<AliTRDclusterizerMI::MakeCluster> ");
140 printf("TRD must be version 1 (slow simulator).\n");
146 AliTRDgeometry *geo = AliTRDgeometry::GetGeometry(fRunLoader);
148 // Create a default parameter class if none is defined
150 fPar = new AliTRDparameter("TRDparameter","Standard TRD parameter");
151 printf("<AliTRDclusterizerMI::MakeCluster> ");
152 printf("Create the default parameter object.\n");
155 Float_t timeBinSize = fPar->GetTimeBinSize();
156 // Half of ampl.region
157 const Float_t kAmWidth = AliTRDgeometry::AmThick()/2.;
159 Float_t omegaTau = fPar->GetOmegaTau();
161 printf("<AliTRDclusterizerMI::MakeCluster> ");
162 printf("OmegaTau = %f \n",omegaTau);
163 printf("<AliTRDclusterizerMI::MakeCluster> ");
164 printf("Start creating clusters.\n");
167 AliTRDdataArrayI *digits;
168 AliTRDdataArrayI *track0;
169 AliTRDdataArrayI *track1;
170 AliTRDdataArrayI *track2;
172 // Threshold value for the maximum
173 Int_t maxThresh = fPar->GetClusMaxThresh();
174 // Threshold value for the digit signal
175 Int_t sigThresh = fPar->GetClusSigThresh();
177 // Iteration limit for unfolding procedure
178 const Float_t kEpsilon = 0.01;
180 const Int_t kNclus = 3;
181 const Int_t kNsig = 5;
182 const Int_t kNtrack = 3 * kNclus;
187 Float_t ratioLeft = 1.0;
188 Float_t ratioRight = 1.0;
190 Float_t padSignal[kNsig];
191 Float_t clusterSignal[kNclus];
192 Float_t clusterPads[kNclus];
193 Int_t clusterDigit[kNclus];
194 Int_t clusterTracks[kNtrack];
197 Int_t chamEnd = AliTRDgeometry::Ncham();
199 Int_t planEnd = AliTRDgeometry::Nplan();
201 Int_t sectEnd = AliTRDgeometry::Nsect();
203 // Start clustering in every chamber
204 for (Int_t icham = chamBeg; icham < chamEnd; icham++) {
205 for (Int_t iplan = planBeg; iplan < planEnd; iplan++) {
206 for (Int_t isect = sectBeg; isect < sectEnd; isect++) {
208 Int_t idet = geo->GetDetector(iplan,icham,isect);
211 Int_t nClusters2pad = 0;
212 Int_t nClusters3pad = 0;
213 Int_t nClusters4pad = 0;
214 Int_t nClusters5pad = 0;
215 Int_t nClustersLarge = 0;
218 printf("<AliTRDclusterizerMI::MakeCluster> ");
219 printf("Analyzing chamber %d, plane %d, sector %d.\n"
223 Int_t nRowMax = fPar->GetRowMax(iplan,icham,isect);
224 Int_t nColMax = fPar->GetColMax(iplan);
225 Int_t nTimeBefore = fPar->GetTimeBefore();
226 Int_t nTimeTotal = fPar->GetTimeTotal();
228 Float_t row0 = fPar->GetRow0(iplan,icham,isect);
229 Float_t col0 = fPar->GetCol0(iplan);
230 Float_t rowSize = fPar->GetRowPadSize(iplan,icham,isect);
231 Float_t colSize = fPar->GetColPadSize(iplan);
234 digits = fDigitsManager->GetDigits(idet);
236 track0 = fDigitsManager->GetDictionary(idet,0);
238 track1 = fDigitsManager->GetDictionary(idet,1);
240 track2 = fDigitsManager->GetDictionary(idet,2);
243 // Loop through the chamber and find the maxima
244 for ( row = 0; row < nRowMax; row++) {
245 for ( col = 2; col < nColMax; col++) {
246 for (time = 0; time < nTimeTotal; time++) {
248 Int_t signalL = TMath::Abs(digits->GetDataUnchecked(row,col ,time));
249 Int_t signalM = TMath::Abs(digits->GetDataUnchecked(row,col-1,time));
250 Int_t signalR = TMath::Abs(digits->GetDataUnchecked(row,col-2,time));
252 // Look for the maximum
253 if (signalM >= maxThresh) {
254 if (((signalL >= sigThresh) &&
255 (signalL < signalM)) ||
256 ((signalR >= sigThresh) &&
257 (signalR < signalM))) {
258 // Maximum found, mark the position by a negative signal
259 digits->SetDataUnchecked(row,col-1,time,-signalM);
267 // Now check the maxima and calculate the cluster position
268 for ( row = 0; row < nRowMax ; row++) {
269 for (time = 0; time < nTimeTotal; time++) {
270 for ( col = 1; col < nColMax-1; col++) {
273 if (digits->GetDataUnchecked(row,col,time) < 0) {
276 for (iPad = 0; iPad < kNclus; iPad++) {
277 Int_t iPadCol = col - 1 + iPad;
278 clusterSignal[iPad] = TMath::Abs(digits->GetDataUnchecked(row
281 clusterDigit[iPad] = digits->GetIndexUnchecked(row,iPadCol,time);
282 clusterTracks[3*iPad ] = track0->GetDataUnchecked(row,iPadCol,time) - 1;
283 clusterTracks[3*iPad+1] = track1->GetDataUnchecked(row,iPadCol,time) - 1;
284 clusterTracks[3*iPad+2] = track2->GetDataUnchecked(row,iPadCol,time) - 1;
287 // Count the number of pads in the cluster
290 while (TMath::Abs(digits->GetDataUnchecked(row,col-ii ,time))
294 if (col-ii < 0) break;
297 while (TMath::Abs(digits->GetDataUnchecked(row,col+ii+1,time))
301 if (col+ii+1 >= nColMax) break;
328 // Don't analyze large clusters
329 //if (iType == 4) continue;
331 // Look for 5 pad cluster with minimum in the middle
332 Bool_t fivePadCluster = kFALSE;
333 if (col < nColMax-3) {
334 if (digits->GetDataUnchecked(row,col+2,time) < 0) {
335 fivePadCluster = kTRUE;
337 if ((fivePadCluster) && (col < nColMax-5)) {
338 if (digits->GetDataUnchecked(row,col+4,time) >= sigThresh) {
339 fivePadCluster = kFALSE;
342 if ((fivePadCluster) && (col > 1)) {
343 if (digits->GetDataUnchecked(row,col-2,time) >= sigThresh) {
344 fivePadCluster = kFALSE;
350 // Modify the signal of the overlapping pad for the left part
351 // of the cluster which remains from a previous unfolding
353 clusterSignal[0] *= ratioLeft;
358 // Unfold the 5 pad cluster
359 if (fivePadCluster) {
360 for (iPad = 0; iPad < kNsig; iPad++) {
361 padSignal[iPad] = TMath::Abs(digits->GetDataUnchecked(row
365 // Unfold the two maxima and set the signal on
366 // the overlapping pad to the ratio
367 ratioRight = Unfold(kEpsilon,iplan,padSignal);
368 ratioLeft = 1.0 - ratioRight;
369 clusterSignal[2] *= ratioRight;
374 Float_t clusterCharge = clusterSignal[0]
378 // The position of the cluster
379 clusterPads[0] = row + 0.5;
380 // Take the shift of the additional time bins into account
381 clusterPads[2] = time - nTimeBefore + 0.5;
385 // Calculate the position of the cluster by using the
386 // lookup table method
387 clusterPads[1] = col + 0.5
388 + fPar->LUTposition(iplan,clusterSignal[0]
395 // Calculate the position of the cluster by using the
396 // center of gravity method
397 clusterPads[1] = col + 0.5
398 + (clusterSignal[2] - clusterSignal[0])
403 Float_t q0 = clusterSignal[0];
404 Float_t q1 = clusterSignal[1];
405 Float_t q2 = clusterSignal[2];
406 Float_t clusterSigmaY2 = (q1*(q0+q2)+4*q0*q2) /
407 (clusterCharge*clusterCharge);
409 // Correct for ExB displacement
411 Int_t local_time_bin = (Int_t) clusterPads[2];
412 Float_t driftLength = local_time_bin * timeBinSize + kAmWidth;
413 Float_t colSize = fPar->GetColPadSize(iplan);
414 Float_t deltaY = omegaTau*driftLength/colSize;
415 clusterPads[1] = clusterPads[1] - deltaY;
419 // Calculate the position and the error
420 Float_t clusterPos[3];
421 clusterPos[0] = clusterPads[1] * colSize + col0;
422 clusterPos[1] = clusterPads[0] * rowSize + row0;
423 clusterPos[2] = clusterPads[2];
424 Float_t clusterSig[2];
425 clusterSig[0] = (clusterSigmaY2 + 1./12.) * colSize*colSize;
426 clusterSig[1] = rowSize * rowSize / 12.;
429 AliTRDclusterMI * cluster = AddCluster();
430 Float_t sigma, relpos;
431 MakeCluster(clusterSignal, clusterPos, sigma,relpos);
433 clusterPos[0] = clusterPads[1] * colSize + col0;
434 clusterPos[1] = clusterPads[0] * rowSize + row0;
435 clusterPos[2] = clusterPads[2];
436 SetCluster(cluster, clusterPos,idet,clusterCharge,clusterTracks,clusterSig,iType,sigma,relpos);
437 // Add the cluster to the output array
438 // fTRD->AddCluster(clusterPos
450 // Compress the arrays
451 digits->Compress(1,0);
452 track0->Compress(1,0);
453 track1->Compress(1,0);
454 track2->Compress(1,0);
456 // Write the cluster and reset the array
461 printf("<AliTRDclusterizerMI::MakeCluster> ");
462 printf("Found %d clusters in total.\n"
464 printf(" 2pad: %d\n",nClusters2pad);
465 printf(" 3pad: %d\n",nClusters3pad);
466 printf(" 4pad: %d\n",nClusters4pad);
467 printf(" 5pad: %d\n",nClusters5pad);
468 printf(" Large: %d\n",nClustersLarge);
476 printf("<AliTRDclusterizerMI::MakeCluster> ");
484 //_____________________________________________________________________________
485 Float_t AliTRDclusterizerMI::Unfold(Float_t eps, Int_t plane, Float_t* padSignal)
488 // Method to unfold neighbouring maxima.
489 // The charge ratio on the overlapping pad is calculated
490 // until there is no more change within the range given by eps.
491 // The resulting ratio is then returned to the calling method.
495 Int_t itStep = 0; // Count iteration steps
497 Float_t ratio = 0.5; // Start value for ratio
498 Float_t prevRatio = 0; // Store previous ratio
500 Float_t newLeftSignal[3] = {0}; // Array to store left cluster signal
501 Float_t newRightSignal[3] = {0}; // Array to store right cluster signal
502 Float_t newSignal[3] = {0};
504 // Start the iteration
505 while ((TMath::Abs(prevRatio - ratio) > eps) && (itStep < 10)) {
510 // Cluster position according to charge ratio
511 Float_t maxLeft = (ratio*padSignal[2] - padSignal[0])
512 / (padSignal[0] + padSignal[1] + ratio*padSignal[2]);
513 Float_t maxRight = (padSignal[4] - (1-ratio)*padSignal[2])
514 / ((1-ratio)*padSignal[2] + padSignal[3] + padSignal[4]);
516 // Set cluster charge ratio
517 irc = fPar->PadResponse(1.0,maxLeft ,plane,newSignal);
518 Float_t ampLeft = padSignal[1] / newSignal[1];
519 irc = fPar->PadResponse(1.0,maxRight,plane,newSignal);
520 Float_t ampRight = padSignal[3] / newSignal[1];
522 // Apply pad response to parameters
523 irc = fPar->PadResponse(ampLeft ,maxLeft ,plane,newLeftSignal );
524 irc = fPar->PadResponse(ampRight,maxRight,plane,newRightSignal);
526 // Calculate new overlapping ratio
527 ratio = TMath::Min((Float_t)1.0,newLeftSignal[2] /
528 (newLeftSignal[2] + newRightSignal[0]));