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 "AliTRDdataArrayF.h"
42 #include "AliTRDdataArrayI.h"
43 #include "AliTRDdataArrayS.h"
44 #include "AliTRDdataArrayDigits.h"
45 #include "AliTRDdigitsManager.h"
46 #include "AliTRDrawData.h"
47 #include "AliTRDcalibDB.h"
48 #include "AliTRDrecoParam.h"
49 #include "AliTRDCommonParam.h"
50 #include "AliTRDtransform.h"
51 #include "AliTRDSignalIndex.h"
52 #include "AliTRDrawStreamBase.h"
53 #include "AliTRDfeeParam.h"
55 #include "Cal/AliTRDCalROC.h"
56 #include "Cal/AliTRDCalDet.h"
57 #include "Cal/AliTRDCalSingleChamberStatus.h"
59 ClassImp(AliTRDclusterizer)
61 //_____________________________________________________________________________
62 AliTRDclusterizer::AliTRDclusterizer(AliTRDReconstructor *rec)
70 ,fTrackletContainer(NULL)
75 ,fTransform(new AliTRDtransform(0))
80 // AliTRDclusterizer default constructor
83 AliTRDcalibDB *trd = 0x0;
84 if (!(trd = AliTRDcalibDB::Instance())) {
85 AliFatal("Could not get calibration object");
88 fRawVersion = AliTRDfeeParam::Instance()->GetRAWversion();
90 // Initialize debug stream
92 if(fReconstructor->GetStreamLevel(AliTRDReconstructor::kClusterizer) > 1){
93 TDirectory *savedir = gDirectory;
94 //fgDebugStreamer = new TTreeSRedirector("TRD.ClusterizerDebug.root");
101 //_____________________________________________________________________________
102 AliTRDclusterizer::AliTRDclusterizer(const Text_t *name, const Text_t *title, AliTRDReconstructor *rec)
109 ,fDigitsManager(new AliTRDdigitsManager())
110 ,fTrackletContainer(NULL)
114 ,fIndexesMaxima(NULL)
115 ,fTransform(new AliTRDtransform(0))
120 // AliTRDclusterizer constructor
123 AliTRDcalibDB *trd = 0x0;
124 if (!(trd = AliTRDcalibDB::Instance())) {
125 AliFatal("Could not get calibration object");
128 // Initialize debug stream
130 if (fReconstructor->GetStreamLevel(AliTRDReconstructor::kClusterizer) > 1){
131 TDirectory *savedir = gDirectory;
132 //fgDebugStreamer = new TTreeSRedirector("TRD.ClusterizerDebug.root");
137 fDigitsManager->CreateArrays();
139 fRawVersion = AliTRDfeeParam::Instance()->GetRAWversion();
145 //_____________________________________________________________________________
146 AliTRDclusterizer::AliTRDclusterizer(const AliTRDclusterizer &c)
148 ,fReconstructor(c.fReconstructor)
153 ,fDigitsManager(NULL)
154 ,fTrackletContainer(NULL)
158 ,fIndexesMaxima(NULL)
164 // AliTRDclusterizer copy constructor
171 //_____________________________________________________________________________
172 AliTRDclusterizer::~AliTRDclusterizer()
175 // AliTRDclusterizer destructor
178 if (fRecPoints/* && IsClustersOwner()*/){
179 fRecPoints->Delete();
183 if (fDigitsManager) {
184 delete fDigitsManager;
185 fDigitsManager = NULL;
188 if (fTrackletContainer){
189 delete fTrackletContainer;
190 fTrackletContainer = NULL;
199 delete fIndexesMaxima;
200 fIndexesMaxima = NULL;
215 //_____________________________________________________________________________
216 AliTRDclusterizer &AliTRDclusterizer::operator=(const AliTRDclusterizer &c)
219 // Assignment operator
224 ((AliTRDclusterizer &) c).Copy(*this);
231 //_____________________________________________________________________________
232 void AliTRDclusterizer::Copy(TObject &c) const
238 ((AliTRDclusterizer &) c).fClusterTree = NULL;
239 ((AliTRDclusterizer &) c).fRecPoints = NULL;
240 ((AliTRDclusterizer &) c).fTrackletTree = NULL;
241 ((AliTRDclusterizer &) c).fDigitsManager = NULL;
242 ((AliTRDclusterizer &) c).fTrackletContainer = NULL;
243 ((AliTRDclusterizer &) c).fAddLabels = fAddLabels;
244 ((AliTRDclusterizer &) c).fRawVersion = fRawVersion;
245 ((AliTRDclusterizer &) c).fIndexesOut = NULL;
246 ((AliTRDclusterizer &) c).fIndexesMaxima = NULL;
247 ((AliTRDclusterizer &) c).fTransform = NULL;
248 ((AliTRDclusterizer &) c).fLUTbin = 0;
249 ((AliTRDclusterizer &) c).fLUT = NULL;
253 //_____________________________________________________________________________
254 Bool_t AliTRDclusterizer::Open(const Char_t *name, Int_t nEvent)
257 // Opens the AliROOT file. Output and input are in the same file
260 TString evfoldname = AliConfig::GetDefaultEventFolderName();
261 fRunLoader = AliRunLoader::GetRunLoader(evfoldname);
264 fRunLoader = AliRunLoader::Open(name);
268 AliError(Form("Can not open session for file %s.",name));
279 //_____________________________________________________________________________
280 Bool_t AliTRDclusterizer::OpenOutput()
283 // Open the output file
286 if (!fReconstructor->IsWritingClusters()) return kTRUE;
288 TObjArray *ioArray = 0x0;
290 AliLoader* loader = fRunLoader->GetLoader("TRDLoader");
291 loader->MakeTree("R");
293 fClusterTree = loader->TreeR();
294 fClusterTree->Branch("TRDcluster", "TObjArray", &ioArray, 32000, 0);
300 //_____________________________________________________________________________
301 Bool_t AliTRDclusterizer::OpenOutput(TTree *clusterTree)
304 // Connect the output tree
308 if (fReconstructor->IsWritingClusters()){
309 TObjArray *ioArray = 0x0;
310 fClusterTree = clusterTree;
311 fClusterTree->Branch("TRDcluster", "TObjArray", &ioArray, 32000, 0);
315 if (fReconstructor->IsWritingTracklets()){
316 TString evfoldname = AliConfig::GetDefaultEventFolderName();
317 fRunLoader = AliRunLoader::GetRunLoader(evfoldname);
320 fRunLoader = AliRunLoader::Open("galice.root");
323 AliError(Form("Can not open session for file galice.root."));
327 UInt_t **leaves = new UInt_t *[2];
328 AliDataLoader *dl = fRunLoader->GetLoader("TRDLoader")->GetDataLoader("tracklets");
330 AliError("Could not get the tracklets data loader!");
331 AliDataLoader *dl = new AliDataLoader("TRD.Tracklets.root","tracklets", "tracklets");
332 fRunLoader->GetLoader("TRDLoader")->AddDataLoader(dl);
335 fTrackletTree = dl->Tree();
339 fTrackletTree = dl->Tree();
341 TBranch *trkbranch = fTrackletTree->GetBranch("trkbranch");
343 fTrackletTree->Branch("trkbranch",leaves[0],"det/i:side/i:tracklets[256]/i");
351 //_____________________________________________________________________________
352 Bool_t AliTRDclusterizer::OpenInput(Int_t nEvent)
355 // Opens a ROOT-file with TRD-hits and reads in the digits-tree
358 // Import the Trees for the event nEvent in the file
359 fRunLoader->GetEvent(nEvent);
365 //_____________________________________________________________________________
366 Bool_t AliTRDclusterizer::WriteClusters(Int_t det)
369 // Fills TRDcluster branch in the tree with the clusters
370 // found in detector = det. For det=-1 writes the tree.
374 (det >= AliTRDgeometry::Ndet())) {
375 AliError(Form("Unexpected detector index %d.\n",det));
379 TObjArray *ioArray = new TObjArray(400);
380 TBranch *branch = fClusterTree->GetBranch("TRDcluster");
382 branch = fClusterTree->Branch("TRDcluster","TObjArray",&ioArray,32000,0);
383 } else branch->SetAddress(&ioArray);
385 Int_t nRecPoints = RecPoints()->GetEntriesFast();
387 for (Int_t i = 0; i < nRecPoints; i++) {
388 AliTRDcluster *c = (AliTRDcluster *) RecPoints()->UncheckedAt(i);
389 if(det != c->GetDetector()) continue;
392 fClusterTree->Fill();
396 for (Int_t i = 0; i < nRecPoints; i++) {
397 AliTRDcluster *c = (AliTRDcluster *) RecPoints()->UncheckedAt(i);
398 if(c->GetDetector() != detOld){
399 fClusterTree->Fill();
401 detOld = c->GetDetector();
412 //_____________________________________________________________________________
413 Bool_t AliTRDclusterizer::WriteTracklets(Int_t det)
416 // Write the raw data tracklets into seperate file
419 UInt_t **leaves = new UInt_t *[2];
420 for (Int_t i=0; i<2 ;i++){
421 leaves[i] = new UInt_t[258];
422 leaves[i][0] = det; // det
423 leaves[i][1] = i; // side
424 memcpy(leaves[i]+2, fTrackletContainer[i], sizeof(UInt_t) * 256);
428 AliDataLoader *dl = fRunLoader->GetLoader("TRDLoader")->GetDataLoader("tracklets");
430 fTrackletTree = dl->Tree();
433 TBranch *trkbranch = fTrackletTree->GetBranch("trkbranch");
435 trkbranch = fTrackletTree->Branch("trkbranch",leaves[0],"det/i:side/i:tracklets[256]/i");
438 for (Int_t i=0; i<2; i++){
439 if (leaves[i][2]>0) {
440 trkbranch->SetAddress(leaves[i]);
441 fTrackletTree->Fill();
445 AliDataLoader *dl = fRunLoader->GetLoader("TRDLoader")->GetDataLoader("tracklets");
446 dl->WriteData("OVERWRITE");
454 //_____________________________________________________________________________
455 void AliTRDclusterizer::ResetHelperIndexes(AliTRDSignalIndex *indexesIn)
458 // Reset the helper indexes
463 // carefull here - we assume that only row number may change - most probable
464 if (indexesIn->GetNrow() <= fIndexesOut->GetNrow())
465 fIndexesOut->ResetContent();
467 fIndexesOut->ResetContentConditional(indexesIn->GetNrow()
468 , indexesIn->GetNcol()
469 , indexesIn->GetNtime());
473 fIndexesOut = new AliTRDSignalIndex(indexesIn->GetNrow()
474 , indexesIn->GetNcol()
475 , indexesIn->GetNtime());
480 // carefull here - we assume that only row number may change - most probable
481 if (indexesIn->GetNrow() <= fIndexesMaxima->GetNrow())
483 fIndexesMaxima->ResetContent();
487 fIndexesMaxima->ResetContentConditional(indexesIn->GetNrow()
488 , indexesIn->GetNcol()
489 , indexesIn->GetNtime());
494 fIndexesMaxima = new AliTRDSignalIndex(indexesIn->GetNrow()
495 , indexesIn->GetNcol()
496 , indexesIn->GetNtime());
501 //_____________________________________________________________________________
502 Bool_t AliTRDclusterizer::ReadDigits()
505 // Reads the digits arrays from the input aliroot file
509 AliError("No run loader available");
513 AliLoader* loader = fRunLoader->GetLoader("TRDLoader");
514 if (!loader->TreeD()) {
515 loader->LoadDigits();
518 // Read in the digit arrays
519 return (fDigitsManager->ReadDigits(loader->TreeD()));
523 //_____________________________________________________________________________
524 Bool_t AliTRDclusterizer::ReadDigits(TTree *digitsTree)
527 // Reads the digits arrays from the input tree
530 // Read in the digit arrays
531 return (fDigitsManager->ReadDigits(digitsTree));
535 //_____________________________________________________________________________
536 Bool_t AliTRDclusterizer::ReadDigits(AliRawReader *rawReader)
539 // Reads the digits arrays from the ddl file
543 fDigitsManager = raw.Raw2Digits(rawReader);
549 //_____________________________________________________________________________
550 Bool_t AliTRDclusterizer::MakeClusters()
553 // Creates clusters from digits
556 // Propagate info from the digits manager
557 if (fAddLabels == kTRUE){
558 fAddLabels = fDigitsManager->UsesDictionaries();
561 Bool_t fReturn = kTRUE;
562 for (Int_t i = 0; i < AliTRDgeometry::kNdet; i++){
564 AliTRDdataArrayDigits *digitsIn = (AliTRDdataArrayDigits*) fDigitsManager->GetDigits(i);
565 // This is to take care of switched off super modules
566 if (!digitsIn->HasData()) continue;
568 AliTRDSignalIndex* indexes = fDigitsManager->GetIndexes(i);
569 if (indexes->IsAllocated() == kFALSE){
570 fDigitsManager->BuildIndexes(i);
574 if (indexes->HasEntry()){
576 for (Int_t iDict = 0; iDict < AliTRDdigitsManager::kNDict; iDict++){
577 AliTRDdataArrayI *tracksIn = 0;
578 tracksIn = (AliTRDdataArrayI *) fDigitsManager->GetDictionary(i,iDict);
582 fR = MakeClusters(i);
583 fReturn = fR && fReturn;
587 // if(IsWritingClusters()) WriteClusters(i);
591 // No compress just remove
592 fDigitsManager->RemoveDigits(i);
593 fDigitsManager->RemoveDictionaries(i);
594 fDigitsManager->ClearIndexes(i);
597 if(fReconstructor->IsWritingClusters()) WriteClusters(-1);
599 AliInfo(Form("Number of found clusters : %d", RecPoints()->GetEntriesFast()));
605 //_____________________________________________________________________________
606 Bool_t AliTRDclusterizer::Raw2Clusters(AliRawReader *rawReader)
609 // Creates clusters from raw data
612 return Raw2ClustersChamber(rawReader);
616 //_____________________________________________________________________________
617 Bool_t AliTRDclusterizer::Raw2ClustersChamber(AliRawReader *rawReader)
620 // Creates clusters from raw data
623 // Create the digits manager
624 if (!fDigitsManager){
625 fDigitsManager = new AliTRDdigitsManager();
626 fDigitsManager->CreateArrays();
629 fDigitsManager->SetUseDictionaries(fAddLabels);
631 AliTRDrawStreamBase *pinput = AliTRDrawStreamBase::GetRawStream(rawReader);
632 AliTRDrawStreamBase &input = *pinput;
634 AliInfo(Form("Stream version: %s", input.IsA()->GetName()));
637 while ((det = input.NextChamber(fDigitsManager)) >= 0){
638 Bool_t iclusterBranch = kFALSE;
639 if (fDigitsManager->GetIndexes(det)->HasEntry()){
640 iclusterBranch = MakeClusters(det);
643 fDigitsManager->RemoveDigits(det);
644 fDigitsManager->RemoveDictionaries(det);
645 fDigitsManager->ClearIndexes(det);
647 if(fReconstructor->IsWritingClusters()) WriteClusters(-1);
649 delete fDigitsManager;
650 fDigitsManager = NULL;
655 AliInfo(Form("Number of found clusters : %d", RecPoints()->GetEntriesFast()));
660 //_____________________________________________________________________________
661 UChar_t AliTRDclusterizer::GetStatus(Short_t &signal)
664 // Check if a pad is masked
669 if(signal>0 && TESTBIT(signal, 10)){
671 for(int ibit=0; ibit<4; ibit++){
672 if(TESTBIT(signal, 11+ibit)){
673 SETBIT(status, ibit);
674 CLRBIT(signal, 11+ibit);
681 //_____________________________________________________________________________
682 Bool_t AliTRDclusterizer::MakeClusters(Int_t det)
685 // Generates the cluster.
689 // digits should be expanded beforehand!
690 // digitsIn->Expand();
691 AliTRDdataArrayDigits *digitsIn = (AliTRDdataArrayDigits *) fDigitsManager->GetDigits(det);
693 // This is to take care of switched off super modules
694 if (!digitsIn->HasData())
699 AliTRDSignalIndex *indexesIn = fDigitsManager->GetIndexes(det);
700 if (indexesIn->IsAllocated() == kFALSE)
702 AliError("Indexes do not exist!");
706 AliTRDcalibDB *calibration = AliTRDcalibDB::Instance();
709 AliFatal("No AliTRDcalibDB instance available\n");
714 // There is no ADC threshold anymore, and simParam should not be used in clusterizer. KO
715 Float_t adcThreshold = 0;
717 if (!fReconstructor){
718 AliError("Reconstructor not set\n");
722 // Threshold value for the maximum
723 Float_t maxThresh = fReconstructor->GetRecoParam()->GetClusMaxThresh();
724 // Threshold value for the digit signal
725 Float_t sigThresh = fReconstructor->GetRecoParam()->GetClusSigThresh();
727 // Threshold value for the maximum ( cut noise)
728 Float_t minMaxCutSigma = fReconstructor->GetRecoParam()->GetMinMaxCutSigma();
729 // Threshold value for the sum pad ( cut noise)
730 Float_t minLeftRightCutSigma = fReconstructor->GetRecoParam()->GetMinLeftRightCutSigma();
732 // Iteration limit for unfolding procedure
733 const Float_t kEpsilon = 0.01;
734 const Int_t kNclus = 3;
735 const Int_t kNsig = 5;
738 Double_t ratioLeft = 1.0;
739 Double_t ratioRight = 1.0;
741 Double_t padSignal[kNsig];
742 Double_t clusterSignal[kNclus];
744 Int_t istack = indexesIn->GetStack();
745 Int_t ilayer = indexesIn->GetLayer();
746 Int_t isector = indexesIn->GetSM();
748 // Start clustering in the chamber
750 Int_t idet = AliTRDgeometry::GetDetector(ilayer,istack,isector);
753 AliError("Strange Detector number Missmatch!");
757 // TRD space point transformation
758 fTransform->SetDetector(det);
760 Int_t iGeoLayer = AliGeomManager::kTRD1 + ilayer;
761 Int_t iGeoModule = istack + AliTRDgeometry::Nstack() * isector;
762 UShort_t volid = AliGeomManager::LayerToVolUID(iGeoLayer,iGeoModule);
764 Int_t nColMax = digitsIn->GetNcol();
765 Int_t nRowMax = digitsIn->GetNrow();
766 Int_t nTimeTotal = digitsIn->GetNtime();
768 // Detector wise calibration object for the gain factors
769 const AliTRDCalDet *calGainFactorDet = calibration->GetGainFactorDet();
770 // Calibration object with pad wise values for the gain factors
771 AliTRDCalROC *calGainFactorROC = calibration->GetGainFactorROC(idet);
772 // Calibration value for chamber wise gain factor
773 Float_t calGainFactorDetValue = calGainFactorDet->GetValue(idet);
775 // Detector wise calibration object for the noise
776 const AliTRDCalDet *calNoiseDet = calibration->GetNoiseDet();
777 // Calibration object with pad wise values for the noise
778 AliTRDCalROC *calNoiseROC = calibration->GetNoiseROC(idet);
779 // Calibration value for chamber wise noise
780 Float_t calNoiseDetValue = calNoiseDet->GetValue(idet);
784 AliTRDdataArrayF *digitsOut = new AliTRDdataArrayF(nRowMax, nColMax, nTimeTotal);
785 AliTRDdataArrayS padStatus(nRowMax, nColMax, nTimeTotal);
787 ResetHelperIndexes(indexesIn);
789 // Apply the gain and the tail cancelation via digital filter
790 TailCancelation(digitsIn
797 ,calGainFactorDetValue);
804 UChar_t status[3]={0, 0, 0}, ipos = 0;
805 fIndexesOut->ResetCounters();
806 while (fIndexesOut->NextRCTbinIndex(row, col, time)) {
808 Float_t signalM = TMath::Abs(digitsOut->GetDataUnchecked(row,col,time));
809 status[1] = digitsIn->GetPadStatus(row,col,time);
810 if(status[1]) SETBIT(ipos, AliTRDcluster::kMaskedCenter);
812 if(signalM < maxThresh) continue;
814 Float_t noiseMiddleThresh = minMaxCutSigma*calNoiseDetValue*calNoiseROC->GetValue(col,row);
815 if (signalM < noiseMiddleThresh) continue;
817 if (col + 1 >= nColMax || col-1 < 0) continue;
819 Float_t signalL = TMath::Abs(digitsOut->GetDataUnchecked(row,col+1,time));
820 status[0] = digitsIn->GetPadStatus(row,col+1,time);
821 if(status[0]) SETBIT(ipos, AliTRDcluster::kMaskedLeft);
823 Float_t signalR = TMath::Abs(digitsOut->GetDataUnchecked(row,col-1,time));
824 status[2] = digitsIn->GetPadStatus(row,col-1,time);
825 if(status[2]) SETBIT(ipos, AliTRDcluster::kMaskedRight);
827 // reject candidates with more than 1 problematic pad
828 if(ipos == 3 || ipos > 4) continue;
830 if(!status[1]){ // good central pad
831 if(!ipos){ // all pads are OK
832 if ((signalL <= signalM) && (signalR < signalM)) {
833 if ((signalL >= sigThresh) || (signalR >= sigThresh)) {
834 Float_t noiseSumThresh = minLeftRightCutSigma*calNoiseDetValue*calNoiseROC->GetValue(col,row);
835 if((signalL+signalR+signalM) >= noiseSumThresh){
836 // Maximum found, mark the position by a negative signal
837 digitsOut->SetDataUnchecked(row,col,time,-signalM);
838 fIndexesMaxima->AddIndexTBin(row,col,time);
839 padStatus.SetDataUnchecked(row, col, time, ipos);
843 } else { // one of the neighbouring pads are bad
844 if(status[0] && signalR < signalM && signalR >= sigThresh){
845 digitsOut->SetDataUnchecked(row,col,time,-signalM);
846 digitsOut->SetDataUnchecked(row, col, time+1, 0.);
847 fIndexesMaxima->AddIndexTBin(row,col,time);
848 padStatus.SetDataUnchecked(row, col, time, ipos);
849 } else if(status[2] && signalL <= signalM && signalL >= sigThresh){
850 digitsOut->SetDataUnchecked(row,col,time,-signalM);
851 digitsOut->SetDataUnchecked(row, col, time-1, 0.);
852 fIndexesMaxima->AddIndexTBin(row,col,time);
853 padStatus.SetDataUnchecked(row, col, time, ipos);
856 } else { // wrong maximum pad
857 if ((signalL >= sigThresh) || (signalR >= sigThresh)) {
858 // Maximum found, mark the position by a negative signal
859 digitsOut->SetDataUnchecked(row,col,time,-maxThresh);
860 fIndexesMaxima->AddIndexTBin(row,col,time);
861 padStatus.SetDataUnchecked(row, col, time, ipos);
866 // The index to the first cluster of a given ROC
867 Int_t firstClusterROC = -1;
868 // The number of cluster in a given ROC
869 Int_t nClusterROC = 0;
871 // Now check the maxima and calculate the cluster position
872 fIndexesMaxima->ResetCounters();
873 while (fIndexesMaxima->NextRCTbinIndex(row, col, time)) {
876 if (digitsOut->GetDataUnchecked(row,col,time) < 0.0) {
878 for (iPad = 0; iPad < kNclus; iPad++) {
879 Int_t iPadCol = col - 1 + iPad;
880 clusterSignal[iPad] = TMath::Abs(digitsOut->GetDataUnchecked(row,iPadCol,time));
883 // Count the number of pads in the cluster
888 while (TMath::Abs(digitsOut->GetDataUnchecked(row,col-ii ,time)) >= sigThresh) {
891 if (col-ii < 0) break;
895 while (TMath::Abs(digitsOut->GetDataUnchecked(row,col+ii+1,time)) >= sigThresh) {
898 if (col+ii+1 >= nColMax) break;
902 // Look for 5 pad cluster with minimum in the middle
903 Bool_t fivePadCluster = kFALSE;
904 if (col < (nColMax - 3)){
905 if (digitsOut->GetDataUnchecked(row,col+2,time) < 0) {
906 fivePadCluster = kTRUE;
908 if ((fivePadCluster) && (col < (nColMax - 5))) {
909 if (digitsOut->GetDataUnchecked(row,col+4,time) >= sigThresh) {
910 fivePadCluster = kFALSE;
913 if ((fivePadCluster) && (col > 1)) {
914 if (digitsOut->GetDataUnchecked(row,col-2,time) >= sigThresh) {
915 fivePadCluster = kFALSE;
921 // Modify the signal of the overlapping pad for the left part
922 // of the cluster which remains from a previous unfolding
924 clusterSignal[0] *= ratioLeft;
928 // Unfold the 5 pad cluster
930 for (iPad = 0; iPad < kNsig; iPad++) {
931 padSignal[iPad] = TMath::Abs(digitsOut->GetDataUnchecked(row
935 // Unfold the two maxima and set the signal on
936 // the overlapping pad to the ratio
937 ratioRight = Unfold(kEpsilon,ilayer,padSignal);
938 ratioLeft = 1.0 - ratioRight;
939 clusterSignal[2] *= ratioRight;
943 // The position of the cluster in COL direction relative to the center pad (pad units)
944 Double_t clusterPosCol = 0.0;
945 if (fReconstructor->GetRecoParam()->IsLUT()) {
946 // Calculate the position of the cluster by using the
947 // lookup table method
948 clusterPosCol = LUTposition(ilayer,clusterSignal[0]
953 // Calculate the position of the cluster by using the
954 // center of gravity method
955 for (Int_t i = 0; i < kNsig; i++) {
958 padSignal[2] = TMath::Abs(digitsOut->GetDataUnchecked(row,col ,time)); // Central pad
959 padSignal[3] = TMath::Abs(digitsOut->GetDataUnchecked(row,col+1,time)); // Left pad
960 padSignal[1] = TMath::Abs(digitsOut->GetDataUnchecked(row,col-1,time)); // Right pad
962 (TMath::Abs(digitsOut->GetDataUnchecked(row,col-2,time)) < padSignal[1])) {
963 padSignal[4] = TMath::Abs(digitsOut->GetDataUnchecked(row,col-2,time));
965 if ((col < nColMax - 3) &&
966 (TMath::Abs(digitsOut->GetDataUnchecked(row,col+2,time)) < padSignal[3])) {
967 padSignal[0] = TMath::Abs(digitsOut->GetDataUnchecked(row,col+2,time));
969 clusterPosCol = GetCOG(padSignal);
972 // Store the amplitudes of the pads in the cluster for later analysis
973 // and check whether one of these pads is masked in the database
974 Short_t signals[7] = { 0, 0, 0, 0, 0, 0, 0 };
975 for (Int_t jPad = col-3; jPad <= col+3; jPad++) {
977 (jPad >= nColMax-1)) {
980 signals[jPad-col+3] = TMath::Nint(TMath::Abs(digitsOut->GetDataUnchecked(row,jPad,time)));
983 // Transform the local cluster coordinates into calibrated
984 // space point positions defined in the local tracking system.
985 // Here the calibration for T0, Vdrift and ExB is applied as well.
986 Double_t clusterXYZ[6];
987 clusterXYZ[0] = clusterPosCol;
988 clusterXYZ[1] = clusterSignal[2];
989 clusterXYZ[2] = clusterSignal[1];
990 clusterXYZ[3] = clusterSignal[0];
999 if (fTransform->Transform(clusterXYZ,clusterRCT,((UInt_t) time),out,0)) {
1001 // Add the cluster to the output array
1002 // The track indices will be stored later
1003 Float_t clusterPos[3];
1004 clusterPos[0] = clusterXYZ[0];
1005 clusterPos[1] = clusterXYZ[1];
1006 clusterPos[2] = clusterXYZ[2];
1007 Float_t clusterSig[2];
1008 clusterSig[0] = clusterXYZ[4];
1009 clusterSig[1] = clusterXYZ[5];
1010 Double_t clusterCharge = clusterXYZ[3];
1011 Char_t clusterTimeBin = ((Char_t) clusterRCT[2]);
1013 Int_t n = RecPoints()->GetEntriesFast();
1014 AliTRDcluster *cluster = new((*RecPoints())[n]) AliTRDcluster(idet
1019 ,((Char_t) nPadCount)
1027 cluster->SetInChamber(!out);
1029 UChar_t maskPosition = padStatus.GetDataUnchecked(row, col, time);
1031 cluster->SetPadMaskedPosition(maskPosition);
1032 if (maskPosition & AliTRDcluster::kMaskedLeft) {
1033 cluster->SetPadMaskedStatus(status[0]);
1035 else if (maskPosition & AliTRDcluster::kMaskedCenter) {
1036 cluster->SetPadMaskedStatus(status[1]);
1039 cluster->SetPadMaskedStatus(status[2]);
1043 // Temporarily store the row, column and time bin of the center pad
1044 // Used to later on assign the track indices
1045 cluster->SetLabel( row,0);
1046 cluster->SetLabel( col,1);
1047 cluster->SetLabel(time,2);
1049 // Store the index of the first cluster in the current ROC
1050 if (firstClusterROC < 0) {
1051 firstClusterROC = RecPoints()->GetEntriesFast() - 1;
1054 // Count the number of cluster in the current ROC
1057 } // if: Transform ok ?
1059 } // if: Maximum found ?
1066 AddLabels(idet,firstClusterROC,nClusterROC);
1073 //_____________________________________________________________________________
1074 Bool_t AliTRDclusterizer::AddLabels(Int_t idet, Int_t firstClusterROC, Int_t nClusterROC)
1077 // Add the track indices to the found clusters
1080 const Int_t kNclus = 3;
1081 const Int_t kNdict = AliTRDdigitsManager::kNDict;
1082 const Int_t kNtrack = kNdict * kNclus;
1084 Int_t iClusterROC = 0;
1091 // Temporary array to collect the track indices
1092 Int_t *idxTracks = new Int_t[kNtrack*nClusterROC];
1094 // Loop through the dictionary arrays one-by-one
1095 // to keep memory consumption low
1096 AliTRDdataArrayI *tracksIn = 0;
1097 for (Int_t iDict = 0; iDict < kNdict; iDict++) {
1099 // tracksIn should be expanded beforehand!
1100 tracksIn = (AliTRDdataArrayI *) fDigitsManager->GetDictionary(idet,iDict);
1102 // Loop though the clusters found in this ROC
1103 for (iClusterROC = 0; iClusterROC < nClusterROC; iClusterROC++) {
1105 AliTRDcluster *cluster = (AliTRDcluster *)
1106 RecPoints()->UncheckedAt(firstClusterROC+iClusterROC);
1107 row = cluster->GetLabel(0);
1108 col = cluster->GetLabel(1);
1109 time = cluster->GetLabel(2);
1111 for (iPad = 0; iPad < kNclus; iPad++) {
1112 Int_t iPadCol = col - 1 + iPad;
1113 Int_t index = tracksIn->GetDataUnchecked(row,iPadCol,time) - 1;
1114 idxTracks[3*iPad+iDict + iClusterROC*kNtrack] = index;
1121 // Copy the track indices into the cluster
1122 // Loop though the clusters found in this ROC
1123 for (iClusterROC = 0; iClusterROC < nClusterROC; iClusterROC++) {
1125 AliTRDcluster *cluster = (AliTRDcluster *)
1126 RecPoints()->UncheckedAt(firstClusterROC+iClusterROC);
1127 cluster->SetLabel(-9999,0);
1128 cluster->SetLabel(-9999,1);
1129 cluster->SetLabel(-9999,2);
1131 cluster->AddTrackIndex(&idxTracks[iClusterROC*kNtrack]);
1135 delete [] idxTracks;
1141 //_____________________________________________________________________________
1142 Double_t AliTRDclusterizer::GetCOG(Double_t signal[5]) const
1146 // Used for clusters with more than 3 pads - where LUT not applicable
1149 Double_t sum = signal[0]
1156 // Go to 3 pad COG ????
1158 Double_t res = (0.0 * (-signal[0] + signal[4])
1159 + (-signal[1] + signal[3])) / sum;
1165 //_____________________________________________________________________________
1166 Double_t AliTRDclusterizer::Unfold(Double_t eps, Int_t layer, Double_t *padSignal)
1169 // Method to unfold neighbouring maxima.
1170 // The charge ratio on the overlapping pad is calculated
1171 // until there is no more change within the range given by eps.
1172 // The resulting ratio is then returned to the calling method.
1175 AliTRDcalibDB *calibration = AliTRDcalibDB::Instance();
1177 AliError("No AliTRDcalibDB instance available\n");
1182 Int_t itStep = 0; // Count iteration steps
1184 Double_t ratio = 0.5; // Start value for ratio
1185 Double_t prevRatio = 0.0; // Store previous ratio
1187 Double_t newLeftSignal[3] = { 0.0, 0.0, 0.0 }; // Array to store left cluster signal
1188 Double_t newRightSignal[3] = { 0.0, 0.0, 0.0 }; // Array to store right cluster signal
1189 Double_t newSignal[3] = { 0.0, 0.0, 0.0 };
1191 // Start the iteration
1192 while ((TMath::Abs(prevRatio - ratio) > eps) && (itStep < 10)) {
1197 // Cluster position according to charge ratio
1198 Double_t maxLeft = (ratio*padSignal[2] - padSignal[0])
1199 / (padSignal[0] + padSignal[1] + ratio*padSignal[2]);
1200 Double_t maxRight = (padSignal[4] - (1-ratio)*padSignal[2])
1201 / ((1.0 - ratio)*padSignal[2] + padSignal[3] + padSignal[4]);
1203 // Set cluster charge ratio
1204 irc = calibration->PadResponse(1.0,maxLeft ,layer,newSignal);
1205 Double_t ampLeft = padSignal[1] / newSignal[1];
1206 irc = calibration->PadResponse(1.0,maxRight,layer,newSignal);
1207 Double_t ampRight = padSignal[3] / newSignal[1];
1209 // Apply pad response to parameters
1210 irc = calibration->PadResponse(ampLeft ,maxLeft ,layer,newLeftSignal );
1211 irc = calibration->PadResponse(ampRight,maxRight,layer,newRightSignal);
1213 // Calculate new overlapping ratio
1214 ratio = TMath::Min((Double_t) 1.0
1215 ,newLeftSignal[2] / (newLeftSignal[2] + newRightSignal[0]));
1223 //_____________________________________________________________________________
1224 void AliTRDclusterizer::TailCancelation(AliTRDdataArrayDigits *digitsIn
1225 , AliTRDdataArrayF *digitsOut
1226 , AliTRDSignalIndex *indexesIn
1227 , AliTRDSignalIndex *indexesOut
1229 , Float_t adcThreshold
1230 , AliTRDCalROC *calGainFactorROC
1231 , Float_t calGainFactorDetValue)
1234 // Applies the tail cancelation and gain factors:
1235 // Transform digitsIn to digitsOut
1242 Double_t *inADC = new Double_t[nTimeTotal]; // ADC data before tail cancellation
1243 Double_t *outADC = new Double_t[nTimeTotal]; // ADC data after tail cancellation
1244 indexesIn->ResetCounters();
1245 while (indexesIn->NextRCIndex(iRow, iCol))
1247 Float_t calGainFactorROCValue = calGainFactorROC->GetValue(iCol,iRow);
1248 Double_t gain = calGainFactorDetValue
1249 * calGainFactorROCValue;
1251 Bool_t corrupted = kFALSE;
1252 for (iTime = 0; iTime < nTimeTotal; iTime++)
1254 // Apply gain gain factor
1255 inADC[iTime] = digitsIn->GetDataUnchecked(iRow,iCol,iTime);
1256 if(digitsIn->GetPadStatus(iRow, iCol, iTime)) corrupted = kTRUE;
1257 inADC[iTime] /= gain;
1258 outADC[iTime] = inADC[iTime];
1262 // Apply the tail cancelation via the digital filter
1263 // (only for non-coorupted pads)
1264 if (fReconstructor->GetRecoParam() ->IsTailCancelation())
1266 DeConvExp(inADC,outADC,nTimeTotal,fReconstructor->GetRecoParam() ->GetTCnexp());
1270 indexesIn->ResetTbinCounter();
1271 while (indexesIn->NextTbinIndex(iTime))
1273 // Store the amplitude of the digit if above threshold
1274 if (outADC[iTime] > adcThreshold)
1276 digitsOut->SetDataUnchecked(iRow,iCol,iTime,outADC[iTime]);
1277 indexesOut->AddIndexTBin(iRow,iCol,iTime);
1281 } // while irow icol
1290 //_____________________________________________________________________________
1291 void AliTRDclusterizer::DeConvExp(Double_t *source, Double_t *target
1292 , Int_t n, Int_t nexp)
1295 // Tail cancellation by deconvolution for PASA v4 TRF
1299 Double_t coefficients[2];
1301 // Initialization (coefficient = alpha, rates = lambda)
1307 if (nexp == 1) { // 1 Exponentials
1313 if (nexp == 2) { // 2 Exponentials
1315 fReconstructor->GetTCParams(par);
1316 r1 = par[0];//1.156;
1317 r2 = par[1];//0.130;
1318 c1 = par[2];//0.114;
1319 c2 = par[3];//0.624;
1322 coefficients[0] = c1;
1323 coefficients[1] = c2;
1327 rates[0] = TMath::Exp(-dt/(r1));
1328 rates[1] = TMath::Exp(-dt/(r2));
1333 Double_t reminder[2];
1334 Double_t correction = 0.0;
1335 Double_t result = 0.0;
1337 // Attention: computation order is important
1338 for (k = 0; k < nexp; k++) {
1342 for (i = 0; i < n; i++) {
1344 result = (source[i] - correction); // No rescaling
1347 for (k = 0; k < nexp; k++) {
1348 reminder[k] = rates[k] * (reminder[k] + coefficients[k] * result);
1352 for (k = 0; k < nexp; k++) {
1353 correction += reminder[k];
1360 //_____________________________________________________________________________
1361 void AliTRDclusterizer::ResetRecPoints()
1364 // Resets the list of rec points
1368 fRecPoints->Delete();
1373 //_____________________________________________________________________________
1374 TClonesArray *AliTRDclusterizer::RecPoints()
1377 // Returns the list of rec points
1381 if(!(fRecPoints = AliTRDReconstructor::GetClusters())){
1382 // determine number of clusters which has to be allocated
1383 Float_t nclusters = fReconstructor->GetRecoParam()->GetNClusters();
1384 if(fReconstructor->IsHLT()) nclusters /= AliTRDgeometry::kNsector;
1386 fRecPoints = new TClonesArray("AliTRDcluster", Int_t(nclusters));
1388 //SetClustersOwner(kTRUE);
1389 AliTRDReconstructor::SetClusters(0x0);
1395 //_____________________________________________________________________________
1396 void AliTRDclusterizer::FillLUT()
1402 const Int_t kNlut = 128;
1404 fLUTbin = AliTRDgeometry::kNlayer * kNlut;
1406 // The lookup table from Bogdan
1407 Float_t lut[AliTRDgeometry::kNlayer][kNlut] = {
1409 0.0070, 0.0150, 0.0224, 0.0298, 0.0374, 0.0454, 0.0533, 0.0611,
1410 0.0684, 0.0755, 0.0827, 0.0900, 0.0975, 0.1049, 0.1120, 0.1187,
1411 0.1253, 0.1318, 0.1385, 0.1453, 0.1519, 0.1584, 0.1646, 0.1704,
1412 0.1762, 0.1821, 0.1879, 0.1938, 0.1996, 0.2053, 0.2108, 0.2160,
1413 0.2210, 0.2260, 0.2310, 0.2361, 0.2411, 0.2461, 0.2509, 0.2557,
1414 0.2602, 0.2646, 0.2689, 0.2732, 0.2774, 0.2816, 0.2859, 0.2901,
1415 0.2942, 0.2983, 0.3022, 0.3061, 0.3099, 0.3136, 0.3172, 0.3207,
1416 0.3242, 0.3278, 0.3312, 0.3347, 0.3382, 0.3416, 0.3450, 0.3483,
1417 0.3515, 0.3547, 0.3579, 0.3609, 0.3639, 0.3669, 0.3698, 0.3727,
1418 0.3756, 0.3785, 0.3813, 0.3842, 0.3870, 0.3898, 0.3926, 0.3952,
1419 0.3979, 0.4005, 0.4032, 0.4057, 0.4082, 0.4108, 0.4132, 0.4157,
1420 0.4181, 0.4205, 0.4228, 0.4252, 0.4275, 0.4299, 0.4322, 0.4345,
1421 0.4367, 0.4390, 0.4412, 0.4434, 0.4456, 0.4478, 0.4499, 0.4520,
1422 0.4541, 0.4562, 0.4583, 0.4603, 0.4623, 0.4643, 0.4663, 0.4683,
1423 0.4702, 0.4722, 0.4741, 0.4758, 0.4774, 0.4790, 0.4805, 0.4824,
1424 0.4844, 0.4863, 0.4883, 0.4902, 0.4921, 0.4940, 0.4959, 0.4978
1427 0.0072, 0.0156, 0.0235, 0.0313, 0.0394, 0.0478, 0.0561, 0.0642,
1428 0.0718, 0.0792, 0.0868, 0.0947, 0.1025, 0.1101, 0.1172, 0.1241,
1429 0.1309, 0.1378, 0.1449, 0.1518, 0.1586, 0.1650, 0.1710, 0.1770,
1430 0.1830, 0.1891, 0.1952, 0.2011, 0.2070, 0.2125, 0.2177, 0.2229,
1431 0.2280, 0.2332, 0.2383, 0.2435, 0.2484, 0.2533, 0.2581, 0.2627,
1432 0.2670, 0.2714, 0.2757, 0.2799, 0.2842, 0.2884, 0.2927, 0.2968,
1433 0.3008, 0.3048, 0.3086, 0.3123, 0.3159, 0.3195, 0.3231, 0.3266,
1434 0.3301, 0.3335, 0.3370, 0.3404, 0.3438, 0.3471, 0.3504, 0.3536,
1435 0.3567, 0.3598, 0.3628, 0.3657, 0.3686, 0.3715, 0.3744, 0.3772,
1436 0.3800, 0.3828, 0.3856, 0.3884, 0.3911, 0.3938, 0.3965, 0.3991,
1437 0.4016, 0.4042, 0.4067, 0.4092, 0.4116, 0.4140, 0.4164, 0.4187,
1438 0.4211, 0.4234, 0.4257, 0.4280, 0.4302, 0.4325, 0.4347, 0.4369,
1439 0.4391, 0.4413, 0.4434, 0.4456, 0.4477, 0.4497, 0.4518, 0.4538,
1440 0.4558, 0.4578, 0.4598, 0.4618, 0.4637, 0.4656, 0.4675, 0.4694,
1441 0.4713, 0.4732, 0.4750, 0.4766, 0.4781, 0.4797, 0.4813, 0.4832,
1442 0.4851, 0.4870, 0.4888, 0.4906, 0.4925, 0.4942, 0.4960, 0.4978
1445 0.0075, 0.0163, 0.0246, 0.0328, 0.0415, 0.0504, 0.0592, 0.0674,
1446 0.0753, 0.0832, 0.0914, 0.0996, 0.1077, 0.1154, 0.1225, 0.1296,
1447 0.1369, 0.1442, 0.1515, 0.1585, 0.1652, 0.1714, 0.1776, 0.1839,
1448 0.1902, 0.1965, 0.2025, 0.2085, 0.2141, 0.2194, 0.2247, 0.2299,
1449 0.2352, 0.2405, 0.2457, 0.2507, 0.2557, 0.2604, 0.2649, 0.2693,
1450 0.2737, 0.2780, 0.2823, 0.2867, 0.2909, 0.2951, 0.2992, 0.3033,
1451 0.3072, 0.3110, 0.3146, 0.3182, 0.3218, 0.3253, 0.3288, 0.3323,
1452 0.3357, 0.3392, 0.3426, 0.3459, 0.3492, 0.3524, 0.3555, 0.3586,
1453 0.3616, 0.3645, 0.3674, 0.3703, 0.3731, 0.3759, 0.3787, 0.3815,
1454 0.3843, 0.3870, 0.3897, 0.3925, 0.3950, 0.3976, 0.4002, 0.4027,
1455 0.4052, 0.4076, 0.4101, 0.4124, 0.4148, 0.4171, 0.4194, 0.4217,
1456 0.4239, 0.4262, 0.4284, 0.4306, 0.4328, 0.4350, 0.4371, 0.4393,
1457 0.4414, 0.4435, 0.4455, 0.4476, 0.4496, 0.4516, 0.4536, 0.4555,
1458 0.4575, 0.4594, 0.4613, 0.4632, 0.4650, 0.4669, 0.4687, 0.4705,
1459 0.4723, 0.4741, 0.4758, 0.4773, 0.4789, 0.4804, 0.4821, 0.4839,
1460 0.4857, 0.4875, 0.4893, 0.4910, 0.4928, 0.4945, 0.4961, 0.4978
1463 0.0078, 0.0171, 0.0258, 0.0345, 0.0438, 0.0532, 0.0624, 0.0708,
1464 0.0791, 0.0875, 0.0962, 0.1048, 0.1130, 0.1206, 0.1281, 0.1356,
1465 0.1432, 0.1508, 0.1582, 0.1651, 0.1716, 0.1780, 0.1845, 0.1910,
1466 0.1975, 0.2038, 0.2099, 0.2155, 0.2210, 0.2263, 0.2317, 0.2371,
1467 0.2425, 0.2477, 0.2528, 0.2578, 0.2626, 0.2671, 0.2715, 0.2759,
1468 0.2803, 0.2846, 0.2890, 0.2933, 0.2975, 0.3016, 0.3056, 0.3095,
1469 0.3132, 0.3168, 0.3204, 0.3239, 0.3274, 0.3309, 0.3344, 0.3378,
1470 0.3412, 0.3446, 0.3479, 0.3511, 0.3543, 0.3574, 0.3603, 0.3633,
1471 0.3662, 0.3690, 0.3718, 0.3747, 0.3774, 0.3802, 0.3829, 0.3857,
1472 0.3883, 0.3910, 0.3936, 0.3962, 0.3987, 0.4012, 0.4037, 0.4061,
1473 0.4085, 0.4109, 0.4132, 0.4155, 0.4177, 0.4200, 0.4222, 0.4244,
1474 0.4266, 0.4288, 0.4309, 0.4331, 0.4352, 0.4373, 0.4394, 0.4414,
1475 0.4435, 0.4455, 0.4475, 0.4494, 0.4514, 0.4533, 0.4552, 0.4571,
1476 0.4590, 0.4608, 0.4626, 0.4645, 0.4662, 0.4680, 0.4698, 0.4715,
1477 0.4733, 0.4750, 0.4766, 0.4781, 0.4796, 0.4812, 0.4829, 0.4846,
1478 0.4863, 0.4880, 0.4897, 0.4914, 0.4930, 0.4946, 0.4963, 0.4979
1481 0.0081, 0.0178, 0.0270, 0.0364, 0.0463, 0.0562, 0.0656, 0.0744,
1482 0.0831, 0.0921, 0.1013, 0.1102, 0.1183, 0.1261, 0.1339, 0.1419,
1483 0.1499, 0.1576, 0.1648, 0.1715, 0.1782, 0.1849, 0.1917, 0.1984,
1484 0.2048, 0.2110, 0.2167, 0.2223, 0.2278, 0.2333, 0.2389, 0.2444,
1485 0.2497, 0.2548, 0.2598, 0.2645, 0.2691, 0.2735, 0.2780, 0.2824,
1486 0.2868, 0.2912, 0.2955, 0.2997, 0.3038, 0.3078, 0.3116, 0.3152,
1487 0.3188, 0.3224, 0.3259, 0.3294, 0.3329, 0.3364, 0.3398, 0.3432,
1488 0.3465, 0.3497, 0.3529, 0.3561, 0.3591, 0.3620, 0.3649, 0.3677,
1489 0.3705, 0.3733, 0.3761, 0.3788, 0.3816, 0.3843, 0.3869, 0.3896,
1490 0.3922, 0.3948, 0.3973, 0.3998, 0.4022, 0.4047, 0.4070, 0.4094,
1491 0.4117, 0.4139, 0.4162, 0.4184, 0.4206, 0.4227, 0.4249, 0.4270,
1492 0.4291, 0.4313, 0.4334, 0.4354, 0.4375, 0.4395, 0.4415, 0.4435,
1493 0.4455, 0.4474, 0.4493, 0.4512, 0.4531, 0.4550, 0.4568, 0.4586,
1494 0.4604, 0.4622, 0.4639, 0.4657, 0.4674, 0.4691, 0.4708, 0.4725,
1495 0.4742, 0.4758, 0.4773, 0.4788, 0.4803, 0.4819, 0.4836, 0.4852,
1496 0.4869, 0.4885, 0.4901, 0.4917, 0.4933, 0.4948, 0.4964, 0.4979
1499 0.0085, 0.0189, 0.0288, 0.0389, 0.0497, 0.0603, 0.0699, 0.0792,
1500 0.0887, 0.0985, 0.1082, 0.1170, 0.1253, 0.1336, 0.1421, 0.1505,
1501 0.1587, 0.1662, 0.1733, 0.1803, 0.1874, 0.1945, 0.2014, 0.2081,
1502 0.2143, 0.2201, 0.2259, 0.2316, 0.2374, 0.2431, 0.2487, 0.2541,
1503 0.2593, 0.2642, 0.2689, 0.2735, 0.2781, 0.2826, 0.2872, 0.2917,
1504 0.2961, 0.3003, 0.3045, 0.3086, 0.3125, 0.3162, 0.3198, 0.3235,
1505 0.3270, 0.3306, 0.3342, 0.3377, 0.3411, 0.3446, 0.3479, 0.3511,
1506 0.3543, 0.3575, 0.3605, 0.3634, 0.3663, 0.3691, 0.3720, 0.3748,
1507 0.3775, 0.3803, 0.3830, 0.3857, 0.3884, 0.3911, 0.3937, 0.3962,
1508 0.3987, 0.4012, 0.4036, 0.4060, 0.4084, 0.4107, 0.4129, 0.4152,
1509 0.4174, 0.4196, 0.4218, 0.4239, 0.4261, 0.4282, 0.4303, 0.4324,
1510 0.4344, 0.4365, 0.4385, 0.4405, 0.4425, 0.4445, 0.4464, 0.4483,
1511 0.4502, 0.4521, 0.4539, 0.4558, 0.4576, 0.4593, 0.4611, 0.4629,
1512 0.4646, 0.4663, 0.4680, 0.4697, 0.4714, 0.4730, 0.4747, 0.4759,
1513 0.4769, 0.4780, 0.4790, 0.4800, 0.4811, 0.4827, 0.4843, 0.4859,
1514 0.4874, 0.4889, 0.4905, 0.4920, 0.4935, 0.4950, 0.4965, 0.4979
1521 fLUT = new Double_t[fLUTbin];
1523 for (Int_t ilayer = 0; ilayer < AliTRDgeometry::kNlayer; ilayer++) {
1524 for (Int_t ilut = 0; ilut < kNlut; ilut++ ) {
1525 fLUT[ilayer*kNlut+ilut] = lut[ilayer][ilut];
1531 //_____________________________________________________________________________
1532 Double_t AliTRDclusterizer::LUTposition(Int_t ilayer
1535 , Double_t ampR) const
1538 // Calculates the cluster position using the lookup table.
1539 // Method provided by Bogdan Vulpescu.
1542 const Int_t kNlut = 128;
1553 Double_t xMin[AliTRDgeometry::kNlayer] = { 0.006492, 0.006377, 0.006258
1554 , 0.006144, 0.006030, 0.005980 };
1555 Double_t xMax[AliTRDgeometry::kNlayer] = { 0.960351, 0.965870, 0.970445
1556 , 0.974352, 0.977667, 0.996101 };
1559 x = (ampL - ampR) / ampC;
1562 else if (ampL < ampR) {
1563 x = (ampR - ampL) / ampC;
1569 xmin = xMin[ilayer] + 0.000005;
1570 xmax = xMax[ilayer] - 0.000005;
1571 xwid = (xmax - xmin) / 127.0;
1576 else if (x > xmax) {
1577 pos = side * 0.5000;
1580 ix = (Int_t) ((x - xmin) / xwid);
1581 pos = side * fLUT[ilayer*kNlut+ix];