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"
56 #include "Cal/AliTRDCalSingleChamberStatus.h"
58 ClassImp(AliTRDclusterizer)
60 //_____________________________________________________________________________
61 AliTRDclusterizer::AliTRDclusterizer()
71 ,fTransform(new AliTRDtransform(0))
76 // AliTRDclusterizer default constructor
79 fRawVersion = AliTRDfeeParam::Instance()->GetRAWversion();
83 //_____________________________________________________________________________
84 AliTRDclusterizer::AliTRDclusterizer(const Text_t *name, const Text_t *title)
89 ,fDigitsManager(new AliTRDdigitsManager())
94 ,fTransform(new AliTRDtransform(0))
99 // AliTRDclusterizer constructor
102 fDigitsManager->CreateArrays();
104 fRawVersion = AliTRDfeeParam::Instance()->GetRAWversion();
110 //_____________________________________________________________________________
111 AliTRDclusterizer::AliTRDclusterizer(const AliTRDclusterizer &c)
116 ,fDigitsManager(NULL)
120 ,fIndexesMaxima(NULL)
126 // AliTRDclusterizer copy constructor
133 //_____________________________________________________________________________
134 AliTRDclusterizer::~AliTRDclusterizer()
137 // AliTRDclusterizer destructor
142 fRecPoints->Delete();
148 delete fDigitsManager;
149 fDigitsManager = NULL;
160 delete fIndexesMaxima;
161 fIndexesMaxima = NULL;
178 //_____________________________________________________________________________
179 AliTRDclusterizer &AliTRDclusterizer::operator=(const AliTRDclusterizer &c)
182 // Assignment operator
187 ((AliTRDclusterizer &) c).Copy(*this);
193 //_____________________________________________________________________________
194 void AliTRDclusterizer::Copy(TObject &c) const
200 ((AliTRDclusterizer &) c).fClusterTree = NULL;
201 ((AliTRDclusterizer &) c).fRecPoints = NULL;
202 ((AliTRDclusterizer &) c).fDigitsManager = NULL;
203 ((AliTRDclusterizer &) c).fAddLabels = fAddLabels;
204 ((AliTRDclusterizer &) c).fRawVersion = fRawVersion;
205 ((AliTRDclusterizer &) c).fIndexesOut = NULL;
206 ((AliTRDclusterizer &) c).fIndexesMaxima = NULL;
207 ((AliTRDclusterizer &) c).fTransform = NULL;
208 ((AliTRDclusterizer &) c).fLUTbin = 0;
209 ((AliTRDclusterizer &) c).fLUT = NULL;
213 //_____________________________________________________________________________
214 Bool_t AliTRDclusterizer::Open(const Char_t *name, Int_t nEvent)
217 // Opens the AliROOT file. Output and input are in the same file
220 TString evfoldname = AliConfig::GetDefaultEventFolderName();
221 fRunLoader = AliRunLoader::GetRunLoader(evfoldname);
224 fRunLoader = AliRunLoader::Open(name);
228 AliError(Form("Can not open session for file %s.",name));
239 //_____________________________________________________________________________
240 Bool_t AliTRDclusterizer::OpenOutput()
243 // Open the output file
246 TObjArray *ioArray = 0;
248 AliLoader* loader = fRunLoader->GetLoader("TRDLoader");
249 loader->MakeTree("R");
251 fClusterTree = loader->TreeR();
252 fClusterTree->Branch("TRDcluster","TObjArray",&ioArray,32000,0);
258 //_____________________________________________________________________________
259 Bool_t AliTRDclusterizer::OpenOutput(TTree *clusterTree)
262 // Connect the output tree
265 TObjArray *ioArray = 0;
267 fClusterTree = clusterTree;
268 fClusterTree->Branch("TRDcluster","TObjArray",&ioArray,32000,0);
274 //_____________________________________________________________________________
275 Bool_t AliTRDclusterizer::OpenInput(Int_t nEvent)
278 // Opens a ROOT-file with TRD-hits and reads in the digits-tree
281 // Import the Trees for the event nEvent in the file
282 fRunLoader->GetEvent(nEvent);
288 //_____________________________________________________________________________
289 Bool_t AliTRDclusterizer::WriteClusters(Int_t det)
292 // Fills TRDcluster branch in the tree with the clusters
293 // found in detector = det. For det=-1 writes the tree.
297 (det >= AliTRDgeometry::Ndet())) {
298 AliError(Form("Unexpected detector index %d.\n",det));
302 TBranch *branch = fClusterTree->GetBranch("TRDcluster");
304 TObjArray *ioArray = 0;
305 branch = fClusterTree->Branch("TRDcluster","TObjArray",&ioArray,32000,0);
309 (det < AliTRDgeometry::Ndet())) {
311 Int_t nRecPoints = RecPoints()->GetEntriesFast();
312 TObjArray *detRecPoints = new TObjArray(400);
314 for (Int_t i = 0; i < nRecPoints; i++) {
315 AliTRDcluster *c = (AliTRDcluster *) RecPoints()->UncheckedAt(i);
316 if (det == c->GetDetector()) {
317 detRecPoints->AddLast(c);
320 AliError(Form("Attempt to write a cluster with unexpected detector index: got=%d expected=%d\n"
326 branch->SetAddress(&detRecPoints);
327 fClusterTree->Fill();
337 AliInfo(Form("Writing the cluster tree %s for event %d."
338 ,fClusterTree->GetName(),fRunLoader->GetEventNumber()));
342 branch->SetAddress(&fRecPoints);
344 AliLoader *loader = fRunLoader->GetLoader("TRDLoader");
345 loader->WriteRecPoints("OVERWRITE");
350 AliError("Cluster tree does not exist. Cannot write clusters.\n");
359 AliError(Form("Unexpected detector index %d.\n",det));
365 //_____________________________________________________________________________
366 void AliTRDclusterizer::ResetHelperIndexes(AliTRDSignalIndex *indexesIn)
369 // Reset the helper indexes
374 // carefull here - we assume that only row number may change - most probable
375 if (indexesIn->GetNrow() <= fIndexesOut->GetNrow())
376 fIndexesOut->ResetContent();
378 fIndexesOut->ResetContentConditional(indexesIn->GetNrow()
379 , indexesIn->GetNcol()
380 , indexesIn->GetNtime());
384 fIndexesOut = new AliTRDSignalIndex(indexesIn->GetNrow()
385 , indexesIn->GetNcol()
386 , indexesIn->GetNtime());
391 // carefull here - we assume that only row number may change - most probable
392 if (indexesIn->GetNrow() <= fIndexesMaxima->GetNrow())
394 fIndexesMaxima->ResetContent();
398 fIndexesMaxima->ResetContentConditional(indexesIn->GetNrow()
399 , indexesIn->GetNcol()
400 , indexesIn->GetNtime());
405 fIndexesMaxima = new AliTRDSignalIndex(indexesIn->GetNrow()
406 , indexesIn->GetNcol()
407 , indexesIn->GetNtime());
412 //_____________________________________________________________________________
413 Bool_t AliTRDclusterizer::ReadDigits()
416 // Reads the digits arrays from the input aliroot file
420 AliError("No run loader available");
424 AliLoader* loader = fRunLoader->GetLoader("TRDLoader");
425 if (!loader->TreeD()) {
426 loader->LoadDigits();
429 // Read in the digit arrays
430 return (fDigitsManager->ReadDigits(loader->TreeD()));
434 //_____________________________________________________________________________
435 Bool_t AliTRDclusterizer::ReadDigits(TTree *digitsTree)
438 // Reads the digits arrays from the input tree
441 // Read in the digit arrays
442 return (fDigitsManager->ReadDigits(digitsTree));
446 //_____________________________________________________________________________
447 Bool_t AliTRDclusterizer::ReadDigits(AliRawReader *rawReader)
450 // Reads the digits arrays from the ddl file
454 fDigitsManager = raw.Raw2Digits(rawReader);
460 //_____________________________________________________________________________
461 Bool_t AliTRDclusterizer::MakeClusters()
464 // Creates clusters from digits
467 // Propagate info from the digits manager
468 if (fAddLabels == kTRUE)
470 fAddLabels = fDigitsManager->UsesDictionaries();
473 Bool_t fReturn = kTRUE;
474 for (Int_t i = 0; i < AliTRDgeometry::kNdet; i++)
477 AliTRDdataArrayS *digitsIn = (AliTRDdataArrayS *) fDigitsManager->GetDigits(i);
478 // This is to take care of switched off super modules
479 if (!digitsIn->HasData())
484 AliTRDSignalIndex* indexes = fDigitsManager->GetIndexes(i);
485 if (indexes->IsAllocated() == kFALSE)
487 fDigitsManager->BuildIndexes(i);
491 if (indexes->HasEntry())
495 for (Int_t iDict = 0; iDict < AliTRDdigitsManager::kNDict; iDict++)
497 AliTRDdataArrayI *tracksIn = 0;
498 tracksIn = (AliTRDdataArrayI *) fDigitsManager->GetDictionary(i,iDict);
502 fR = MakeClusters(i);
503 fReturn = fR && fReturn;
512 // No compress just remove
513 fDigitsManager->RemoveDigits(i);
514 fDigitsManager->RemoveDictionaries(i);
515 fDigitsManager->ClearIndexes(i);
523 //_____________________________________________________________________________
524 Bool_t AliTRDclusterizer::Raw2Clusters(AliRawReader *rawReader)
527 // Creates clusters from raw data
530 return Raw2ClustersChamber(rawReader);
534 //_____________________________________________________________________________
535 Bool_t AliTRDclusterizer::Raw2ClustersChamber(AliRawReader *rawReader)
538 // Creates clusters from raw data
541 // Create the digits manager
544 fDigitsManager = new AliTRDdigitsManager();
545 fDigitsManager->CreateArrays();
548 fDigitsManager->SetUseDictionaries(fAddLabels);
550 AliTRDrawStreamBase *pinput = AliTRDrawStreamBase::GetRawStream(rawReader);
551 AliTRDrawStreamBase &input = *pinput;
553 AliInfo(Form("Stream version: %s", input.IsA()->GetName()));
556 while ((det = input.NextChamber(fDigitsManager)) >= 0)
558 Bool_t iclusterBranch = kFALSE;
559 if (fDigitsManager->GetIndexes(det)->HasEntry())
561 iclusterBranch = MakeClusters(det);
563 if (iclusterBranch == kFALSE)
568 fDigitsManager->RemoveDigits(det);
569 fDigitsManager->RemoveDictionaries(det);
570 fDigitsManager->ClearIndexes(det);
573 delete fDigitsManager;
574 fDigitsManager = NULL;
582 //_____________________________________________________________________________
583 Bool_t AliTRDclusterizer::MakeClusters(Int_t det)
586 // Generates the cluster.
590 // digits should be expanded beforehand!
591 // digitsIn->Expand();
592 AliTRDdataArrayS *digitsIn = (AliTRDdataArrayS *) fDigitsManager->GetDigits(det);
594 // This is to take care of switched off super modules
595 if (!digitsIn->HasData())
600 AliTRDSignalIndex *indexesIn = fDigitsManager->GetIndexes(det);
601 if (indexesIn->IsAllocated() == kFALSE)
603 AliError("Indexes do not exist!");
607 AliTRDcalibDB *calibration = AliTRDcalibDB::Instance();
610 AliFatal("No AliTRDcalibDB instance available\n");
615 // There is no ADC threshold anymore, and simParam should not be used in clusterizer. KO
616 Float_t adcThreshold = 0;
618 if (!AliTRDReconstructor::RecoParam())
620 AliError("RecoParam does not exist\n");
624 // Threshold value for the maximum
625 Float_t maxThresh = AliTRDReconstructor::RecoParam()->GetClusMaxThresh();
626 // Threshold value for the digit signal
627 Float_t sigThresh = AliTRDReconstructor::RecoParam()->GetClusSigThresh();
629 // Iteration limit for unfolding procedure
630 const Float_t kEpsilon = 0.01;
631 const Int_t kNclus = 3;
632 const Int_t kNsig = 5;
635 Double_t ratioLeft = 1.0;
636 Double_t ratioRight = 1.0;
638 Double_t padSignal[kNsig];
639 Double_t clusterSignal[kNclus];
641 Int_t icham = indexesIn->GetChamber();
642 Int_t iplan = indexesIn->GetPlane();
643 Int_t isect = indexesIn->GetSM();
645 // Start clustering in the chamber
647 Int_t idet = AliTRDgeometry::GetDetector(iplan,icham,isect);
650 AliError("Strange Detector number Missmatch!");
654 // TRD space point transformation
655 fTransform->SetDetector(det);
657 Int_t ilayer = AliGeomManager::kTRD1 + iplan;
658 Int_t imodule = icham + AliTRDgeometry::Ncham() * isect;
659 UShort_t volid = AliGeomManager::LayerToVolUID(ilayer,imodule);
661 Int_t nColMax = digitsIn->GetNcol();
662 Int_t nTimeTotal = digitsIn->GetNtime();
664 // Detector wise calibration object for the gain factors
665 const AliTRDCalDet *calGainFactorDet = calibration->GetGainFactorDet();
666 // Calibration object with pad wise values for the gain factors
667 AliTRDCalROC *calGainFactorROC = calibration->GetGainFactorROC(idet);
668 // Calibration value for chamber wise gain factor
669 Float_t calGainFactorDetValue = calGainFactorDet->GetValue(idet);
671 // Calibration object with the pad status information
672 AliTRDCalSingleChamberStatus *calPadStatusROC = calibration->GetPadStatusROC(idet);
676 AliTRDdataArrayF *digitsOut = new AliTRDdataArrayF(digitsIn->GetNrow()
678 ,digitsIn->GetNtime());
680 ResetHelperIndexes(indexesIn);
682 // Apply the gain and the tail cancelation via digital filter
683 TailCancelation(digitsIn
690 ,calGainFactorDetValue);
697 fIndexesOut->ResetCounters();
698 while (fIndexesOut->NextRCTbinIndex(row, col, time))
701 Float_t signalM = TMath::Abs(digitsOut->GetDataUnchecked(row,col,time));
703 // Look for the maximum
704 if (signalM >= maxThresh)
707 if (col + 1 >= nColMax || col-1 < 0)
710 Float_t signalL = TMath::Abs(digitsOut->GetDataUnchecked(row,col+1,time));
711 Float_t signalR = TMath::Abs(digitsOut->GetDataUnchecked(row,col-1,time));
713 if ((TMath::Abs(signalL) <= signalM) &&
714 (TMath::Abs(signalR) < signalM))
716 if ((TMath::Abs(signalL) >= sigThresh) ||
717 (TMath::Abs(signalR) >= sigThresh))
719 // Maximum found, mark the position by a negative signal
720 digitsOut->SetDataUnchecked(row,col,time,-signalM);
721 fIndexesMaxima->AddIndexTBin(row,col,time);
729 // The index to the first cluster of a given ROC
730 Int_t firstClusterROC = -1;
731 // The number of cluster in a given ROC
732 Int_t nClusterROC = 0;
734 // Now check the maxima and calculate the cluster position
735 fIndexesMaxima->ResetCounters();
736 while (fIndexesMaxima->NextRCTbinIndex(row, col, time))
740 if (digitsOut->GetDataUnchecked(row,col,time) < 0.0)
743 for (iPad = 0; iPad < kNclus; iPad++)
745 Int_t iPadCol = col - 1 + iPad;
746 clusterSignal[iPad] = TMath::Abs(digitsOut->GetDataUnchecked(row,iPadCol,time));
749 // Count the number of pads in the cluster
754 while (TMath::Abs(digitsOut->GetDataUnchecked(row,col-ii ,time)) >= sigThresh)
758 if (col-ii < 0) break;
762 while (TMath::Abs(digitsOut->GetDataUnchecked(row,col+ii+1,time)) >= sigThresh)
766 if (col+ii+1 >= nColMax) break;
770 // Look for 5 pad cluster with minimum in the middle
771 Bool_t fivePadCluster = kFALSE;
772 if (col < (nColMax - 3))
774 if (digitsOut->GetDataUnchecked(row,col+2,time) < 0)
776 fivePadCluster = kTRUE;
778 if ((fivePadCluster) && (col < (nColMax - 5)))
780 if (digitsOut->GetDataUnchecked(row,col+4,time) >= sigThresh)
782 fivePadCluster = kFALSE;
785 if ((fivePadCluster) && (col > 1))
787 if (digitsOut->GetDataUnchecked(row,col-2,time) >= sigThresh)
789 fivePadCluster = kFALSE;
795 // Modify the signal of the overlapping pad for the left part
796 // of the cluster which remains from a previous unfolding
799 clusterSignal[0] *= ratioLeft;
803 // Unfold the 5 pad cluster
806 for (iPad = 0; iPad < kNsig; iPad++)
808 padSignal[iPad] = TMath::Abs(digitsOut->GetDataUnchecked(row
812 // Unfold the two maxima and set the signal on
813 // the overlapping pad to the ratio
814 ratioRight = Unfold(kEpsilon,iplan,padSignal);
815 ratioLeft = 1.0 - ratioRight;
816 clusterSignal[2] *= ratioRight;
820 // The position of the cluster in COL direction relative to the center pad (pad units)
821 Double_t clusterPosCol = 0.0;
822 if (AliTRDReconstructor::RecoParam()->LUTOn())
824 // Calculate the position of the cluster by using the
825 // lookup table method
826 clusterPosCol = LUTposition(iplan,clusterSignal[0]
832 // Calculate the position of the cluster by using the
833 // center of gravity method
834 for (Int_t i = 0; i < kNsig; i++)
838 padSignal[2] = TMath::Abs(digitsOut->GetDataUnchecked(row,col ,time)); // Central pad
839 padSignal[1] = TMath::Abs(digitsOut->GetDataUnchecked(row,col-1,time)); // Left pad
840 padSignal[3] = TMath::Abs(digitsOut->GetDataUnchecked(row,col+1,time)); // Right pad
842 (TMath::Abs(digitsOut->GetDataUnchecked(row,col-2,time)) < padSignal[1]))
844 padSignal[0] = TMath::Abs(digitsOut->GetDataUnchecked(row,col-2,time));
846 if ((col < nColMax - 3) &&
847 (TMath::Abs(digitsOut->GetDataUnchecked(row,col+2,time)) < padSignal[3]))
849 padSignal[4] = TMath::Abs(digitsOut->GetDataUnchecked(row,col+2,time));
851 clusterPosCol = GetCOG(padSignal);
854 // Store the amplitudes of the pads in the cluster for later analysis
855 // and check whether one of these pads is masked in the database
856 Short_t signals[7] = { 0, 0, 0, 0, 0, 0, 0 };
857 Bool_t hasMasked = kFALSE;
858 for (Int_t jPad = col-3; jPad <= col+3; jPad++)
865 signals[jPad-col+3] = TMath::Nint(TMath::Abs(digitsOut->GetDataUnchecked(row,jPad,time)));
866 if (calPadStatusROC->IsMasked(jPad,row)) {
871 // Transform the local cluster coordinates into calibrated
872 // space point positions defined in the local tracking system.
873 // Here the calibration for T0, Vdrift and ExB is applied as well.
874 Double_t clusterXYZ[6];
875 clusterXYZ[0] = clusterPosCol;
876 clusterXYZ[1] = clusterSignal[0];
877 clusterXYZ[2] = clusterSignal[1];
878 clusterXYZ[3] = clusterSignal[2];
887 if (fTransform->Transform(clusterXYZ, clusterRCT, ((UInt_t) time), out, 0)) {
889 // Add the cluster to the output array
890 // The track indices will be stored later
891 Float_t clusterPos[3];
892 clusterPos[0] = clusterXYZ[0];
893 clusterPos[1] = clusterXYZ[1];
894 clusterPos[2] = clusterXYZ[2];
895 Float_t clusterSig[2];
896 clusterSig[0] = clusterXYZ[4];
897 clusterSig[1] = clusterXYZ[5];
898 Double_t clusterCharge = clusterXYZ[3];
899 Char_t clusterTimeBin = ((Char_t) clusterRCT[2]);
900 AliTRDcluster *cluster = new AliTRDcluster(idet
905 ,((Char_t) nPadCount)
913 cluster->SetInChamber(!out);
914 cluster->SetMaskedPad(hasMasked);
916 // Temporarily store the row, column and time bin of the center pad
917 // Used to later on assign the track indices
918 cluster->SetLabel( row,0);
919 cluster->SetLabel( col,1);
920 cluster->SetLabel(time,2);
922 RecPoints()->Add(cluster);
924 // Store the index of the first cluster in the current ROC
925 if (firstClusterROC < 0)
927 firstClusterROC = RecPoints()->GetEntriesFast() - 1;
930 // Count the number of cluster in the current ROC
933 } // if: Transform ok ?
935 } // if: Maximum found ?
943 AddLabels(idet, firstClusterROC, nClusterROC);
946 // Write the cluster and reset the array
954 //_____________________________________________________________________________
955 Bool_t AliTRDclusterizer::AddLabels(Int_t idet, Int_t firstClusterROC, Int_t nClusterROC)
958 // Add the track indices to the found clusters
961 const Int_t kNclus = 3;
962 const Int_t kNdict = AliTRDdigitsManager::kNDict;
963 const Int_t kNtrack = kNdict * kNclus;
965 Int_t iClusterROC = 0;
972 // Temporary array to collect the track indices
973 Int_t *idxTracks = new Int_t[kNtrack*nClusterROC];
975 // Loop through the dictionary arrays one-by-one
976 // to keep memory consumption low
977 AliTRDdataArrayI *tracksIn = 0;
978 for (Int_t iDict = 0; iDict < kNdict; iDict++) {
980 // tracksIn should be expanded beforehand!
981 tracksIn = (AliTRDdataArrayI *) fDigitsManager->GetDictionary(idet,iDict);
983 // Loop though the clusters found in this ROC
984 for (iClusterROC = 0; iClusterROC < nClusterROC; iClusterROC++) {
986 AliTRDcluster *cluster = (AliTRDcluster *)
987 RecPoints()->UncheckedAt(firstClusterROC+iClusterROC);
988 row = cluster->GetLabel(0);
989 col = cluster->GetLabel(1);
990 time = cluster->GetLabel(2);
992 for (iPad = 0; iPad < kNclus; iPad++) {
993 Int_t iPadCol = col - 1 + iPad;
994 Int_t index = tracksIn->GetDataUnchecked(row,iPadCol,time) - 1;
995 idxTracks[3*iPad+iDict + iClusterROC*kNtrack] = index;
1002 // Copy the track indices into the cluster
1003 // Loop though the clusters found in this ROC
1004 for (iClusterROC = 0; iClusterROC < nClusterROC; iClusterROC++) {
1006 AliTRDcluster *cluster = (AliTRDcluster *)
1007 RecPoints()->UncheckedAt(firstClusterROC+iClusterROC);
1008 cluster->SetLabel(-9999,0);
1009 cluster->SetLabel(-9999,1);
1010 cluster->SetLabel(-9999,2);
1012 cluster->AddTrackIndex(&idxTracks[iClusterROC*kNtrack]);
1016 delete [] idxTracks;
1022 //_____________________________________________________________________________
1023 Double_t AliTRDclusterizer::GetCOG(Double_t signal[5]) const
1027 // Used for clusters with more than 3 pads - where LUT not applicable
1030 Double_t sum = signal[0]
1036 Double_t res = (0.0 * (-signal[0] + signal[4])
1037 + (-signal[1] + signal[3])) / sum;
1043 //_____________________________________________________________________________
1044 Double_t AliTRDclusterizer::Unfold(Double_t eps, Int_t plane, Double_t *padSignal)
1047 // Method to unfold neighbouring maxima.
1048 // The charge ratio on the overlapping pad is calculated
1049 // until there is no more change within the range given by eps.
1050 // The resulting ratio is then returned to the calling method.
1053 AliTRDcalibDB *calibration = AliTRDcalibDB::Instance();
1055 AliError("No AliTRDcalibDB instance available\n");
1060 Int_t itStep = 0; // Count iteration steps
1062 Double_t ratio = 0.5; // Start value for ratio
1063 Double_t prevRatio = 0.0; // Store previous ratio
1065 Double_t newLeftSignal[3] = { 0.0, 0.0, 0.0 }; // Array to store left cluster signal
1066 Double_t newRightSignal[3] = { 0.0, 0.0, 0.0 }; // Array to store right cluster signal
1067 Double_t newSignal[3] = { 0.0, 0.0, 0.0 };
1069 // Start the iteration
1070 while ((TMath::Abs(prevRatio - ratio) > eps) && (itStep < 10)) {
1075 // Cluster position according to charge ratio
1076 Double_t maxLeft = (ratio*padSignal[2] - padSignal[0])
1077 / (padSignal[0] + padSignal[1] + ratio*padSignal[2]);
1078 Double_t maxRight = (padSignal[4] - (1-ratio)*padSignal[2])
1079 / ((1.0 - ratio)*padSignal[2] + padSignal[3] + padSignal[4]);
1081 // Set cluster charge ratio
1082 irc = calibration->PadResponse(1.0,maxLeft ,plane,newSignal);
1083 Double_t ampLeft = padSignal[1] / newSignal[1];
1084 irc = calibration->PadResponse(1.0,maxRight,plane,newSignal);
1085 Double_t ampRight = padSignal[3] / newSignal[1];
1087 // Apply pad response to parameters
1088 irc = calibration->PadResponse(ampLeft ,maxLeft ,plane,newLeftSignal );
1089 irc = calibration->PadResponse(ampRight,maxRight,plane,newRightSignal);
1091 // Calculate new overlapping ratio
1092 ratio = TMath::Min((Double_t) 1.0
1093 ,newLeftSignal[2] / (newLeftSignal[2] + newRightSignal[0]));
1101 //_____________________________________________________________________________
1102 void AliTRDclusterizer::TailCancelation(AliTRDdataArrayS *digitsIn
1103 , AliTRDdataArrayF *digitsOut
1104 , AliTRDSignalIndex *indexesIn
1105 , AliTRDSignalIndex *indexesOut
1107 , Float_t adcThreshold
1108 , AliTRDCalROC *calGainFactorROC
1109 , Float_t calGainFactorDetValue)
1112 // Applies the tail cancelation and gain factors:
1113 // Transform digitsIn to digitsOut
1120 Double_t *inADC = new Double_t[nTimeTotal]; // ADC data before tail cancellation
1121 Double_t *outADC = new Double_t[nTimeTotal]; // ADC data after tail cancellation
1122 indexesIn->ResetCounters();
1123 while (indexesIn->NextRCIndex(iRow, iCol))
1125 Float_t calGainFactorROCValue = calGainFactorROC->GetValue(iCol,iRow);
1126 Double_t gain = calGainFactorDetValue
1127 * calGainFactorROCValue;
1129 for (iTime = 0; iTime < nTimeTotal; iTime++)
1131 // Apply gain gain factor
1132 inADC[iTime] = digitsIn->GetDataUnchecked(iRow,iCol,iTime);
1133 inADC[iTime] /= gain;
1134 outADC[iTime] = inADC[iTime];
1137 // Apply the tail cancelation via the digital filter
1138 if (AliTRDReconstructor::RecoParam()->TCOn())
1140 DeConvExp(inADC,outADC,nTimeTotal,AliTRDReconstructor::RecoParam()->GetTCnexp());
1143 indexesIn->ResetTbinCounter();
1144 while (indexesIn->NextTbinIndex(iTime))
1146 // Store the amplitude of the digit if above threshold
1147 if (outADC[iTime] > adcThreshold)
1149 digitsOut->SetDataUnchecked(iRow,iCol,iTime,outADC[iTime]);
1150 indexesOut->AddIndexTBin(iRow,iCol,iTime);
1154 } // while irow icol
1163 //_____________________________________________________________________________
1164 void AliTRDclusterizer::DeConvExp(Double_t *source, Double_t *target
1165 , Int_t n, Int_t nexp)
1168 // Tail cancellation by deconvolution for PASA v4 TRF
1172 Double_t coefficients[2];
1174 // Initialization (coefficient = alpha, rates = lambda)
1180 if (nexp == 1) { // 1 Exponentials
1186 if (nexp == 2) { // 2 Exponentials
1193 coefficients[0] = c1;
1194 coefficients[1] = c2;
1198 rates[0] = TMath::Exp(-dt/(r1));
1199 rates[1] = TMath::Exp(-dt/(r2));
1204 Double_t reminder[2];
1205 Double_t correction = 0.0;
1206 Double_t result = 0.0;
1208 // Attention: computation order is important
1209 for (k = 0; k < nexp; k++) {
1213 for (i = 0; i < n; i++) {
1215 result = (source[i] - correction); // No rescaling
1218 for (k = 0; k < nexp; k++) {
1219 reminder[k] = rates[k] * (reminder[k] + coefficients[k] * result);
1223 for (k = 0; k < nexp; k++) {
1224 correction += reminder[k];
1231 //_____________________________________________________________________________
1232 void AliTRDclusterizer::ResetRecPoints()
1235 // Resets the list of rec points
1239 fRecPoints->Delete();
1244 //_____________________________________________________________________________
1245 TObjArray *AliTRDclusterizer::RecPoints()
1248 // Returns the list of rec points
1252 fRecPoints = new TObjArray(400);
1259 //_____________________________________________________________________________
1260 void AliTRDclusterizer::FillLUT()
1266 const Int_t kNlut = 128;
1268 fLUTbin = AliTRDgeometry::kNplan * kNlut;
1270 // The lookup table from Bogdan
1271 Float_t lut[AliTRDgeometry::kNplan][kNlut] = {
1273 0.0070, 0.0150, 0.0224, 0.0298, 0.0374, 0.0454, 0.0533, 0.0611,
1274 0.0684, 0.0755, 0.0827, 0.0900, 0.0975, 0.1049, 0.1120, 0.1187,
1275 0.1253, 0.1318, 0.1385, 0.1453, 0.1519, 0.1584, 0.1646, 0.1704,
1276 0.1762, 0.1821, 0.1879, 0.1938, 0.1996, 0.2053, 0.2108, 0.2160,
1277 0.2210, 0.2260, 0.2310, 0.2361, 0.2411, 0.2461, 0.2509, 0.2557,
1278 0.2602, 0.2646, 0.2689, 0.2732, 0.2774, 0.2816, 0.2859, 0.2901,
1279 0.2942, 0.2983, 0.3022, 0.3061, 0.3099, 0.3136, 0.3172, 0.3207,
1280 0.3242, 0.3278, 0.3312, 0.3347, 0.3382, 0.3416, 0.3450, 0.3483,
1281 0.3515, 0.3547, 0.3579, 0.3609, 0.3639, 0.3669, 0.3698, 0.3727,
1282 0.3756, 0.3785, 0.3813, 0.3842, 0.3870, 0.3898, 0.3926, 0.3952,
1283 0.3979, 0.4005, 0.4032, 0.4057, 0.4082, 0.4108, 0.4132, 0.4157,
1284 0.4181, 0.4205, 0.4228, 0.4252, 0.4275, 0.4299, 0.4322, 0.4345,
1285 0.4367, 0.4390, 0.4412, 0.4434, 0.4456, 0.4478, 0.4499, 0.4520,
1286 0.4541, 0.4562, 0.4583, 0.4603, 0.4623, 0.4643, 0.4663, 0.4683,
1287 0.4702, 0.4722, 0.4741, 0.4758, 0.4774, 0.4790, 0.4805, 0.4824,
1288 0.4844, 0.4863, 0.4883, 0.4902, 0.4921, 0.4940, 0.4959, 0.4978
1291 0.0072, 0.0156, 0.0235, 0.0313, 0.0394, 0.0478, 0.0561, 0.0642,
1292 0.0718, 0.0792, 0.0868, 0.0947, 0.1025, 0.1101, 0.1172, 0.1241,
1293 0.1309, 0.1378, 0.1449, 0.1518, 0.1586, 0.1650, 0.1710, 0.1770,
1294 0.1830, 0.1891, 0.1952, 0.2011, 0.2070, 0.2125, 0.2177, 0.2229,
1295 0.2280, 0.2332, 0.2383, 0.2435, 0.2484, 0.2533, 0.2581, 0.2627,
1296 0.2670, 0.2714, 0.2757, 0.2799, 0.2842, 0.2884, 0.2927, 0.2968,
1297 0.3008, 0.3048, 0.3086, 0.3123, 0.3159, 0.3195, 0.3231, 0.3266,
1298 0.3301, 0.3335, 0.3370, 0.3404, 0.3438, 0.3471, 0.3504, 0.3536,
1299 0.3567, 0.3598, 0.3628, 0.3657, 0.3686, 0.3715, 0.3744, 0.3772,
1300 0.3800, 0.3828, 0.3856, 0.3884, 0.3911, 0.3938, 0.3965, 0.3991,
1301 0.4016, 0.4042, 0.4067, 0.4092, 0.4116, 0.4140, 0.4164, 0.4187,
1302 0.4211, 0.4234, 0.4257, 0.4280, 0.4302, 0.4325, 0.4347, 0.4369,
1303 0.4391, 0.4413, 0.4434, 0.4456, 0.4477, 0.4497, 0.4518, 0.4538,
1304 0.4558, 0.4578, 0.4598, 0.4618, 0.4637, 0.4656, 0.4675, 0.4694,
1305 0.4713, 0.4732, 0.4750, 0.4766, 0.4781, 0.4797, 0.4813, 0.4832,
1306 0.4851, 0.4870, 0.4888, 0.4906, 0.4925, 0.4942, 0.4960, 0.4978
1309 0.0075, 0.0163, 0.0246, 0.0328, 0.0415, 0.0504, 0.0592, 0.0674,
1310 0.0753, 0.0832, 0.0914, 0.0996, 0.1077, 0.1154, 0.1225, 0.1296,
1311 0.1369, 0.1442, 0.1515, 0.1585, 0.1652, 0.1714, 0.1776, 0.1839,
1312 0.1902, 0.1965, 0.2025, 0.2085, 0.2141, 0.2194, 0.2247, 0.2299,
1313 0.2352, 0.2405, 0.2457, 0.2507, 0.2557, 0.2604, 0.2649, 0.2693,
1314 0.2737, 0.2780, 0.2823, 0.2867, 0.2909, 0.2951, 0.2992, 0.3033,
1315 0.3072, 0.3110, 0.3146, 0.3182, 0.3218, 0.3253, 0.3288, 0.3323,
1316 0.3357, 0.3392, 0.3426, 0.3459, 0.3492, 0.3524, 0.3555, 0.3586,
1317 0.3616, 0.3645, 0.3674, 0.3703, 0.3731, 0.3759, 0.3787, 0.3815,
1318 0.3843, 0.3870, 0.3897, 0.3925, 0.3950, 0.3976, 0.4002, 0.4027,
1319 0.4052, 0.4076, 0.4101, 0.4124, 0.4148, 0.4171, 0.4194, 0.4217,
1320 0.4239, 0.4262, 0.4284, 0.4306, 0.4328, 0.4350, 0.4371, 0.4393,
1321 0.4414, 0.4435, 0.4455, 0.4476, 0.4496, 0.4516, 0.4536, 0.4555,
1322 0.4575, 0.4594, 0.4613, 0.4632, 0.4650, 0.4669, 0.4687, 0.4705,
1323 0.4723, 0.4741, 0.4758, 0.4773, 0.4789, 0.4804, 0.4821, 0.4839,
1324 0.4857, 0.4875, 0.4893, 0.4910, 0.4928, 0.4945, 0.4961, 0.4978
1327 0.0078, 0.0171, 0.0258, 0.0345, 0.0438, 0.0532, 0.0624, 0.0708,
1328 0.0791, 0.0875, 0.0962, 0.1048, 0.1130, 0.1206, 0.1281, 0.1356,
1329 0.1432, 0.1508, 0.1582, 0.1651, 0.1716, 0.1780, 0.1845, 0.1910,
1330 0.1975, 0.2038, 0.2099, 0.2155, 0.2210, 0.2263, 0.2317, 0.2371,
1331 0.2425, 0.2477, 0.2528, 0.2578, 0.2626, 0.2671, 0.2715, 0.2759,
1332 0.2803, 0.2846, 0.2890, 0.2933, 0.2975, 0.3016, 0.3056, 0.3095,
1333 0.3132, 0.3168, 0.3204, 0.3239, 0.3274, 0.3309, 0.3344, 0.3378,
1334 0.3412, 0.3446, 0.3479, 0.3511, 0.3543, 0.3574, 0.3603, 0.3633,
1335 0.3662, 0.3690, 0.3718, 0.3747, 0.3774, 0.3802, 0.3829, 0.3857,
1336 0.3883, 0.3910, 0.3936, 0.3962, 0.3987, 0.4012, 0.4037, 0.4061,
1337 0.4085, 0.4109, 0.4132, 0.4155, 0.4177, 0.4200, 0.4222, 0.4244,
1338 0.4266, 0.4288, 0.4309, 0.4331, 0.4352, 0.4373, 0.4394, 0.4414,
1339 0.4435, 0.4455, 0.4475, 0.4494, 0.4514, 0.4533, 0.4552, 0.4571,
1340 0.4590, 0.4608, 0.4626, 0.4645, 0.4662, 0.4680, 0.4698, 0.4715,
1341 0.4733, 0.4750, 0.4766, 0.4781, 0.4796, 0.4812, 0.4829, 0.4846,
1342 0.4863, 0.4880, 0.4897, 0.4914, 0.4930, 0.4946, 0.4963, 0.4979
1345 0.0081, 0.0178, 0.0270, 0.0364, 0.0463, 0.0562, 0.0656, 0.0744,
1346 0.0831, 0.0921, 0.1013, 0.1102, 0.1183, 0.1261, 0.1339, 0.1419,
1347 0.1499, 0.1576, 0.1648, 0.1715, 0.1782, 0.1849, 0.1917, 0.1984,
1348 0.2048, 0.2110, 0.2167, 0.2223, 0.2278, 0.2333, 0.2389, 0.2444,
1349 0.2497, 0.2548, 0.2598, 0.2645, 0.2691, 0.2735, 0.2780, 0.2824,
1350 0.2868, 0.2912, 0.2955, 0.2997, 0.3038, 0.3078, 0.3116, 0.3152,
1351 0.3188, 0.3224, 0.3259, 0.3294, 0.3329, 0.3364, 0.3398, 0.3432,
1352 0.3465, 0.3497, 0.3529, 0.3561, 0.3591, 0.3620, 0.3649, 0.3677,
1353 0.3705, 0.3733, 0.3761, 0.3788, 0.3816, 0.3843, 0.3869, 0.3896,
1354 0.3922, 0.3948, 0.3973, 0.3998, 0.4022, 0.4047, 0.4070, 0.4094,
1355 0.4117, 0.4139, 0.4162, 0.4184, 0.4206, 0.4227, 0.4249, 0.4270,
1356 0.4291, 0.4313, 0.4334, 0.4354, 0.4375, 0.4395, 0.4415, 0.4435,
1357 0.4455, 0.4474, 0.4493, 0.4512, 0.4531, 0.4550, 0.4568, 0.4586,
1358 0.4604, 0.4622, 0.4639, 0.4657, 0.4674, 0.4691, 0.4708, 0.4725,
1359 0.4742, 0.4758, 0.4773, 0.4788, 0.4803, 0.4819, 0.4836, 0.4852,
1360 0.4869, 0.4885, 0.4901, 0.4917, 0.4933, 0.4948, 0.4964, 0.4979
1363 0.0085, 0.0189, 0.0288, 0.0389, 0.0497, 0.0603, 0.0699, 0.0792,
1364 0.0887, 0.0985, 0.1082, 0.1170, 0.1253, 0.1336, 0.1421, 0.1505,
1365 0.1587, 0.1662, 0.1733, 0.1803, 0.1874, 0.1945, 0.2014, 0.2081,
1366 0.2143, 0.2201, 0.2259, 0.2316, 0.2374, 0.2431, 0.2487, 0.2541,
1367 0.2593, 0.2642, 0.2689, 0.2735, 0.2781, 0.2826, 0.2872, 0.2917,
1368 0.2961, 0.3003, 0.3045, 0.3086, 0.3125, 0.3162, 0.3198, 0.3235,
1369 0.3270, 0.3306, 0.3342, 0.3377, 0.3411, 0.3446, 0.3479, 0.3511,
1370 0.3543, 0.3575, 0.3605, 0.3634, 0.3663, 0.3691, 0.3720, 0.3748,
1371 0.3775, 0.3803, 0.3830, 0.3857, 0.3884, 0.3911, 0.3937, 0.3962,
1372 0.3987, 0.4012, 0.4036, 0.4060, 0.4084, 0.4107, 0.4129, 0.4152,
1373 0.4174, 0.4196, 0.4218, 0.4239, 0.4261, 0.4282, 0.4303, 0.4324,
1374 0.4344, 0.4365, 0.4385, 0.4405, 0.4425, 0.4445, 0.4464, 0.4483,
1375 0.4502, 0.4521, 0.4539, 0.4558, 0.4576, 0.4593, 0.4611, 0.4629,
1376 0.4646, 0.4663, 0.4680, 0.4697, 0.4714, 0.4730, 0.4747, 0.4759,
1377 0.4769, 0.4780, 0.4790, 0.4800, 0.4811, 0.4827, 0.4843, 0.4859,
1378 0.4874, 0.4889, 0.4905, 0.4920, 0.4935, 0.4950, 0.4965, 0.4979
1385 fLUT = new Double_t[fLUTbin];
1387 for (Int_t iplan = 0; iplan < AliTRDgeometry::kNplan; iplan++) {
1388 for (Int_t ilut = 0; ilut < kNlut; ilut++ ) {
1389 fLUT[iplan*kNlut+ilut] = lut[iplan][ilut];
1395 //_____________________________________________________________________________
1396 Double_t AliTRDclusterizer::LUTposition(Int_t iplane, Double_t ampL
1397 , Double_t ampC, Double_t ampR) const
1400 // Calculates the cluster position using the lookup table.
1401 // Method provided by Bogdan Vulpescu.
1404 const Int_t kNlut = 128;
1415 Double_t xMin[AliTRDgeometry::kNplan] = { 0.006492, 0.006377, 0.006258
1416 , 0.006144, 0.006030, 0.005980 };
1417 Double_t xMax[AliTRDgeometry::kNplan] = { 0.960351, 0.965870, 0.970445
1418 , 0.974352, 0.977667, 0.996101 };
1421 x = (ampL - ampR) / ampC;
1424 else if (ampL < ampR) {
1425 x = (ampR - ampL) / ampC;
1431 xmin = xMin[iplane] + 0.000005;
1432 xmax = xMax[iplane] - 0.000005;
1433 xwid = (xmax - xmin) / 127.0;
1438 else if (x > xmax) {
1439 pos = side * 0.5000;
1442 ix = (Int_t) ((x - xmin) / xwid);
1443 pos = side * fLUT[iplane*kNlut+ix];