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 "TTreeStream.h"
56 #include "Cal/AliTRDCalROC.h"
57 #include "Cal/AliTRDCalDet.h"
58 #include "Cal/AliTRDCalSingleChamberStatus.h"
60 ClassImp(AliTRDclusterizer)
62 //_____________________________________________________________________________
63 AliTRDclusterizer::AliTRDclusterizer(AliTRDReconstructor *rec)
71 ,fTrackletContainer(NULL)
76 ,fTransform(new AliTRDtransform(0))
81 // AliTRDclusterizer default constructor
84 AliTRDcalibDB *trd = 0x0;
85 if (!(trd = AliTRDcalibDB::Instance())) {
86 AliFatal("Could not get calibration object");
89 fRawVersion = AliTRDfeeParam::Instance()->GetRAWversion();
91 // Initialize debug stream
93 if(fReconstructor->GetStreamLevel(AliTRDReconstructor::kClusterizer) > 1){
94 TDirectory *savedir = gDirectory;
95 //fgGetDebugStream = new TTreeSRedirector("TRD.ClusterizerDebug.root");
102 //_____________________________________________________________________________
103 AliTRDclusterizer::AliTRDclusterizer(const Text_t *name, const Text_t *title, AliTRDReconstructor *rec)
110 ,fDigitsManager(new AliTRDdigitsManager())
111 ,fTrackletContainer(NULL)
115 ,fIndexesMaxima(NULL)
116 ,fTransform(new AliTRDtransform(0))
121 // AliTRDclusterizer constructor
124 AliTRDcalibDB *trd = 0x0;
125 if (!(trd = AliTRDcalibDB::Instance())) {
126 AliFatal("Could not get calibration object");
129 fDigitsManager->CreateArrays();
131 fRawVersion = AliTRDfeeParam::Instance()->GetRAWversion();
137 //_____________________________________________________________________________
138 AliTRDclusterizer::AliTRDclusterizer(const AliTRDclusterizer &c)
140 ,fReconstructor(c.fReconstructor)
145 ,fDigitsManager(NULL)
146 ,fTrackletContainer(NULL)
150 ,fIndexesMaxima(NULL)
156 // AliTRDclusterizer copy constructor
163 //_____________________________________________________________________________
164 AliTRDclusterizer::~AliTRDclusterizer()
167 // AliTRDclusterizer destructor
170 if (fRecPoints/* && IsClustersOwner()*/){
171 fRecPoints->Delete();
175 if (fDigitsManager) {
176 delete fDigitsManager;
177 fDigitsManager = NULL;
180 if (fTrackletContainer){
181 delete fTrackletContainer;
182 fTrackletContainer = NULL;
191 delete fIndexesMaxima;
192 fIndexesMaxima = NULL;
207 //_____________________________________________________________________________
208 AliTRDclusterizer &AliTRDclusterizer::operator=(const AliTRDclusterizer &c)
211 // Assignment operator
216 ((AliTRDclusterizer &) c).Copy(*this);
223 //_____________________________________________________________________________
224 void AliTRDclusterizer::Copy(TObject &c) const
230 ((AliTRDclusterizer &) c).fClusterTree = NULL;
231 ((AliTRDclusterizer &) c).fRecPoints = NULL;
232 ((AliTRDclusterizer &) c).fTrackletTree = NULL;
233 ((AliTRDclusterizer &) c).fDigitsManager = NULL;
234 ((AliTRDclusterizer &) c).fTrackletContainer = NULL;
235 ((AliTRDclusterizer &) c).fAddLabels = fAddLabels;
236 ((AliTRDclusterizer &) c).fRawVersion = fRawVersion;
237 ((AliTRDclusterizer &) c).fIndexesOut = NULL;
238 ((AliTRDclusterizer &) c).fIndexesMaxima = NULL;
239 ((AliTRDclusterizer &) c).fTransform = NULL;
240 ((AliTRDclusterizer &) c).fLUTbin = 0;
241 ((AliTRDclusterizer &) c).fLUT = NULL;
245 //_____________________________________________________________________________
246 Bool_t AliTRDclusterizer::Open(const Char_t *name, Int_t nEvent)
249 // Opens the AliROOT file. Output and input are in the same file
252 TString evfoldname = AliConfig::GetDefaultEventFolderName();
253 fRunLoader = AliRunLoader::GetRunLoader(evfoldname);
256 fRunLoader = AliRunLoader::Open(name);
260 AliError(Form("Can not open session for file %s.",name));
271 //_____________________________________________________________________________
272 Bool_t AliTRDclusterizer::OpenOutput()
275 // Open the output file
278 if (!fReconstructor->IsWritingClusters()) return kTRUE;
280 TObjArray *ioArray = 0x0;
282 AliLoader* loader = fRunLoader->GetLoader("TRDLoader");
283 loader->MakeTree("R");
285 fClusterTree = loader->TreeR();
286 fClusterTree->Branch("TRDcluster", "TObjArray", &ioArray, 32000, 0);
292 //_____________________________________________________________________________
293 Bool_t AliTRDclusterizer::OpenOutput(TTree *clusterTree)
296 // Connect the output tree
300 if (fReconstructor->IsWritingClusters()){
301 TObjArray *ioArray = 0x0;
302 fClusterTree = clusterTree;
303 fClusterTree->Branch("TRDcluster", "TObjArray", &ioArray, 32000, 0);
307 if (fReconstructor->IsWritingTracklets()){
308 TString evfoldname = AliConfig::GetDefaultEventFolderName();
309 fRunLoader = AliRunLoader::GetRunLoader(evfoldname);
312 fRunLoader = AliRunLoader::Open("galice.root");
315 AliError(Form("Can not open session for file galice.root."));
319 UInt_t **leaves = new UInt_t *[2];
320 AliDataLoader *dl = fRunLoader->GetLoader("TRDLoader")->GetDataLoader("tracklets");
322 AliError("Could not get the tracklets data loader!");
323 dl = new AliDataLoader("TRD.Tracklets.root","tracklets", "tracklets");
324 fRunLoader->GetLoader("TRDLoader")->AddDataLoader(dl);
327 fTrackletTree = dl->Tree();
331 fTrackletTree = dl->Tree();
333 TBranch *trkbranch = fTrackletTree->GetBranch("trkbranch");
335 fTrackletTree->Branch("trkbranch",leaves[0],"det/i:side/i:tracklets[256]/i");
343 //_____________________________________________________________________________
344 Bool_t AliTRDclusterizer::OpenInput(Int_t nEvent)
347 // Opens a ROOT-file with TRD-hits and reads in the digits-tree
350 // Import the Trees for the event nEvent in the file
351 fRunLoader->GetEvent(nEvent);
357 //_____________________________________________________________________________
358 Bool_t AliTRDclusterizer::WriteClusters(Int_t det)
361 // Fills TRDcluster branch in the tree with the clusters
362 // found in detector = det. For det=-1 writes the tree.
366 (det >= AliTRDgeometry::Ndet())) {
367 AliError(Form("Unexpected detector index %d.\n",det));
371 TObjArray *ioArray = new TObjArray(400);
372 TBranch *branch = fClusterTree->GetBranch("TRDcluster");
374 branch = fClusterTree->Branch("TRDcluster","TObjArray",&ioArray,32000,0);
375 } else branch->SetAddress(&ioArray);
377 Int_t nRecPoints = RecPoints()->GetEntriesFast();
379 for (Int_t i = 0; i < nRecPoints; i++) {
380 AliTRDcluster *c = (AliTRDcluster *) RecPoints()->UncheckedAt(i);
381 if(det != c->GetDetector()) continue;
384 fClusterTree->Fill();
388 for (Int_t i = 0; i < nRecPoints; i++) {
389 AliTRDcluster *c = (AliTRDcluster *) RecPoints()->UncheckedAt(i);
390 if(c->GetDetector() != detOld){
391 fClusterTree->Fill();
393 detOld = c->GetDetector();
404 //_____________________________________________________________________________
405 Bool_t AliTRDclusterizer::WriteTracklets(Int_t det)
408 // Write the raw data tracklets into seperate file
411 UInt_t **leaves = new UInt_t *[2];
412 for (Int_t i=0; i<2 ;i++){
413 leaves[i] = new UInt_t[258];
414 leaves[i][0] = det; // det
415 leaves[i][1] = i; // side
416 memcpy(leaves[i]+2, fTrackletContainer[i], sizeof(UInt_t) * 256);
420 AliDataLoader *dl = fRunLoader->GetLoader("TRDLoader")->GetDataLoader("tracklets");
422 fTrackletTree = dl->Tree();
425 TBranch *trkbranch = fTrackletTree->GetBranch("trkbranch");
427 trkbranch = fTrackletTree->Branch("trkbranch",leaves[0],"det/i:side/i:tracklets[256]/i");
430 for (Int_t i=0; i<2; i++){
431 if (leaves[i][2]>0) {
432 trkbranch->SetAddress(leaves[i]);
433 fTrackletTree->Fill();
437 AliDataLoader *dl = fRunLoader->GetLoader("TRDLoader")->GetDataLoader("tracklets");
438 dl->WriteData("OVERWRITE");
446 //_____________________________________________________________________________
447 void AliTRDclusterizer::ResetHelperIndexes(AliTRDSignalIndex *indexesIn)
450 // Reset the helper indexes
455 // carefull here - we assume that only row number may change - most probable
456 if (indexesIn->GetNrow() <= fIndexesOut->GetNrow())
457 fIndexesOut->ResetContent();
459 fIndexesOut->ResetContentConditional(indexesIn->GetNrow()
460 , indexesIn->GetNcol()
461 , indexesIn->GetNtime());
465 fIndexesOut = new AliTRDSignalIndex(indexesIn->GetNrow()
466 , indexesIn->GetNcol()
467 , indexesIn->GetNtime());
472 // carefull here - we assume that only row number may change - most probable
473 if (indexesIn->GetNrow() <= fIndexesMaxima->GetNrow())
475 fIndexesMaxima->ResetContent();
479 fIndexesMaxima->ResetContentConditional(indexesIn->GetNrow()
480 , indexesIn->GetNcol()
481 , indexesIn->GetNtime());
486 fIndexesMaxima = new AliTRDSignalIndex(indexesIn->GetNrow()
487 , indexesIn->GetNcol()
488 , indexesIn->GetNtime());
493 //_____________________________________________________________________________
494 Bool_t AliTRDclusterizer::ReadDigits()
497 // Reads the digits arrays from the input aliroot file
501 AliError("No run loader available");
505 AliLoader* loader = fRunLoader->GetLoader("TRDLoader");
506 if (!loader->TreeD()) {
507 loader->LoadDigits();
510 // Read in the digit arrays
511 return (fDigitsManager->ReadDigits(loader->TreeD()));
515 //_____________________________________________________________________________
516 Bool_t AliTRDclusterizer::ReadDigits(TTree *digitsTree)
519 // Reads the digits arrays from the input tree
522 // Read in the digit arrays
523 return (fDigitsManager->ReadDigits(digitsTree));
527 //_____________________________________________________________________________
528 Bool_t AliTRDclusterizer::ReadDigits(AliRawReader *rawReader)
531 // Reads the digits arrays from the ddl file
535 fDigitsManager = raw.Raw2Digits(rawReader);
541 //_____________________________________________________________________________
542 Bool_t AliTRDclusterizer::MakeClusters()
545 // Creates clusters from digits
548 // Propagate info from the digits manager
549 if (fAddLabels == kTRUE){
550 fAddLabels = fDigitsManager->UsesDictionaries();
553 Bool_t fReturn = kTRUE;
554 for (Int_t i = 0; i < AliTRDgeometry::kNdet; i++){
556 AliTRDarrayADC *digitsIn = (AliTRDarrayADC*) fDigitsManager->GetDigits(i); //mod
557 // This is to take care of switched off super modules
558 if (!digitsIn->HasData()) continue;
560 digitsIn->DeleteNegatives(); // Restore digits array to >=0 values
561 AliTRDSignalIndex* indexes = fDigitsManager->GetIndexes(i);
562 if (indexes->IsAllocated() == kFALSE){
563 fDigitsManager->BuildIndexes(i);
567 if (indexes->HasEntry()){
569 for (Int_t iDict = 0; iDict < AliTRDdigitsManager::kNDict; iDict++){
570 AliTRDarrayDictionary *tracksIn = 0; //mod
571 tracksIn = (AliTRDarrayDictionary *) fDigitsManager->GetDictionary(i,iDict); //mod
575 fR = MakeClusters(i);
576 fReturn = fR && fReturn;
580 // if(IsWritingClusters()) WriteClusters(i);
584 // No compress just remove
585 fDigitsManager->RemoveDigits(i);
586 fDigitsManager->RemoveDictionaries(i);
587 fDigitsManager->ClearIndexes(i);
590 if(fReconstructor->IsWritingClusters()) WriteClusters(-1);
592 AliInfo(Form("Number of found clusters : %d", RecPoints()->GetEntriesFast()));
598 //_____________________________________________________________________________
599 Bool_t AliTRDclusterizer::Raw2Clusters(AliRawReader *rawReader)
602 // Creates clusters from raw data
605 return Raw2ClustersChamber(rawReader);
609 //_____________________________________________________________________________
610 Bool_t AliTRDclusterizer::Raw2ClustersChamber(AliRawReader *rawReader)
613 // Creates clusters from raw data
616 // Create the digits manager
617 if (!fDigitsManager){
618 fDigitsManager = new AliTRDdigitsManager();
619 fDigitsManager->CreateArrays();
622 fDigitsManager->SetUseDictionaries(fAddLabels);
624 // tracklet container for raw tracklet writing
625 if (!fTrackletContainer && fReconstructor->IsWritingTracklets()) {
626 // maximum tracklets for one HC
627 const Int_t kTrackletChmb=256;
628 fTrackletContainer = new UInt_t *[2];
629 fTrackletContainer[0] = new UInt_t[kTrackletChmb];
630 fTrackletContainer[1] = new UInt_t[kTrackletChmb];
634 AliTRDrawStreamBase *pinput = AliTRDrawStreamBase::GetRawStream(rawReader);
635 AliTRDrawStreamBase &input = *pinput;
637 AliInfo(Form("Stream version: %s", input.IsA()->GetName()));
640 while ((det = input.NextChamber(fDigitsManager,fTrackletContainer)) >= 0){
641 Bool_t iclusterBranch = kFALSE;
642 if (fDigitsManager->GetIndexes(det)->HasEntry()){
643 iclusterBranch = MakeClusters(det);
646 fDigitsManager->RemoveDigits(det);
647 fDigitsManager->RemoveDictionaries(det);
648 fDigitsManager->ClearIndexes(det);
650 if (!fReconstructor->IsWritingTracklets()) continue;
651 if (*(fTrackletContainer[0]) > 0 || *(fTrackletContainer[1]) > 0) WriteTracklets(det);
653 if (fReconstructor->IsWritingTracklets()){
654 delete [] fTrackletContainer[0];
655 delete [] fTrackletContainer[1];
656 delete [] fTrackletContainer;
657 fTrackletContainer = NULL;
660 if(fReconstructor->IsWritingClusters()) WriteClusters(-1);
662 delete fDigitsManager;
663 fDigitsManager = NULL;
668 AliInfo(Form("Number of found clusters : %d", RecPoints()->GetEntriesFast()));
673 //_____________________________________________________________________________
674 UChar_t AliTRDclusterizer::GetStatus(Short_t &signal)
677 // Check if a pad is masked
682 if(signal>0 && TESTBIT(signal, 10)){
684 for(int ibit=0; ibit<4; ibit++){
685 if(TESTBIT(signal, 11+ibit)){
686 SETBIT(status, ibit);
687 CLRBIT(signal, 11+ibit);
694 //_____________________________________________________________________________
695 void AliTRDclusterizer::SetPadStatus(UChar_t status, UChar_t &out){
697 // Set the pad status into out
698 // First three bits are needed for the position encoding
700 status = status << 3;
704 //_____________________________________________________________________________
705 UChar_t AliTRDclusterizer::GetPadStatus(UChar_t encoding){
707 // return the staus encoding of the corrupted pad
709 return static_cast<UChar_t>(encoding >> 3);
712 //_____________________________________________________________________________
713 Int_t AliTRDclusterizer::GetCorruption(UChar_t encoding){
715 // Return the position of the corruption
720 //_____________________________________________________________________________
721 Bool_t AliTRDclusterizer::MakeClusters(Int_t det)
724 // Generates the cluster.
728 // digits should be expanded beforehand!
729 // digitsIn->Expand();
730 AliTRDarrayADC *digitsIn = (AliTRDarrayADC *) fDigitsManager->GetDigits(det); //mod
732 // This is to take care of switched off super modules
733 if (!digitsIn->HasData())
738 AliTRDSignalIndex *indexesIn = fDigitsManager->GetIndexes(det);
739 if (indexesIn->IsAllocated() == kFALSE)
741 AliError("Indexes do not exist!");
745 AliTRDcalibDB *calibration = AliTRDcalibDB::Instance();
748 AliFatal("No AliTRDcalibDB instance available\n");
753 // There is no ADC threshold anymore, and simParam should not be used in clusterizer. KO
754 Float_t adcThreshold = 0;
756 if (!fReconstructor){
757 AliError("Reconstructor not set\n");
761 TTreeSRedirector *fDebugStream = fReconstructor->GetDebugStream(AliTRDReconstructor::kClusterizer);
763 // Threshold value for the maximum
764 Float_t maxThresh = fReconstructor->GetRecoParam()->GetClusMaxThresh();
765 // Threshold value for the digit signal
766 Float_t sigThresh = fReconstructor->GetRecoParam()->GetClusSigThresh();
768 // Threshold value for the maximum ( cut noise)
769 Float_t minMaxCutSigma = fReconstructor->GetRecoParam()->GetMinMaxCutSigma();
770 // Threshold value for the sum pad ( cut noise)
771 Float_t minLeftRightCutSigma = fReconstructor->GetRecoParam()->GetMinLeftRightCutSigma();
773 // Iteration limit for unfolding procedure
774 const Float_t kEpsilon = 0.01;
775 const Int_t kNclus = 3;
776 const Int_t kNsig = 5;
779 Double_t ratioLeft = 1.0;
780 Double_t ratioRight = 1.0;
782 Double_t padSignal[kNsig];
783 Double_t clusterSignal[kNclus];
785 Int_t istack = indexesIn->GetStack();
786 Int_t ilayer = indexesIn->GetLayer();
787 Int_t isector = indexesIn->GetSM();
789 // Start clustering in the chamber
791 Int_t idet = AliTRDgeometry::GetDetector(ilayer,istack,isector);
793 AliError("Strange Detector number Missmatch!");
797 // TRD space point transformation
798 fTransform->SetDetector(det);
800 Int_t iGeoLayer = AliGeomManager::kTRD1 + ilayer;
801 Int_t iGeoModule = istack + AliTRDgeometry::Nstack() * isector;
802 UShort_t volid = AliGeomManager::LayerToVolUID(iGeoLayer,iGeoModule);
804 Int_t nColMax = digitsIn->GetNcol();
805 Int_t nRowMax = digitsIn->GetNrow();
806 Int_t nTimeTotal = digitsIn->GetNtime();
808 // Detector wise calibration object for the gain factors
809 const AliTRDCalDet *calGainFactorDet = calibration->GetGainFactorDet();
810 // Calibration object with pad wise values for the gain factors
811 AliTRDCalROC *calGainFactorROC = calibration->GetGainFactorROC(idet);
812 // Calibration value for chamber wise gain factor
813 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 AliTRDarraySignal *digitsOut = new AliTRDarraySignal(nRowMax, nColMax, nTimeTotal);
825 AliTRDarrayADC 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 Int_t nMaximas = 0, nCorrupted = 0;
847 while (fIndexesOut->NextRCTbinIndex(row, col, time)) {
849 ipos = 0; for(Int_t is=3; is--;) status[is] = 0;
851 Float_t signalM = TMath::Abs(digitsOut->GetData(row,col,time));
852 status[1] = digitsIn->GetPadStatus(row,col,time);
853 if(status[1]) SETBIT(ipos, AliTRDcluster::kMaskedCenter);
855 if(signalM < maxThresh) continue;
857 Float_t noiseMiddleThresh = minMaxCutSigma*calNoiseDetValue*calNoiseROC->GetValue(col,row);
858 if (signalM < noiseMiddleThresh) continue;
860 if (col + 1 >= nColMax || col-1 < 0) continue;
862 Float_t signalL = TMath::Abs(digitsOut->GetData(row,col+1,time));
863 status[0] = digitsIn->GetPadStatus(row,col+1,time);
864 if(status[0]) SETBIT(ipos, AliTRDcluster::kMaskedLeft);
866 Float_t signalR = TMath::Abs(digitsOut->GetData(row,col-1,time));
867 status[2] = digitsIn->GetPadStatus(row,col-1,time);
868 if(status[2]) SETBIT(ipos, AliTRDcluster::kMaskedRight);
870 // reject candidates with more than 1 problematic pad
871 if(ipos == 3 || ipos > 4) continue;
873 if (!status[1]) { // good central pad
874 if (!ipos) { // all pads are OK
875 if ((signalL <= signalM) && (signalR < signalM)) {
876 if ((signalL >= sigThresh) || (signalR >= sigThresh)) {
877 Float_t noiseSumThresh = minLeftRightCutSigma
879 * calNoiseROC->GetValue(col,row);
880 if ((signalL+signalR+signalM) >= noiseSumThresh) {
881 // Maximum found, mark the position by a negative signal
882 digitsOut->SetData(row,col,time,-signalM);
883 fIndexesMaxima->AddIndexTBin(row,col,time);
884 padStatus.SetData(row, col, time, ipos); // No corruption
888 } else { // one of the neighbouring pads are bad
889 if (status[0] && signalR < signalM && signalR >= sigThresh) {
890 digitsOut->SetData(row,col,time,-signalM);
891 digitsOut->SetData(row, col, time+1, 0.);
892 fIndexesMaxima->AddIndexTBin(row,col,time);
893 SetPadStatus(status[0], ipos);
894 padStatus.SetData(row, col, time, ipos);
896 else if (status[2] && signalL <= signalM && signalL >= sigThresh) {
897 digitsOut->SetData(row,col,time,-signalM);
898 digitsOut->SetData(row, col, time-1, 0.);
899 fIndexesMaxima->AddIndexTBin(row,col,time);
900 SetPadStatus(status[2], ipos);
901 padStatus.SetData(row, col, time, ipos);
905 else { // wrong maximum pad
906 if ((signalL >= sigThresh) || (signalR >= sigThresh)) {
907 // Maximum found, mark the position by a negative signal
908 digitsOut->SetData(row,col,time,-maxThresh);
909 fIndexesMaxima->AddIndexTBin(row,col,time);
910 SetPadStatus(status[1], ipos);
911 padStatus.SetData(row, col, time, ipos);
916 // The index to the first cluster of a given ROC
917 Int_t firstClusterROC = -1;
918 // The number of cluster in a given ROC
919 Int_t nClusterROC = 0;
921 // Now check the maxima and calculate the cluster position
922 fIndexesMaxima->ResetCounters();
923 while (fIndexesMaxima->NextRCTbinIndex(row, col, time)) {
926 if (digitsOut->GetData(row,col,time) < 0.0) {
928 for (iPad = 0; iPad < kNclus; iPad++) {
929 Int_t iPadCol = col - 1 + iPad;
930 clusterSignal[iPad] = TMath::Abs(digitsOut->GetData(row,iPadCol,time));
933 // Count the number of pads in the cluster
938 while (TMath::Abs(digitsOut->GetData(row,col-ii ,time)) >= sigThresh) {
941 if (col-ii < 0) break;
945 while (TMath::Abs(digitsOut->GetData(row,col+ii+1,time)) >= sigThresh) {
948 if (col+ii+1 >= nColMax) break;
952 // Look for 5 pad cluster with minimum in the middle
953 Bool_t fivePadCluster = kFALSE;
954 if (col < (nColMax - 3)){
955 if (digitsOut->GetData(row,col+2,time) < 0) {
956 fivePadCluster = kTRUE;
958 if ((fivePadCluster) && (col < (nColMax - 5))) {
959 if (digitsOut->GetData(row,col+4,time) >= sigThresh) {
960 fivePadCluster = kFALSE;
963 if ((fivePadCluster) && (col > 1)) {
964 if (digitsOut->GetData(row,col-2,time) >= sigThresh) {
965 fivePadCluster = kFALSE;
971 // Modify the signal of the overlapping pad for the left part
972 // of the cluster which remains from a previous unfolding
974 clusterSignal[0] *= ratioLeft;
978 // Unfold the 5 pad cluster
979 if (fivePadCluster) {
980 for (iPad = 0; iPad < kNsig; iPad++) {
981 padSignal[iPad] = TMath::Abs(digitsOut->GetData(row
985 // Unfold the two maxima and set the signal on
986 // the overlapping pad to the ratio
987 ratioRight = Unfold(kEpsilon,ilayer,padSignal);
988 ratioLeft = 1.0 - ratioRight;
989 clusterSignal[2] *= ratioRight;
993 // The position of the cluster in COL direction relative to the center pad (pad units)
994 Double_t clusterPosCol = 0.0;
995 if (fReconstructor->GetRecoParam()->IsLUT()) {
996 // Calculate the position of the cluster by using the
997 // lookup table method
998 clusterPosCol = LUTposition(ilayer,clusterSignal[0]
1003 // Calculate the position of the cluster by using the
1004 // center of gravity method
1005 for (Int_t i = 0; i < kNsig; i++) {
1008 padSignal[2] = TMath::Abs(digitsOut->GetData(row,col ,time)); // Central pad
1009 padSignal[3] = TMath::Abs(digitsOut->GetData(row,col+1,time)); // Left pad
1010 padSignal[1] = TMath::Abs(digitsOut->GetData(row,col-1,time)); // Right pad
1012 (TMath::Abs(digitsOut->GetData(row,col-2,time)) < padSignal[1])) {
1013 padSignal[4] = TMath::Abs(digitsOut->GetData(row,col-2,time));
1015 if ((col < nColMax - 3) &&
1016 (TMath::Abs(digitsOut->GetData(row,col+2,time)) < padSignal[3])) {
1017 padSignal[0] = TMath::Abs(digitsOut->GetData(row,col+2,time));
1019 clusterPosCol = GetCOG(padSignal);
1022 // Store the amplitudes of the pads in the cluster for later analysis
1023 // and check whether one of these pads is masked in the database
1024 Short_t signals[7] = { 0, 0, 0, 0, 0, 0, 0 };
1025 for (Int_t jPad = col-3; jPad <= col+3; jPad++) {
1027 (jPad >= nColMax-1)) {
1030 signals[jPad-col+3] = TMath::Nint(TMath::Abs(digitsOut->GetData(row,jPad,time)));
1033 // Transform the local cluster coordinates into calibrated
1034 // space point positions defined in the local tracking system.
1035 // Here the calibration for T0, Vdrift and ExB is applied as well.
1036 Double_t clusterXYZ[6];
1037 clusterXYZ[0] = clusterPosCol;
1038 clusterXYZ[1] = clusterSignal[2];
1039 clusterXYZ[2] = clusterSignal[1];
1040 clusterXYZ[3] = clusterSignal[0];
1041 clusterXYZ[4] = 0.0;
1042 clusterXYZ[5] = 0.0;
1043 Int_t clusterRCT[3];
1044 clusterRCT[0] = row;
1045 clusterRCT[1] = col;
1049 if (fTransform->Transform(clusterXYZ,clusterRCT,((UInt_t) time),out,0)) {
1051 // Add the cluster to the output array
1052 // The track indices will be stored later
1053 Float_t clusterPos[3];
1054 clusterPos[0] = clusterXYZ[0];
1055 clusterPos[1] = clusterXYZ[1];
1056 clusterPos[2] = clusterXYZ[2];
1057 Float_t clusterSig[2];
1058 clusterSig[0] = clusterXYZ[4];
1059 clusterSig[1] = clusterXYZ[5];
1060 Double_t clusterCharge = clusterXYZ[3];
1061 Char_t clusterTimeBin = ((Char_t) clusterRCT[2]);
1063 Int_t n = RecPoints()->GetEntriesFast();
1064 AliTRDcluster *cluster = new((*RecPoints())[n]) AliTRDcluster(
1066 clusterCharge, clusterPos, clusterSig,
1068 ((Char_t) nPadCount),
1070 ((UChar_t) col), ((UChar_t) row), ((UChar_t) time),
1071 clusterTimeBin, clusterPosCol,
1073 cluster->SetInChamber(!out);
1075 UChar_t maskPosition = GetCorruption(padStatus.GetData(row, col, time));
1076 UChar_t padstatus = GetPadStatus(padStatus.GetData(row, col, time));
1078 cluster->SetPadMaskedPosition(maskPosition);
1079 cluster->SetPadMaskedStatus(padstatus);
1082 // Temporarily store the row, column and time bin of the center pad
1083 // Used to later on assign the track indices
1084 cluster->SetLabel( row,0);
1085 cluster->SetLabel( col,1);
1086 cluster->SetLabel(time,2);
1088 // Store the index of the first cluster in the current ROC
1089 if (firstClusterROC < 0) {
1090 firstClusterROC = RecPoints()->GetEntriesFast() - 1;
1093 // Count the number of cluster in the current ROC
1096 } // if: Transform ok ?
1098 } // if: Maximum found ?
1102 if(fReconstructor->GetStreamLevel(AliTRDReconstructor::kClusterizer) > 2){
1103 (*fDebugStream) << "MakeClusters"
1104 << "Detector=" << det
1105 << "NMaxima=" << nMaximas
1106 << "NClusters=" << nClusterROC
1107 << "NCorrupted=" << nCorrupted
1114 AddLabels(idet,firstClusterROC,nClusterROC);
1121 //_____________________________________________________________________________
1122 Bool_t AliTRDclusterizer::AddLabels(Int_t idet, Int_t firstClusterROC, Int_t nClusterROC)
1125 // Add the track indices to the found clusters
1128 const Int_t kNclus = 3;
1129 const Int_t kNdict = AliTRDdigitsManager::kNDict;
1130 const Int_t kNtrack = kNdict * kNclus;
1132 Int_t iClusterROC = 0;
1139 // Temporary array to collect the track indices
1140 Int_t *idxTracks = new Int_t[kNtrack*nClusterROC];
1142 // Loop through the dictionary arrays one-by-one
1143 // to keep memory consumption low
1144 AliTRDarrayDictionary *tracksIn = 0; //mod
1145 for (Int_t iDict = 0; iDict < kNdict; iDict++) {
1147 // tracksIn should be expanded beforehand!
1148 tracksIn = (AliTRDarrayDictionary *) fDigitsManager->GetDictionary(idet,iDict);
1150 // Loop though the clusters found in this ROC
1151 for (iClusterROC = 0; iClusterROC < nClusterROC; iClusterROC++) {
1153 AliTRDcluster *cluster = (AliTRDcluster *)
1154 RecPoints()->UncheckedAt(firstClusterROC+iClusterROC);
1155 row = cluster->GetLabel(0);
1156 col = cluster->GetLabel(1);
1157 time = cluster->GetLabel(2);
1159 for (iPad = 0; iPad < kNclus; iPad++) {
1160 Int_t iPadCol = col - 1 + iPad;
1161 Int_t index = tracksIn->GetData(row,iPadCol,time); //Modification of -1 in Track
1162 idxTracks[3*iPad+iDict + iClusterROC*kNtrack] = index;
1169 // Copy the track indices into the cluster
1170 // Loop though the clusters found in this ROC
1171 for (iClusterROC = 0; iClusterROC < nClusterROC; iClusterROC++) {
1173 AliTRDcluster *cluster = (AliTRDcluster *)
1174 RecPoints()->UncheckedAt(firstClusterROC+iClusterROC);
1175 cluster->SetLabel(-9999,0);
1176 cluster->SetLabel(-9999,1);
1177 cluster->SetLabel(-9999,2);
1179 cluster->AddTrackIndex(&idxTracks[iClusterROC*kNtrack]);
1183 delete [] idxTracks;
1189 //_____________________________________________________________________________
1190 Double_t AliTRDclusterizer::GetCOG(Double_t signal[5]) const
1194 // Used for clusters with more than 3 pads - where LUT not applicable
1197 Double_t sum = signal[0]
1204 // Go to 3 pad COG ????
1206 Double_t res = (0.0 * (-signal[0] + signal[4])
1207 + (-signal[1] + signal[3])) / sum;
1213 //_____________________________________________________________________________
1214 Double_t AliTRDclusterizer::Unfold(Double_t eps, Int_t layer, Double_t *padSignal)
1217 // Method to unfold neighbouring maxima.
1218 // The charge ratio on the overlapping pad is calculated
1219 // until there is no more change within the range given by eps.
1220 // The resulting ratio is then returned to the calling method.
1223 AliTRDcalibDB *calibration = AliTRDcalibDB::Instance();
1225 AliError("No AliTRDcalibDB instance available\n");
1230 Int_t itStep = 0; // Count iteration steps
1232 Double_t ratio = 0.5; // Start value for ratio
1233 Double_t prevRatio = 0.0; // Store previous ratio
1235 Double_t newLeftSignal[3] = { 0.0, 0.0, 0.0 }; // Array to store left cluster signal
1236 Double_t newRightSignal[3] = { 0.0, 0.0, 0.0 }; // Array to store right cluster signal
1237 Double_t newSignal[3] = { 0.0, 0.0, 0.0 };
1239 // Start the iteration
1240 while ((TMath::Abs(prevRatio - ratio) > eps) && (itStep < 10)) {
1245 // Cluster position according to charge ratio
1246 Double_t maxLeft = (ratio*padSignal[2] - padSignal[0])
1247 / (padSignal[0] + padSignal[1] + ratio*padSignal[2]);
1248 Double_t maxRight = (padSignal[4] - (1-ratio)*padSignal[2])
1249 / ((1.0 - ratio)*padSignal[2] + padSignal[3] + padSignal[4]);
1251 // Set cluster charge ratio
1252 irc = calibration->PadResponse(1.0,maxLeft ,layer,newSignal);
1253 Double_t ampLeft = padSignal[1] / newSignal[1];
1254 irc = calibration->PadResponse(1.0,maxRight,layer,newSignal);
1255 Double_t ampRight = padSignal[3] / newSignal[1];
1257 // Apply pad response to parameters
1258 irc = calibration->PadResponse(ampLeft ,maxLeft ,layer,newLeftSignal );
1259 irc = calibration->PadResponse(ampRight,maxRight,layer,newRightSignal);
1261 // Calculate new overlapping ratio
1262 ratio = TMath::Min((Double_t) 1.0
1263 ,newLeftSignal[2] / (newLeftSignal[2] + newRightSignal[0]));
1271 //_____________________________________________________________________________
1272 void AliTRDclusterizer::TailCancelation(AliTRDarrayADC *digitsIn
1273 , AliTRDarraySignal *digitsOut
1274 , AliTRDSignalIndex *indexesIn
1275 , AliTRDSignalIndex *indexesOut
1277 , Float_t adcThreshold
1278 , AliTRDCalROC *calGainFactorROC
1279 , Float_t calGainFactorDetValue)
1282 // Applies the tail cancelation and gain factors:
1283 // Transform digitsIn to digitsOut
1290 Double_t *inADC = new Double_t[nTimeTotal]; // ADC data before tail cancellation
1291 Double_t *outADC = new Double_t[nTimeTotal]; // ADC data after tail cancellation
1292 indexesIn->ResetCounters();
1293 TTreeSRedirector *fDebugStream = fReconstructor->GetDebugStream(AliTRDReconstructor::kClusterizer);
1294 while (indexesIn->NextRCIndex(iRow, iCol))
1296 Float_t calGainFactorROCValue = calGainFactorROC->GetValue(iCol,iRow);
1297 Double_t gain = calGainFactorDetValue
1298 * calGainFactorROCValue;
1300 Bool_t corrupted = kFALSE;
1301 for (iTime = 0; iTime < nTimeTotal; iTime++)
1303 // Apply gain gain factor
1304 inADC[iTime] = digitsIn->GetDataB(iRow,iCol,iTime);
1305 if (digitsIn->GetPadStatus(iRow, iCol, iTime)) corrupted = kTRUE;
1306 inADC[iTime] /= gain;
1307 outADC[iTime] = inADC[iTime];
1308 if(fReconstructor->GetStreamLevel(AliTRDReconstructor::kClusterizer) > 7){
1309 (*fDebugStream) << "TailCancellation"
1313 << "inADC=" << inADC[iTime]
1315 << "outADC=" << outADC[iTime]
1316 << "corrupted=" << corrupted
1322 // Apply the tail cancelation via the digital filter
1323 // (only for non-coorupted pads)
1324 if (fReconstructor->GetRecoParam() ->IsTailCancelation())
1326 DeConvExp(inADC,outADC,nTimeTotal,fReconstructor->GetRecoParam() ->GetTCnexp());
1330 indexesIn->ResetTbinCounter();
1332 while (indexesIn->NextTbinIndex(iTime))
1334 // Store the amplitude of the digit if above threshold
1335 if (outADC[iTime] > adcThreshold)
1337 digitsOut->SetData(iRow,iCol,iTime,outADC[iTime]);
1338 indexesOut->AddIndexTBin(iRow,iCol,iTime);
1342 } // while irow icol
1351 //_____________________________________________________________________________
1352 void AliTRDclusterizer::DeConvExp(Double_t *source, Double_t *target
1353 , Int_t n, Int_t nexp)
1356 // Tail cancellation by deconvolution for PASA v4 TRF
1360 Double_t coefficients[2];
1362 // Initialization (coefficient = alpha, rates = lambda)
1368 if (nexp == 1) { // 1 Exponentials
1374 if (nexp == 2) { // 2 Exponentials
1376 fReconstructor->GetTCParams(par);
1377 r1 = par[0];//1.156;
1378 r2 = par[1];//0.130;
1379 c1 = par[2];//0.114;
1380 c2 = par[3];//0.624;
1383 coefficients[0] = c1;
1384 coefficients[1] = c2;
1388 rates[0] = TMath::Exp(-dt/(r1));
1389 rates[1] = TMath::Exp(-dt/(r2));
1394 Double_t reminder[2];
1395 Double_t correction = 0.0;
1396 Double_t result = 0.0;
1398 // Attention: computation order is important
1399 for (k = 0; k < nexp; k++) {
1403 for (i = 0; i < n; i++) {
1405 result = (source[i] - correction); // No rescaling
1408 for (k = 0; k < nexp; k++) {
1409 reminder[k] = rates[k] * (reminder[k] + coefficients[k] * result);
1413 for (k = 0; k < nexp; k++) {
1414 correction += reminder[k];
1421 //_____________________________________________________________________________
1422 void AliTRDclusterizer::ResetRecPoints()
1425 // Resets the list of rec points
1429 fRecPoints->Delete();
1434 //_____________________________________________________________________________
1435 TClonesArray *AliTRDclusterizer::RecPoints()
1438 // Returns the list of rec points
1442 if(!(fRecPoints = AliTRDReconstructor::GetClusters())){
1443 // determine number of clusters which has to be allocated
1444 Float_t nclusters = fReconstructor->GetRecoParam()->GetNClusters();
1445 if(fReconstructor->IsHLT()) nclusters /= AliTRDgeometry::kNsector;
1447 fRecPoints = new TClonesArray("AliTRDcluster", Int_t(nclusters));
1449 //SetClustersOwner(kTRUE);
1450 AliTRDReconstructor::SetClusters(0x0);
1456 //_____________________________________________________________________________
1457 void AliTRDclusterizer::FillLUT()
1463 const Int_t kNlut = 128;
1465 fLUTbin = AliTRDgeometry::kNlayer * kNlut;
1467 // The lookup table from Bogdan
1468 Float_t lut[AliTRDgeometry::kNlayer][kNlut] = {
1470 0.0070, 0.0150, 0.0224, 0.0298, 0.0374, 0.0454, 0.0533, 0.0611,
1471 0.0684, 0.0755, 0.0827, 0.0900, 0.0975, 0.1049, 0.1120, 0.1187,
1472 0.1253, 0.1318, 0.1385, 0.1453, 0.1519, 0.1584, 0.1646, 0.1704,
1473 0.1762, 0.1821, 0.1879, 0.1938, 0.1996, 0.2053, 0.2108, 0.2160,
1474 0.2210, 0.2260, 0.2310, 0.2361, 0.2411, 0.2461, 0.2509, 0.2557,
1475 0.2602, 0.2646, 0.2689, 0.2732, 0.2774, 0.2816, 0.2859, 0.2901,
1476 0.2942, 0.2983, 0.3022, 0.3061, 0.3099, 0.3136, 0.3172, 0.3207,
1477 0.3242, 0.3278, 0.3312, 0.3347, 0.3382, 0.3416, 0.3450, 0.3483,
1478 0.3515, 0.3547, 0.3579, 0.3609, 0.3639, 0.3669, 0.3698, 0.3727,
1479 0.3756, 0.3785, 0.3813, 0.3842, 0.3870, 0.3898, 0.3926, 0.3952,
1480 0.3979, 0.4005, 0.4032, 0.4057, 0.4082, 0.4108, 0.4132, 0.4157,
1481 0.4181, 0.4205, 0.4228, 0.4252, 0.4275, 0.4299, 0.4322, 0.4345,
1482 0.4367, 0.4390, 0.4412, 0.4434, 0.4456, 0.4478, 0.4499, 0.4520,
1483 0.4541, 0.4562, 0.4583, 0.4603, 0.4623, 0.4643, 0.4663, 0.4683,
1484 0.4702, 0.4722, 0.4741, 0.4758, 0.4774, 0.4790, 0.4805, 0.4824,
1485 0.4844, 0.4863, 0.4883, 0.4902, 0.4921, 0.4940, 0.4959, 0.4978
1488 0.0072, 0.0156, 0.0235, 0.0313, 0.0394, 0.0478, 0.0561, 0.0642,
1489 0.0718, 0.0792, 0.0868, 0.0947, 0.1025, 0.1101, 0.1172, 0.1241,
1490 0.1309, 0.1378, 0.1449, 0.1518, 0.1586, 0.1650, 0.1710, 0.1770,
1491 0.1830, 0.1891, 0.1952, 0.2011, 0.2070, 0.2125, 0.2177, 0.2229,
1492 0.2280, 0.2332, 0.2383, 0.2435, 0.2484, 0.2533, 0.2581, 0.2627,
1493 0.2670, 0.2714, 0.2757, 0.2799, 0.2842, 0.2884, 0.2927, 0.2968,
1494 0.3008, 0.3048, 0.3086, 0.3123, 0.3159, 0.3195, 0.3231, 0.3266,
1495 0.3301, 0.3335, 0.3370, 0.3404, 0.3438, 0.3471, 0.3504, 0.3536,
1496 0.3567, 0.3598, 0.3628, 0.3657, 0.3686, 0.3715, 0.3744, 0.3772,
1497 0.3800, 0.3828, 0.3856, 0.3884, 0.3911, 0.3938, 0.3965, 0.3991,
1498 0.4016, 0.4042, 0.4067, 0.4092, 0.4116, 0.4140, 0.4164, 0.4187,
1499 0.4211, 0.4234, 0.4257, 0.4280, 0.4302, 0.4325, 0.4347, 0.4369,
1500 0.4391, 0.4413, 0.4434, 0.4456, 0.4477, 0.4497, 0.4518, 0.4538,
1501 0.4558, 0.4578, 0.4598, 0.4618, 0.4637, 0.4656, 0.4675, 0.4694,
1502 0.4713, 0.4732, 0.4750, 0.4766, 0.4781, 0.4797, 0.4813, 0.4832,
1503 0.4851, 0.4870, 0.4888, 0.4906, 0.4925, 0.4942, 0.4960, 0.4978
1506 0.0075, 0.0163, 0.0246, 0.0328, 0.0415, 0.0504, 0.0592, 0.0674,
1507 0.0753, 0.0832, 0.0914, 0.0996, 0.1077, 0.1154, 0.1225, 0.1296,
1508 0.1369, 0.1442, 0.1515, 0.1585, 0.1652, 0.1714, 0.1776, 0.1839,
1509 0.1902, 0.1965, 0.2025, 0.2085, 0.2141, 0.2194, 0.2247, 0.2299,
1510 0.2352, 0.2405, 0.2457, 0.2507, 0.2557, 0.2604, 0.2649, 0.2693,
1511 0.2737, 0.2780, 0.2823, 0.2867, 0.2909, 0.2951, 0.2992, 0.3033,
1512 0.3072, 0.3110, 0.3146, 0.3182, 0.3218, 0.3253, 0.3288, 0.3323,
1513 0.3357, 0.3392, 0.3426, 0.3459, 0.3492, 0.3524, 0.3555, 0.3586,
1514 0.3616, 0.3645, 0.3674, 0.3703, 0.3731, 0.3759, 0.3787, 0.3815,
1515 0.3843, 0.3870, 0.3897, 0.3925, 0.3950, 0.3976, 0.4002, 0.4027,
1516 0.4052, 0.4076, 0.4101, 0.4124, 0.4148, 0.4171, 0.4194, 0.4217,
1517 0.4239, 0.4262, 0.4284, 0.4306, 0.4328, 0.4350, 0.4371, 0.4393,
1518 0.4414, 0.4435, 0.4455, 0.4476, 0.4496, 0.4516, 0.4536, 0.4555,
1519 0.4575, 0.4594, 0.4613, 0.4632, 0.4650, 0.4669, 0.4687, 0.4705,
1520 0.4723, 0.4741, 0.4758, 0.4773, 0.4789, 0.4804, 0.4821, 0.4839,
1521 0.4857, 0.4875, 0.4893, 0.4910, 0.4928, 0.4945, 0.4961, 0.4978
1524 0.0078, 0.0171, 0.0258, 0.0345, 0.0438, 0.0532, 0.0624, 0.0708,
1525 0.0791, 0.0875, 0.0962, 0.1048, 0.1130, 0.1206, 0.1281, 0.1356,
1526 0.1432, 0.1508, 0.1582, 0.1651, 0.1716, 0.1780, 0.1845, 0.1910,
1527 0.1975, 0.2038, 0.2099, 0.2155, 0.2210, 0.2263, 0.2317, 0.2371,
1528 0.2425, 0.2477, 0.2528, 0.2578, 0.2626, 0.2671, 0.2715, 0.2759,
1529 0.2803, 0.2846, 0.2890, 0.2933, 0.2975, 0.3016, 0.3056, 0.3095,
1530 0.3132, 0.3168, 0.3204, 0.3239, 0.3274, 0.3309, 0.3344, 0.3378,
1531 0.3412, 0.3446, 0.3479, 0.3511, 0.3543, 0.3574, 0.3603, 0.3633,
1532 0.3662, 0.3690, 0.3718, 0.3747, 0.3774, 0.3802, 0.3829, 0.3857,
1533 0.3883, 0.3910, 0.3936, 0.3962, 0.3987, 0.4012, 0.4037, 0.4061,
1534 0.4085, 0.4109, 0.4132, 0.4155, 0.4177, 0.4200, 0.4222, 0.4244,
1535 0.4266, 0.4288, 0.4309, 0.4331, 0.4352, 0.4373, 0.4394, 0.4414,
1536 0.4435, 0.4455, 0.4475, 0.4494, 0.4514, 0.4533, 0.4552, 0.4571,
1537 0.4590, 0.4608, 0.4626, 0.4645, 0.4662, 0.4680, 0.4698, 0.4715,
1538 0.4733, 0.4750, 0.4766, 0.4781, 0.4796, 0.4812, 0.4829, 0.4846,
1539 0.4863, 0.4880, 0.4897, 0.4914, 0.4930, 0.4946, 0.4963, 0.4979
1542 0.0081, 0.0178, 0.0270, 0.0364, 0.0463, 0.0562, 0.0656, 0.0744,
1543 0.0831, 0.0921, 0.1013, 0.1102, 0.1183, 0.1261, 0.1339, 0.1419,
1544 0.1499, 0.1576, 0.1648, 0.1715, 0.1782, 0.1849, 0.1917, 0.1984,
1545 0.2048, 0.2110, 0.2167, 0.2223, 0.2278, 0.2333, 0.2389, 0.2444,
1546 0.2497, 0.2548, 0.2598, 0.2645, 0.2691, 0.2735, 0.2780, 0.2824,
1547 0.2868, 0.2912, 0.2955, 0.2997, 0.3038, 0.3078, 0.3116, 0.3152,
1548 0.3188, 0.3224, 0.3259, 0.3294, 0.3329, 0.3364, 0.3398, 0.3432,
1549 0.3465, 0.3497, 0.3529, 0.3561, 0.3591, 0.3620, 0.3649, 0.3677,
1550 0.3705, 0.3733, 0.3761, 0.3788, 0.3816, 0.3843, 0.3869, 0.3896,
1551 0.3922, 0.3948, 0.3973, 0.3998, 0.4022, 0.4047, 0.4070, 0.4094,
1552 0.4117, 0.4139, 0.4162, 0.4184, 0.4206, 0.4227, 0.4249, 0.4270,
1553 0.4291, 0.4313, 0.4334, 0.4354, 0.4375, 0.4395, 0.4415, 0.4435,
1554 0.4455, 0.4474, 0.4493, 0.4512, 0.4531, 0.4550, 0.4568, 0.4586,
1555 0.4604, 0.4622, 0.4639, 0.4657, 0.4674, 0.4691, 0.4708, 0.4725,
1556 0.4742, 0.4758, 0.4773, 0.4788, 0.4803, 0.4819, 0.4836, 0.4852,
1557 0.4869, 0.4885, 0.4901, 0.4917, 0.4933, 0.4948, 0.4964, 0.4979
1560 0.0085, 0.0189, 0.0288, 0.0389, 0.0497, 0.0603, 0.0699, 0.0792,
1561 0.0887, 0.0985, 0.1082, 0.1170, 0.1253, 0.1336, 0.1421, 0.1505,
1562 0.1587, 0.1662, 0.1733, 0.1803, 0.1874, 0.1945, 0.2014, 0.2081,
1563 0.2143, 0.2201, 0.2259, 0.2316, 0.2374, 0.2431, 0.2487, 0.2541,
1564 0.2593, 0.2642, 0.2689, 0.2735, 0.2781, 0.2826, 0.2872, 0.2917,
1565 0.2961, 0.3003, 0.3045, 0.3086, 0.3125, 0.3162, 0.3198, 0.3235,
1566 0.3270, 0.3306, 0.3342, 0.3377, 0.3411, 0.3446, 0.3479, 0.3511,
1567 0.3543, 0.3575, 0.3605, 0.3634, 0.3663, 0.3691, 0.3720, 0.3748,
1568 0.3775, 0.3803, 0.3830, 0.3857, 0.3884, 0.3911, 0.3937, 0.3962,
1569 0.3987, 0.4012, 0.4036, 0.4060, 0.4084, 0.4107, 0.4129, 0.4152,
1570 0.4174, 0.4196, 0.4218, 0.4239, 0.4261, 0.4282, 0.4303, 0.4324,
1571 0.4344, 0.4365, 0.4385, 0.4405, 0.4425, 0.4445, 0.4464, 0.4483,
1572 0.4502, 0.4521, 0.4539, 0.4558, 0.4576, 0.4593, 0.4611, 0.4629,
1573 0.4646, 0.4663, 0.4680, 0.4697, 0.4714, 0.4730, 0.4747, 0.4759,
1574 0.4769, 0.4780, 0.4790, 0.4800, 0.4811, 0.4827, 0.4843, 0.4859,
1575 0.4874, 0.4889, 0.4905, 0.4920, 0.4935, 0.4950, 0.4965, 0.4979
1582 fLUT = new Double_t[fLUTbin];
1584 for (Int_t ilayer = 0; ilayer < AliTRDgeometry::kNlayer; ilayer++) {
1585 for (Int_t ilut = 0; ilut < kNlut; ilut++ ) {
1586 fLUT[ilayer*kNlut+ilut] = lut[ilayer][ilut];
1592 //_____________________________________________________________________________
1593 Double_t AliTRDclusterizer::LUTposition(Int_t ilayer
1596 , Double_t ampR) const
1599 // Calculates the cluster position using the lookup table.
1600 // Method provided by Bogdan Vulpescu.
1603 const Int_t kNlut = 128;
1614 Double_t xMin[AliTRDgeometry::kNlayer] = { 0.006492, 0.006377, 0.006258
1615 , 0.006144, 0.006030, 0.005980 };
1616 Double_t xMax[AliTRDgeometry::kNlayer] = { 0.960351, 0.965870, 0.970445
1617 , 0.974352, 0.977667, 0.996101 };
1620 x = (ampL - ampR) / ampC;
1623 else if (ampL < ampR) {
1624 x = (ampR - ampL) / ampC;
1630 xmin = xMin[ilayer] + 0.000005;
1631 xmax = xMax[ilayer] - 0.000005;
1632 xwid = (xmax - xmin) / 127.0;
1637 else if (x > xmax) {
1638 pos = side * 0.5000;
1641 ix = (Int_t) ((x - xmin) / xwid);
1642 pos = side * fLUT[ilayer*kNlut+ix];