2 /**************************************************************************
3 * Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
5 * Author: The ALICE Off-line Project. *
6 * Contributors are mentioned in the code where appropriate. *
8 * Permission to use, copy, modify and distribute this software and its *
9 * documentation strictly for non-commercial purposes is hereby granted *
10 * without fee, provided that the above copyright notice appears in all *
11 * copies and that both the copyright notice and this permission notice *
12 * appear in the supporting documentation. The authors make no claims *
13 * about the suitability of this software for any purpose. It is *
14 * provided "as is" without express or implied warranty. *
15 **************************************************************************/
19 ///////////////////////////////////////////////////////////////////////////////
21 // TRD cluster finder //
23 ///////////////////////////////////////////////////////////////////////////////
30 #include "AliRunLoader.h"
31 #include "AliLoader.h"
32 #include "AliRawReader.h"
34 #include "AliAlignObj.h"
36 #include "AliTRDclusterizerV2.h"
37 #include "AliTRDgeometry.h"
38 #include "AliTRDdataArrayF.h"
39 #include "AliTRDdataArrayI.h"
40 #include "AliTRDdigitsManager.h"
41 #include "AliTRDrawData.h"
42 #include "AliTRDcalibDB.h"
43 #include "AliTRDSimParam.h"
44 #include "AliTRDRecParam.h"
45 #include "AliTRDcluster.h"
46 #include "AliTRDtransform.h"
47 #include "AliTRDSignalIndex.h"
48 #include "AliTRDRawStream.h"
49 #include "AliTRDRawStreamV2.h"
50 #include "AliTRDfeeParam.h"
52 #include "Cal/AliTRDCalROC.h"
53 #include "Cal/AliTRDCalDet.h"
55 ClassImp(AliTRDclusterizerV2)
57 //_____________________________________________________________________________
58 AliTRDclusterizerV2::AliTRDclusterizerV2()
68 // AliTRDclusterizerV2 default constructor
71 fRawVersion = AliTRDfeeParam::Instance()->GetRAWversion();
75 //_____________________________________________________________________________
76 AliTRDclusterizerV2::AliTRDclusterizerV2(const Text_t *name, const Text_t *title)
77 :AliTRDclusterizer(name,title)
78 ,fDigitsManager(new AliTRDdigitsManager())
83 ,fTransform(new AliTRDtransform(0))
86 // AliTRDclusterizerV2 constructor
89 fDigitsManager->CreateArrays();
91 fRawVersion = AliTRDfeeParam::Instance()->GetRAWversion();
95 //_____________________________________________________________________________
96 AliTRDclusterizerV2::AliTRDclusterizerV2(const AliTRDclusterizerV2 &c)
102 ,fIndexesMaxima(NULL)
106 // AliTRDclusterizerV2 copy constructor
111 //_____________________________________________________________________________
112 AliTRDclusterizerV2::~AliTRDclusterizerV2()
115 // AliTRDclusterizerV2 destructor
120 delete fDigitsManager;
121 fDigitsManager = NULL;
132 delete fIndexesMaxima;
133 fIndexesMaxima = NULL;
144 //_____________________________________________________________________________
145 AliTRDclusterizerV2 &AliTRDclusterizerV2::operator=(const AliTRDclusterizerV2 &c)
148 // Assignment operator
151 if (this != &c) ((AliTRDclusterizerV2 &) c).Copy(*this);
156 //_____________________________________________________________________________
157 void AliTRDclusterizerV2::Copy(TObject &c) const
163 ((AliTRDclusterizerV2 &) c).fDigitsManager = NULL;
164 ((AliTRDclusterizerV2 &) c).fAddLabels = fAddLabels;
165 ((AliTRDclusterizerV2 &) c).fRawVersion = fRawVersion;
166 ((AliTRDclusterizerV2 &) c).fIndexesOut = NULL;
167 ((AliTRDclusterizerV2 &) c).fIndexesMaxima = NULL;
168 ((AliTRDclusterizerV2 &) c).fTransform = NULL;
170 AliTRDclusterizer::Copy(c);
174 //_____________________________________________________________________________
175 void AliTRDclusterizerV2::ResetHelperIndexes(AliTRDSignalIndex *indexesIn)
178 // Reset the helper indexes
183 // carefull here - we assume that only row number may change - most probable
184 if (indexesIn->GetNrow() <= fIndexesOut->GetNrow())
185 fIndexesOut->ResetContent();
187 fIndexesOut->ResetContentConditional(indexesIn->GetNrow()
188 , indexesIn->GetNcol()
189 , indexesIn->GetNtime());
193 fIndexesOut = new AliTRDSignalIndex(indexesIn->GetNrow()
194 , indexesIn->GetNcol()
195 , indexesIn->GetNtime());
200 // carefull here - we assume that only row number may change - most probable
201 if (indexesIn->GetNrow() <= fIndexesMaxima->GetNrow())
203 fIndexesMaxima->ResetContent();
207 fIndexesMaxima->ResetContentConditional(indexesIn->GetNrow()
208 , indexesIn->GetNcol()
209 , indexesIn->GetNtime());
214 fIndexesMaxima = new AliTRDSignalIndex(indexesIn->GetNrow()
215 , indexesIn->GetNcol()
216 , indexesIn->GetNtime());
221 //_____________________________________________________________________________
222 Bool_t AliTRDclusterizerV2::ReadDigits()
225 // Reads the digits arrays from the input aliroot file
229 AliError("No run loader available");
233 AliLoader* loader = fRunLoader->GetLoader("TRDLoader");
234 if (!loader->TreeD()) {
235 loader->LoadDigits();
238 // Read in the digit arrays
239 return (fDigitsManager->ReadDigits(loader->TreeD()));
243 //_____________________________________________________________________________
244 Bool_t AliTRDclusterizerV2::ReadDigits(TTree *digitsTree)
247 // Reads the digits arrays from the input tree
250 // Read in the digit arrays
251 return (fDigitsManager->ReadDigits(digitsTree));
255 //_____________________________________________________________________________
256 Bool_t AliTRDclusterizerV2::ReadDigits(AliRawReader *rawReader)
259 // Reads the digits arrays from the ddl file
263 fDigitsManager = raw.Raw2Digits(rawReader);
269 //_____________________________________________________________________________
270 Bool_t AliTRDclusterizerV2::MakeClusters()
273 // Creates clusters from digits
276 // Propagate info from the digits manager
277 if (fAddLabels == kTRUE)
279 fAddLabels = fDigitsManager->UsesDictionaries();
282 Bool_t fReturn = kTRUE;
283 for (Int_t i = 0; i < AliTRDgeometry::kNdet; i++)
286 AliTRDdataArrayI *digitsIn = fDigitsManager->GetDigits(i);
287 // This is to take care of switched off super modules
288 if (digitsIn->GetNtime() == 0)
293 AliTRDSignalIndex* indexes = fDigitsManager->GetIndexes(i);
294 if (indexes->IsAllocated() == kFALSE)
296 fDigitsManager->BuildIndexes(i);
300 if (indexes->HasEntry())
304 for (Int_t iDict = 0; iDict < AliTRDdigitsManager::kNDict; iDict++)
306 AliTRDdataArrayI *tracksIn = 0;
307 tracksIn = fDigitsManager->GetDictionary(i,iDict);
311 fR = MakeClusters(i);
312 fReturn = fR && fReturn;
321 // No compress just remove
322 fDigitsManager->RemoveDigits(i);
323 fDigitsManager->RemoveDictionaries(i);
324 fDigitsManager->ClearIndexes(i);
332 //_____________________________________________________________________________
333 Bool_t AliTRDclusterizerV2::Raw2Clusters(AliRawReader *rawReader)
336 // Creates clusters from raw data
339 AliTRDdataArrayI *digits = 0;
340 AliTRDdataArrayI *track0 = 0;
341 AliTRDdataArrayI *track1 = 0;
342 AliTRDdataArrayI *track2 = 0;
344 AliTRDSignalIndex *indexes = 0;
346 // Create the digits manager
349 fDigitsManager = new AliTRDdigitsManager();
350 fDigitsManager->CreateArrays();
353 AliTRDRawStreamV2 input(rawReader);
354 input.SetRawVersion( fRawVersion );
357 AliInfo(Form("Stream version: %s", input.IsA()->GetName()));
359 // Loop through the digits
366 det = input.GetDet();
373 digits = fDigitsManager->GetDigits(lastdet);
374 Bool_t iclusterBranch = kFALSE;
375 if (indexes->HasEntry())
376 iclusterBranch = MakeClusters(lastdet);
377 if (iclusterBranch == kFALSE)
379 WriteClusters(lastdet);
386 fDigitsManager->RemoveDigits(lastdet);
387 fDigitsManager->RemoveDictionaries(lastdet);
388 fDigitsManager->ClearIndexes(lastdet);
393 // Add a container for the digits of this detector
394 digits = fDigitsManager->GetDigits(det);
395 track0 = fDigitsManager->GetDictionary(det,0);
396 track1 = fDigitsManager->GetDictionary(det,1);
397 track2 = fDigitsManager->GetDictionary(det,2);
399 // Allocate memory space for the digits buffer
400 if (digits->GetNtime() == 0)
402 //AliDebug(5, Form("Alloc digits for det %d", det));
403 digits->Allocate(input.GetMaxRow(),input.GetMaxCol(), input.GetNumberOfTimeBins());
404 track0->Allocate(input.GetMaxRow(),input.GetMaxCol(), input.GetNumberOfTimeBins());
405 track1->Allocate(input.GetMaxRow(),input.GetMaxCol(), input.GetNumberOfTimeBins());
406 track2->Allocate(input.GetMaxRow(),input.GetMaxCol(), input.GetNumberOfTimeBins());
409 indexes = fDigitsManager->GetIndexes(det);
410 indexes->SetSM(input.GetSM());
411 indexes->SetStack(input.GetStack());
412 indexes->SetLayer(input.GetLayer());
413 indexes->SetDetNumber(det);
414 if (indexes->IsAllocated() == kFALSE)
416 indexes->Allocate(input.GetMaxRow(), input.GetMaxCol(), input.GetNumberOfTimeBins());
421 for (it = 0; it < 3; it++)
423 if ( input.GetTimeBin() + it < input.GetNumberOfTimeBins() )
425 if (input.GetSignals()[it] > 0)
427 digits->SetDataUnchecked(input.GetRow(), input.GetCol(),
428 input.GetTimeBin() + it, input.GetSignals()[it]);
430 indexes->AddIndexTBin(input.GetRow(), input.GetCol(),
431 input.GetTimeBin() + it);
432 track0->SetDataUnchecked(input.GetRow(), input.GetCol(),
433 input.GetTimeBin() + it, 0);
434 track1->SetDataUnchecked(input.GetRow(), input.GetCol(),
435 input.GetTimeBin() + it, 0);
436 track2->SetDataUnchecked(input.GetRow(), input.GetCol(),
437 input.GetTimeBin() + it, 0);
446 Bool_t iclusterBranch = kFALSE;
447 if (indexes->HasEntry())
449 iclusterBranch = MakeClusters(lastdet);
451 if (iclusterBranch == kFALSE)
453 WriteClusters(lastdet);
456 //MakeClusters(lastdet);
459 fDigitsManager->RemoveDigits(lastdet);
460 fDigitsManager->RemoveDictionaries(lastdet);
461 fDigitsManager->ClearIndexes(lastdet);
465 delete fDigitsManager;
466 fDigitsManager = NULL;
471 //_____________________________________________________________________________
472 Bool_t AliTRDclusterizerV2::Raw2ClustersChamber(AliRawReader *rawReader)
475 // Creates clusters from raw data
478 // Create the digits manager
481 fDigitsManager = new AliTRDdigitsManager();
482 fDigitsManager->CreateArrays();
485 fDigitsManager->SetUseDictionaries(fAddLabels);
487 AliTRDRawStreamV2 input(rawReader);
488 input.SetRawVersion( fRawVersion );
491 AliInfo(Form("Stream version: %s", input.IsA()->GetName()));
494 while ((det = input.NextChamber(fDigitsManager)) >= 0)
496 Bool_t iclusterBranch = kFALSE;
497 if (fDigitsManager->GetIndexes(det)->HasEntry())
499 iclusterBranch = MakeClusters(det);
501 if (iclusterBranch == kFALSE)
506 fDigitsManager->RemoveDigits(det);
507 fDigitsManager->RemoveDictionaries(det);
508 fDigitsManager->ClearIndexes(det);
511 delete fDigitsManager;
512 fDigitsManager = NULL;
517 //_____________________________________________________________________________
518 Bool_t AliTRDclusterizerV2::MakeClusters(Int_t det)
521 // Generates the cluster.
525 // digits should be expanded beforehand!
526 // digitsIn->Expand();
527 AliTRDdataArrayI *digitsIn = fDigitsManager->GetDigits(det);
529 // This is to take care of switched off super modules
530 if (digitsIn->GetNtime() == 0)
535 AliTRDSignalIndex *indexesIn = fDigitsManager->GetIndexes(det);
536 if (indexesIn->IsAllocated() == kFALSE)
538 AliError("Indexes do not exist!");
542 AliTRDcalibDB *calibration = AliTRDcalibDB::Instance();
545 AliFatal("No AliTRDcalibDB instance available\n");
549 AliTRDRecParam *recParam = AliTRDRecParam::Instance();
552 AliError("No AliTRDRecParam instance available\n");
557 // There is no ADC threshold anymore, and simParam should not be used in clusterizer. KO
558 Float_t ADCthreshold = 0;
560 // Threshold value for the maximum
561 Float_t maxThresh = recParam->GetClusMaxThresh();
562 // Threshold value for the digit signal
563 Float_t sigThresh = recParam->GetClusSigThresh();
565 // Iteration limit for unfolding procedure
566 const Float_t kEpsilon = 0.01;
567 const Int_t kNclus = 3;
568 const Int_t kNsig = 5;
571 Double_t ratioLeft = 1.0;
572 Double_t ratioRight = 1.0;
574 Double_t padSignal[kNsig];
575 Double_t clusterSignal[kNclus];
577 Int_t icham = indexesIn->GetChamber();
578 Int_t iplan = indexesIn->GetPlane();
579 Int_t isect = indexesIn->GetSM();
581 // Start clustering in the chamber
583 Int_t idet = AliTRDgeometry::GetDetector(iplan,icham,isect);
586 AliError("Strange Detector number Missmatch!");
590 // TRD space point transformation
591 fTransform->SetDetector(det);
593 Int_t ilayer = AliGeomManager::kTRD1 + iplan;
594 Int_t imodule = icham + AliTRDgeometry::Ncham() * isect;
595 UShort_t volid = AliGeomManager::LayerToVolUID(ilayer,imodule);
597 Int_t nColMax = digitsIn->GetNcol();
598 Int_t nTimeTotal = digitsIn->GetNtime();
600 // Detector wise calibration object for the gain factors
601 const AliTRDCalDet *calGainFactorDet = calibration->GetGainFactorDet();
602 // Calibration object with pad wise values for the gain factors
603 AliTRDCalROC *calGainFactorROC = calibration->GetGainFactorROC(idet);
604 // Calibration value for chamber wise gain factor
605 Float_t calGainFactorDetValue = calGainFactorDet->GetValue(idet);
609 AliTRDdataArrayF *digitsOut = new AliTRDdataArrayF(digitsIn->GetNrow()
611 ,digitsIn->GetNtime());
613 ResetHelperIndexes(indexesIn);
615 // Apply the gain and the tail cancelation via digital filter
616 TailCancelation(digitsIn
623 ,calGainFactorDetValue);
630 fIndexesOut->ResetCounters();
631 while (fIndexesOut->NextRCTbinIndex(row, col, time))
634 Float_t signalM = TMath::Abs(digitsOut->GetDataUnchecked(row,col,time));
636 // Look for the maximum
637 if (signalM >= maxThresh)
640 if (col + 1 >= nColMax || col-1 < 0)
643 Float_t signalL = TMath::Abs(digitsOut->GetDataUnchecked(row,col+1,time));
644 Float_t signalR = TMath::Abs(digitsOut->GetDataUnchecked(row,col-1,time));
646 if ((TMath::Abs(signalL) <= signalM) &&
647 (TMath::Abs(signalR) < signalM))
649 if ((TMath::Abs(signalL) >= sigThresh) ||
650 (TMath::Abs(signalR) >= sigThresh))
652 // Maximum found, mark the position by a negative signal
653 digitsOut->SetDataUnchecked(row,col,time,-signalM);
654 fIndexesMaxima->AddIndexTBin(row,col,time);
662 // The index to the first cluster of a given ROC
663 Int_t firstClusterROC = -1;
664 // The number of cluster in a given ROC
665 Int_t nClusterROC = 0;
667 // Now check the maxima and calculate the cluster position
668 fIndexesMaxima->ResetCounters();
669 while (fIndexesMaxima->NextRCTbinIndex(row, col, time))
673 if (digitsOut->GetDataUnchecked(row,col,time) < 0.0)
676 for (iPad = 0; iPad < kNclus; iPad++)
678 Int_t iPadCol = col - 1 + iPad;
679 clusterSignal[iPad] = TMath::Abs(digitsOut->GetDataUnchecked(row,iPadCol,time));
682 // Count the number of pads in the cluster
687 while (TMath::Abs(digitsOut->GetDataUnchecked(row,col-ii ,time)) >= sigThresh)
691 if (col-ii < 0) break;
695 while (TMath::Abs(digitsOut->GetDataUnchecked(row,col+ii+1,time)) >= sigThresh)
699 if (col+ii+1 >= nColMax) break;
703 // Look for 5 pad cluster with minimum in the middle
704 Bool_t fivePadCluster = kFALSE;
705 if (col < (nColMax - 3))
707 if (digitsOut->GetDataUnchecked(row,col+2,time) < 0)
709 fivePadCluster = kTRUE;
711 if ((fivePadCluster) && (col < (nColMax - 5)))
713 if (digitsOut->GetDataUnchecked(row,col+4,time) >= sigThresh)
715 fivePadCluster = kFALSE;
718 if ((fivePadCluster) && (col > 1))
720 if (digitsOut->GetDataUnchecked(row,col-2,time) >= sigThresh)
722 fivePadCluster = kFALSE;
728 // Modify the signal of the overlapping pad for the left part
729 // of the cluster which remains from a previous unfolding
732 clusterSignal[0] *= ratioLeft;
736 // Unfold the 5 pad cluster
739 for (iPad = 0; iPad < kNsig; iPad++)
741 padSignal[iPad] = TMath::Abs(digitsOut->GetDataUnchecked(row
745 // Unfold the two maxima and set the signal on
746 // the overlapping pad to the ratio
747 ratioRight = Unfold(kEpsilon,iplan,padSignal);
748 ratioLeft = 1.0 - ratioRight;
749 clusterSignal[2] *= ratioRight;
753 // The position of the cluster in COL direction relative to the center pad (pad units)
754 Double_t clusterPosCol = 0.0;
755 if (recParam->LUTOn())
757 // Calculate the position of the cluster by using the
758 // lookup table method
759 clusterPosCol = recParam->LUTposition(iplan
766 // Calculate the position of the cluster by using the
767 // center of gravity method
768 for (Int_t i = 0; i < kNsig; i++)
772 padSignal[2] = TMath::Abs(digitsOut->GetDataUnchecked(row,col ,time)); // Central pad
773 padSignal[1] = TMath::Abs(digitsOut->GetDataUnchecked(row,col-1,time)); // Left pad
774 padSignal[3] = TMath::Abs(digitsOut->GetDataUnchecked(row,col+1,time)); // Right pad
776 (TMath::Abs(digitsOut->GetDataUnchecked(row,col-2,time)) < padSignal[1]))
778 padSignal[0] = TMath::Abs(digitsOut->GetDataUnchecked(row,col-2,time));
780 if ((col < nColMax - 3) &&
781 (TMath::Abs(digitsOut->GetDataUnchecked(row,col+2,time)) < padSignal[3]))
783 padSignal[4] = TMath::Abs(digitsOut->GetDataUnchecked(row,col+2,time));
785 clusterPosCol = GetCOG(padSignal);
788 // Store the amplitudes of the pads in the cluster for later analysis
789 Short_t signals[7] = { 0, 0, 0, 0, 0, 0, 0 };
790 for (Int_t jPad = col-3; jPad <= col+3; jPad++)
797 signals[jPad-col+3] = TMath::Nint(TMath::Abs(digitsOut->GetDataUnchecked(row,jPad,time)));
800 // Transform the local cluster coordinates into calibrated
801 // space point positions defined in the local tracking system.
802 // Here the calibration for T0, Vdrift and ExB is applied as well.
803 Double_t clusterXYZ[6];
804 clusterXYZ[0] = clusterPosCol;
805 clusterXYZ[1] = clusterSignal[0];
806 clusterXYZ[2] = clusterSignal[1];
807 clusterXYZ[3] = clusterSignal[2];
814 fTransform->Transform(clusterXYZ,clusterRCT,((UInt_t) time),0);
816 // Add the cluster to the output array
817 // The track indices will be stored later
818 Float_t clusterPos[3];
819 clusterPos[0] = clusterXYZ[0];
820 clusterPos[1] = clusterXYZ[1];
821 clusterPos[2] = clusterXYZ[2];
822 Float_t clusterSig[2];
823 clusterSig[0] = clusterXYZ[4];
824 clusterSig[1] = clusterXYZ[5];
825 Double_t clusterCharge = clusterXYZ[3];
826 Char_t clusterTimeBin = ((Char_t) clusterRCT[2]);
827 AliTRDcluster *cluster = new AliTRDcluster(idet
832 ,((Char_t) nPadCount)
841 // Temporarily store the row, column and time bin of the center pad
842 // Used to later on assign the track indices
843 cluster->SetLabel( row,0);
844 cluster->SetLabel( col,1);
845 cluster->SetLabel(time,2);
847 RecPoints()->Add(cluster);
849 // Store the index of the first cluster in the current ROC
850 if (firstClusterROC < 0)
852 firstClusterROC = RecPoints()->GetEntriesFast() - 1;
855 // Count the number of cluster in the current ROC
858 } // if: Maximum found ?
866 AddLabels(idet, firstClusterROC, nClusterROC);
869 // Write the cluster and reset the array
877 //_____________________________________________________________________________
878 Bool_t AliTRDclusterizerV2::AddLabels(Int_t idet, Int_t firstClusterROC, Int_t nClusterROC)
881 // Add the track indices to the found clusters
884 const Int_t kNclus = 3;
885 const Int_t kNdict = AliTRDdigitsManager::kNDict;
886 const Int_t kNtrack = kNdict * kNclus;
888 Int_t iClusterROC = 0;
895 // Temporary array to collect the track indices
896 Int_t *idxTracks = new Int_t[kNtrack*nClusterROC];
898 // Loop through the dictionary arrays one-by-one
899 // to keep memory consumption low
900 AliTRDdataArrayI *tracksIn = 0;
901 for (Int_t iDict = 0; iDict < kNdict; iDict++) {
903 // tracksIn should be expanded beforehand!
904 tracksIn = fDigitsManager->GetDictionary(idet,iDict);
906 // Loop though the clusters found in this ROC
907 for (iClusterROC = 0; iClusterROC < nClusterROC; iClusterROC++) {
909 AliTRDcluster *cluster = (AliTRDcluster *)
910 RecPoints()->UncheckedAt(firstClusterROC+iClusterROC);
911 row = cluster->GetLabel(0);
912 col = cluster->GetLabel(1);
913 time = cluster->GetLabel(2);
915 for (iPad = 0; iPad < kNclus; iPad++) {
916 Int_t iPadCol = col - 1 + iPad;
917 Int_t index = tracksIn->GetDataUnchecked(row,iPadCol,time) - 1;
918 idxTracks[3*iPad+iDict + iClusterROC*kNtrack] = index;
925 // Copy the track indices into the cluster
926 // Loop though the clusters found in this ROC
927 for (iClusterROC = 0; iClusterROC < nClusterROC; iClusterROC++) {
929 AliTRDcluster *cluster = (AliTRDcluster *)
930 RecPoints()->UncheckedAt(firstClusterROC+iClusterROC);
931 cluster->SetLabel(-9999,0);
932 cluster->SetLabel(-9999,1);
933 cluster->SetLabel(-9999,2);
935 cluster->AddTrackIndex(&idxTracks[iClusterROC*kNtrack]);
945 //_____________________________________________________________________________
946 Double_t AliTRDclusterizerV2::GetCOG(Double_t signal[5])
950 // Used for clusters with more than 3 pads - where LUT not applicable
953 Double_t sum = signal[0]
959 Double_t res = (0.0 * (-signal[0] + signal[4])
960 + (-signal[1] + signal[3])) / sum;
966 //_____________________________________________________________________________
967 Double_t AliTRDclusterizerV2::Unfold(Double_t eps, Int_t plane, Double_t *padSignal)
970 // Method to unfold neighbouring maxima.
971 // The charge ratio on the overlapping pad is calculated
972 // until there is no more change within the range given by eps.
973 // The resulting ratio is then returned to the calling method.
976 AliTRDcalibDB *calibration = AliTRDcalibDB::Instance();
978 AliError("No AliTRDcalibDB instance available\n");
983 Int_t itStep = 0; // Count iteration steps
985 Double_t ratio = 0.5; // Start value for ratio
986 Double_t prevRatio = 0.0; // Store previous ratio
988 Double_t newLeftSignal[3] = { 0.0, 0.0, 0.0 }; // Array to store left cluster signal
989 Double_t newRightSignal[3] = { 0.0, 0.0, 0.0 }; // Array to store right cluster signal
990 Double_t newSignal[3] = { 0.0, 0.0, 0.0 };
992 // Start the iteration
993 while ((TMath::Abs(prevRatio - ratio) > eps) && (itStep < 10)) {
998 // Cluster position according to charge ratio
999 Double_t maxLeft = (ratio*padSignal[2] - padSignal[0])
1000 / (padSignal[0] + padSignal[1] + ratio*padSignal[2]);
1001 Double_t maxRight = (padSignal[4] - (1-ratio)*padSignal[2])
1002 / ((1.0 - ratio)*padSignal[2] + padSignal[3] + padSignal[4]);
1004 // Set cluster charge ratio
1005 irc = calibration->PadResponse(1.0,maxLeft ,plane,newSignal);
1006 Double_t ampLeft = padSignal[1] / newSignal[1];
1007 irc = calibration->PadResponse(1.0,maxRight,plane,newSignal);
1008 Double_t ampRight = padSignal[3] / newSignal[1];
1010 // Apply pad response to parameters
1011 irc = calibration->PadResponse(ampLeft ,maxLeft ,plane,newLeftSignal );
1012 irc = calibration->PadResponse(ampRight,maxRight,plane,newRightSignal);
1014 // Calculate new overlapping ratio
1015 ratio = TMath::Min((Double_t) 1.0
1016 ,newLeftSignal[2] / (newLeftSignal[2] + newRightSignal[0]));
1024 //_____________________________________________________________________________
1025 void AliTRDclusterizerV2::TailCancelation(AliTRDdataArrayI *digitsIn
1026 , AliTRDdataArrayF *digitsOut
1027 , AliTRDSignalIndex *indexesIn
1028 , AliTRDSignalIndex *indexesOut
1030 , Float_t ADCthreshold
1031 , AliTRDCalROC *calGainFactorROC
1032 , Float_t calGainFactorDetValue)
1035 // Applies the tail cancelation and gain factors:
1036 // Transform digitsIn to digitsOut
1043 AliTRDRecParam *recParam = AliTRDRecParam::Instance();
1046 AliError("No AliTRDRecParam instance available\n");
1050 Double_t *inADC = new Double_t[nTimeTotal]; // ADC data before tail cancellation
1051 Double_t *outADC = new Double_t[nTimeTotal]; // ADC data after tail cancellation
1052 indexesIn->ResetCounters();
1053 while (indexesIn->NextRCIndex(iRow, iCol))
1055 Float_t calGainFactorROCValue = calGainFactorROC->GetValue(iCol,iRow);
1056 Double_t gain = calGainFactorDetValue
1057 * calGainFactorROCValue;
1059 for (iTime = 0; iTime < nTimeTotal; iTime++)
1061 // Apply gain gain factor
1062 inADC[iTime] = digitsIn->GetDataUnchecked(iRow,iCol,iTime);
1063 inADC[iTime] /= gain;
1064 outADC[iTime] = inADC[iTime];
1067 // Apply the tail cancelation via the digital filter
1068 if (recParam->TCOn())
1070 DeConvExp(inADC,outADC,nTimeTotal,recParam->GetTCnexp());
1073 indexesIn->ResetTbinCounter();
1074 while (indexesIn->NextTbinIndex(iTime))
1076 // Store the amplitude of the digit if above threshold
1077 if (outADC[iTime] > ADCthreshold)
1079 digitsOut->SetDataUnchecked(iRow,iCol,iTime,outADC[iTime]);
1080 indexesOut->AddIndexTBin(iRow,iCol,iTime);
1093 //_____________________________________________________________________________
1094 void AliTRDclusterizerV2::DeConvExp(Double_t *source, Double_t *target
1095 , Int_t n, Int_t nexp)
1098 // Tail cancellation by deconvolution for PASA v4 TRF
1102 Double_t coefficients[2];
1104 // Initialization (coefficient = alpha, rates = lambda)
1110 if (nexp == 1) { // 1 Exponentials
1116 if (nexp == 2) { // 2 Exponentials
1123 coefficients[0] = c1;
1124 coefficients[1] = c2;
1128 rates[0] = TMath::Exp(-dt/(r1));
1129 rates[1] = TMath::Exp(-dt/(r2));
1134 Double_t reminder[2];
1135 Double_t correction = 0.0;
1136 Double_t result = 0.0;
1138 // Attention: computation order is important
1139 for (k = 0; k < nexp; k++) {
1143 for (i = 0; i < n; i++) {
1145 result = (source[i] - correction); // No rescaling
1148 for (k = 0; k < nexp; k++) {
1149 reminder[k] = rates[k] * (reminder[k] + coefficients[k] * result);
1153 for (k = 0; k < nexp; k++) {
1154 correction += reminder[k];