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 ///////////////////////////////////////////////////////////////////////////////
29 #include <TObjArray.h>
31 #include "AliRunLoader.h"
32 #include "AliLoader.h"
33 #include "AliRawReader.h"
35 #include "AliAlignObj.h"
37 #include "AliTRDclusterizer.h"
38 #include "AliTRDcluster.h"
39 #include "AliTRDReconstructor.h"
40 #include "AliTRDgeometry.h"
41 #include "AliTRDdataArrayF.h"
42 #include "AliTRDdataArrayI.h"
43 #include "AliTRDdataArrayS.h"
44 #include "AliTRDdigitsManager.h"
45 #include "AliTRDrawData.h"
46 #include "AliTRDcalibDB.h"
47 #include "AliTRDrecoParam.h"
48 #include "AliTRDCommonParam.h"
49 #include "AliTRDtransform.h"
50 #include "AliTRDSignalIndex.h"
51 #include "AliTRDrawStreamBase.h"
52 #include "AliTRDfeeParam.h"
54 #include "Cal/AliTRDCalROC.h"
55 #include "Cal/AliTRDCalDet.h"
57 ClassImp(AliTRDclusterizer)
59 //_____________________________________________________________________________
60 AliTRDclusterizer::AliTRDclusterizer()
70 ,fTransform(new AliTRDtransform(0))
75 // AliTRDclusterizer default constructor
78 fRawVersion = AliTRDfeeParam::Instance()->GetRAWversion();
82 //_____________________________________________________________________________
83 AliTRDclusterizer::AliTRDclusterizer(const Text_t *name, const Text_t *title)
88 ,fDigitsManager(new AliTRDdigitsManager())
93 ,fTransform(new AliTRDtransform(0))
98 // AliTRDclusterizer constructor
101 fDigitsManager->CreateArrays();
103 fRawVersion = AliTRDfeeParam::Instance()->GetRAWversion();
109 //_____________________________________________________________________________
110 AliTRDclusterizer::AliTRDclusterizer(const AliTRDclusterizer &c)
115 ,fDigitsManager(NULL)
119 ,fIndexesMaxima(NULL)
125 // AliTRDclusterizer copy constructor
132 //_____________________________________________________________________________
133 AliTRDclusterizer::~AliTRDclusterizer()
136 // AliTRDclusterizer destructor
141 fRecPoints->Delete();
147 delete fDigitsManager;
148 fDigitsManager = NULL;
159 delete fIndexesMaxima;
160 fIndexesMaxima = NULL;
177 //_____________________________________________________________________________
178 AliTRDclusterizer &AliTRDclusterizer::operator=(const AliTRDclusterizer &c)
181 // Assignment operator
186 ((AliTRDclusterizer &) c).Copy(*this);
192 //_____________________________________________________________________________
193 void AliTRDclusterizer::Copy(TObject &c) const
199 ((AliTRDclusterizer &) c).fClusterTree = NULL;
200 ((AliTRDclusterizer &) c).fRecPoints = NULL;
201 ((AliTRDclusterizer &) c).fDigitsManager = NULL;
202 ((AliTRDclusterizer &) c).fAddLabels = fAddLabels;
203 ((AliTRDclusterizer &) c).fRawVersion = fRawVersion;
204 ((AliTRDclusterizer &) c).fIndexesOut = NULL;
205 ((AliTRDclusterizer &) c).fIndexesMaxima = NULL;
206 ((AliTRDclusterizer &) c).fTransform = NULL;
207 ((AliTRDclusterizer &) c).fLUTbin = 0;
208 ((AliTRDclusterizer &) c).fLUT = NULL;
212 //_____________________________________________________________________________
213 Bool_t AliTRDclusterizer::Open(const Char_t *name, Int_t nEvent)
216 // Opens the AliROOT file. Output and input are in the same file
219 TString evfoldname = AliConfig::GetDefaultEventFolderName();
220 fRunLoader = AliRunLoader::GetRunLoader(evfoldname);
223 fRunLoader = AliRunLoader::Open(name);
227 AliError(Form("Can not open session for file %s.",name));
238 //_____________________________________________________________________________
239 Bool_t AliTRDclusterizer::OpenOutput()
242 // Open the output file
245 TObjArray *ioArray = 0;
247 AliLoader* loader = fRunLoader->GetLoader("TRDLoader");
248 loader->MakeTree("R");
250 fClusterTree = loader->TreeR();
251 fClusterTree->Branch("TRDcluster","TObjArray",&ioArray,32000,0);
257 //_____________________________________________________________________________
258 Bool_t AliTRDclusterizer::OpenOutput(TTree *clusterTree)
261 // Connect the output tree
264 TObjArray *ioArray = 0;
266 fClusterTree = clusterTree;
267 fClusterTree->Branch("TRDcluster","TObjArray",&ioArray,32000,0);
273 //_____________________________________________________________________________
274 Bool_t AliTRDclusterizer::OpenInput(Int_t nEvent)
277 // Opens a ROOT-file with TRD-hits and reads in the digits-tree
280 // Import the Trees for the event nEvent in the file
281 fRunLoader->GetEvent(nEvent);
287 //_____________________________________________________________________________
288 Bool_t AliTRDclusterizer::WriteClusters(Int_t det)
291 // Fills TRDcluster branch in the tree with the clusters
292 // found in detector = det. For det=-1 writes the tree.
296 (det >= AliTRDgeometry::Ndet())) {
297 AliError(Form("Unexpected detector index %d.\n",det));
301 TBranch *branch = fClusterTree->GetBranch("TRDcluster");
303 TObjArray *ioArray = 0;
304 branch = fClusterTree->Branch("TRDcluster","TObjArray",&ioArray,32000,0);
308 (det < AliTRDgeometry::Ndet())) {
310 Int_t nRecPoints = RecPoints()->GetEntriesFast();
311 TObjArray *detRecPoints = new TObjArray(400);
313 for (Int_t i = 0; i < nRecPoints; i++) {
314 AliTRDcluster *c = (AliTRDcluster *) RecPoints()->UncheckedAt(i);
315 if (det == c->GetDetector()) {
316 detRecPoints->AddLast(c);
319 AliError(Form("Attempt to write a cluster with unexpected detector index: got=%d expected=%d\n"
325 branch->SetAddress(&detRecPoints);
326 fClusterTree->Fill();
336 AliInfo(Form("Writing the cluster tree %s for event %d."
337 ,fClusterTree->GetName(),fRunLoader->GetEventNumber()));
341 branch->SetAddress(&fRecPoints);
343 AliLoader *loader = fRunLoader->GetLoader("TRDLoader");
344 loader->WriteRecPoints("OVERWRITE");
349 AliError("Cluster tree does not exist. Cannot write clusters.\n");
358 AliError(Form("Unexpected detector index %d.\n",det));
364 //_____________________________________________________________________________
365 void AliTRDclusterizer::ResetHelperIndexes(AliTRDSignalIndex *indexesIn)
368 // Reset the helper indexes
373 // carefull here - we assume that only row number may change - most probable
374 if (indexesIn->GetNrow() <= fIndexesOut->GetNrow())
375 fIndexesOut->ResetContent();
377 fIndexesOut->ResetContentConditional(indexesIn->GetNrow()
378 , indexesIn->GetNcol()
379 , indexesIn->GetNtime());
383 fIndexesOut = new AliTRDSignalIndex(indexesIn->GetNrow()
384 , indexesIn->GetNcol()
385 , indexesIn->GetNtime());
390 // carefull here - we assume that only row number may change - most probable
391 if (indexesIn->GetNrow() <= fIndexesMaxima->GetNrow())
393 fIndexesMaxima->ResetContent();
397 fIndexesMaxima->ResetContentConditional(indexesIn->GetNrow()
398 , indexesIn->GetNcol()
399 , indexesIn->GetNtime());
404 fIndexesMaxima = new AliTRDSignalIndex(indexesIn->GetNrow()
405 , indexesIn->GetNcol()
406 , indexesIn->GetNtime());
411 //_____________________________________________________________________________
412 Bool_t AliTRDclusterizer::ReadDigits()
415 // Reads the digits arrays from the input aliroot file
419 AliError("No run loader available");
423 AliLoader* loader = fRunLoader->GetLoader("TRDLoader");
424 if (!loader->TreeD()) {
425 loader->LoadDigits();
428 // Read in the digit arrays
429 return (fDigitsManager->ReadDigits(loader->TreeD()));
433 //_____________________________________________________________________________
434 Bool_t AliTRDclusterizer::ReadDigits(TTree *digitsTree)
437 // Reads the digits arrays from the input tree
440 // Read in the digit arrays
441 return (fDigitsManager->ReadDigits(digitsTree));
445 //_____________________________________________________________________________
446 Bool_t AliTRDclusterizer::ReadDigits(AliRawReader *rawReader)
449 // Reads the digits arrays from the ddl file
453 fDigitsManager = raw.Raw2Digits(rawReader);
459 //_____________________________________________________________________________
460 Bool_t AliTRDclusterizer::MakeClusters()
463 // Creates clusters from digits
466 // Propagate info from the digits manager
467 if (fAddLabels == kTRUE)
469 fAddLabels = fDigitsManager->UsesDictionaries();
472 Bool_t fReturn = kTRUE;
473 for (Int_t i = 0; i < AliTRDgeometry::kNdet; i++)
476 AliTRDdataArrayS *digitsIn = (AliTRDdataArrayS *) fDigitsManager->GetDigits(i);
477 // This is to take care of switched off super modules
478 if (!digitsIn->HasData())
483 AliTRDSignalIndex* indexes = fDigitsManager->GetIndexes(i);
484 if (indexes->IsAllocated() == kFALSE)
486 fDigitsManager->BuildIndexes(i);
490 if (indexes->HasEntry())
494 for (Int_t iDict = 0; iDict < AliTRDdigitsManager::kNDict; iDict++)
496 AliTRDdataArrayI *tracksIn = 0;
497 tracksIn = (AliTRDdataArrayI *) fDigitsManager->GetDictionary(i,iDict);
501 fR = MakeClusters(i);
502 fReturn = fR && fReturn;
511 // No compress just remove
512 fDigitsManager->RemoveDigits(i);
513 fDigitsManager->RemoveDictionaries(i);
514 fDigitsManager->ClearIndexes(i);
522 //_____________________________________________________________________________
523 Bool_t AliTRDclusterizer::Raw2Clusters(AliRawReader *rawReader)
526 // Creates clusters from raw data
529 return Raw2ClustersChamber(rawReader);
533 //_____________________________________________________________________________
534 Bool_t AliTRDclusterizer::Raw2ClustersChamber(AliRawReader *rawReader)
537 // Creates clusters from raw data
540 // Create the digits manager
543 fDigitsManager = new AliTRDdigitsManager();
544 fDigitsManager->CreateArrays();
547 fDigitsManager->SetUseDictionaries(fAddLabels);
549 AliTRDrawStreamBase *pinput = AliTRDrawStreamBase::GetRawStream(rawReader);
550 AliTRDrawStreamBase &input = *pinput;
552 AliInfo(Form("Stream version: %s", input.IsA()->GetName()));
555 while ((det = input.NextChamber(fDigitsManager)) >= 0)
557 Bool_t iclusterBranch = kFALSE;
558 if (fDigitsManager->GetIndexes(det)->HasEntry())
560 iclusterBranch = MakeClusters(det);
562 if (iclusterBranch == kFALSE)
567 fDigitsManager->RemoveDigits(det);
568 fDigitsManager->RemoveDictionaries(det);
569 fDigitsManager->ClearIndexes(det);
572 delete fDigitsManager;
573 fDigitsManager = NULL;
581 //_____________________________________________________________________________
582 Bool_t AliTRDclusterizer::MakeClusters(Int_t det)
585 // Generates the cluster.
589 // digits should be expanded beforehand!
590 // digitsIn->Expand();
591 AliTRDdataArrayS *digitsIn = (AliTRDdataArrayS *) fDigitsManager->GetDigits(det);
593 // This is to take care of switched off super modules
594 if (!digitsIn->HasData())
599 AliTRDSignalIndex *indexesIn = fDigitsManager->GetIndexes(det);
600 if (indexesIn->IsAllocated() == kFALSE)
602 AliError("Indexes do not exist!");
606 AliTRDcalibDB *calibration = AliTRDcalibDB::Instance();
609 AliFatal("No AliTRDcalibDB instance available\n");
614 // There is no ADC threshold anymore, and simParam should not be used in clusterizer. KO
615 Float_t adcThreshold = 0;
617 if (!AliTRDReconstructor::RecoParam())
619 AliError("RecoParam does not exist\n");
623 // Threshold value for the maximum
624 Float_t maxThresh = AliTRDReconstructor::RecoParam()->GetClusMaxThresh();
625 // Threshold value for the digit signal
626 Float_t sigThresh = AliTRDReconstructor::RecoParam()->GetClusSigThresh();
628 // Iteration limit for unfolding procedure
629 const Float_t kEpsilon = 0.01;
630 const Int_t kNclus = 3;
631 const Int_t kNsig = 5;
634 Double_t ratioLeft = 1.0;
635 Double_t ratioRight = 1.0;
637 Double_t padSignal[kNsig];
638 Double_t clusterSignal[kNclus];
640 Int_t icham = indexesIn->GetChamber();
641 Int_t iplan = indexesIn->GetPlane();
642 Int_t isect = indexesIn->GetSM();
644 // Start clustering in the chamber
646 Int_t idet = AliTRDgeometry::GetDetector(iplan,icham,isect);
649 AliError("Strange Detector number Missmatch!");
653 // TRD space point transformation
654 fTransform->SetDetector(det);
656 Int_t ilayer = AliGeomManager::kTRD1 + iplan;
657 Int_t imodule = icham + AliTRDgeometry::Ncham() * isect;
658 UShort_t volid = AliGeomManager::LayerToVolUID(ilayer,imodule);
660 Int_t nColMax = digitsIn->GetNcol();
661 Int_t nTimeTotal = digitsIn->GetNtime();
663 // Detector wise calibration object for the gain factors
664 const AliTRDCalDet *calGainFactorDet = calibration->GetGainFactorDet();
665 // Calibration object with pad wise values for the gain factors
666 AliTRDCalROC *calGainFactorROC = calibration->GetGainFactorROC(idet);
667 // Calibration value for chamber wise gain factor
668 Float_t calGainFactorDetValue = calGainFactorDet->GetValue(idet);
672 AliTRDdataArrayF *digitsOut = new AliTRDdataArrayF(digitsIn->GetNrow()
674 ,digitsIn->GetNtime());
676 ResetHelperIndexes(indexesIn);
678 // Apply the gain and the tail cancelation via digital filter
679 TailCancelation(digitsIn
686 ,calGainFactorDetValue);
693 fIndexesOut->ResetCounters();
694 while (fIndexesOut->NextRCTbinIndex(row, col, time))
697 Float_t signalM = TMath::Abs(digitsOut->GetDataUnchecked(row,col,time));
699 // Look for the maximum
700 if (signalM >= maxThresh)
703 if (col + 1 >= nColMax || col-1 < 0)
706 Float_t signalL = TMath::Abs(digitsOut->GetDataUnchecked(row,col+1,time));
707 Float_t signalR = TMath::Abs(digitsOut->GetDataUnchecked(row,col-1,time));
709 if ((TMath::Abs(signalL) <= signalM) &&
710 (TMath::Abs(signalR) < signalM))
712 if ((TMath::Abs(signalL) >= sigThresh) ||
713 (TMath::Abs(signalR) >= sigThresh))
715 // Maximum found, mark the position by a negative signal
716 digitsOut->SetDataUnchecked(row,col,time,-signalM);
717 fIndexesMaxima->AddIndexTBin(row,col,time);
725 // The index to the first cluster of a given ROC
726 Int_t firstClusterROC = -1;
727 // The number of cluster in a given ROC
728 Int_t nClusterROC = 0;
730 // Now check the maxima and calculate the cluster position
731 fIndexesMaxima->ResetCounters();
732 while (fIndexesMaxima->NextRCTbinIndex(row, col, time))
736 if (digitsOut->GetDataUnchecked(row,col,time) < 0.0)
739 for (iPad = 0; iPad < kNclus; iPad++)
741 Int_t iPadCol = col - 1 + iPad;
742 clusterSignal[iPad] = TMath::Abs(digitsOut->GetDataUnchecked(row,iPadCol,time));
745 // Count the number of pads in the cluster
750 while (TMath::Abs(digitsOut->GetDataUnchecked(row,col-ii ,time)) >= sigThresh)
754 if (col-ii < 0) break;
758 while (TMath::Abs(digitsOut->GetDataUnchecked(row,col+ii+1,time)) >= sigThresh)
762 if (col+ii+1 >= nColMax) break;
766 // Look for 5 pad cluster with minimum in the middle
767 Bool_t fivePadCluster = kFALSE;
768 if (col < (nColMax - 3))
770 if (digitsOut->GetDataUnchecked(row,col+2,time) < 0)
772 fivePadCluster = kTRUE;
774 if ((fivePadCluster) && (col < (nColMax - 5)))
776 if (digitsOut->GetDataUnchecked(row,col+4,time) >= sigThresh)
778 fivePadCluster = kFALSE;
781 if ((fivePadCluster) && (col > 1))
783 if (digitsOut->GetDataUnchecked(row,col-2,time) >= sigThresh)
785 fivePadCluster = kFALSE;
791 // Modify the signal of the overlapping pad for the left part
792 // of the cluster which remains from a previous unfolding
795 clusterSignal[0] *= ratioLeft;
799 // Unfold the 5 pad cluster
802 for (iPad = 0; iPad < kNsig; iPad++)
804 padSignal[iPad] = TMath::Abs(digitsOut->GetDataUnchecked(row
808 // Unfold the two maxima and set the signal on
809 // the overlapping pad to the ratio
810 ratioRight = Unfold(kEpsilon,iplan,padSignal);
811 ratioLeft = 1.0 - ratioRight;
812 clusterSignal[2] *= ratioRight;
816 // The position of the cluster in COL direction relative to the center pad (pad units)
817 Double_t clusterPosCol = 0.0;
818 if (AliTRDReconstructor::RecoParam()->LUTOn())
820 // Calculate the position of the cluster by using the
821 // lookup table method
822 clusterPosCol = LUTposition(iplan,clusterSignal[0]
828 // Calculate the position of the cluster by using the
829 // center of gravity method
830 for (Int_t i = 0; i < kNsig; i++)
834 padSignal[2] = TMath::Abs(digitsOut->GetDataUnchecked(row,col ,time)); // Central pad
835 padSignal[1] = TMath::Abs(digitsOut->GetDataUnchecked(row,col-1,time)); // Left pad
836 padSignal[3] = TMath::Abs(digitsOut->GetDataUnchecked(row,col+1,time)); // Right pad
838 (TMath::Abs(digitsOut->GetDataUnchecked(row,col-2,time)) < padSignal[1]))
840 padSignal[0] = TMath::Abs(digitsOut->GetDataUnchecked(row,col-2,time));
842 if ((col < nColMax - 3) &&
843 (TMath::Abs(digitsOut->GetDataUnchecked(row,col+2,time)) < padSignal[3]))
845 padSignal[4] = TMath::Abs(digitsOut->GetDataUnchecked(row,col+2,time));
847 clusterPosCol = GetCOG(padSignal);
850 // Store the amplitudes of the pads in the cluster for later analysis
851 Short_t signals[7] = { 0, 0, 0, 0, 0, 0, 0 };
852 for (Int_t jPad = col-3; jPad <= col+3; jPad++)
859 signals[jPad-col+3] = TMath::Nint(TMath::Abs(digitsOut->GetDataUnchecked(row,jPad,time)));
862 // Transform the local cluster coordinates into calibrated
863 // space point positions defined in the local tracking system.
864 // Here the calibration for T0, Vdrift and ExB is applied as well.
865 Double_t clusterXYZ[6];
866 clusterXYZ[0] = clusterPosCol;
867 clusterXYZ[1] = clusterSignal[0];
868 clusterXYZ[2] = clusterSignal[1];
869 clusterXYZ[3] = clusterSignal[2];
878 if (fTransform->Transform(clusterXYZ, clusterRCT, ((UInt_t) time), out, 0)) {
880 // Add the cluster to the output array
881 // The track indices will be stored later
882 Float_t clusterPos[3];
883 clusterPos[0] = clusterXYZ[0];
884 clusterPos[1] = clusterXYZ[1];
885 clusterPos[2] = clusterXYZ[2];
886 Float_t clusterSig[2];
887 clusterSig[0] = clusterXYZ[4];
888 clusterSig[1] = clusterXYZ[5];
889 Double_t clusterCharge = clusterXYZ[3];
890 Char_t clusterTimeBin = ((Char_t) clusterRCT[2]);
891 AliTRDcluster *cluster = new AliTRDcluster(idet
896 ,((Char_t) nPadCount)
904 cluster->SetInChamber(!out);
906 // Temporarily store the row, column and time bin of the center pad
907 // Used to later on assign the track indices
908 cluster->SetLabel( row,0);
909 cluster->SetLabel( col,1);
910 cluster->SetLabel(time,2);
912 RecPoints()->Add(cluster);
914 // Store the index of the first cluster in the current ROC
915 if (firstClusterROC < 0)
917 firstClusterROC = RecPoints()->GetEntriesFast() - 1;
920 // Count the number of cluster in the current ROC
923 } // if: Transform ok ?
925 } // if: Maximum found ?
933 AddLabels(idet, firstClusterROC, nClusterROC);
936 // Write the cluster and reset the array
944 //_____________________________________________________________________________
945 Bool_t AliTRDclusterizer::AddLabels(Int_t idet, Int_t firstClusterROC, Int_t nClusterROC)
948 // Add the track indices to the found clusters
951 const Int_t kNclus = 3;
952 const Int_t kNdict = AliTRDdigitsManager::kNDict;
953 const Int_t kNtrack = kNdict * kNclus;
955 Int_t iClusterROC = 0;
962 // Temporary array to collect the track indices
963 Int_t *idxTracks = new Int_t[kNtrack*nClusterROC];
965 // Loop through the dictionary arrays one-by-one
966 // to keep memory consumption low
967 AliTRDdataArrayI *tracksIn = 0;
968 for (Int_t iDict = 0; iDict < kNdict; iDict++) {
970 // tracksIn should be expanded beforehand!
971 tracksIn = (AliTRDdataArrayI *) fDigitsManager->GetDictionary(idet,iDict);
973 // Loop though the clusters found in this ROC
974 for (iClusterROC = 0; iClusterROC < nClusterROC; iClusterROC++) {
976 AliTRDcluster *cluster = (AliTRDcluster *)
977 RecPoints()->UncheckedAt(firstClusterROC+iClusterROC);
978 row = cluster->GetLabel(0);
979 col = cluster->GetLabel(1);
980 time = cluster->GetLabel(2);
982 for (iPad = 0; iPad < kNclus; iPad++) {
983 Int_t iPadCol = col - 1 + iPad;
984 Int_t index = tracksIn->GetDataUnchecked(row,iPadCol,time) - 1;
985 idxTracks[3*iPad+iDict + iClusterROC*kNtrack] = index;
992 // Copy the track indices into the cluster
993 // Loop though the clusters found in this ROC
994 for (iClusterROC = 0; iClusterROC < nClusterROC; iClusterROC++) {
996 AliTRDcluster *cluster = (AliTRDcluster *)
997 RecPoints()->UncheckedAt(firstClusterROC+iClusterROC);
998 cluster->SetLabel(-9999,0);
999 cluster->SetLabel(-9999,1);
1000 cluster->SetLabel(-9999,2);
1002 cluster->AddTrackIndex(&idxTracks[iClusterROC*kNtrack]);
1006 delete [] idxTracks;
1012 //_____________________________________________________________________________
1013 Double_t AliTRDclusterizer::GetCOG(Double_t signal[5]) const
1017 // Used for clusters with more than 3 pads - where LUT not applicable
1020 Double_t sum = signal[0]
1026 Double_t res = (0.0 * (-signal[0] + signal[4])
1027 + (-signal[1] + signal[3])) / sum;
1033 //_____________________________________________________________________________
1034 Double_t AliTRDclusterizer::Unfold(Double_t eps, Int_t plane, Double_t *padSignal)
1037 // Method to unfold neighbouring maxima.
1038 // The charge ratio on the overlapping pad is calculated
1039 // until there is no more change within the range given by eps.
1040 // The resulting ratio is then returned to the calling method.
1043 AliTRDcalibDB *calibration = AliTRDcalibDB::Instance();
1045 AliError("No AliTRDcalibDB instance available\n");
1050 Int_t itStep = 0; // Count iteration steps
1052 Double_t ratio = 0.5; // Start value for ratio
1053 Double_t prevRatio = 0.0; // Store previous ratio
1055 Double_t newLeftSignal[3] = { 0.0, 0.0, 0.0 }; // Array to store left cluster signal
1056 Double_t newRightSignal[3] = { 0.0, 0.0, 0.0 }; // Array to store right cluster signal
1057 Double_t newSignal[3] = { 0.0, 0.0, 0.0 };
1059 // Start the iteration
1060 while ((TMath::Abs(prevRatio - ratio) > eps) && (itStep < 10)) {
1065 // Cluster position according to charge ratio
1066 Double_t maxLeft = (ratio*padSignal[2] - padSignal[0])
1067 / (padSignal[0] + padSignal[1] + ratio*padSignal[2]);
1068 Double_t maxRight = (padSignal[4] - (1-ratio)*padSignal[2])
1069 / ((1.0 - ratio)*padSignal[2] + padSignal[3] + padSignal[4]);
1071 // Set cluster charge ratio
1072 irc = calibration->PadResponse(1.0,maxLeft ,plane,newSignal);
1073 Double_t ampLeft = padSignal[1] / newSignal[1];
1074 irc = calibration->PadResponse(1.0,maxRight,plane,newSignal);
1075 Double_t ampRight = padSignal[3] / newSignal[1];
1077 // Apply pad response to parameters
1078 irc = calibration->PadResponse(ampLeft ,maxLeft ,plane,newLeftSignal );
1079 irc = calibration->PadResponse(ampRight,maxRight,plane,newRightSignal);
1081 // Calculate new overlapping ratio
1082 ratio = TMath::Min((Double_t) 1.0
1083 ,newLeftSignal[2] / (newLeftSignal[2] + newRightSignal[0]));
1091 //_____________________________________________________________________________
1092 void AliTRDclusterizer::TailCancelation(AliTRDdataArrayS *digitsIn
1093 , AliTRDdataArrayF *digitsOut
1094 , AliTRDSignalIndex *indexesIn
1095 , AliTRDSignalIndex *indexesOut
1097 , Float_t adcThreshold
1098 , AliTRDCalROC *calGainFactorROC
1099 , Float_t calGainFactorDetValue)
1102 // Applies the tail cancelation and gain factors:
1103 // Transform digitsIn to digitsOut
1110 Double_t *inADC = new Double_t[nTimeTotal]; // ADC data before tail cancellation
1111 Double_t *outADC = new Double_t[nTimeTotal]; // ADC data after tail cancellation
1112 indexesIn->ResetCounters();
1113 while (indexesIn->NextRCIndex(iRow, iCol))
1115 Float_t calGainFactorROCValue = calGainFactorROC->GetValue(iCol,iRow);
1116 Double_t gain = calGainFactorDetValue
1117 * calGainFactorROCValue;
1119 for (iTime = 0; iTime < nTimeTotal; iTime++)
1121 // Apply gain gain factor
1122 inADC[iTime] = digitsIn->GetDataUnchecked(iRow,iCol,iTime);
1123 inADC[iTime] /= gain;
1124 outADC[iTime] = inADC[iTime];
1127 // Apply the tail cancelation via the digital filter
1128 if (AliTRDReconstructor::RecoParam()->TCOn())
1130 DeConvExp(inADC,outADC,nTimeTotal,AliTRDReconstructor::RecoParam()->GetTCnexp());
1133 indexesIn->ResetTbinCounter();
1134 while (indexesIn->NextTbinIndex(iTime))
1136 // Store the amplitude of the digit if above threshold
1137 if (outADC[iTime] > adcThreshold)
1139 digitsOut->SetDataUnchecked(iRow,iCol,iTime,outADC[iTime]);
1140 indexesOut->AddIndexTBin(iRow,iCol,iTime);
1144 } // while irow icol
1153 //_____________________________________________________________________________
1154 void AliTRDclusterizer::DeConvExp(Double_t *source, Double_t *target
1155 , Int_t n, Int_t nexp)
1158 // Tail cancellation by deconvolution for PASA v4 TRF
1162 Double_t coefficients[2];
1164 // Initialization (coefficient = alpha, rates = lambda)
1170 if (nexp == 1) { // 1 Exponentials
1176 if (nexp == 2) { // 2 Exponentials
1183 coefficients[0] = c1;
1184 coefficients[1] = c2;
1188 rates[0] = TMath::Exp(-dt/(r1));
1189 rates[1] = TMath::Exp(-dt/(r2));
1194 Double_t reminder[2];
1195 Double_t correction = 0.0;
1196 Double_t result = 0.0;
1198 // Attention: computation order is important
1199 for (k = 0; k < nexp; k++) {
1203 for (i = 0; i < n; i++) {
1205 result = (source[i] - correction); // No rescaling
1208 for (k = 0; k < nexp; k++) {
1209 reminder[k] = rates[k] * (reminder[k] + coefficients[k] * result);
1213 for (k = 0; k < nexp; k++) {
1214 correction += reminder[k];
1221 //_____________________________________________________________________________
1222 void AliTRDclusterizer::ResetRecPoints()
1225 // Resets the list of rec points
1229 fRecPoints->Delete();
1234 //_____________________________________________________________________________
1235 TObjArray *AliTRDclusterizer::RecPoints()
1238 // Returns the list of rec points
1242 fRecPoints = new TObjArray(400);
1249 //_____________________________________________________________________________
1250 void AliTRDclusterizer::FillLUT()
1256 const Int_t kNlut = 128;
1258 fLUTbin = AliTRDgeometry::kNplan * kNlut;
1260 // The lookup table from Bogdan
1261 Float_t lut[AliTRDgeometry::kNplan][kNlut] = {
1263 0.0070, 0.0150, 0.0224, 0.0298, 0.0374, 0.0454, 0.0533, 0.0611,
1264 0.0684, 0.0755, 0.0827, 0.0900, 0.0975, 0.1049, 0.1120, 0.1187,
1265 0.1253, 0.1318, 0.1385, 0.1453, 0.1519, 0.1584, 0.1646, 0.1704,
1266 0.1762, 0.1821, 0.1879, 0.1938, 0.1996, 0.2053, 0.2108, 0.2160,
1267 0.2210, 0.2260, 0.2310, 0.2361, 0.2411, 0.2461, 0.2509, 0.2557,
1268 0.2602, 0.2646, 0.2689, 0.2732, 0.2774, 0.2816, 0.2859, 0.2901,
1269 0.2942, 0.2983, 0.3022, 0.3061, 0.3099, 0.3136, 0.3172, 0.3207,
1270 0.3242, 0.3278, 0.3312, 0.3347, 0.3382, 0.3416, 0.3450, 0.3483,
1271 0.3515, 0.3547, 0.3579, 0.3609, 0.3639, 0.3669, 0.3698, 0.3727,
1272 0.3756, 0.3785, 0.3813, 0.3842, 0.3870, 0.3898, 0.3926, 0.3952,
1273 0.3979, 0.4005, 0.4032, 0.4057, 0.4082, 0.4108, 0.4132, 0.4157,
1274 0.4181, 0.4205, 0.4228, 0.4252, 0.4275, 0.4299, 0.4322, 0.4345,
1275 0.4367, 0.4390, 0.4412, 0.4434, 0.4456, 0.4478, 0.4499, 0.4520,
1276 0.4541, 0.4562, 0.4583, 0.4603, 0.4623, 0.4643, 0.4663, 0.4683,
1277 0.4702, 0.4722, 0.4741, 0.4758, 0.4774, 0.4790, 0.4805, 0.4824,
1278 0.4844, 0.4863, 0.4883, 0.4902, 0.4921, 0.4940, 0.4959, 0.4978
1281 0.0072, 0.0156, 0.0235, 0.0313, 0.0394, 0.0478, 0.0561, 0.0642,
1282 0.0718, 0.0792, 0.0868, 0.0947, 0.1025, 0.1101, 0.1172, 0.1241,
1283 0.1309, 0.1378, 0.1449, 0.1518, 0.1586, 0.1650, 0.1710, 0.1770,
1284 0.1830, 0.1891, 0.1952, 0.2011, 0.2070, 0.2125, 0.2177, 0.2229,
1285 0.2280, 0.2332, 0.2383, 0.2435, 0.2484, 0.2533, 0.2581, 0.2627,
1286 0.2670, 0.2714, 0.2757, 0.2799, 0.2842, 0.2884, 0.2927, 0.2968,
1287 0.3008, 0.3048, 0.3086, 0.3123, 0.3159, 0.3195, 0.3231, 0.3266,
1288 0.3301, 0.3335, 0.3370, 0.3404, 0.3438, 0.3471, 0.3504, 0.3536,
1289 0.3567, 0.3598, 0.3628, 0.3657, 0.3686, 0.3715, 0.3744, 0.3772,
1290 0.3800, 0.3828, 0.3856, 0.3884, 0.3911, 0.3938, 0.3965, 0.3991,
1291 0.4016, 0.4042, 0.4067, 0.4092, 0.4116, 0.4140, 0.4164, 0.4187,
1292 0.4211, 0.4234, 0.4257, 0.4280, 0.4302, 0.4325, 0.4347, 0.4369,
1293 0.4391, 0.4413, 0.4434, 0.4456, 0.4477, 0.4497, 0.4518, 0.4538,
1294 0.4558, 0.4578, 0.4598, 0.4618, 0.4637, 0.4656, 0.4675, 0.4694,
1295 0.4713, 0.4732, 0.4750, 0.4766, 0.4781, 0.4797, 0.4813, 0.4832,
1296 0.4851, 0.4870, 0.4888, 0.4906, 0.4925, 0.4942, 0.4960, 0.4978
1299 0.0075, 0.0163, 0.0246, 0.0328, 0.0415, 0.0504, 0.0592, 0.0674,
1300 0.0753, 0.0832, 0.0914, 0.0996, 0.1077, 0.1154, 0.1225, 0.1296,
1301 0.1369, 0.1442, 0.1515, 0.1585, 0.1652, 0.1714, 0.1776, 0.1839,
1302 0.1902, 0.1965, 0.2025, 0.2085, 0.2141, 0.2194, 0.2247, 0.2299,
1303 0.2352, 0.2405, 0.2457, 0.2507, 0.2557, 0.2604, 0.2649, 0.2693,
1304 0.2737, 0.2780, 0.2823, 0.2867, 0.2909, 0.2951, 0.2992, 0.3033,
1305 0.3072, 0.3110, 0.3146, 0.3182, 0.3218, 0.3253, 0.3288, 0.3323,
1306 0.3357, 0.3392, 0.3426, 0.3459, 0.3492, 0.3524, 0.3555, 0.3586,
1307 0.3616, 0.3645, 0.3674, 0.3703, 0.3731, 0.3759, 0.3787, 0.3815,
1308 0.3843, 0.3870, 0.3897, 0.3925, 0.3950, 0.3976, 0.4002, 0.4027,
1309 0.4052, 0.4076, 0.4101, 0.4124, 0.4148, 0.4171, 0.4194, 0.4217,
1310 0.4239, 0.4262, 0.4284, 0.4306, 0.4328, 0.4350, 0.4371, 0.4393,
1311 0.4414, 0.4435, 0.4455, 0.4476, 0.4496, 0.4516, 0.4536, 0.4555,
1312 0.4575, 0.4594, 0.4613, 0.4632, 0.4650, 0.4669, 0.4687, 0.4705,
1313 0.4723, 0.4741, 0.4758, 0.4773, 0.4789, 0.4804, 0.4821, 0.4839,
1314 0.4857, 0.4875, 0.4893, 0.4910, 0.4928, 0.4945, 0.4961, 0.4978
1317 0.0078, 0.0171, 0.0258, 0.0345, 0.0438, 0.0532, 0.0624, 0.0708,
1318 0.0791, 0.0875, 0.0962, 0.1048, 0.1130, 0.1206, 0.1281, 0.1356,
1319 0.1432, 0.1508, 0.1582, 0.1651, 0.1716, 0.1780, 0.1845, 0.1910,
1320 0.1975, 0.2038, 0.2099, 0.2155, 0.2210, 0.2263, 0.2317, 0.2371,
1321 0.2425, 0.2477, 0.2528, 0.2578, 0.2626, 0.2671, 0.2715, 0.2759,
1322 0.2803, 0.2846, 0.2890, 0.2933, 0.2975, 0.3016, 0.3056, 0.3095,
1323 0.3132, 0.3168, 0.3204, 0.3239, 0.3274, 0.3309, 0.3344, 0.3378,
1324 0.3412, 0.3446, 0.3479, 0.3511, 0.3543, 0.3574, 0.3603, 0.3633,
1325 0.3662, 0.3690, 0.3718, 0.3747, 0.3774, 0.3802, 0.3829, 0.3857,
1326 0.3883, 0.3910, 0.3936, 0.3962, 0.3987, 0.4012, 0.4037, 0.4061,
1327 0.4085, 0.4109, 0.4132, 0.4155, 0.4177, 0.4200, 0.4222, 0.4244,
1328 0.4266, 0.4288, 0.4309, 0.4331, 0.4352, 0.4373, 0.4394, 0.4414,
1329 0.4435, 0.4455, 0.4475, 0.4494, 0.4514, 0.4533, 0.4552, 0.4571,
1330 0.4590, 0.4608, 0.4626, 0.4645, 0.4662, 0.4680, 0.4698, 0.4715,
1331 0.4733, 0.4750, 0.4766, 0.4781, 0.4796, 0.4812, 0.4829, 0.4846,
1332 0.4863, 0.4880, 0.4897, 0.4914, 0.4930, 0.4946, 0.4963, 0.4979
1335 0.0081, 0.0178, 0.0270, 0.0364, 0.0463, 0.0562, 0.0656, 0.0744,
1336 0.0831, 0.0921, 0.1013, 0.1102, 0.1183, 0.1261, 0.1339, 0.1419,
1337 0.1499, 0.1576, 0.1648, 0.1715, 0.1782, 0.1849, 0.1917, 0.1984,
1338 0.2048, 0.2110, 0.2167, 0.2223, 0.2278, 0.2333, 0.2389, 0.2444,
1339 0.2497, 0.2548, 0.2598, 0.2645, 0.2691, 0.2735, 0.2780, 0.2824,
1340 0.2868, 0.2912, 0.2955, 0.2997, 0.3038, 0.3078, 0.3116, 0.3152,
1341 0.3188, 0.3224, 0.3259, 0.3294, 0.3329, 0.3364, 0.3398, 0.3432,
1342 0.3465, 0.3497, 0.3529, 0.3561, 0.3591, 0.3620, 0.3649, 0.3677,
1343 0.3705, 0.3733, 0.3761, 0.3788, 0.3816, 0.3843, 0.3869, 0.3896,
1344 0.3922, 0.3948, 0.3973, 0.3998, 0.4022, 0.4047, 0.4070, 0.4094,
1345 0.4117, 0.4139, 0.4162, 0.4184, 0.4206, 0.4227, 0.4249, 0.4270,
1346 0.4291, 0.4313, 0.4334, 0.4354, 0.4375, 0.4395, 0.4415, 0.4435,
1347 0.4455, 0.4474, 0.4493, 0.4512, 0.4531, 0.4550, 0.4568, 0.4586,
1348 0.4604, 0.4622, 0.4639, 0.4657, 0.4674, 0.4691, 0.4708, 0.4725,
1349 0.4742, 0.4758, 0.4773, 0.4788, 0.4803, 0.4819, 0.4836, 0.4852,
1350 0.4869, 0.4885, 0.4901, 0.4917, 0.4933, 0.4948, 0.4964, 0.4979
1353 0.0085, 0.0189, 0.0288, 0.0389, 0.0497, 0.0603, 0.0699, 0.0792,
1354 0.0887, 0.0985, 0.1082, 0.1170, 0.1253, 0.1336, 0.1421, 0.1505,
1355 0.1587, 0.1662, 0.1733, 0.1803, 0.1874, 0.1945, 0.2014, 0.2081,
1356 0.2143, 0.2201, 0.2259, 0.2316, 0.2374, 0.2431, 0.2487, 0.2541,
1357 0.2593, 0.2642, 0.2689, 0.2735, 0.2781, 0.2826, 0.2872, 0.2917,
1358 0.2961, 0.3003, 0.3045, 0.3086, 0.3125, 0.3162, 0.3198, 0.3235,
1359 0.3270, 0.3306, 0.3342, 0.3377, 0.3411, 0.3446, 0.3479, 0.3511,
1360 0.3543, 0.3575, 0.3605, 0.3634, 0.3663, 0.3691, 0.3720, 0.3748,
1361 0.3775, 0.3803, 0.3830, 0.3857, 0.3884, 0.3911, 0.3937, 0.3962,
1362 0.3987, 0.4012, 0.4036, 0.4060, 0.4084, 0.4107, 0.4129, 0.4152,
1363 0.4174, 0.4196, 0.4218, 0.4239, 0.4261, 0.4282, 0.4303, 0.4324,
1364 0.4344, 0.4365, 0.4385, 0.4405, 0.4425, 0.4445, 0.4464, 0.4483,
1365 0.4502, 0.4521, 0.4539, 0.4558, 0.4576, 0.4593, 0.4611, 0.4629,
1366 0.4646, 0.4663, 0.4680, 0.4697, 0.4714, 0.4730, 0.4747, 0.4759,
1367 0.4769, 0.4780, 0.4790, 0.4800, 0.4811, 0.4827, 0.4843, 0.4859,
1368 0.4874, 0.4889, 0.4905, 0.4920, 0.4935, 0.4950, 0.4965, 0.4979
1375 fLUT = new Double_t[fLUTbin];
1377 for (Int_t iplan = 0; iplan < AliTRDgeometry::kNplan; iplan++) {
1378 for (Int_t ilut = 0; ilut < kNlut; ilut++ ) {
1379 fLUT[iplan*kNlut+ilut] = lut[iplan][ilut];
1385 //_____________________________________________________________________________
1386 Double_t AliTRDclusterizer::LUTposition(Int_t iplane, Double_t ampL
1387 , Double_t ampC, Double_t ampR) const
1390 // Calculates the cluster position using the lookup table.
1391 // Method provided by Bogdan Vulpescu.
1394 const Int_t kNlut = 128;
1405 Double_t xMin[AliTRDgeometry::kNplan] = { 0.006492, 0.006377, 0.006258
1406 , 0.006144, 0.006030, 0.005980 };
1407 Double_t xMax[AliTRDgeometry::kNplan] = { 0.960351, 0.965870, 0.970445
1408 , 0.974352, 0.977667, 0.996101 };
1411 x = (ampL - ampR) / ampC;
1414 else if (ampL < ampR) {
1415 x = (ampR - ampL) / ampC;
1421 xmin = xMin[iplane] + 0.000005;
1422 xmax = xMax[iplane] - 0.000005;
1423 xwid = (xmax - xmin) / 127.0;
1428 else if (x > xmax) {
1429 pos = side * 0.5000;
1432 ix = (Int_t) ((x - xmin) / xwid);
1433 pos = side * fLUT[iplane*kNlut+ix];