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 <TClonesArray.h>
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 "AliTRDarraySignal.h"
42 #include "AliTRDarrayDictionary.h"
43 #include "AliTRDarrayADC.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(AliTRDReconstructor *rec)
69 ,fTrackletContainer(NULL)
74 ,fTransform(new AliTRDtransform(0))
79 // AliTRDclusterizer default constructor
82 AliTRDcalibDB *trd = 0x0;
83 if (!(trd = AliTRDcalibDB::Instance())) {
84 AliFatal("Could not get calibration object");
87 fRawVersion = AliTRDfeeParam::Instance()->GetRAWversion();
89 // Initialize debug stream
91 if(fReconstructor->GetStreamLevel(AliTRDReconstructor::kClusterizer) > 1){
92 TDirectory *savedir = gDirectory;
93 //fgDebugStreamer = new TTreeSRedirector("TRD.ClusterizerDebug.root");
100 //_____________________________________________________________________________
101 AliTRDclusterizer::AliTRDclusterizer(const Text_t *name, const Text_t *title, AliTRDReconstructor *rec)
108 ,fDigitsManager(new AliTRDdigitsManager())
109 ,fTrackletContainer(NULL)
113 ,fIndexesMaxima(NULL)
114 ,fTransform(new AliTRDtransform(0))
119 // AliTRDclusterizer constructor
122 AliTRDcalibDB *trd = 0x0;
123 if (!(trd = AliTRDcalibDB::Instance())) {
124 AliFatal("Could not get calibration object");
127 // Initialize debug stream
129 if (fReconstructor->GetStreamLevel(AliTRDReconstructor::kClusterizer) > 1){
130 TDirectory *savedir = gDirectory;
131 //fgDebugStreamer = new TTreeSRedirector("TRD.ClusterizerDebug.root");
136 fDigitsManager->CreateArrays();
138 fRawVersion = AliTRDfeeParam::Instance()->GetRAWversion();
144 //_____________________________________________________________________________
145 AliTRDclusterizer::AliTRDclusterizer(const AliTRDclusterizer &c)
147 ,fReconstructor(c.fReconstructor)
152 ,fDigitsManager(NULL)
153 ,fTrackletContainer(NULL)
157 ,fIndexesMaxima(NULL)
163 // AliTRDclusterizer copy constructor
170 //_____________________________________________________________________________
171 AliTRDclusterizer::~AliTRDclusterizer()
174 // AliTRDclusterizer destructor
177 if (fRecPoints/* && IsClustersOwner()*/){
178 fRecPoints->Delete();
182 if (fDigitsManager) {
183 delete fDigitsManager;
184 fDigitsManager = NULL;
187 if (fTrackletContainer){
188 delete fTrackletContainer;
189 fTrackletContainer = NULL;
198 delete fIndexesMaxima;
199 fIndexesMaxima = NULL;
214 //_____________________________________________________________________________
215 AliTRDclusterizer &AliTRDclusterizer::operator=(const AliTRDclusterizer &c)
218 // Assignment operator
223 ((AliTRDclusterizer &) c).Copy(*this);
230 //_____________________________________________________________________________
231 void AliTRDclusterizer::Copy(TObject &c) const
237 ((AliTRDclusterizer &) c).fClusterTree = NULL;
238 ((AliTRDclusterizer &) c).fRecPoints = NULL;
239 ((AliTRDclusterizer &) c).fTrackletTree = NULL;
240 ((AliTRDclusterizer &) c).fDigitsManager = NULL;
241 ((AliTRDclusterizer &) c).fTrackletContainer = NULL;
242 ((AliTRDclusterizer &) c).fAddLabels = fAddLabels;
243 ((AliTRDclusterizer &) c).fRawVersion = fRawVersion;
244 ((AliTRDclusterizer &) c).fIndexesOut = NULL;
245 ((AliTRDclusterizer &) c).fIndexesMaxima = NULL;
246 ((AliTRDclusterizer &) c).fTransform = NULL;
247 ((AliTRDclusterizer &) c).fLUTbin = 0;
248 ((AliTRDclusterizer &) c).fLUT = NULL;
252 //_____________________________________________________________________________
253 Bool_t AliTRDclusterizer::Open(const Char_t *name, Int_t nEvent)
256 // Opens the AliROOT file. Output and input are in the same file
259 TString evfoldname = AliConfig::GetDefaultEventFolderName();
260 fRunLoader = AliRunLoader::GetRunLoader(evfoldname);
263 fRunLoader = AliRunLoader::Open(name);
267 AliError(Form("Can not open session for file %s.",name));
278 //_____________________________________________________________________________
279 Bool_t AliTRDclusterizer::OpenOutput()
282 // Open the output file
285 if (!fReconstructor->IsWritingClusters()) return kTRUE;
287 TObjArray *ioArray = 0x0;
289 AliLoader* loader = fRunLoader->GetLoader("TRDLoader");
290 loader->MakeTree("R");
292 fClusterTree = loader->TreeR();
293 fClusterTree->Branch("TRDcluster", "TObjArray", &ioArray, 32000, 0);
299 //_____________________________________________________________________________
300 Bool_t AliTRDclusterizer::OpenOutput(TTree *clusterTree)
303 // Connect the output tree
307 if (fReconstructor->IsWritingClusters()){
308 TObjArray *ioArray = 0x0;
309 fClusterTree = clusterTree;
310 fClusterTree->Branch("TRDcluster", "TObjArray", &ioArray, 32000, 0);
314 if (fReconstructor->IsWritingTracklets()){
315 TString evfoldname = AliConfig::GetDefaultEventFolderName();
316 fRunLoader = AliRunLoader::GetRunLoader(evfoldname);
319 fRunLoader = AliRunLoader::Open("galice.root");
322 AliError(Form("Can not open session for file galice.root."));
326 UInt_t **leaves = new UInt_t *[2];
327 AliDataLoader *dl = fRunLoader->GetLoader("TRDLoader")->GetDataLoader("tracklets");
329 AliError("Could not get the tracklets data loader!");
330 dl = new AliDataLoader("TRD.Tracklets.root","tracklets", "tracklets");
331 fRunLoader->GetLoader("TRDLoader")->AddDataLoader(dl);
334 fTrackletTree = dl->Tree();
338 fTrackletTree = dl->Tree();
340 TBranch *trkbranch = fTrackletTree->GetBranch("trkbranch");
342 fTrackletTree->Branch("trkbranch",leaves[0],"det/i:side/i:tracklets[256]/i");
350 //_____________________________________________________________________________
351 Bool_t AliTRDclusterizer::OpenInput(Int_t nEvent)
354 // Opens a ROOT-file with TRD-hits and reads in the digits-tree
357 // Import the Trees for the event nEvent in the file
358 fRunLoader->GetEvent(nEvent);
364 //_____________________________________________________________________________
365 Bool_t AliTRDclusterizer::WriteClusters(Int_t det)
368 // Fills TRDcluster branch in the tree with the clusters
369 // found in detector = det. For det=-1 writes the tree.
373 (det >= AliTRDgeometry::Ndet())) {
374 AliError(Form("Unexpected detector index %d.\n",det));
378 TObjArray *ioArray = new TObjArray(400);
379 TBranch *branch = fClusterTree->GetBranch("TRDcluster");
381 branch = fClusterTree->Branch("TRDcluster","TObjArray",&ioArray,32000,0);
382 } else branch->SetAddress(&ioArray);
384 Int_t nRecPoints = RecPoints()->GetEntriesFast();
386 for (Int_t i = 0; i < nRecPoints; i++) {
387 AliTRDcluster *c = (AliTRDcluster *) RecPoints()->UncheckedAt(i);
388 if(det != c->GetDetector()) continue;
391 fClusterTree->Fill();
395 for (Int_t i = 0; i < nRecPoints; i++) {
396 AliTRDcluster *c = (AliTRDcluster *) RecPoints()->UncheckedAt(i);
397 if(c->GetDetector() != detOld){
398 fClusterTree->Fill();
400 detOld = c->GetDetector();
411 //_____________________________________________________________________________
412 Bool_t AliTRDclusterizer::WriteTracklets(Int_t det)
415 // Write the raw data tracklets into seperate file
418 UInt_t **leaves = new UInt_t *[2];
419 for (Int_t i=0; i<2 ;i++){
420 leaves[i] = new UInt_t[258];
421 leaves[i][0] = det; // det
422 leaves[i][1] = i; // side
423 memcpy(leaves[i]+2, fTrackletContainer[i], sizeof(UInt_t) * 256);
427 AliDataLoader *dl = fRunLoader->GetLoader("TRDLoader")->GetDataLoader("tracklets");
429 fTrackletTree = dl->Tree();
432 TBranch *trkbranch = fTrackletTree->GetBranch("trkbranch");
434 trkbranch = fTrackletTree->Branch("trkbranch",leaves[0],"det/i:side/i:tracklets[256]/i");
437 for (Int_t i=0; i<2; i++){
438 if (leaves[i][2]>0) {
439 trkbranch->SetAddress(leaves[i]);
440 fTrackletTree->Fill();
444 AliDataLoader *dl = fRunLoader->GetLoader("TRDLoader")->GetDataLoader("tracklets");
445 dl->WriteData("OVERWRITE");
453 //_____________________________________________________________________________
454 void AliTRDclusterizer::ResetHelperIndexes(AliTRDSignalIndex *indexesIn)
457 // Reset the helper indexes
462 // carefull here - we assume that only row number may change - most probable
463 if (indexesIn->GetNrow() <= fIndexesOut->GetNrow())
464 fIndexesOut->ResetContent();
466 fIndexesOut->ResetContentConditional(indexesIn->GetNrow()
467 , indexesIn->GetNcol()
468 , indexesIn->GetNtime());
472 fIndexesOut = new AliTRDSignalIndex(indexesIn->GetNrow()
473 , indexesIn->GetNcol()
474 , indexesIn->GetNtime());
479 // carefull here - we assume that only row number may change - most probable
480 if (indexesIn->GetNrow() <= fIndexesMaxima->GetNrow())
482 fIndexesMaxima->ResetContent();
486 fIndexesMaxima->ResetContentConditional(indexesIn->GetNrow()
487 , indexesIn->GetNcol()
488 , indexesIn->GetNtime());
493 fIndexesMaxima = new AliTRDSignalIndex(indexesIn->GetNrow()
494 , indexesIn->GetNcol()
495 , indexesIn->GetNtime());
500 //_____________________________________________________________________________
501 Bool_t AliTRDclusterizer::ReadDigits()
504 // Reads the digits arrays from the input aliroot file
508 AliError("No run loader available");
512 AliLoader* loader = fRunLoader->GetLoader("TRDLoader");
513 if (!loader->TreeD()) {
514 loader->LoadDigits();
517 // Read in the digit arrays
518 return (fDigitsManager->ReadDigits(loader->TreeD()));
522 //_____________________________________________________________________________
523 Bool_t AliTRDclusterizer::ReadDigits(TTree *digitsTree)
526 // Reads the digits arrays from the input tree
529 // Read in the digit arrays
530 return (fDigitsManager->ReadDigits(digitsTree));
534 //_____________________________________________________________________________
535 Bool_t AliTRDclusterizer::ReadDigits(AliRawReader *rawReader)
538 // Reads the digits arrays from the ddl file
542 fDigitsManager = raw.Raw2Digits(rawReader);
548 //_____________________________________________________________________________
549 Bool_t AliTRDclusterizer::MakeClusters()
552 // Creates clusters from digits
555 // Propagate info from the digits manager
556 if (fAddLabels == kTRUE){
557 fAddLabels = fDigitsManager->UsesDictionaries();
560 Bool_t fReturn = kTRUE;
561 for (Int_t i = 0; i < AliTRDgeometry::kNdet; i++){
563 AliTRDarrayADC *digitsIn = (AliTRDarrayADC*) fDigitsManager->GetDigits(i); //mod
564 // This is to take care of switched off super modules
565 if (!digitsIn->HasData()) continue;
567 AliTRDSignalIndex* indexes = fDigitsManager->GetIndexes(i);
568 if (indexes->IsAllocated() == kFALSE){
569 fDigitsManager->BuildIndexes(i);
573 if (indexes->HasEntry()){
575 for (Int_t iDict = 0; iDict < AliTRDdigitsManager::kNDict; iDict++){
576 AliTRDarrayDictionary *tracksIn = 0; //mod
577 tracksIn = (AliTRDarrayDictionary *) fDigitsManager->GetDictionary(i,iDict); //mod
581 fR = MakeClusters(i);
582 fReturn = fR && fReturn;
586 // if(IsWritingClusters()) WriteClusters(i);
590 // No compress just remove
591 fDigitsManager->RemoveDigits(i);
592 fDigitsManager->RemoveDictionaries(i);
593 fDigitsManager->ClearIndexes(i);
596 if(fReconstructor->IsWritingClusters()) WriteClusters(-1);
598 AliInfo(Form("Number of found clusters : %d", RecPoints()->GetEntriesFast()));
604 //_____________________________________________________________________________
605 Bool_t AliTRDclusterizer::Raw2Clusters(AliRawReader *rawReader)
608 // Creates clusters from raw data
611 return Raw2ClustersChamber(rawReader);
615 //_____________________________________________________________________________
616 Bool_t AliTRDclusterizer::Raw2ClustersChamber(AliRawReader *rawReader)
619 // Creates clusters from raw data
622 // Create the digits manager
623 if (!fDigitsManager){
624 fDigitsManager = new AliTRDdigitsManager();
625 fDigitsManager->CreateArrays();
628 fDigitsManager->SetUseDictionaries(fAddLabels);
630 // tracklet container for raw tracklet writing
631 if (!fTrackletContainer && fReconstructor->IsWritingTracklets()) {
632 // maximum tracklets for one HC
633 const Int_t kTrackletChmb=256;
634 fTrackletContainer = new UInt_t *[2];
635 fTrackletContainer[0] = new UInt_t[kTrackletChmb];
636 fTrackletContainer[1] = new UInt_t[kTrackletChmb];
640 AliTRDrawStreamBase *pinput = AliTRDrawStreamBase::GetRawStream(rawReader);
641 AliTRDrawStreamBase &input = *pinput;
643 AliInfo(Form("Stream version: %s", input.IsA()->GetName()));
646 while ((det = input.NextChamber(fDigitsManager,fTrackletContainer)) >= 0){
647 Bool_t iclusterBranch = kFALSE;
648 if (fDigitsManager->GetIndexes(det)->HasEntry()){
649 iclusterBranch = MakeClusters(det);
652 fDigitsManager->RemoveDigits(det);
653 fDigitsManager->RemoveDictionaries(det);
654 fDigitsManager->ClearIndexes(det);
656 if (!fReconstructor->IsWritingTracklets()) continue;
657 if (*(fTrackletContainer[0]) > 0 || *(fTrackletContainer[1]) > 0) WriteTracklets(det);
659 if (fReconstructor->IsWritingTracklets()){
660 delete [] fTrackletContainer[0];
661 delete [] fTrackletContainer[1];
662 delete [] fTrackletContainer;
663 fTrackletContainer = NULL;
666 if(fReconstructor->IsWritingClusters()) WriteClusters(-1);
668 delete fDigitsManager;
669 fDigitsManager = NULL;
674 AliInfo(Form("Number of found clusters : %d", RecPoints()->GetEntriesFast()));
679 //_____________________________________________________________________________
680 UChar_t AliTRDclusterizer::GetStatus(Short_t &signal)
683 // Check if a pad is masked
688 if(signal>0 && TESTBIT(signal, 10)){
690 for(int ibit=0; ibit<4; ibit++){
691 if(TESTBIT(signal, 11+ibit)){
692 SETBIT(status, ibit);
693 CLRBIT(signal, 11+ibit);
700 //_____________________________________________________________________________
701 void AliTRDclusterizer::SetPadStatus(UChar_t status, UChar_t &out){
703 // Set the pad status into out
704 // First three bits are needed for the position encoding
706 status = status << 3;
710 //_____________________________________________________________________________
711 UChar_t AliTRDclusterizer::GetPadStatus(UChar_t encoding){
713 // return the staus encoding of the corrupted pad
715 return static_cast<UChar_t>(encoding >> 3);
718 //_____________________________________________________________________________
719 Int_t AliTRDclusterizer::GetCorruption(UChar_t encoding){
721 // Return the position of the corruption
726 //_____________________________________________________________________________
727 Bool_t AliTRDclusterizer::MakeClusters(Int_t det)
730 // Generates the cluster.
734 // digits should be expanded beforehand!
735 // digitsIn->Expand();
736 AliTRDarrayADC *digitsIn = (AliTRDarrayADC *) fDigitsManager->GetDigits(det); //mod
738 // This is to take care of switched off super modules
739 if (!digitsIn->HasData())
744 AliTRDSignalIndex *indexesIn = fDigitsManager->GetIndexes(det);
745 if (indexesIn->IsAllocated() == kFALSE)
747 AliError("Indexes do not exist!");
751 AliTRDcalibDB *calibration = AliTRDcalibDB::Instance();
754 AliFatal("No AliTRDcalibDB instance available\n");
759 // There is no ADC threshold anymore, and simParam should not be used in clusterizer. KO
760 Float_t adcThreshold = 0;
762 if (!fReconstructor){
763 AliError("Reconstructor not set\n");
767 // Threshold value for the maximum
768 Float_t maxThresh = fReconstructor->GetRecoParam()->GetClusMaxThresh();
769 // Threshold value for the digit signal
770 Float_t sigThresh = fReconstructor->GetRecoParam()->GetClusSigThresh();
772 // Threshold value for the maximum ( cut noise)
773 Float_t minMaxCutSigma = fReconstructor->GetRecoParam()->GetMinMaxCutSigma();
774 // Threshold value for the sum pad ( cut noise)
775 Float_t minLeftRightCutSigma = fReconstructor->GetRecoParam()->GetMinLeftRightCutSigma();
777 // Iteration limit for unfolding procedure
778 const Float_t kEpsilon = 0.01;
779 const Int_t kNclus = 3;
780 const Int_t kNsig = 5;
783 Double_t ratioLeft = 1.0;
784 Double_t ratioRight = 1.0;
786 Double_t padSignal[kNsig];
787 Double_t clusterSignal[kNclus];
789 Int_t istack = indexesIn->GetStack();
790 Int_t ilayer = indexesIn->GetLayer();
791 Int_t isector = indexesIn->GetSM();
793 // Start clustering in the chamber
795 Int_t idet = AliTRDgeometry::GetDetector(ilayer,istack,isector);
797 AliError("Strange Detector number Missmatch!");
801 // TRD space point transformation
802 fTransform->SetDetector(det);
804 Int_t iGeoLayer = AliGeomManager::kTRD1 + ilayer;
805 Int_t iGeoModule = istack + AliTRDgeometry::Nstack() * isector;
806 UShort_t volid = AliGeomManager::LayerToVolUID(iGeoLayer,iGeoModule);
808 Int_t nColMax = digitsIn->GetNcol();
809 Int_t nRowMax = digitsIn->GetNrow();
810 Int_t nTimeTotal = digitsIn->GetNtime();
812 // Detector wise calibration object for the gain factors
813 const AliTRDCalDet *calGainFactorDet = calibration->GetGainFactorDet();
814 // Calibration object with pad wise values for the gain factors
815 AliTRDCalROC *calGainFactorROC = calibration->GetGainFactorROC(idet);
816 // Calibration value for chamber wise gain factor
817 Float_t calGainFactorDetValue = calGainFactorDet->GetValue(idet);
819 // Detector wise calibration object for the noise
820 const AliTRDCalDet *calNoiseDet = calibration->GetNoiseDet();
821 // Calibration object with pad wise values for the noise
822 AliTRDCalROC *calNoiseROC = calibration->GetNoiseROC(idet);
823 // Calibration value for chamber wise noise
824 Float_t calNoiseDetValue = calNoiseDet->GetValue(idet);
828 AliTRDarraySignal *digitsOut = new AliTRDarraySignal(nRowMax, nColMax, nTimeTotal);
829 AliTRDarrayADC padStatus(nRowMax, nColMax, nTimeTotal);
831 ResetHelperIndexes(indexesIn);
833 // Apply the gain and the tail cancelation via digital filter
834 TailCancelation(digitsIn
841 ,calGainFactorDetValue);
848 UChar_t status[3]={0, 0, 0}, ipos = 0;
849 fIndexesOut->ResetCounters();
850 while (fIndexesOut->NextRCTbinIndex(row, col, time)) {
852 ipos = 0; for(Int_t is=3; is--;) status[is] = 0;
854 Float_t signalM = TMath::Abs(digitsOut->GetData(row,col,time));
855 status[1] = digitsIn->GetPadStatus(row,col,time);
856 if(status[1]) SETBIT(ipos, AliTRDcluster::kMaskedCenter);
858 if(signalM < maxThresh) continue;
860 Float_t noiseMiddleThresh = minMaxCutSigma*calNoiseDetValue*calNoiseROC->GetValue(col,row);
861 if (signalM < noiseMiddleThresh) continue;
863 if (col + 1 >= nColMax || col-1 < 0) continue;
865 Float_t signalL = TMath::Abs(digitsOut->GetData(row,col+1,time));
866 status[0] = digitsIn->GetPadStatus(row,col+1,time);
867 if(status[0]) SETBIT(ipos, AliTRDcluster::kMaskedLeft);
869 Float_t signalR = TMath::Abs(digitsOut->GetData(row,col-1,time));
870 status[2] = digitsIn->GetPadStatus(row,col-1,time);
871 if(status[2]) SETBIT(ipos, AliTRDcluster::kMaskedRight);
873 // reject candidates with more than 1 problematic pad
874 if(ipos == 3 || ipos > 4) continue;
876 if (!status[1]) { // good central pad
877 if (!ipos) { // all pads are OK
878 if ((signalL <= signalM) && (signalR < signalM)) {
879 if ((signalL >= sigThresh) || (signalR >= sigThresh)) {
880 Float_t noiseSumThresh = minLeftRightCutSigma
882 * calNoiseROC->GetValue(col,row);
883 if ((signalL+signalR+signalM) >= noiseSumThresh) {
884 // Maximum found, mark the position by a negative signal
885 digitsOut->SetData(row,col,time,-signalM);
886 fIndexesMaxima->AddIndexTBin(row,col,time);
887 padStatus.SetData(row, col, time, ipos); // No corruption
891 } else { // one of the neighbouring pads are bad
892 if (status[0] && signalR < signalM && signalR >= sigThresh) {
893 digitsOut->SetData(row,col,time,-signalM);
894 digitsOut->SetData(row, col, time+1, 0.);
895 fIndexesMaxima->AddIndexTBin(row,col,time);
896 SetPadStatus(status[0], ipos);
897 padStatus.SetData(row, col, time, ipos);
899 else if (status[2] && signalL <= signalM && signalL >= sigThresh) {
900 digitsOut->SetData(row,col,time,-signalM);
901 digitsOut->SetData(row, col, time-1, 0.);
902 fIndexesMaxima->AddIndexTBin(row,col,time);
903 SetPadStatus(status[2], ipos);
904 padStatus.SetData(row, col, time, ipos);
908 else { // wrong maximum pad
909 if ((signalL >= sigThresh) || (signalR >= sigThresh)) {
910 // Maximum found, mark the position by a negative signal
911 digitsOut->SetData(row,col,time,-maxThresh);
912 fIndexesMaxima->AddIndexTBin(row,col,time);
913 SetPadStatus(status[1], ipos);
914 padStatus.SetData(row, col, time, ipos);
919 // The index to the first cluster of a given ROC
920 Int_t firstClusterROC = -1;
921 // The number of cluster in a given ROC
922 Int_t nClusterROC = 0;
924 // Now check the maxima and calculate the cluster position
925 fIndexesMaxima->ResetCounters();
926 while (fIndexesMaxima->NextRCTbinIndex(row, col, time)) {
929 if (digitsOut->GetData(row,col,time) < 0.0) {
931 for (iPad = 0; iPad < kNclus; iPad++) {
932 Int_t iPadCol = col - 1 + iPad;
933 clusterSignal[iPad] = TMath::Abs(digitsOut->GetData(row,iPadCol,time));
936 // Count the number of pads in the cluster
941 while (TMath::Abs(digitsOut->GetData(row,col-ii ,time)) >= sigThresh) {
944 if (col-ii < 0) break;
948 while (TMath::Abs(digitsOut->GetData(row,col+ii+1,time)) >= sigThresh) {
951 if (col+ii+1 >= nColMax) break;
955 // Look for 5 pad cluster with minimum in the middle
956 Bool_t fivePadCluster = kFALSE;
957 if (col < (nColMax - 3)){
958 if (digitsOut->GetData(row,col+2,time) < 0) {
959 fivePadCluster = kTRUE;
961 if ((fivePadCluster) && (col < (nColMax - 5))) {
962 if (digitsOut->GetData(row,col+4,time) >= sigThresh) {
963 fivePadCluster = kFALSE;
966 if ((fivePadCluster) && (col > 1)) {
967 if (digitsOut->GetData(row,col-2,time) >= sigThresh) {
968 fivePadCluster = kFALSE;
974 // Modify the signal of the overlapping pad for the left part
975 // of the cluster which remains from a previous unfolding
977 clusterSignal[0] *= ratioLeft;
981 // Unfold the 5 pad cluster
982 if (fivePadCluster) {
983 for (iPad = 0; iPad < kNsig; iPad++) {
984 padSignal[iPad] = TMath::Abs(digitsOut->GetData(row
988 // Unfold the two maxima and set the signal on
989 // the overlapping pad to the ratio
990 ratioRight = Unfold(kEpsilon,ilayer,padSignal);
991 ratioLeft = 1.0 - ratioRight;
992 clusterSignal[2] *= ratioRight;
996 // The position of the cluster in COL direction relative to the center pad (pad units)
997 Double_t clusterPosCol = 0.0;
998 if (fReconstructor->GetRecoParam()->IsLUT()) {
999 // Calculate the position of the cluster by using the
1000 // lookup table method
1001 clusterPosCol = LUTposition(ilayer,clusterSignal[0]
1006 // Calculate the position of the cluster by using the
1007 // center of gravity method
1008 for (Int_t i = 0; i < kNsig; i++) {
1011 padSignal[2] = TMath::Abs(digitsOut->GetData(row,col ,time)); // Central pad
1012 padSignal[3] = TMath::Abs(digitsOut->GetData(row,col+1,time)); // Left pad
1013 padSignal[1] = TMath::Abs(digitsOut->GetData(row,col-1,time)); // Right pad
1015 (TMath::Abs(digitsOut->GetData(row,col-2,time)) < padSignal[1])) {
1016 padSignal[4] = TMath::Abs(digitsOut->GetData(row,col-2,time));
1018 if ((col < nColMax - 3) &&
1019 (TMath::Abs(digitsOut->GetData(row,col+2,time)) < padSignal[3])) {
1020 padSignal[0] = TMath::Abs(digitsOut->GetData(row,col+2,time));
1022 clusterPosCol = GetCOG(padSignal);
1025 // Store the amplitudes of the pads in the cluster for later analysis
1026 // and check whether one of these pads is masked in the database
1027 Short_t signals[7] = { 0, 0, 0, 0, 0, 0, 0 };
1028 for (Int_t jPad = col-3; jPad <= col+3; jPad++) {
1030 (jPad >= nColMax-1)) {
1033 signals[jPad-col+3] = TMath::Nint(TMath::Abs(digitsOut->GetData(row,jPad,time)));
1036 // Transform the local cluster coordinates into calibrated
1037 // space point positions defined in the local tracking system.
1038 // Here the calibration for T0, Vdrift and ExB is applied as well.
1039 Double_t clusterXYZ[6];
1040 clusterXYZ[0] = clusterPosCol;
1041 clusterXYZ[1] = clusterSignal[2];
1042 clusterXYZ[2] = clusterSignal[1];
1043 clusterXYZ[3] = clusterSignal[0];
1044 clusterXYZ[4] = 0.0;
1045 clusterXYZ[5] = 0.0;
1046 Int_t clusterRCT[3];
1047 clusterRCT[0] = row;
1048 clusterRCT[1] = col;
1052 if (fTransform->Transform(clusterXYZ,clusterRCT,((UInt_t) time),out,0)) {
1054 // Add the cluster to the output array
1055 // The track indices will be stored later
1056 Float_t clusterPos[3];
1057 clusterPos[0] = clusterXYZ[0];
1058 clusterPos[1] = clusterXYZ[1];
1059 clusterPos[2] = clusterXYZ[2];
1060 Float_t clusterSig[2];
1061 clusterSig[0] = clusterXYZ[4];
1062 clusterSig[1] = clusterXYZ[5];
1063 Double_t clusterCharge = clusterXYZ[3];
1064 Char_t clusterTimeBin = ((Char_t) clusterRCT[2]);
1066 Int_t n = RecPoints()->GetEntriesFast();
1067 AliTRDcluster *cluster = new((*RecPoints())[n]) AliTRDcluster(
1069 clusterCharge, clusterPos, clusterSig,
1071 ((Char_t) nPadCount),
1073 ((UChar_t) col), ((UChar_t) row), ((UChar_t) time),
1074 clusterTimeBin, clusterPosCol,
1076 cluster->SetInChamber(!out);
1078 UChar_t maskPosition = GetCorruption(padStatus.GetData(row, col, time));
1079 UChar_t padstatus = GetPadStatus(padStatus.GetData(row, col, time));
1081 cluster->SetPadMaskedPosition(maskPosition);
1082 cluster->SetPadMaskedStatus(padstatus);
1085 // Temporarily store the row, column and time bin of the center pad
1086 // Used to later on assign the track indices
1087 cluster->SetLabel( row,0);
1088 cluster->SetLabel( col,1);
1089 cluster->SetLabel(time,2);
1091 // Store the index of the first cluster in the current ROC
1092 if (firstClusterROC < 0) {
1093 firstClusterROC = RecPoints()->GetEntriesFast() - 1;
1096 // Count the number of cluster in the current ROC
1099 } // if: Transform ok ?
1101 } // if: Maximum found ?
1108 AddLabels(idet,firstClusterROC,nClusterROC);
1115 //_____________________________________________________________________________
1116 Bool_t AliTRDclusterizer::AddLabels(Int_t idet, Int_t firstClusterROC, Int_t nClusterROC)
1119 // Add the track indices to the found clusters
1122 const Int_t kNclus = 3;
1123 const Int_t kNdict = AliTRDdigitsManager::kNDict;
1124 const Int_t kNtrack = kNdict * kNclus;
1126 Int_t iClusterROC = 0;
1133 // Temporary array to collect the track indices
1134 Int_t *idxTracks = new Int_t[kNtrack*nClusterROC];
1136 // Loop through the dictionary arrays one-by-one
1137 // to keep memory consumption low
1138 AliTRDarrayDictionary *tracksIn = 0; //mod
1139 for (Int_t iDict = 0; iDict < kNdict; iDict++) {
1141 // tracksIn should be expanded beforehand!
1142 tracksIn = (AliTRDarrayDictionary *) fDigitsManager->GetDictionary(idet,iDict);
1144 // Loop though the clusters found in this ROC
1145 for (iClusterROC = 0; iClusterROC < nClusterROC; iClusterROC++) {
1147 AliTRDcluster *cluster = (AliTRDcluster *)
1148 RecPoints()->UncheckedAt(firstClusterROC+iClusterROC);
1149 row = cluster->GetLabel(0);
1150 col = cluster->GetLabel(1);
1151 time = cluster->GetLabel(2);
1153 for (iPad = 0; iPad < kNclus; iPad++) {
1154 Int_t iPadCol = col - 1 + iPad;
1155 Int_t index = tracksIn->GetData(row,iPadCol,time); //Modification of -1 in Track
1156 idxTracks[3*iPad+iDict + iClusterROC*kNtrack] = index;
1163 // Copy the track indices into the cluster
1164 // Loop though the clusters found in this ROC
1165 for (iClusterROC = 0; iClusterROC < nClusterROC; iClusterROC++) {
1167 AliTRDcluster *cluster = (AliTRDcluster *)
1168 RecPoints()->UncheckedAt(firstClusterROC+iClusterROC);
1169 cluster->SetLabel(-9999,0);
1170 cluster->SetLabel(-9999,1);
1171 cluster->SetLabel(-9999,2);
1173 cluster->AddTrackIndex(&idxTracks[iClusterROC*kNtrack]);
1177 delete [] idxTracks;
1183 //_____________________________________________________________________________
1184 Double_t AliTRDclusterizer::GetCOG(Double_t signal[5]) const
1188 // Used for clusters with more than 3 pads - where LUT not applicable
1191 Double_t sum = signal[0]
1198 // Go to 3 pad COG ????
1200 Double_t res = (0.0 * (-signal[0] + signal[4])
1201 + (-signal[1] + signal[3])) / sum;
1207 //_____________________________________________________________________________
1208 Double_t AliTRDclusterizer::Unfold(Double_t eps, Int_t layer, Double_t *padSignal)
1211 // Method to unfold neighbouring maxima.
1212 // The charge ratio on the overlapping pad is calculated
1213 // until there is no more change within the range given by eps.
1214 // The resulting ratio is then returned to the calling method.
1217 AliTRDcalibDB *calibration = AliTRDcalibDB::Instance();
1219 AliError("No AliTRDcalibDB instance available\n");
1224 Int_t itStep = 0; // Count iteration steps
1226 Double_t ratio = 0.5; // Start value for ratio
1227 Double_t prevRatio = 0.0; // Store previous ratio
1229 Double_t newLeftSignal[3] = { 0.0, 0.0, 0.0 }; // Array to store left cluster signal
1230 Double_t newRightSignal[3] = { 0.0, 0.0, 0.0 }; // Array to store right cluster signal
1231 Double_t newSignal[3] = { 0.0, 0.0, 0.0 };
1233 // Start the iteration
1234 while ((TMath::Abs(prevRatio - ratio) > eps) && (itStep < 10)) {
1239 // Cluster position according to charge ratio
1240 Double_t maxLeft = (ratio*padSignal[2] - padSignal[0])
1241 / (padSignal[0] + padSignal[1] + ratio*padSignal[2]);
1242 Double_t maxRight = (padSignal[4] - (1-ratio)*padSignal[2])
1243 / ((1.0 - ratio)*padSignal[2] + padSignal[3] + padSignal[4]);
1245 // Set cluster charge ratio
1246 irc = calibration->PadResponse(1.0,maxLeft ,layer,newSignal);
1247 Double_t ampLeft = padSignal[1] / newSignal[1];
1248 irc = calibration->PadResponse(1.0,maxRight,layer,newSignal);
1249 Double_t ampRight = padSignal[3] / newSignal[1];
1251 // Apply pad response to parameters
1252 irc = calibration->PadResponse(ampLeft ,maxLeft ,layer,newLeftSignal );
1253 irc = calibration->PadResponse(ampRight,maxRight,layer,newRightSignal);
1255 // Calculate new overlapping ratio
1256 ratio = TMath::Min((Double_t) 1.0
1257 ,newLeftSignal[2] / (newLeftSignal[2] + newRightSignal[0]));
1265 //_____________________________________________________________________________
1266 void AliTRDclusterizer::TailCancelation(AliTRDarrayADC *digitsIn
1267 , AliTRDarraySignal *digitsOut
1268 , AliTRDSignalIndex *indexesIn
1269 , AliTRDSignalIndex *indexesOut
1271 , Float_t adcThreshold
1272 , AliTRDCalROC *calGainFactorROC
1273 , Float_t calGainFactorDetValue)
1276 // Applies the tail cancelation and gain factors:
1277 // Transform digitsIn to digitsOut
1284 Double_t *inADC = new Double_t[nTimeTotal]; // ADC data before tail cancellation
1285 Double_t *outADC = new Double_t[nTimeTotal]; // ADC data after tail cancellation
1286 indexesIn->ResetCounters();
1287 while (indexesIn->NextRCIndex(iRow, iCol))
1289 Float_t calGainFactorROCValue = calGainFactorROC->GetValue(iCol,iRow);
1290 Double_t gain = calGainFactorDetValue
1291 * calGainFactorROCValue;
1293 Bool_t corrupted = kFALSE;
1294 for (iTime = 0; iTime < nTimeTotal; iTime++)
1296 // Apply gain gain factor
1297 inADC[iTime] = digitsIn->GetDataB(iRow,iCol,iTime);
1298 if (digitsIn->GetPadStatus(iRow, iCol, iTime)) corrupted = kTRUE;
1299 inADC[iTime] /= gain;
1300 outADC[iTime] = inADC[iTime];
1304 // Apply the tail cancelation via the digital filter
1305 // (only for non-coorupted pads)
1306 if (fReconstructor->GetRecoParam() ->IsTailCancelation())
1308 DeConvExp(inADC,outADC,nTimeTotal,fReconstructor->GetRecoParam() ->GetTCnexp());
1312 indexesIn->ResetTbinCounter();
1314 while (indexesIn->NextTbinIndex(iTime))
1316 // Store the amplitude of the digit if above threshold
1317 if (outADC[iTime] > adcThreshold)
1319 digitsOut->SetData(iRow,iCol,iTime,outADC[iTime]);
1320 indexesOut->AddIndexTBin(iRow,iCol,iTime);
1324 } // while irow icol
1333 //_____________________________________________________________________________
1334 void AliTRDclusterizer::DeConvExp(Double_t *source, Double_t *target
1335 , Int_t n, Int_t nexp)
1338 // Tail cancellation by deconvolution for PASA v4 TRF
1342 Double_t coefficients[2];
1344 // Initialization (coefficient = alpha, rates = lambda)
1350 if (nexp == 1) { // 1 Exponentials
1356 if (nexp == 2) { // 2 Exponentials
1358 fReconstructor->GetTCParams(par);
1359 r1 = par[0];//1.156;
1360 r2 = par[1];//0.130;
1361 c1 = par[2];//0.114;
1362 c2 = par[3];//0.624;
1365 coefficients[0] = c1;
1366 coefficients[1] = c2;
1370 rates[0] = TMath::Exp(-dt/(r1));
1371 rates[1] = TMath::Exp(-dt/(r2));
1376 Double_t reminder[2];
1377 Double_t correction = 0.0;
1378 Double_t result = 0.0;
1380 // Attention: computation order is important
1381 for (k = 0; k < nexp; k++) {
1385 for (i = 0; i < n; i++) {
1387 result = (source[i] - correction); // No rescaling
1390 for (k = 0; k < nexp; k++) {
1391 reminder[k] = rates[k] * (reminder[k] + coefficients[k] * result);
1395 for (k = 0; k < nexp; k++) {
1396 correction += reminder[k];
1403 //_____________________________________________________________________________
1404 void AliTRDclusterizer::ResetRecPoints()
1407 // Resets the list of rec points
1411 fRecPoints->Delete();
1416 //_____________________________________________________________________________
1417 TClonesArray *AliTRDclusterizer::RecPoints()
1420 // Returns the list of rec points
1424 if(!(fRecPoints = AliTRDReconstructor::GetClusters())){
1425 // determine number of clusters which has to be allocated
1426 Float_t nclusters = fReconstructor->GetRecoParam()->GetNClusters();
1427 if(fReconstructor->IsHLT()) nclusters /= AliTRDgeometry::kNsector;
1429 fRecPoints = new TClonesArray("AliTRDcluster", Int_t(nclusters));
1431 //SetClustersOwner(kTRUE);
1432 AliTRDReconstructor::SetClusters(0x0);
1438 //_____________________________________________________________________________
1439 void AliTRDclusterizer::FillLUT()
1445 const Int_t kNlut = 128;
1447 fLUTbin = AliTRDgeometry::kNlayer * kNlut;
1449 // The lookup table from Bogdan
1450 Float_t lut[AliTRDgeometry::kNlayer][kNlut] = {
1452 0.0070, 0.0150, 0.0224, 0.0298, 0.0374, 0.0454, 0.0533, 0.0611,
1453 0.0684, 0.0755, 0.0827, 0.0900, 0.0975, 0.1049, 0.1120, 0.1187,
1454 0.1253, 0.1318, 0.1385, 0.1453, 0.1519, 0.1584, 0.1646, 0.1704,
1455 0.1762, 0.1821, 0.1879, 0.1938, 0.1996, 0.2053, 0.2108, 0.2160,
1456 0.2210, 0.2260, 0.2310, 0.2361, 0.2411, 0.2461, 0.2509, 0.2557,
1457 0.2602, 0.2646, 0.2689, 0.2732, 0.2774, 0.2816, 0.2859, 0.2901,
1458 0.2942, 0.2983, 0.3022, 0.3061, 0.3099, 0.3136, 0.3172, 0.3207,
1459 0.3242, 0.3278, 0.3312, 0.3347, 0.3382, 0.3416, 0.3450, 0.3483,
1460 0.3515, 0.3547, 0.3579, 0.3609, 0.3639, 0.3669, 0.3698, 0.3727,
1461 0.3756, 0.3785, 0.3813, 0.3842, 0.3870, 0.3898, 0.3926, 0.3952,
1462 0.3979, 0.4005, 0.4032, 0.4057, 0.4082, 0.4108, 0.4132, 0.4157,
1463 0.4181, 0.4205, 0.4228, 0.4252, 0.4275, 0.4299, 0.4322, 0.4345,
1464 0.4367, 0.4390, 0.4412, 0.4434, 0.4456, 0.4478, 0.4499, 0.4520,
1465 0.4541, 0.4562, 0.4583, 0.4603, 0.4623, 0.4643, 0.4663, 0.4683,
1466 0.4702, 0.4722, 0.4741, 0.4758, 0.4774, 0.4790, 0.4805, 0.4824,
1467 0.4844, 0.4863, 0.4883, 0.4902, 0.4921, 0.4940, 0.4959, 0.4978
1470 0.0072, 0.0156, 0.0235, 0.0313, 0.0394, 0.0478, 0.0561, 0.0642,
1471 0.0718, 0.0792, 0.0868, 0.0947, 0.1025, 0.1101, 0.1172, 0.1241,
1472 0.1309, 0.1378, 0.1449, 0.1518, 0.1586, 0.1650, 0.1710, 0.1770,
1473 0.1830, 0.1891, 0.1952, 0.2011, 0.2070, 0.2125, 0.2177, 0.2229,
1474 0.2280, 0.2332, 0.2383, 0.2435, 0.2484, 0.2533, 0.2581, 0.2627,
1475 0.2670, 0.2714, 0.2757, 0.2799, 0.2842, 0.2884, 0.2927, 0.2968,
1476 0.3008, 0.3048, 0.3086, 0.3123, 0.3159, 0.3195, 0.3231, 0.3266,
1477 0.3301, 0.3335, 0.3370, 0.3404, 0.3438, 0.3471, 0.3504, 0.3536,
1478 0.3567, 0.3598, 0.3628, 0.3657, 0.3686, 0.3715, 0.3744, 0.3772,
1479 0.3800, 0.3828, 0.3856, 0.3884, 0.3911, 0.3938, 0.3965, 0.3991,
1480 0.4016, 0.4042, 0.4067, 0.4092, 0.4116, 0.4140, 0.4164, 0.4187,
1481 0.4211, 0.4234, 0.4257, 0.4280, 0.4302, 0.4325, 0.4347, 0.4369,
1482 0.4391, 0.4413, 0.4434, 0.4456, 0.4477, 0.4497, 0.4518, 0.4538,
1483 0.4558, 0.4578, 0.4598, 0.4618, 0.4637, 0.4656, 0.4675, 0.4694,
1484 0.4713, 0.4732, 0.4750, 0.4766, 0.4781, 0.4797, 0.4813, 0.4832,
1485 0.4851, 0.4870, 0.4888, 0.4906, 0.4925, 0.4942, 0.4960, 0.4978
1488 0.0075, 0.0163, 0.0246, 0.0328, 0.0415, 0.0504, 0.0592, 0.0674,
1489 0.0753, 0.0832, 0.0914, 0.0996, 0.1077, 0.1154, 0.1225, 0.1296,
1490 0.1369, 0.1442, 0.1515, 0.1585, 0.1652, 0.1714, 0.1776, 0.1839,
1491 0.1902, 0.1965, 0.2025, 0.2085, 0.2141, 0.2194, 0.2247, 0.2299,
1492 0.2352, 0.2405, 0.2457, 0.2507, 0.2557, 0.2604, 0.2649, 0.2693,
1493 0.2737, 0.2780, 0.2823, 0.2867, 0.2909, 0.2951, 0.2992, 0.3033,
1494 0.3072, 0.3110, 0.3146, 0.3182, 0.3218, 0.3253, 0.3288, 0.3323,
1495 0.3357, 0.3392, 0.3426, 0.3459, 0.3492, 0.3524, 0.3555, 0.3586,
1496 0.3616, 0.3645, 0.3674, 0.3703, 0.3731, 0.3759, 0.3787, 0.3815,
1497 0.3843, 0.3870, 0.3897, 0.3925, 0.3950, 0.3976, 0.4002, 0.4027,
1498 0.4052, 0.4076, 0.4101, 0.4124, 0.4148, 0.4171, 0.4194, 0.4217,
1499 0.4239, 0.4262, 0.4284, 0.4306, 0.4328, 0.4350, 0.4371, 0.4393,
1500 0.4414, 0.4435, 0.4455, 0.4476, 0.4496, 0.4516, 0.4536, 0.4555,
1501 0.4575, 0.4594, 0.4613, 0.4632, 0.4650, 0.4669, 0.4687, 0.4705,
1502 0.4723, 0.4741, 0.4758, 0.4773, 0.4789, 0.4804, 0.4821, 0.4839,
1503 0.4857, 0.4875, 0.4893, 0.4910, 0.4928, 0.4945, 0.4961, 0.4978
1506 0.0078, 0.0171, 0.0258, 0.0345, 0.0438, 0.0532, 0.0624, 0.0708,
1507 0.0791, 0.0875, 0.0962, 0.1048, 0.1130, 0.1206, 0.1281, 0.1356,
1508 0.1432, 0.1508, 0.1582, 0.1651, 0.1716, 0.1780, 0.1845, 0.1910,
1509 0.1975, 0.2038, 0.2099, 0.2155, 0.2210, 0.2263, 0.2317, 0.2371,
1510 0.2425, 0.2477, 0.2528, 0.2578, 0.2626, 0.2671, 0.2715, 0.2759,
1511 0.2803, 0.2846, 0.2890, 0.2933, 0.2975, 0.3016, 0.3056, 0.3095,
1512 0.3132, 0.3168, 0.3204, 0.3239, 0.3274, 0.3309, 0.3344, 0.3378,
1513 0.3412, 0.3446, 0.3479, 0.3511, 0.3543, 0.3574, 0.3603, 0.3633,
1514 0.3662, 0.3690, 0.3718, 0.3747, 0.3774, 0.3802, 0.3829, 0.3857,
1515 0.3883, 0.3910, 0.3936, 0.3962, 0.3987, 0.4012, 0.4037, 0.4061,
1516 0.4085, 0.4109, 0.4132, 0.4155, 0.4177, 0.4200, 0.4222, 0.4244,
1517 0.4266, 0.4288, 0.4309, 0.4331, 0.4352, 0.4373, 0.4394, 0.4414,
1518 0.4435, 0.4455, 0.4475, 0.4494, 0.4514, 0.4533, 0.4552, 0.4571,
1519 0.4590, 0.4608, 0.4626, 0.4645, 0.4662, 0.4680, 0.4698, 0.4715,
1520 0.4733, 0.4750, 0.4766, 0.4781, 0.4796, 0.4812, 0.4829, 0.4846,
1521 0.4863, 0.4880, 0.4897, 0.4914, 0.4930, 0.4946, 0.4963, 0.4979
1524 0.0081, 0.0178, 0.0270, 0.0364, 0.0463, 0.0562, 0.0656, 0.0744,
1525 0.0831, 0.0921, 0.1013, 0.1102, 0.1183, 0.1261, 0.1339, 0.1419,
1526 0.1499, 0.1576, 0.1648, 0.1715, 0.1782, 0.1849, 0.1917, 0.1984,
1527 0.2048, 0.2110, 0.2167, 0.2223, 0.2278, 0.2333, 0.2389, 0.2444,
1528 0.2497, 0.2548, 0.2598, 0.2645, 0.2691, 0.2735, 0.2780, 0.2824,
1529 0.2868, 0.2912, 0.2955, 0.2997, 0.3038, 0.3078, 0.3116, 0.3152,
1530 0.3188, 0.3224, 0.3259, 0.3294, 0.3329, 0.3364, 0.3398, 0.3432,
1531 0.3465, 0.3497, 0.3529, 0.3561, 0.3591, 0.3620, 0.3649, 0.3677,
1532 0.3705, 0.3733, 0.3761, 0.3788, 0.3816, 0.3843, 0.3869, 0.3896,
1533 0.3922, 0.3948, 0.3973, 0.3998, 0.4022, 0.4047, 0.4070, 0.4094,
1534 0.4117, 0.4139, 0.4162, 0.4184, 0.4206, 0.4227, 0.4249, 0.4270,
1535 0.4291, 0.4313, 0.4334, 0.4354, 0.4375, 0.4395, 0.4415, 0.4435,
1536 0.4455, 0.4474, 0.4493, 0.4512, 0.4531, 0.4550, 0.4568, 0.4586,
1537 0.4604, 0.4622, 0.4639, 0.4657, 0.4674, 0.4691, 0.4708, 0.4725,
1538 0.4742, 0.4758, 0.4773, 0.4788, 0.4803, 0.4819, 0.4836, 0.4852,
1539 0.4869, 0.4885, 0.4901, 0.4917, 0.4933, 0.4948, 0.4964, 0.4979
1542 0.0085, 0.0189, 0.0288, 0.0389, 0.0497, 0.0603, 0.0699, 0.0792,
1543 0.0887, 0.0985, 0.1082, 0.1170, 0.1253, 0.1336, 0.1421, 0.1505,
1544 0.1587, 0.1662, 0.1733, 0.1803, 0.1874, 0.1945, 0.2014, 0.2081,
1545 0.2143, 0.2201, 0.2259, 0.2316, 0.2374, 0.2431, 0.2487, 0.2541,
1546 0.2593, 0.2642, 0.2689, 0.2735, 0.2781, 0.2826, 0.2872, 0.2917,
1547 0.2961, 0.3003, 0.3045, 0.3086, 0.3125, 0.3162, 0.3198, 0.3235,
1548 0.3270, 0.3306, 0.3342, 0.3377, 0.3411, 0.3446, 0.3479, 0.3511,
1549 0.3543, 0.3575, 0.3605, 0.3634, 0.3663, 0.3691, 0.3720, 0.3748,
1550 0.3775, 0.3803, 0.3830, 0.3857, 0.3884, 0.3911, 0.3937, 0.3962,
1551 0.3987, 0.4012, 0.4036, 0.4060, 0.4084, 0.4107, 0.4129, 0.4152,
1552 0.4174, 0.4196, 0.4218, 0.4239, 0.4261, 0.4282, 0.4303, 0.4324,
1553 0.4344, 0.4365, 0.4385, 0.4405, 0.4425, 0.4445, 0.4464, 0.4483,
1554 0.4502, 0.4521, 0.4539, 0.4558, 0.4576, 0.4593, 0.4611, 0.4629,
1555 0.4646, 0.4663, 0.4680, 0.4697, 0.4714, 0.4730, 0.4747, 0.4759,
1556 0.4769, 0.4780, 0.4790, 0.4800, 0.4811, 0.4827, 0.4843, 0.4859,
1557 0.4874, 0.4889, 0.4905, 0.4920, 0.4935, 0.4950, 0.4965, 0.4979
1564 fLUT = new Double_t[fLUTbin];
1566 for (Int_t ilayer = 0; ilayer < AliTRDgeometry::kNlayer; ilayer++) {
1567 for (Int_t ilut = 0; ilut < kNlut; ilut++ ) {
1568 fLUT[ilayer*kNlut+ilut] = lut[ilayer][ilut];
1574 //_____________________________________________________________________________
1575 Double_t AliTRDclusterizer::LUTposition(Int_t ilayer
1578 , Double_t ampR) const
1581 // Calculates the cluster position using the lookup table.
1582 // Method provided by Bogdan Vulpescu.
1585 const Int_t kNlut = 128;
1596 Double_t xMin[AliTRDgeometry::kNlayer] = { 0.006492, 0.006377, 0.006258
1597 , 0.006144, 0.006030, 0.005980 };
1598 Double_t xMax[AliTRDgeometry::kNlayer] = { 0.960351, 0.965870, 0.970445
1599 , 0.974352, 0.977667, 0.996101 };
1602 x = (ampL - ampR) / ampC;
1605 else if (ampL < ampR) {
1606 x = (ampR - ampL) / ampC;
1612 xmin = xMin[ilayer] + 0.000005;
1613 xmax = xMax[ilayer] - 0.000005;
1614 xwid = (xmax - xmin) / 127.0;
1619 else if (x > xmax) {
1620 pos = side * 0.5000;
1623 ix = (Int_t) ((x - xmin) / xwid);
1624 pos = side * fLUT[ilayer*kNlut+ix];