1 /**************************************************************************
2 * Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
4 * Author: The ALICE Off-line Project. *
5 * Contributors are mentioned in the code where appropriate. *
7 * Permission to use, copy, modify and distribute this software and its *
8 * documentation strictly for non-commercial purposes is hereby granted *
9 * without fee, provided that the above copyright notice appears in all *
10 * copies and that both the copyright notice and this permission notice *
11 * appear in the supporting documentation. The authors make no claims *
12 * about the suitability of this software for any purpose. It is *
13 * provided "as is" without express or implied warranty. *
14 **************************************************************************/
18 ///////////////////////////////////////////////////////////////////////////////
20 // TRD cluster finder //
22 ///////////////////////////////////////////////////////////////////////////////
28 #include <TObjArray.h>
30 #include "AliRunLoader.h"
31 #include "AliLoader.h"
32 #include "AliRawReader.h"
34 #include "AliAlignObj.h"
36 #include "AliTRDclusterizer.h"
37 #include "AliTRDcluster.h"
38 #include "AliTRDReconstructor.h"
39 #include "AliTRDgeometry.h"
40 #include "AliTRDdataArrayF.h"
41 #include "AliTRDdataArrayI.h"
42 #include "AliTRDdataArrayS.h"
43 #include "AliTRDdataArrayDigits.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()
68 ,fTrackletContainer(NULL)
73 ,fTransform(new AliTRDtransform(0))
78 // AliTRDclusterizer default constructor
81 AliTRDcalibDB *trd = 0x0;
82 if (!(trd = AliTRDcalibDB::Instance())) {
83 AliFatal("Could not get calibration object");
86 fRawVersion = AliTRDfeeParam::Instance()->GetRAWversion();
91 //_____________________________________________________________________________
92 AliTRDclusterizer::AliTRDclusterizer(const Text_t *name, const Text_t *title)
98 ,fDigitsManager(new AliTRDdigitsManager())
99 ,fTrackletContainer(NULL)
103 ,fIndexesMaxima(NULL)
104 ,fTransform(new AliTRDtransform(0))
109 // AliTRDclusterizer constructor
112 AliTRDcalibDB *trd = 0x0;
113 if (!(trd = AliTRDcalibDB::Instance())) {
114 AliFatal("Could not get calibration object");
117 fDigitsManager->CreateArrays();
119 fRawVersion = AliTRDfeeParam::Instance()->GetRAWversion();
125 //_____________________________________________________________________________
126 AliTRDclusterizer::AliTRDclusterizer(const AliTRDclusterizer &c)
132 ,fTrackletContainer(NULL)
133 ,fDigitsManager(NULL)
137 ,fIndexesMaxima(NULL)
143 // AliTRDclusterizer copy constructor
150 //_____________________________________________________________________________
151 AliTRDclusterizer::~AliTRDclusterizer()
154 // AliTRDclusterizer destructor
159 fRecPoints->Delete();
165 delete fDigitsManager;
166 fDigitsManager = NULL;
169 if (fTrackletContainer)
171 delete fTrackletContainer;
172 fTrackletContainer = NULL;
183 delete fIndexesMaxima;
184 fIndexesMaxima = NULL;
201 //_____________________________________________________________________________
202 AliTRDclusterizer &AliTRDclusterizer::operator=(const AliTRDclusterizer &c)
205 // Assignment operator
210 ((AliTRDclusterizer &) c).Copy(*this);
217 //_____________________________________________________________________________
218 void AliTRDclusterizer::Copy(TObject &c) const
224 ((AliTRDclusterizer &) c).fClusterTree = NULL;
225 ((AliTRDclusterizer &) c).fRecPoints = NULL;
226 ((AliTRDclusterizer &) c).fTrackletTree = NULL;
227 ((AliTRDclusterizer &) c).fDigitsManager = NULL;
228 ((AliTRDclusterizer &) c).fTrackletContainer = NULL;
229 ((AliTRDclusterizer &) c).fAddLabels = fAddLabels;
230 ((AliTRDclusterizer &) c).fRawVersion = fRawVersion;
231 ((AliTRDclusterizer &) c).fIndexesOut = NULL;
232 ((AliTRDclusterizer &) c).fIndexesMaxima = NULL;
233 ((AliTRDclusterizer &) c).fTransform = NULL;
234 ((AliTRDclusterizer &) c).fLUTbin = 0;
235 ((AliTRDclusterizer &) c).fLUT = NULL;
239 //_____________________________________________________________________________
240 Bool_t AliTRDclusterizer::Open(const Char_t *name, Int_t nEvent)
243 // Opens the AliROOT file. Output and input are in the same file
246 TString evfoldname = AliConfig::GetDefaultEventFolderName();
247 fRunLoader = AliRunLoader::GetRunLoader(evfoldname);
250 fRunLoader = AliRunLoader::Open(name);
254 AliError(Form("Can not open session for file %s.",name));
265 //_____________________________________________________________________________
266 Bool_t AliTRDclusterizer::OpenOutput()
269 // Open the output file
272 TObjArray *ioArray = 0;
274 AliLoader* loader = fRunLoader->GetLoader("TRDLoader");
275 loader->MakeTree("R");
277 fClusterTree = loader->TreeR();
278 fClusterTree->Branch("TRDcluster","TObjArray",&ioArray,32000,0);
284 //_____________________________________________________________________________
285 Bool_t AliTRDclusterizer::OpenOutput(TTree *clusterTree)
288 // Connect the output tree
291 TObjArray *ioArray = 0;
293 fClusterTree = clusterTree;
294 fClusterTree->Branch("TRDcluster","TObjArray",&ioArray,32000,0);
298 if (AliTRDReconstructor::GetRecoParam()->IsTrackletWriteEnabled()){
299 TString evfoldname = AliConfig::GetDefaultEventFolderName();
300 fRunLoader = AliRunLoader::GetRunLoader(evfoldname);
303 fRunLoader = AliRunLoader::Open("galice.root");
306 AliError(Form("Can not open session for file galice.root."));
310 UInt_t **leaves = new UInt_t *[2];
311 AliDataLoader *dl = fRunLoader->GetLoader("TRDLoader")->GetDataLoader("tracklets");
313 AliError("Could not get the tracklets data loader!");
314 AliDataLoader *dl = new AliDataLoader("TRD.Tracklets.root","tracklets", "tracklets");
315 fRunLoader->GetLoader("TRDLoader")->AddDataLoader(dl);
318 fTrackletTree = dl->Tree();
322 fTrackletTree = dl->Tree();
324 TBranch *trkbranch = fTrackletTree->GetBranch("trkbranch");
326 fTrackletTree->Branch("trkbranch",leaves[0],"det/i:side/i:tracklets[256]/i");
334 //_____________________________________________________________________________
335 Bool_t AliTRDclusterizer::OpenInput(Int_t nEvent)
338 // Opens a ROOT-file with TRD-hits and reads in the digits-tree
341 // Import the Trees for the event nEvent in the file
342 fRunLoader->GetEvent(nEvent);
348 //_____________________________________________________________________________
349 Bool_t AliTRDclusterizer::WriteClusters(Int_t det)
352 // Fills TRDcluster branch in the tree with the clusters
353 // found in detector = det. For det=-1 writes the tree.
357 (det >= AliTRDgeometry::Ndet())) {
358 AliError(Form("Unexpected detector index %d.\n",det));
362 TBranch *branch = fClusterTree->GetBranch("TRDcluster");
364 TObjArray *ioArray = 0;
365 branch = fClusterTree->Branch("TRDcluster","TObjArray",&ioArray,32000,0);
369 (det < AliTRDgeometry::Ndet())) {
371 Int_t nRecPoints = RecPoints()->GetEntriesFast();
372 TObjArray *detRecPoints = new TObjArray(400);
374 for (Int_t i = 0; i < nRecPoints; i++) {
375 AliTRDcluster *c = (AliTRDcluster *) RecPoints()->UncheckedAt(i);
376 if (det == c->GetDetector()) {
377 detRecPoints->AddLast(c);
380 AliError(Form("Attempt to write a cluster with unexpected detector index: got=%d expected=%d\n"
386 branch->SetAddress(&detRecPoints);
387 fClusterTree->Fill();
397 AliInfo(Form("Writing the cluster tree %s for event %d."
398 ,fClusterTree->GetName(),fRunLoader->GetEventNumber()));
402 branch->SetAddress(&fRecPoints);
404 AliLoader *loader = fRunLoader->GetLoader("TRDLoader");
405 loader->WriteRecPoints("OVERWRITE");
410 AliError("Cluster tree does not exist. Cannot write clusters.\n");
419 AliError(Form("Unexpected detector index %d.\n",det));
425 //_____________________________________________________________________________
426 Bool_t AliTRDclusterizer::WriteTracklets(Int_t det)
429 UInt_t **leaves = new UInt_t *[2];
430 for (Int_t i=0; i<2 ;i++){
431 leaves[i] = new UInt_t[258];
432 leaves[i][0] = det; // det
433 leaves[i][1] = i; // side
434 memcpy(leaves[i]+2, fTrackletContainer[i], sizeof(UInt_t) * 256);
439 AliDataLoader *dl = fRunLoader->GetLoader("TRDLoader")->GetDataLoader("tracklets");
441 fTrackletTree = dl->Tree();
444 TBranch *trkbranch = fTrackletTree->GetBranch("trkbranch");
446 trkbranch = fTrackletTree->Branch("trkbranch",leaves[0],"det/i:side/i:tracklets[256]/i");
449 for (Int_t i=0; i<2; i++){
450 if (leaves[i][2]>0) {
451 trkbranch->SetAddress(leaves[i]);
452 fTrackletTree->Fill();
456 AliDataLoader *dl = fRunLoader->GetLoader("TRDLoader")->GetDataLoader("tracklets");
457 dl->WriteData("OVERWRITE");
464 //_____________________________________________________________________________
465 void AliTRDclusterizer::ResetHelperIndexes(AliTRDSignalIndex *indexesIn)
468 // Reset the helper indexes
473 // carefull here - we assume that only row number may change - most probable
474 if (indexesIn->GetNrow() <= fIndexesOut->GetNrow())
475 fIndexesOut->ResetContent();
477 fIndexesOut->ResetContentConditional(indexesIn->GetNrow()
478 , indexesIn->GetNcol()
479 , indexesIn->GetNtime());
483 fIndexesOut = new AliTRDSignalIndex(indexesIn->GetNrow()
484 , indexesIn->GetNcol()
485 , indexesIn->GetNtime());
490 // carefull here - we assume that only row number may change - most probable
491 if (indexesIn->GetNrow() <= fIndexesMaxima->GetNrow())
493 fIndexesMaxima->ResetContent();
497 fIndexesMaxima->ResetContentConditional(indexesIn->GetNrow()
498 , indexesIn->GetNcol()
499 , indexesIn->GetNtime());
504 fIndexesMaxima = new AliTRDSignalIndex(indexesIn->GetNrow()
505 , indexesIn->GetNcol()
506 , indexesIn->GetNtime());
511 //_____________________________________________________________________________
512 Bool_t AliTRDclusterizer::ReadDigits()
515 // Reads the digits arrays from the input aliroot file
519 AliError("No run loader available");
523 AliLoader* loader = fRunLoader->GetLoader("TRDLoader");
524 if (!loader->TreeD()) {
525 loader->LoadDigits();
528 // Read in the digit arrays
529 return (fDigitsManager->ReadDigits(loader->TreeD()));
533 //_____________________________________________________________________________
534 Bool_t AliTRDclusterizer::ReadDigits(TTree *digitsTree)
537 // Reads the digits arrays from the input tree
540 // Read in the digit arrays
541 return (fDigitsManager->ReadDigits(digitsTree));
545 //_____________________________________________________________________________
546 Bool_t AliTRDclusterizer::ReadDigits(AliRawReader *rawReader)
549 // Reads the digits arrays from the ddl file
553 fDigitsManager = raw.Raw2Digits(rawReader);
559 //_____________________________________________________________________________
560 Bool_t AliTRDclusterizer::MakeClusters()
563 // Creates clusters from digits
566 // Propagate info from the digits manager
567 if (fAddLabels == kTRUE)
569 fAddLabels = fDigitsManager->UsesDictionaries();
572 Bool_t fReturn = kTRUE;
573 for (Int_t i = 0; i < AliTRDgeometry::kNdet; i++)
576 AliTRDdataArrayDigits *digitsIn = (AliTRDdataArrayDigits*) fDigitsManager->GetDigits(i);
577 // This is to take care of switched off super modules
578 if (!digitsIn->HasData())
583 AliTRDSignalIndex* indexes = fDigitsManager->GetIndexes(i);
584 if (indexes->IsAllocated() == kFALSE)
586 fDigitsManager->BuildIndexes(i);
590 if (indexes->HasEntry())
594 for (Int_t iDict = 0; iDict < AliTRDdigitsManager::kNDict; iDict++)
596 AliTRDdataArrayI *tracksIn = 0;
597 tracksIn = (AliTRDdataArrayI *) fDigitsManager->GetDictionary(i,iDict);
601 fR = MakeClusters(i);
602 fReturn = fR && fReturn;
611 // No compress just remove
612 fDigitsManager->RemoveDigits(i);
613 fDigitsManager->RemoveDictionaries(i);
614 fDigitsManager->ClearIndexes(i);
622 //_____________________________________________________________________________
623 Bool_t AliTRDclusterizer::Raw2Clusters(AliRawReader *rawReader)
626 // Creates clusters from raw data
629 return Raw2ClustersChamber(rawReader);
633 //_____________________________________________________________________________
634 Bool_t AliTRDclusterizer::Raw2ClustersChamber(AliRawReader *rawReader)
637 // Creates clusters from raw data
640 // Create the digits manager
643 fDigitsManager = new AliTRDdigitsManager();
644 fDigitsManager->CreateArrays();
647 fDigitsManager->SetUseDictionaries(fAddLabels);
649 // tracklet container for raw tracklet writing
650 if (!fTrackletContainer && AliTRDReconstructor::GetRecoParam()->IsTrackletWriteEnabled())
652 fTrackletContainer = new UInt_t *[2];
653 for (Int_t i=0; i<2 ;i++){
654 fTrackletContainer[i] = new UInt_t[256]; // maximum tracklets for one HC
658 AliTRDrawStreamBase *pinput = AliTRDrawStreamBase::GetRawStream(rawReader);
659 AliTRDrawStreamBase &input = *pinput;
661 AliInfo(Form("Stream version: %s", input.IsA()->GetName()));
664 while ((det = input.NextChamber(fDigitsManager,fTrackletContainer)) >= 0)
666 Bool_t iclusterBranch = kFALSE;
667 if (fDigitsManager->GetIndexes(det)->HasEntry())
669 iclusterBranch = MakeClusters(det);
671 if (iclusterBranch == kFALSE)
676 fDigitsManager->RemoveDigits(det);
677 fDigitsManager->RemoveDictionaries(det);
678 fDigitsManager->ClearIndexes(det);
680 if (!AliTRDReconstructor::GetRecoParam()-> IsTrackletWriteEnabled()) continue;
681 if (*(fTrackletContainer[0]) > 0 || *(fTrackletContainer[1]) > 0) WriteTracklets(det); // if there is tracklet words in this det
684 if (AliTRDReconstructor::GetRecoParam()->IsTrackletWriteEnabled()){
685 delete [] fTrackletContainer;
686 fTrackletContainer = NULL;
689 delete fDigitsManager;
690 fDigitsManager = NULL;
698 //_____________________________________________________________________________
699 UChar_t AliTRDclusterizer::GetStatus(Short_t &signal)
702 // Check if a pad is masked
707 if(signal>0 && TESTBIT(signal, 10)){
709 for(int ibit=0; ibit<4; ibit++){
710 if(TESTBIT(signal, 11+ibit)){
711 SETBIT(status, ibit);
712 CLRBIT(signal, 11+ibit);
719 //_____________________________________________________________________________
720 Bool_t AliTRDclusterizer::MakeClusters(Int_t det)
723 // Generates the cluster.
727 // digits should be expanded beforehand!
728 // digitsIn->Expand();
729 AliTRDdataArrayDigits *digitsIn = (AliTRDdataArrayDigits *) fDigitsManager->GetDigits(det);
731 // This is to take care of switched off super modules
732 if (!digitsIn->HasData())
737 AliTRDSignalIndex *indexesIn = fDigitsManager->GetIndexes(det);
738 if (indexesIn->IsAllocated() == kFALSE)
740 AliError("Indexes do not exist!");
744 AliTRDcalibDB *calibration = AliTRDcalibDB::Instance();
747 AliFatal("No AliTRDcalibDB instance available\n");
752 // There is no ADC threshold anymore, and simParam should not be used in clusterizer. KO
753 Float_t adcThreshold = 0;
755 if (!AliTRDReconstructor::GetRecoParam())
757 AliError("RecoParam does not exist\n");
761 // Threshold value for the maximum
762 Float_t maxThresh = AliTRDReconstructor::GetRecoParam()->GetClusMaxThresh();
763 // Threshold value for the digit signal
764 Float_t sigThresh = AliTRDReconstructor::GetRecoParam()->GetClusSigThresh();
766 // Threshold value for the maximum ( cut noise)
767 Float_t minMaxCutSigma = AliTRDReconstructor::GetRecoParam()->GetMinMaxCutSigma();
768 // Threshold value for the sum pad ( cut noise)
769 Float_t minLeftRightCutSigma = AliTRDReconstructor::GetRecoParam()->GetMinLeftRightCutSigma();
771 // Iteration limit for unfolding procedure
772 const Float_t kEpsilon = 0.01;
773 const Int_t kNclus = 3;
774 const Int_t kNsig = 5;
777 Double_t ratioLeft = 1.0;
778 Double_t ratioRight = 1.0;
780 Double_t padSignal[kNsig];
781 Double_t clusterSignal[kNclus];
783 Int_t istack = indexesIn->GetStack();
784 Int_t ilayer = indexesIn->GetLayer();
785 Int_t isector = indexesIn->GetSM();
787 // Start clustering in the chamber
789 Int_t idet = AliTRDgeometry::GetDetector(ilayer,istack,isector);
792 AliError("Strange Detector number Missmatch!");
796 // TRD space point transformation
797 fTransform->SetDetector(det);
799 Int_t iGeoLayer = AliGeomManager::kTRD1 + ilayer;
800 Int_t iGeoModule = istack + AliTRDgeometry::Nstack() * isector;
801 UShort_t volid = AliGeomManager::LayerToVolUID(iGeoLayer,iGeoModule);
803 Int_t nColMax = digitsIn->GetNcol();
804 Int_t nRowMax = digitsIn->GetNrow();
805 Int_t nTimeTotal = digitsIn->GetNtime();
807 // Detector wise calibration object for the gain factors
808 const AliTRDCalDet *calGainFactorDet = calibration->GetGainFactorDet();
809 // Calibration object with pad wise values for the gain factors
810 AliTRDCalROC *calGainFactorROC = calibration->GetGainFactorROC(idet);
811 // Calibration value for chamber wise gain factor
812 Float_t calGainFactorDetValue = calGainFactorDet->GetValue(idet);
815 // Detector wise calibration object for the noise
816 const AliTRDCalDet *calNoiseDet = calibration->GetNoiseDet();
817 // Calibration object with pad wise values for the noise
818 AliTRDCalROC *calNoiseROC = calibration->GetNoiseROC(idet);
819 // Calibration value for chamber wise noise
820 Float_t calNoiseDetValue = calNoiseDet->GetValue(idet);
824 AliTRDdataArrayF *digitsOut = new AliTRDdataArrayF(nRowMax, nColMax, nTimeTotal);
825 AliTRDdataArrayS padStatus(nRowMax, nColMax, nTimeTotal);
827 ResetHelperIndexes(indexesIn);
829 // Apply the gain and the tail cancelation via digital filter
830 TailCancelation(digitsIn
837 ,calGainFactorDetValue);
844 UChar_t status[3]={0, 0, 0}, ipos = 0;
845 fIndexesOut->ResetCounters();
846 while (fIndexesOut->NextRCTbinIndex(row, col, time)){
848 Float_t signalM = TMath::Abs(digitsOut->GetDataUnchecked(row,col,time));
849 status[1] = digitsIn->GetPadStatus(row,col,time);
850 if(status[1]) SETBIT(ipos, AliTRDcluster::kMaskedCenter);
852 if(signalM < maxThresh) continue;
854 Float_t noiseMiddleThresh = minMaxCutSigma*calNoiseDetValue*calNoiseROC->GetValue(col,row);
855 if (signalM < noiseMiddleThresh) continue;
857 if (col + 1 >= nColMax || col-1 < 0) continue;
859 Float_t signalL = TMath::Abs(digitsOut->GetDataUnchecked(row,col+1,time));
860 status[0] = digitsIn->GetPadStatus(row,col+1,time);
861 if(status[0]) SETBIT(ipos, AliTRDcluster::kMaskedLeft);
863 Float_t signalR = TMath::Abs(digitsOut->GetDataUnchecked(row,col-1,time));
864 status[2] = digitsIn->GetPadStatus(row,col-1,time);
865 if(status[2]) SETBIT(ipos, AliTRDcluster::kMaskedRight);
867 // reject candidates with more than 1 problematic pad
868 if(ipos == 3 || ipos > 4) continue;
870 if(!status[1]){ // good central pad
871 if(!ipos){ // all pads are OK
872 if ((signalL <= signalM) && (signalR < signalM)) {
873 if ((signalL >= sigThresh) || (signalR >= sigThresh)) {
874 Float_t noiseSumThresh = minLeftRightCutSigma*calNoiseDetValue*calNoiseROC->GetValue(col,row);
875 if((signalL+signalR+signalM) >= noiseSumThresh){
876 // Maximum found, mark the position by a negative signal
877 digitsOut->SetDataUnchecked(row,col,time,-signalM);
878 fIndexesMaxima->AddIndexTBin(row,col,time);
879 padStatus.SetDataUnchecked(row, col, time, ipos);
883 } else { // one of the neighbouring pads are bad
884 if(status[0] && signalR < signalM && signalR >= sigThresh){
885 digitsOut->SetDataUnchecked(row,col,time,-signalM);
886 digitsOut->SetDataUnchecked(row, col, time+1, 0.);
887 fIndexesMaxima->AddIndexTBin(row,col,time);
888 padStatus.SetDataUnchecked(row, col, time, ipos);
889 } else if(status[2] && signalL <= signalM && signalL >= sigThresh){
890 digitsOut->SetDataUnchecked(row,col,time,-signalM);
891 digitsOut->SetDataUnchecked(row, col, time-1, 0.);
892 fIndexesMaxima->AddIndexTBin(row,col,time);
893 padStatus.SetDataUnchecked(row, col, time, ipos);
896 } else { // wrong maximum pad
897 if ((signalL >= sigThresh) || (signalR >= sigThresh)) {
898 // Maximum found, mark the position by a negative signal
899 digitsOut->SetDataUnchecked(row,col,time,-maxThresh);
900 fIndexesMaxima->AddIndexTBin(row,col,time);
901 padStatus.SetDataUnchecked(row, col, time, ipos);
906 // The index to the first cluster of a given ROC
907 Int_t firstClusterROC = -1;
908 // The number of cluster in a given ROC
909 Int_t nClusterROC = 0;
911 // Now check the maxima and calculate the cluster position
912 fIndexesMaxima->ResetCounters();
913 while (fIndexesMaxima->NextRCTbinIndex(row, col, time)) {
916 if (digitsOut->GetDataUnchecked(row,col,time) < 0.0) {
918 for (iPad = 0; iPad < kNclus; iPad++) {
919 Int_t iPadCol = col - 1 + iPad;
920 clusterSignal[iPad] = TMath::Abs(digitsOut->GetDataUnchecked(row,iPadCol,time));
923 // Count the number of pads in the cluster
928 while (TMath::Abs(digitsOut->GetDataUnchecked(row,col-ii ,time)) >= sigThresh) {
931 if (col-ii < 0) break;
935 while (TMath::Abs(digitsOut->GetDataUnchecked(row,col+ii+1,time)) >= sigThresh){
938 if (col+ii+1 >= nColMax) break;
942 // Look for 5 pad cluster with minimum in the middle
943 Bool_t fivePadCluster = kFALSE;
944 if (col < (nColMax - 3)){
945 if (digitsOut->GetDataUnchecked(row,col+2,time) < 0) {
946 fivePadCluster = kTRUE;
948 if ((fivePadCluster) && (col < (nColMax - 5))) {
949 if (digitsOut->GetDataUnchecked(row,col+4,time) >= sigThresh){
950 fivePadCluster = kFALSE;
953 if ((fivePadCluster) && (col > 1)){
954 if (digitsOut->GetDataUnchecked(row,col-2,time) >= sigThresh){
955 fivePadCluster = kFALSE;
961 // Modify the signal of the overlapping pad for the left part
962 // of the cluster which remains from a previous unfolding
964 clusterSignal[0] *= ratioLeft;
968 // Unfold the 5 pad cluster
970 for (iPad = 0; iPad < kNsig; iPad++) {
971 padSignal[iPad] = TMath::Abs(digitsOut->GetDataUnchecked(row
975 // Unfold the two maxima and set the signal on
976 // the overlapping pad to the ratio
977 ratioRight = Unfold(kEpsilon,ilayer,padSignal);
978 ratioLeft = 1.0 - ratioRight;
979 clusterSignal[2] *= ratioRight;
983 // The position of the cluster in COL direction relative to the center pad (pad units)
984 Double_t clusterPosCol = 0.0;
985 if (AliTRDReconstructor::GetRecoParam()->IsLUT()) {
986 // Calculate the position of the cluster by using the
987 // lookup table method
988 clusterPosCol = LUTposition(ilayer,clusterSignal[2]
993 // Calculate the position of the cluster by using the
994 // center of gravity method
995 for (Int_t i = 0; i < kNsig; i++) {
998 padSignal[2] = TMath::Abs(digitsOut->GetDataUnchecked(row,col ,time)); // Central pad
999 padSignal[1] = TMath::Abs(digitsOut->GetDataUnchecked(row,col+1,time)); // Left pad
1000 padSignal[3] = TMath::Abs(digitsOut->GetDataUnchecked(row,col-1,time)); // Right pad
1002 (TMath::Abs(digitsOut->GetDataUnchecked(row,col-2,time)) < padSignal[1])) {
1003 padSignal[4] = TMath::Abs(digitsOut->GetDataUnchecked(row,col-2,time));
1005 if ((col < nColMax - 3) &&
1006 (TMath::Abs(digitsOut->GetDataUnchecked(row,col+2,time)) < padSignal[3])){
1007 padSignal[0] = TMath::Abs(digitsOut->GetDataUnchecked(row,col+2,time));
1009 clusterPosCol = GetCOG(padSignal);
1012 // Store the amplitudes of the pads in the cluster for later analysis
1013 // and check whether one of these pads is masked in the database
1014 Short_t signals[7] = { 0, 0, 0, 0, 0, 0, 0 };
1015 for (Int_t jPad = col-3; jPad <= col+3; jPad++) {
1017 (jPad >= nColMax-1)) {
1020 signals[jPad-col+3] = TMath::Nint(TMath::Abs(digitsOut->GetDataUnchecked(row,jPad,time)));
1023 // Transform the local cluster coordinates into calibrated
1024 // space point positions defined in the local tracking system.
1025 // Here the calibration for T0, Vdrift and ExB is applied as well.
1026 Double_t clusterXYZ[6];
1027 clusterXYZ[0] = clusterPosCol;
1028 clusterXYZ[1] = clusterSignal[2];
1029 clusterXYZ[2] = clusterSignal[1];
1030 clusterXYZ[3] = clusterSignal[0];
1031 clusterXYZ[4] = 0.0;
1032 clusterXYZ[5] = 0.0;
1033 Int_t clusterRCT[3];
1034 clusterRCT[0] = row;
1035 clusterRCT[1] = col;
1039 if (fTransform->Transform(clusterXYZ, clusterRCT, ((UInt_t) time), out, 0)) {
1041 // Add the cluster to the output array
1042 // The track indices will be stored later
1043 Float_t clusterPos[3];
1044 clusterPos[0] = clusterXYZ[0];
1045 clusterPos[1] = clusterXYZ[1];
1046 clusterPos[2] = clusterXYZ[2];
1047 Float_t clusterSig[2];
1048 clusterSig[0] = clusterXYZ[4];
1049 clusterSig[1] = clusterXYZ[5];
1050 Double_t clusterCharge = clusterXYZ[3];
1051 Char_t clusterTimeBin = ((Char_t) clusterRCT[2]);
1052 AliTRDcluster *cluster = new AliTRDcluster(idet
1057 ,((Char_t) nPadCount)
1065 cluster->SetInChamber(!out);
1067 UChar_t maskPosition = padStatus.GetDataUnchecked(row, col, time);
1069 cluster->SetPadMaskedPosition(maskPosition);
1070 if (maskPosition & AliTRDcluster::kMaskedLeft) {
1071 cluster->SetPadMaskedStatus(status[0]);
1073 else if (maskPosition & AliTRDcluster::kMaskedCenter) {
1074 cluster->SetPadMaskedStatus(status[1]);
1077 cluster->SetPadMaskedStatus(status[2]);
1081 // Temporarily store the row, column and time bin of the center pad
1082 // Used to later on assign the track indices
1083 cluster->SetLabel( row,0);
1084 cluster->SetLabel( col,1);
1085 cluster->SetLabel(time,2);
1087 RecPoints()->Add(cluster);
1089 // Store the index of the first cluster in the current ROC
1090 if (firstClusterROC < 0) {
1091 firstClusterROC = RecPoints()->GetEntriesFast() - 1;
1094 // Count the number of cluster in the current ROC
1097 } // if: Transform ok ?
1098 } // if: Maximum found ?
1103 if (fAddLabels) AddLabels(idet, firstClusterROC, nClusterROC);
1105 // Write the cluster and reset the array
1106 WriteClusters(idet);
1113 //_____________________________________________________________________________
1114 Bool_t AliTRDclusterizer::AddLabels(Int_t idet, Int_t firstClusterROC, Int_t nClusterROC)
1117 // Add the track indices to the found clusters
1120 const Int_t kNclus = 3;
1121 const Int_t kNdict = AliTRDdigitsManager::kNDict;
1122 const Int_t kNtrack = kNdict * kNclus;
1124 Int_t iClusterROC = 0;
1131 // Temporary array to collect the track indices
1132 Int_t *idxTracks = new Int_t[kNtrack*nClusterROC];
1134 // Loop through the dictionary arrays one-by-one
1135 // to keep memory consumption low
1136 AliTRDdataArrayI *tracksIn = 0;
1137 for (Int_t iDict = 0; iDict < kNdict; iDict++) {
1139 // tracksIn should be expanded beforehand!
1140 tracksIn = (AliTRDdataArrayI *) fDigitsManager->GetDictionary(idet,iDict);
1142 // Loop though the clusters found in this ROC
1143 for (iClusterROC = 0; iClusterROC < nClusterROC; iClusterROC++) {
1145 AliTRDcluster *cluster = (AliTRDcluster *)
1146 RecPoints()->UncheckedAt(firstClusterROC+iClusterROC);
1147 row = cluster->GetLabel(0);
1148 col = cluster->GetLabel(1);
1149 time = cluster->GetLabel(2);
1151 for (iPad = 0; iPad < kNclus; iPad++) {
1152 Int_t iPadCol = col - 1 + iPad;
1153 Int_t index = tracksIn->GetDataUnchecked(row,iPadCol,time) - 1;
1154 idxTracks[3*iPad+iDict + iClusterROC*kNtrack] = index;
1161 // Copy the track indices into the cluster
1162 // Loop though the clusters found in this ROC
1163 for (iClusterROC = 0; iClusterROC < nClusterROC; iClusterROC++) {
1165 AliTRDcluster *cluster = (AliTRDcluster *)
1166 RecPoints()->UncheckedAt(firstClusterROC+iClusterROC);
1167 cluster->SetLabel(-9999,0);
1168 cluster->SetLabel(-9999,1);
1169 cluster->SetLabel(-9999,2);
1171 cluster->AddTrackIndex(&idxTracks[iClusterROC*kNtrack]);
1175 delete [] idxTracks;
1181 //_____________________________________________________________________________
1182 Double_t AliTRDclusterizer::GetCOG(Double_t signal[5]) const
1186 // Used for clusters with more than 3 pads - where LUT not applicable
1189 Double_t sum = signal[0]
1196 Double_t res = (0.0 * (-signal[0] + signal[4])
1197 + (-signal[1] + signal[3])) / sum;
1203 //_____________________________________________________________________________
1204 Double_t AliTRDclusterizer::Unfold(Double_t eps, Int_t layer, Double_t *padSignal)
1207 // Method to unfold neighbouring maxima.
1208 // The charge ratio on the overlapping pad is calculated
1209 // until there is no more change within the range given by eps.
1210 // The resulting ratio is then returned to the calling method.
1213 AliTRDcalibDB *calibration = AliTRDcalibDB::Instance();
1215 AliError("No AliTRDcalibDB instance available\n");
1220 Int_t itStep = 0; // Count iteration steps
1222 Double_t ratio = 0.5; // Start value for ratio
1223 Double_t prevRatio = 0.0; // Store previous ratio
1225 Double_t newLeftSignal[3] = { 0.0, 0.0, 0.0 }; // Array to store left cluster signal
1226 Double_t newRightSignal[3] = { 0.0, 0.0, 0.0 }; // Array to store right cluster signal
1227 Double_t newSignal[3] = { 0.0, 0.0, 0.0 };
1229 // Start the iteration
1230 while ((TMath::Abs(prevRatio - ratio) > eps) && (itStep < 10)) {
1235 // Cluster position according to charge ratio
1236 Double_t maxLeft = (ratio*padSignal[2] - padSignal[0])
1237 / (padSignal[0] + padSignal[1] + ratio*padSignal[2]);
1238 Double_t maxRight = (padSignal[4] - (1-ratio)*padSignal[2])
1239 / ((1.0 - ratio)*padSignal[2] + padSignal[3] + padSignal[4]);
1241 // Set cluster charge ratio
1242 irc = calibration->PadResponse(1.0,maxLeft ,layer,newSignal);
1243 Double_t ampLeft = padSignal[1] / newSignal[1];
1244 irc = calibration->PadResponse(1.0,maxRight,layer,newSignal);
1245 Double_t ampRight = padSignal[3] / newSignal[1];
1247 // Apply pad response to parameters
1248 irc = calibration->PadResponse(ampLeft ,maxLeft ,layer,newLeftSignal );
1249 irc = calibration->PadResponse(ampRight,maxRight,layer,newRightSignal);
1251 // Calculate new overlapping ratio
1252 ratio = TMath::Min((Double_t) 1.0
1253 ,newLeftSignal[2] / (newLeftSignal[2] + newRightSignal[0]));
1261 //_____________________________________________________________________________
1262 void AliTRDclusterizer::TailCancelation(AliTRDdataArrayDigits *digitsIn
1263 , AliTRDdataArrayF *digitsOut
1264 , AliTRDSignalIndex *indexesIn
1265 , AliTRDSignalIndex *indexesOut
1267 , Float_t adcThreshold
1268 , AliTRDCalROC *calGainFactorROC
1269 , Float_t calGainFactorDetValue)
1272 // Applies the tail cancelation and gain factors:
1273 // Transform digitsIn to digitsOut
1280 Double_t *inADC = new Double_t[nTimeTotal]; // ADC data before tail cancellation
1281 Double_t *outADC = new Double_t[nTimeTotal]; // ADC data after tail cancellation
1282 indexesIn->ResetCounters();
1283 while (indexesIn->NextRCIndex(iRow, iCol))
1285 Float_t calGainFactorROCValue = calGainFactorROC->GetValue(iCol,iRow);
1286 Double_t gain = calGainFactorDetValue
1287 * calGainFactorROCValue;
1289 Bool_t corrupted = kFALSE;
1290 for (iTime = 0; iTime < nTimeTotal; iTime++)
1292 // Apply gain gain factor
1293 inADC[iTime] = digitsIn->GetDataUnchecked(iRow,iCol,iTime);
1294 if(digitsIn->GetPadStatus(iRow, iCol, iTime)) corrupted = kTRUE;
1295 inADC[iTime] /= gain;
1296 outADC[iTime] = inADC[iTime];
1300 // Apply the tail cancelation via the digital filter
1301 // (only for non-coorupted pads)
1302 if (AliTRDReconstructor::GetRecoParam()->IsTailCancelation())
1304 DeConvExp(inADC,outADC,nTimeTotal,AliTRDReconstructor::GetRecoParam()->GetTCnexp());
1308 indexesIn->ResetTbinCounter();
1309 while (indexesIn->NextTbinIndex(iTime))
1311 // Store the amplitude of the digit if above threshold
1312 if (outADC[iTime] > adcThreshold)
1314 digitsOut->SetDataUnchecked(iRow,iCol,iTime,outADC[iTime]);
1315 indexesOut->AddIndexTBin(iRow,iCol,iTime);
1319 } // while irow icol
1328 //_____________________________________________________________________________
1329 void AliTRDclusterizer::DeConvExp(Double_t *source, Double_t *target
1330 , Int_t n, Int_t nexp)
1333 // Tail cancellation by deconvolution for PASA v4 TRF
1337 Double_t coefficients[2];
1339 // Initialization (coefficient = alpha, rates = lambda)
1345 if (nexp == 1) { // 1 Exponentials
1351 if (nexp == 2) { // 2 Exponentials
1358 coefficients[0] = c1;
1359 coefficients[1] = c2;
1363 rates[0] = TMath::Exp(-dt/(r1));
1364 rates[1] = TMath::Exp(-dt/(r2));
1369 Double_t reminder[2];
1370 Double_t correction = 0.0;
1371 Double_t result = 0.0;
1373 // Attention: computation order is important
1374 for (k = 0; k < nexp; k++) {
1378 for (i = 0; i < n; i++) {
1380 result = (source[i] - correction); // No rescaling
1383 for (k = 0; k < nexp; k++) {
1384 reminder[k] = rates[k] * (reminder[k] + coefficients[k] * result);
1388 for (k = 0; k < nexp; k++) {
1389 correction += reminder[k];
1396 //_____________________________________________________________________________
1397 void AliTRDclusterizer::ResetRecPoints()
1400 // Resets the list of rec points
1404 fRecPoints->Delete();
1409 //_____________________________________________________________________________
1410 TObjArray *AliTRDclusterizer::RecPoints()
1413 // Returns the list of rec points
1417 fRecPoints = new TObjArray(400);
1424 //_____________________________________________________________________________
1425 void AliTRDclusterizer::FillLUT()
1431 const Int_t kNlut = 128;
1433 fLUTbin = AliTRDgeometry::kNlayer * kNlut;
1435 // The lookup table from Bogdan
1436 Float_t lut[AliTRDgeometry::kNlayer][kNlut] = {
1438 0.0070, 0.0150, 0.0224, 0.0298, 0.0374, 0.0454, 0.0533, 0.0611,
1439 0.0684, 0.0755, 0.0827, 0.0900, 0.0975, 0.1049, 0.1120, 0.1187,
1440 0.1253, 0.1318, 0.1385, 0.1453, 0.1519, 0.1584, 0.1646, 0.1704,
1441 0.1762, 0.1821, 0.1879, 0.1938, 0.1996, 0.2053, 0.2108, 0.2160,
1442 0.2210, 0.2260, 0.2310, 0.2361, 0.2411, 0.2461, 0.2509, 0.2557,
1443 0.2602, 0.2646, 0.2689, 0.2732, 0.2774, 0.2816, 0.2859, 0.2901,
1444 0.2942, 0.2983, 0.3022, 0.3061, 0.3099, 0.3136, 0.3172, 0.3207,
1445 0.3242, 0.3278, 0.3312, 0.3347, 0.3382, 0.3416, 0.3450, 0.3483,
1446 0.3515, 0.3547, 0.3579, 0.3609, 0.3639, 0.3669, 0.3698, 0.3727,
1447 0.3756, 0.3785, 0.3813, 0.3842, 0.3870, 0.3898, 0.3926, 0.3952,
1448 0.3979, 0.4005, 0.4032, 0.4057, 0.4082, 0.4108, 0.4132, 0.4157,
1449 0.4181, 0.4205, 0.4228, 0.4252, 0.4275, 0.4299, 0.4322, 0.4345,
1450 0.4367, 0.4390, 0.4412, 0.4434, 0.4456, 0.4478, 0.4499, 0.4520,
1451 0.4541, 0.4562, 0.4583, 0.4603, 0.4623, 0.4643, 0.4663, 0.4683,
1452 0.4702, 0.4722, 0.4741, 0.4758, 0.4774, 0.4790, 0.4805, 0.4824,
1453 0.4844, 0.4863, 0.4883, 0.4902, 0.4921, 0.4940, 0.4959, 0.4978
1456 0.0072, 0.0156, 0.0235, 0.0313, 0.0394, 0.0478, 0.0561, 0.0642,
1457 0.0718, 0.0792, 0.0868, 0.0947, 0.1025, 0.1101, 0.1172, 0.1241,
1458 0.1309, 0.1378, 0.1449, 0.1518, 0.1586, 0.1650, 0.1710, 0.1770,
1459 0.1830, 0.1891, 0.1952, 0.2011, 0.2070, 0.2125, 0.2177, 0.2229,
1460 0.2280, 0.2332, 0.2383, 0.2435, 0.2484, 0.2533, 0.2581, 0.2627,
1461 0.2670, 0.2714, 0.2757, 0.2799, 0.2842, 0.2884, 0.2927, 0.2968,
1462 0.3008, 0.3048, 0.3086, 0.3123, 0.3159, 0.3195, 0.3231, 0.3266,
1463 0.3301, 0.3335, 0.3370, 0.3404, 0.3438, 0.3471, 0.3504, 0.3536,
1464 0.3567, 0.3598, 0.3628, 0.3657, 0.3686, 0.3715, 0.3744, 0.3772,
1465 0.3800, 0.3828, 0.3856, 0.3884, 0.3911, 0.3938, 0.3965, 0.3991,
1466 0.4016, 0.4042, 0.4067, 0.4092, 0.4116, 0.4140, 0.4164, 0.4187,
1467 0.4211, 0.4234, 0.4257, 0.4280, 0.4302, 0.4325, 0.4347, 0.4369,
1468 0.4391, 0.4413, 0.4434, 0.4456, 0.4477, 0.4497, 0.4518, 0.4538,
1469 0.4558, 0.4578, 0.4598, 0.4618, 0.4637, 0.4656, 0.4675, 0.4694,
1470 0.4713, 0.4732, 0.4750, 0.4766, 0.4781, 0.4797, 0.4813, 0.4832,
1471 0.4851, 0.4870, 0.4888, 0.4906, 0.4925, 0.4942, 0.4960, 0.4978
1474 0.0075, 0.0163, 0.0246, 0.0328, 0.0415, 0.0504, 0.0592, 0.0674,
1475 0.0753, 0.0832, 0.0914, 0.0996, 0.1077, 0.1154, 0.1225, 0.1296,
1476 0.1369, 0.1442, 0.1515, 0.1585, 0.1652, 0.1714, 0.1776, 0.1839,
1477 0.1902, 0.1965, 0.2025, 0.2085, 0.2141, 0.2194, 0.2247, 0.2299,
1478 0.2352, 0.2405, 0.2457, 0.2507, 0.2557, 0.2604, 0.2649, 0.2693,
1479 0.2737, 0.2780, 0.2823, 0.2867, 0.2909, 0.2951, 0.2992, 0.3033,
1480 0.3072, 0.3110, 0.3146, 0.3182, 0.3218, 0.3253, 0.3288, 0.3323,
1481 0.3357, 0.3392, 0.3426, 0.3459, 0.3492, 0.3524, 0.3555, 0.3586,
1482 0.3616, 0.3645, 0.3674, 0.3703, 0.3731, 0.3759, 0.3787, 0.3815,
1483 0.3843, 0.3870, 0.3897, 0.3925, 0.3950, 0.3976, 0.4002, 0.4027,
1484 0.4052, 0.4076, 0.4101, 0.4124, 0.4148, 0.4171, 0.4194, 0.4217,
1485 0.4239, 0.4262, 0.4284, 0.4306, 0.4328, 0.4350, 0.4371, 0.4393,
1486 0.4414, 0.4435, 0.4455, 0.4476, 0.4496, 0.4516, 0.4536, 0.4555,
1487 0.4575, 0.4594, 0.4613, 0.4632, 0.4650, 0.4669, 0.4687, 0.4705,
1488 0.4723, 0.4741, 0.4758, 0.4773, 0.4789, 0.4804, 0.4821, 0.4839,
1489 0.4857, 0.4875, 0.4893, 0.4910, 0.4928, 0.4945, 0.4961, 0.4978
1492 0.0078, 0.0171, 0.0258, 0.0345, 0.0438, 0.0532, 0.0624, 0.0708,
1493 0.0791, 0.0875, 0.0962, 0.1048, 0.1130, 0.1206, 0.1281, 0.1356,
1494 0.1432, 0.1508, 0.1582, 0.1651, 0.1716, 0.1780, 0.1845, 0.1910,
1495 0.1975, 0.2038, 0.2099, 0.2155, 0.2210, 0.2263, 0.2317, 0.2371,
1496 0.2425, 0.2477, 0.2528, 0.2578, 0.2626, 0.2671, 0.2715, 0.2759,
1497 0.2803, 0.2846, 0.2890, 0.2933, 0.2975, 0.3016, 0.3056, 0.3095,
1498 0.3132, 0.3168, 0.3204, 0.3239, 0.3274, 0.3309, 0.3344, 0.3378,
1499 0.3412, 0.3446, 0.3479, 0.3511, 0.3543, 0.3574, 0.3603, 0.3633,
1500 0.3662, 0.3690, 0.3718, 0.3747, 0.3774, 0.3802, 0.3829, 0.3857,
1501 0.3883, 0.3910, 0.3936, 0.3962, 0.3987, 0.4012, 0.4037, 0.4061,
1502 0.4085, 0.4109, 0.4132, 0.4155, 0.4177, 0.4200, 0.4222, 0.4244,
1503 0.4266, 0.4288, 0.4309, 0.4331, 0.4352, 0.4373, 0.4394, 0.4414,
1504 0.4435, 0.4455, 0.4475, 0.4494, 0.4514, 0.4533, 0.4552, 0.4571,
1505 0.4590, 0.4608, 0.4626, 0.4645, 0.4662, 0.4680, 0.4698, 0.4715,
1506 0.4733, 0.4750, 0.4766, 0.4781, 0.4796, 0.4812, 0.4829, 0.4846,
1507 0.4863, 0.4880, 0.4897, 0.4914, 0.4930, 0.4946, 0.4963, 0.4979
1510 0.0081, 0.0178, 0.0270, 0.0364, 0.0463, 0.0562, 0.0656, 0.0744,
1511 0.0831, 0.0921, 0.1013, 0.1102, 0.1183, 0.1261, 0.1339, 0.1419,
1512 0.1499, 0.1576, 0.1648, 0.1715, 0.1782, 0.1849, 0.1917, 0.1984,
1513 0.2048, 0.2110, 0.2167, 0.2223, 0.2278, 0.2333, 0.2389, 0.2444,
1514 0.2497, 0.2548, 0.2598, 0.2645, 0.2691, 0.2735, 0.2780, 0.2824,
1515 0.2868, 0.2912, 0.2955, 0.2997, 0.3038, 0.3078, 0.3116, 0.3152,
1516 0.3188, 0.3224, 0.3259, 0.3294, 0.3329, 0.3364, 0.3398, 0.3432,
1517 0.3465, 0.3497, 0.3529, 0.3561, 0.3591, 0.3620, 0.3649, 0.3677,
1518 0.3705, 0.3733, 0.3761, 0.3788, 0.3816, 0.3843, 0.3869, 0.3896,
1519 0.3922, 0.3948, 0.3973, 0.3998, 0.4022, 0.4047, 0.4070, 0.4094,
1520 0.4117, 0.4139, 0.4162, 0.4184, 0.4206, 0.4227, 0.4249, 0.4270,
1521 0.4291, 0.4313, 0.4334, 0.4354, 0.4375, 0.4395, 0.4415, 0.4435,
1522 0.4455, 0.4474, 0.4493, 0.4512, 0.4531, 0.4550, 0.4568, 0.4586,
1523 0.4604, 0.4622, 0.4639, 0.4657, 0.4674, 0.4691, 0.4708, 0.4725,
1524 0.4742, 0.4758, 0.4773, 0.4788, 0.4803, 0.4819, 0.4836, 0.4852,
1525 0.4869, 0.4885, 0.4901, 0.4917, 0.4933, 0.4948, 0.4964, 0.4979
1528 0.0085, 0.0189, 0.0288, 0.0389, 0.0497, 0.0603, 0.0699, 0.0792,
1529 0.0887, 0.0985, 0.1082, 0.1170, 0.1253, 0.1336, 0.1421, 0.1505,
1530 0.1587, 0.1662, 0.1733, 0.1803, 0.1874, 0.1945, 0.2014, 0.2081,
1531 0.2143, 0.2201, 0.2259, 0.2316, 0.2374, 0.2431, 0.2487, 0.2541,
1532 0.2593, 0.2642, 0.2689, 0.2735, 0.2781, 0.2826, 0.2872, 0.2917,
1533 0.2961, 0.3003, 0.3045, 0.3086, 0.3125, 0.3162, 0.3198, 0.3235,
1534 0.3270, 0.3306, 0.3342, 0.3377, 0.3411, 0.3446, 0.3479, 0.3511,
1535 0.3543, 0.3575, 0.3605, 0.3634, 0.3663, 0.3691, 0.3720, 0.3748,
1536 0.3775, 0.3803, 0.3830, 0.3857, 0.3884, 0.3911, 0.3937, 0.3962,
1537 0.3987, 0.4012, 0.4036, 0.4060, 0.4084, 0.4107, 0.4129, 0.4152,
1538 0.4174, 0.4196, 0.4218, 0.4239, 0.4261, 0.4282, 0.4303, 0.4324,
1539 0.4344, 0.4365, 0.4385, 0.4405, 0.4425, 0.4445, 0.4464, 0.4483,
1540 0.4502, 0.4521, 0.4539, 0.4558, 0.4576, 0.4593, 0.4611, 0.4629,
1541 0.4646, 0.4663, 0.4680, 0.4697, 0.4714, 0.4730, 0.4747, 0.4759,
1542 0.4769, 0.4780, 0.4790, 0.4800, 0.4811, 0.4827, 0.4843, 0.4859,
1543 0.4874, 0.4889, 0.4905, 0.4920, 0.4935, 0.4950, 0.4965, 0.4979
1550 fLUT = new Double_t[fLUTbin];
1552 for (Int_t ilayer = 0; ilayer < AliTRDgeometry::kNlayer; ilayer++) {
1553 for (Int_t ilut = 0; ilut < kNlut; ilut++ ) {
1554 fLUT[ilayer*kNlut+ilut] = lut[ilayer][ilut];
1560 //_____________________________________________________________________________
1561 Double_t AliTRDclusterizer::LUTposition(Int_t ilayer, Double_t ampL
1562 , Double_t ampC, Double_t ampR) const
1565 // Calculates the cluster position using the lookup table.
1566 // Method provided by Bogdan Vulpescu.
1569 const Int_t kNlut = 128;
1580 Double_t xMin[AliTRDgeometry::kNlayer] = { 0.006492, 0.006377, 0.006258
1581 , 0.006144, 0.006030, 0.005980 };
1582 Double_t xMax[AliTRDgeometry::kNlayer] = { 0.960351, 0.965870, 0.970445
1583 , 0.974352, 0.977667, 0.996101 };
1586 x = (ampL - ampR) / ampC;
1589 else if (ampL < ampR) {
1590 x = (ampR - ampL) / ampC;
1596 xmin = xMin[ilayer] + 0.000005;
1597 xmax = xMax[ilayer] - 0.000005;
1598 xwid = (xmax - xmin) / 127.0;
1603 else if (x > xmax) {
1604 pos = side * 0.5000;
1607 ix = (Int_t) ((x - xmin) / xwid);
1608 pos = side * fLUT[ilayer*kNlut+ix];