2 /**************************************************************************
3 * Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
5 * Author: The ALICE Off-line Project. *
6 * Contributors are mentioned in the code where appropriate. *
8 * Permission to use, copy, modify and distribute this software and its *
9 * documentation strictly for non-commercial purposes is hereby granted *
10 * without fee, provided that the above copyright notice appears in all *
11 * copies and that both the copyright notice and this permission notice *
12 * appear in the supporting documentation. The authors make no claims *
13 * about the suitability of this software for any purpose. It is *
14 * provided "as is" without express or implied warranty. *
15 **************************************************************************/
19 ///////////////////////////////////////////////////////////////////////////////
21 // TRD cluster finder //
23 ///////////////////////////////////////////////////////////////////////////////
29 #include <TObjArray.h>
31 #include "AliRunLoader.h"
32 #include "AliLoader.h"
33 #include "AliRawReader.h"
35 #include "AliAlignObj.h"
37 #include "AliTRDclusterizer.h"
38 #include "AliTRDcluster.h"
39 #include "AliTRDReconstructor.h"
40 #include "AliTRDgeometry.h"
41 #include "AliTRDdataArrayF.h"
42 #include "AliTRDdataArrayI.h"
43 #include "AliTRDdataArrayS.h"
44 #include "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()
72 ,fTransform(new AliTRDtransform(0))
77 // AliTRDclusterizer default constructor
80 AliTRDcalibDB *trd = 0x0;
81 if (!(trd = AliTRDcalibDB::Instance())) {
82 AliFatal("Could not get calibration object");
85 fRawVersion = AliTRDfeeParam::Instance()->GetRAWversion();
87 // retrive reco params
88 AliTRDrecoParam *rec = 0x0;
89 if (!(rec = AliTRDReconstructor::RecoParam())){
90 if(!(rec = trd->GetRecoParam(0))){
91 AliInfo("Using default RecoParams = LowFluxParam.");
92 rec = AliTRDrecoParam::GetLowFluxParam();
94 AliTRDReconstructor::SetRecoParam(rec);
98 //_____________________________________________________________________________
99 AliTRDclusterizer::AliTRDclusterizer(const Text_t *name, const Text_t *title)
104 ,fDigitsManager(new AliTRDdigitsManager())
108 ,fIndexesMaxima(NULL)
109 ,fTransform(new AliTRDtransform(0))
114 // AliTRDclusterizer constructor
117 AliTRDcalibDB *trd = 0x0;
118 if (!(trd = AliTRDcalibDB::Instance())) {
119 AliFatal("Could not get calibration object");
122 // retrive reco params
123 AliTRDrecoParam *rec = 0x0;
124 if (!(rec = AliTRDReconstructor::RecoParam())){
125 if(!(rec = trd->GetRecoParam(0))){
126 AliInfo("Using default RecoParams = LowFluxParam.");
127 rec = AliTRDrecoParam::GetLowFluxParam();
129 AliTRDReconstructor::SetRecoParam(rec);
132 fDigitsManager->CreateArrays();
134 fRawVersion = AliTRDfeeParam::Instance()->GetRAWversion();
139 //_____________________________________________________________________________
140 AliTRDclusterizer::AliTRDclusterizer(const AliTRDclusterizer &c)
145 ,fDigitsManager(NULL)
149 ,fIndexesMaxima(NULL)
155 // AliTRDclusterizer copy constructor
162 //_____________________________________________________________________________
163 AliTRDclusterizer::~AliTRDclusterizer()
166 // AliTRDclusterizer destructor
171 fRecPoints->Delete();
177 delete fDigitsManager;
178 fDigitsManager = NULL;
189 delete fIndexesMaxima;
190 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).fDigitsManager = NULL;
233 ((AliTRDclusterizer &) c).fAddLabels = fAddLabels;
234 ((AliTRDclusterizer &) c).fRawVersion = fRawVersion;
235 ((AliTRDclusterizer &) c).fIndexesOut = NULL;
236 ((AliTRDclusterizer &) c).fIndexesMaxima = NULL;
237 ((AliTRDclusterizer &) c).fTransform = NULL;
238 ((AliTRDclusterizer &) c).fLUTbin = 0;
239 ((AliTRDclusterizer &) c).fLUT = NULL;
243 //_____________________________________________________________________________
244 Bool_t AliTRDclusterizer::Open(const Char_t *name, Int_t nEvent)
247 // Opens the AliROOT file. Output and input are in the same file
250 TString evfoldname = AliConfig::GetDefaultEventFolderName();
251 fRunLoader = AliRunLoader::GetRunLoader(evfoldname);
254 fRunLoader = AliRunLoader::Open(name);
258 AliError(Form("Can not open session for file %s.",name));
269 //_____________________________________________________________________________
270 Bool_t AliTRDclusterizer::OpenOutput()
273 // Open the output file
276 TObjArray *ioArray = 0;
278 AliLoader* loader = fRunLoader->GetLoader("TRDLoader");
279 loader->MakeTree("R");
281 fClusterTree = loader->TreeR();
282 fClusterTree->Branch("TRDcluster","TObjArray",&ioArray,32000,0);
288 //_____________________________________________________________________________
289 Bool_t AliTRDclusterizer::OpenOutput(TTree *clusterTree)
292 // Connect the output tree
295 TObjArray *ioArray = 0;
297 fClusterTree = clusterTree;
298 fClusterTree->Branch("TRDcluster","TObjArray",&ioArray,32000,0);
304 //_____________________________________________________________________________
305 Bool_t AliTRDclusterizer::OpenInput(Int_t nEvent)
308 // Opens a ROOT-file with TRD-hits and reads in the digits-tree
311 // Import the Trees for the event nEvent in the file
312 fRunLoader->GetEvent(nEvent);
318 //_____________________________________________________________________________
319 Bool_t AliTRDclusterizer::WriteClusters(Int_t det)
322 // Fills TRDcluster branch in the tree with the clusters
323 // found in detector = det. For det=-1 writes the tree.
327 (det >= AliTRDgeometry::Ndet())) {
328 AliError(Form("Unexpected detector index %d.\n",det));
332 TBranch *branch = fClusterTree->GetBranch("TRDcluster");
334 TObjArray *ioArray = 0;
335 branch = fClusterTree->Branch("TRDcluster","TObjArray",&ioArray,32000,0);
339 (det < AliTRDgeometry::Ndet())) {
341 Int_t nRecPoints = RecPoints()->GetEntriesFast();
342 TObjArray *detRecPoints = new TObjArray(400);
344 for (Int_t i = 0; i < nRecPoints; i++) {
345 AliTRDcluster *c = (AliTRDcluster *) RecPoints()->UncheckedAt(i);
346 if (det == c->GetDetector()) {
347 detRecPoints->AddLast(c);
350 AliError(Form("Attempt to write a cluster with unexpected detector index: got=%d expected=%d\n"
356 branch->SetAddress(&detRecPoints);
357 fClusterTree->Fill();
367 AliInfo(Form("Writing the cluster tree %s for event %d."
368 ,fClusterTree->GetName(),fRunLoader->GetEventNumber()));
372 branch->SetAddress(&fRecPoints);
374 AliLoader *loader = fRunLoader->GetLoader("TRDLoader");
375 loader->WriteRecPoints("OVERWRITE");
380 AliError("Cluster tree does not exist. Cannot write clusters.\n");
389 AliError(Form("Unexpected detector index %d.\n",det));
395 //_____________________________________________________________________________
396 void AliTRDclusterizer::ResetHelperIndexes(AliTRDSignalIndex *indexesIn)
399 // Reset the helper indexes
404 // carefull here - we assume that only row number may change - most probable
405 if (indexesIn->GetNrow() <= fIndexesOut->GetNrow())
406 fIndexesOut->ResetContent();
408 fIndexesOut->ResetContentConditional(indexesIn->GetNrow()
409 , indexesIn->GetNcol()
410 , indexesIn->GetNtime());
414 fIndexesOut = new AliTRDSignalIndex(indexesIn->GetNrow()
415 , indexesIn->GetNcol()
416 , indexesIn->GetNtime());
421 // carefull here - we assume that only row number may change - most probable
422 if (indexesIn->GetNrow() <= fIndexesMaxima->GetNrow())
424 fIndexesMaxima->ResetContent();
428 fIndexesMaxima->ResetContentConditional(indexesIn->GetNrow()
429 , indexesIn->GetNcol()
430 , indexesIn->GetNtime());
435 fIndexesMaxima = new AliTRDSignalIndex(indexesIn->GetNrow()
436 , indexesIn->GetNcol()
437 , indexesIn->GetNtime());
442 //_____________________________________________________________________________
443 Bool_t AliTRDclusterizer::ReadDigits()
446 // Reads the digits arrays from the input aliroot file
450 AliError("No run loader available");
454 AliLoader* loader = fRunLoader->GetLoader("TRDLoader");
455 if (!loader->TreeD()) {
456 loader->LoadDigits();
459 // Read in the digit arrays
460 return (fDigitsManager->ReadDigits(loader->TreeD()));
464 //_____________________________________________________________________________
465 Bool_t AliTRDclusterizer::ReadDigits(TTree *digitsTree)
468 // Reads the digits arrays from the input tree
471 // Read in the digit arrays
472 return (fDigitsManager->ReadDigits(digitsTree));
476 //_____________________________________________________________________________
477 Bool_t AliTRDclusterizer::ReadDigits(AliRawReader *rawReader)
480 // Reads the digits arrays from the ddl file
484 fDigitsManager = raw.Raw2Digits(rawReader);
490 //_____________________________________________________________________________
491 Bool_t AliTRDclusterizer::MakeClusters()
494 // Creates clusters from digits
497 // Propagate info from the digits manager
498 if (fAddLabels == kTRUE)
500 fAddLabels = fDigitsManager->UsesDictionaries();
503 Bool_t fReturn = kTRUE;
504 for (Int_t i = 0; i < AliTRDgeometry::kNdet; i++)
507 AliTRDdataArrayDigits *digitsIn = (AliTRDdataArrayDigits*) fDigitsManager->GetDigits(i);
508 // This is to take care of switched off super modules
509 if (!digitsIn->HasData())
514 AliTRDSignalIndex* indexes = fDigitsManager->GetIndexes(i);
515 if (indexes->IsAllocated() == kFALSE)
517 fDigitsManager->BuildIndexes(i);
521 if (indexes->HasEntry())
525 for (Int_t iDict = 0; iDict < AliTRDdigitsManager::kNDict; iDict++)
527 AliTRDdataArrayI *tracksIn = 0;
528 tracksIn = (AliTRDdataArrayI *) fDigitsManager->GetDictionary(i,iDict);
532 fR = MakeClusters(i);
533 fReturn = fR && fReturn;
542 // No compress just remove
543 fDigitsManager->RemoveDigits(i);
544 fDigitsManager->RemoveDictionaries(i);
545 fDigitsManager->ClearIndexes(i);
553 //_____________________________________________________________________________
554 Bool_t AliTRDclusterizer::Raw2Clusters(AliRawReader *rawReader)
557 // Creates clusters from raw data
560 return Raw2ClustersChamber(rawReader);
564 //_____________________________________________________________________________
565 Bool_t AliTRDclusterizer::Raw2ClustersChamber(AliRawReader *rawReader)
568 // Creates clusters from raw data
571 // Create the digits manager
574 fDigitsManager = new AliTRDdigitsManager();
575 fDigitsManager->CreateArrays();
578 fDigitsManager->SetUseDictionaries(fAddLabels);
580 AliTRDrawStreamBase *pinput = AliTRDrawStreamBase::GetRawStream(rawReader);
581 AliTRDrawStreamBase &input = *pinput;
583 AliInfo(Form("Stream version: %s", input.IsA()->GetName()));
586 while ((det = input.NextChamber(fDigitsManager)) >= 0)
588 Bool_t iclusterBranch = kFALSE;
589 if (fDigitsManager->GetIndexes(det)->HasEntry())
591 iclusterBranch = MakeClusters(det);
593 if (iclusterBranch == kFALSE)
598 fDigitsManager->RemoveDigits(det);
599 fDigitsManager->RemoveDictionaries(det);
600 fDigitsManager->ClearIndexes(det);
603 delete fDigitsManager;
604 fDigitsManager = NULL;
612 //_____________________________________________________________________________
613 UChar_t AliTRDclusterizer::GetStatus(Short_t &signal)
616 // check if pad is masked
617 if(signal>0 && TESTBIT(signal, 10)){
619 for(int ibit=0; ibit<4; ibit++){
620 if(TESTBIT(signal, 11+ibit)){
621 SETBIT(status, ibit);
622 CLRBIT(signal, 11+ibit);
629 //_____________________________________________________________________________
630 Bool_t AliTRDclusterizer::MakeClusters(Int_t det)
633 // Generates the cluster.
637 // digits should be expanded beforehand!
638 // digitsIn->Expand();
639 AliTRDdataArrayDigits *digitsIn = (AliTRDdataArrayDigits *) fDigitsManager->GetDigits(det);
641 // This is to take care of switched off super modules
642 if (!digitsIn->HasData())
647 AliTRDSignalIndex *indexesIn = fDigitsManager->GetIndexes(det);
648 if (indexesIn->IsAllocated() == kFALSE)
650 AliError("Indexes do not exist!");
654 AliTRDcalibDB *calibration = AliTRDcalibDB::Instance();
657 AliFatal("No AliTRDcalibDB instance available\n");
662 // There is no ADC threshold anymore, and simParam should not be used in clusterizer. KO
663 Float_t adcThreshold = 0;
665 if (!AliTRDReconstructor::RecoParam())
667 AliError("RecoParam does not exist\n");
671 // Threshold value for the maximum
672 Float_t maxThresh = AliTRDReconstructor::RecoParam()->GetClusMaxThresh();
673 // Threshold value for the digit signal
674 Float_t sigThresh = AliTRDReconstructor::RecoParam()->GetClusSigThresh();
676 // Threshold value for the maximum ( cut noise)
677 Float_t minMaxCutSigma = AliTRDReconstructor::RecoParam()->GetMinMaxCutSigma();
678 // Threshold value for the sum pad ( cut noise)
679 Float_t minLeftRightCutSigma = AliTRDReconstructor::RecoParam()->GetMinLeftRightCutSigma();
681 // Iteration limit for unfolding procedure
682 const Float_t kEpsilon = 0.01;
683 const Int_t kNclus = 3;
684 const Int_t kNsig = 5;
687 Double_t ratioLeft = 1.0;
688 Double_t ratioRight = 1.0;
690 Double_t padSignal[kNsig];
691 Double_t clusterSignal[kNclus];
693 Int_t istack = indexesIn->GetStack();
694 Int_t ilayer = indexesIn->GetLayer();
695 Int_t isector = indexesIn->GetSM();
697 // Start clustering in the chamber
699 Int_t idet = AliTRDgeometry::GetDetector(ilayer,istack,isector);
702 AliError("Strange Detector number Missmatch!");
706 // TRD space point transformation
707 fTransform->SetDetector(det);
709 Int_t iGeoLayer = AliGeomManager::kTRD1 + ilayer;
710 Int_t iGeoModule = istack + AliTRDgeometry::Nstack() * isector;
711 UShort_t volid = AliGeomManager::LayerToVolUID(iGeoLayer,iGeoModule);
713 Int_t nColMax = digitsIn->GetNcol();
714 Int_t nRowMax = digitsIn->GetNrow();
715 Int_t nTimeTotal = digitsIn->GetNtime();
717 // Detector wise calibration object for the gain factors
718 const AliTRDCalDet *calGainFactorDet = calibration->GetGainFactorDet();
719 // Calibration object with pad wise values for the gain factors
720 AliTRDCalROC *calGainFactorROC = calibration->GetGainFactorROC(idet);
721 // Calibration value for chamber wise gain factor
722 Float_t calGainFactorDetValue = calGainFactorDet->GetValue(idet);
725 // Detector wise calibration object for the noise
726 const AliTRDCalDet *calNoiseDet = calibration->GetNoiseDet();
727 // Calibration object with pad wise values for the noise
728 AliTRDCalROC *calNoiseROC = calibration->GetNoiseROC(idet);
729 // Calibration value for chamber wise noise
730 Float_t calNoiseDetValue = calNoiseDet->GetValue(idet);
734 AliTRDdataArrayF *digitsOut = new AliTRDdataArrayF(nRowMax, nColMax, nTimeTotal);
735 AliTRDdataArrayS padStatus(nRowMax, nColMax, nTimeTotal);
737 ResetHelperIndexes(indexesIn);
739 // Apply the gain and the tail cancelation via digital filter
740 TailCancelation(digitsIn
747 ,calGainFactorDetValue);
754 UChar_t status[3]={0, 0, 0}, ipos = 0;
755 fIndexesOut->ResetCounters();
756 while (fIndexesOut->NextRCTbinIndex(row, col, time)){
757 Float_t signalM = TMath::Abs(digitsOut->GetDataUnchecked(row,col,time));
758 status[1] = digitsIn->GetPadStatus(row,col,time);
759 if(status[1]) SETBIT(ipos, AliTRDcluster::kMaskedCenter);
761 if(signalM < maxThresh) continue;
763 Float_t noiseMiddleThresh = minMaxCutSigma*calNoiseDetValue*calNoiseROC->GetValue(col,row);
764 if (signalM < noiseMiddleThresh) continue;
766 if (col + 1 >= nColMax || col-1 < 0) continue;
768 Float_t signalL = TMath::Abs(digitsOut->GetDataUnchecked(row,col+1,time));
769 status[0] = digitsIn->GetPadStatus(row,col+1,time);
770 if(status[0]) SETBIT(ipos, AliTRDcluster::kMaskedLeft);
772 Float_t signalR = TMath::Abs(digitsOut->GetDataUnchecked(row,col-1,time));
773 status[2] = digitsIn->GetPadStatus(row,col-1,time);
774 if(status[2]) SETBIT(ipos, AliTRDcluster::kMaskedRight);
776 // reject candidates with more than 1 problematic pad
777 if(ipos == 3 || ipos > 4) continue;
779 if(!status[1]){ // good central pad
780 if(!ipos){ // all pads are OK
781 if ((signalL <= signalM) && (signalR < signalM)) {
782 if ((signalL >= sigThresh) || (signalR >= sigThresh)) {
783 Float_t noiseSumThresh = minLeftRightCutSigma*calNoiseDetValue*calNoiseROC->GetValue(col,row);
784 if((signalL+signalR+signalM) >= noiseSumThresh){
785 // Maximum found, mark the position by a negative signal
786 digitsOut->SetDataUnchecked(row,col,time,-signalM);
787 fIndexesMaxima->AddIndexTBin(row,col,time);
788 padStatus.SetDataUnchecked(row, col, time, ipos);
792 } else { // one of the neighbouring pads are bad
793 if(status[0] && signalR < signalM && signalR >= sigThresh){
794 digitsOut->SetDataUnchecked(row,col,time,-signalM);
795 digitsOut->SetDataUnchecked(row, col, time+1, 0.);
796 fIndexesMaxima->AddIndexTBin(row,col,time);
797 padStatus.SetDataUnchecked(row, col, time, ipos);
798 } else if(status[2] && signalL <= signalM && signalL >= sigThresh){
799 digitsOut->SetDataUnchecked(row,col,time,-signalM);
800 digitsOut->SetDataUnchecked(row, col, time-1, 0.);
801 fIndexesMaxima->AddIndexTBin(row,col,time);
802 padStatus.SetDataUnchecked(row, col, time, ipos);
805 } else { // wrong maximum pad
806 if ((signalL >= sigThresh) || (signalR >= sigThresh)) {
807 // Maximum found, mark the position by a negative signal
808 digitsOut->SetDataUnchecked(row,col,time,-maxThresh);
809 fIndexesMaxima->AddIndexTBin(row,col,time);
810 padStatus.SetDataUnchecked(row, col, time, ipos);
815 // The index to the first cluster of a given ROC
816 Int_t firstClusterROC = -1;
817 // The number of cluster in a given ROC
818 Int_t nClusterROC = 0;
820 // Now check the maxima and calculate the cluster position
821 fIndexesMaxima->ResetCounters();
822 while (fIndexesMaxima->NextRCTbinIndex(row, col, time)) {
825 if (digitsOut->GetDataUnchecked(row,col,time) < 0.0) {
826 for (iPad = 0; iPad < kNclus; iPad++) {
827 Int_t iPadCol = col - 1 + iPad;
828 clusterSignal[iPad] = TMath::Abs(digitsOut->GetDataUnchecked(row,iPadCol,time));
831 // Count the number of pads in the cluster
836 while (TMath::Abs(digitsOut->GetDataUnchecked(row,col-ii ,time)) >= sigThresh) {
839 if (col-ii < 0) break;
843 while (TMath::Abs(digitsOut->GetDataUnchecked(row,col+ii+1,time)) >= sigThresh){
846 if (col+ii+1 >= nColMax) break;
850 // Look for 5 pad cluster with minimum in the middle
851 Bool_t fivePadCluster = kFALSE;
852 if (col < (nColMax - 3)){
853 if (digitsOut->GetDataUnchecked(row,col+2,time) < 0) {
854 fivePadCluster = kTRUE;
856 if ((fivePadCluster) && (col < (nColMax - 5))) {
857 if (digitsOut->GetDataUnchecked(row,col+4,time) >= sigThresh){
858 fivePadCluster = kFALSE;
861 if ((fivePadCluster) && (col > 1)){
862 if (digitsOut->GetDataUnchecked(row,col-2,time) >= sigThresh){
863 fivePadCluster = kFALSE;
869 // Modify the signal of the overlapping pad for the left part
870 // of the cluster which remains from a previous unfolding
872 clusterSignal[0] *= ratioLeft;
876 // Unfold the 5 pad cluster
878 for (iPad = 0; iPad < kNsig; iPad++) {
879 padSignal[iPad] = TMath::Abs(digitsOut->GetDataUnchecked(row
883 // Unfold the two maxima and set the signal on
884 // the overlapping pad to the ratio
885 ratioRight = Unfold(kEpsilon,ilayer,padSignal);
886 ratioLeft = 1.0 - ratioRight;
887 clusterSignal[2] *= ratioRight;
891 // The position of the cluster in COL direction relative to the center pad (pad units)
892 Double_t clusterPosCol = 0.0;
893 if (AliTRDReconstructor::RecoParam()->IsLUT()) {
894 // Calculate the position of the cluster by using the
895 // lookup table method
896 clusterPosCol = LUTposition(ilayer,clusterSignal[0]
900 // Calculate the position of the cluster by using the
901 // center of gravity method
902 for (Int_t i = 0; i < kNsig; i++) {
905 padSignal[2] = TMath::Abs(digitsOut->GetDataUnchecked(row,col ,time)); // Central pad
906 padSignal[1] = TMath::Abs(digitsOut->GetDataUnchecked(row,col-1,time)); // Left pad
907 padSignal[3] = TMath::Abs(digitsOut->GetDataUnchecked(row,col+1,time)); // Right pad
910 (TMath::Abs(digitsOut->GetDataUnchecked(row,col-2,time)) < padSignal[1])) {
911 padSignal[0] = TMath::Abs(digitsOut->GetDataUnchecked(row,col-2,time));
913 if ((col < nColMax - 3) &&
914 (TMath::Abs(digitsOut->GetDataUnchecked(row,col+2,time)) < padSignal[3])){
915 padSignal[4] = TMath::Abs(digitsOut->GetDataUnchecked(row,col+2,time));
917 clusterPosCol = GetCOG(padSignal);
920 // Store the amplitudes of the pads in the cluster for later analysis
921 // and check whether one of these pads is masked in the database
922 Short_t signals[7] = { 0, 0, 0, 0, 0, 0, 0 };
923 for (Int_t jPad = col-3; jPad <= col+3; jPad++) {
925 (jPad >= nColMax-1)) {
928 signals[jPad-col+3] = TMath::Nint(TMath::Abs(digitsOut->GetDataUnchecked(row,jPad,time)));
931 // Transform the local cluster coordinates into calibrated
932 // space point positions defined in the local tracking system.
933 // Here the calibration for T0, Vdrift and ExB is applied as well.
934 Double_t clusterXYZ[6];
935 clusterXYZ[0] = clusterPosCol;
936 clusterXYZ[1] = clusterSignal[0];
937 clusterXYZ[2] = clusterSignal[1];
938 clusterXYZ[3] = clusterSignal[2];
947 if (fTransform->Transform(clusterXYZ, clusterRCT, ((UInt_t) time), out, 0)) {
949 // Add the cluster to the output array
950 // The track indices will be stored later
951 Float_t clusterPos[3];
952 clusterPos[0] = clusterXYZ[0];
953 clusterPos[1] = clusterXYZ[1];
954 clusterPos[2] = clusterXYZ[2];
955 Float_t clusterSig[2];
956 clusterSig[0] = clusterXYZ[4];
957 clusterSig[1] = clusterXYZ[5];
958 Double_t clusterCharge = clusterXYZ[3];
959 Char_t clusterTimeBin = ((Char_t) clusterRCT[2]);
960 AliTRDcluster *cluster = new AliTRDcluster(idet
965 ,((Char_t) nPadCount)
973 cluster->SetInChamber(!out);
974 UChar_t maskPosition = padStatus.GetDataUnchecked(row, col, time);
976 cluster->SetPadMaskedPosition(maskPosition);
978 if(maskPosition & AliTRDcluster::kMaskedLeft) cluster->SetPadMaskedStatus(status[0]);
979 else if(maskPosition & AliTRDcluster::kMaskedCenter) cluster->SetPadMaskedStatus(status[1]);
980 else cluster->SetPadMaskedStatus(status[2]);
983 // Temporarily store the row, column and time bin of the center pad
984 // Used to later on assign the track indices
985 cluster->SetLabel( row,0);
986 cluster->SetLabel( col,1);
987 cluster->SetLabel(time,2);
989 RecPoints()->Add(cluster);
991 // Store the index of the first cluster in the current ROC
992 if (firstClusterROC < 0) {
993 firstClusterROC = RecPoints()->GetEntriesFast() - 1;
996 // Count the number of cluster in the current ROC
999 } // if: Transform ok ?
1000 } // if: Maximum found ?
1005 if (fAddLabels) AddLabels(idet, firstClusterROC, nClusterROC);
1007 // Write the cluster and reset the array
1008 WriteClusters(idet);
1015 //_____________________________________________________________________________
1016 Bool_t AliTRDclusterizer::AddLabels(Int_t idet, Int_t firstClusterROC, Int_t nClusterROC)
1019 // Add the track indices to the found clusters
1022 const Int_t kNclus = 3;
1023 const Int_t kNdict = AliTRDdigitsManager::kNDict;
1024 const Int_t kNtrack = kNdict * kNclus;
1026 Int_t iClusterROC = 0;
1033 // Temporary array to collect the track indices
1034 Int_t *idxTracks = new Int_t[kNtrack*nClusterROC];
1036 // Loop through the dictionary arrays one-by-one
1037 // to keep memory consumption low
1038 AliTRDdataArrayI *tracksIn = 0;
1039 for (Int_t iDict = 0; iDict < kNdict; iDict++) {
1041 // tracksIn should be expanded beforehand!
1042 tracksIn = (AliTRDdataArrayI *) fDigitsManager->GetDictionary(idet,iDict);
1044 // Loop though the clusters found in this ROC
1045 for (iClusterROC = 0; iClusterROC < nClusterROC; iClusterROC++) {
1047 AliTRDcluster *cluster = (AliTRDcluster *)
1048 RecPoints()->UncheckedAt(firstClusterROC+iClusterROC);
1049 row = cluster->GetLabel(0);
1050 col = cluster->GetLabel(1);
1051 time = cluster->GetLabel(2);
1053 for (iPad = 0; iPad < kNclus; iPad++) {
1054 Int_t iPadCol = col - 1 + iPad;
1055 Int_t index = tracksIn->GetDataUnchecked(row,iPadCol,time) - 1;
1056 idxTracks[3*iPad+iDict + iClusterROC*kNtrack] = index;
1063 // Copy the track indices into the cluster
1064 // Loop though the clusters found in this ROC
1065 for (iClusterROC = 0; iClusterROC < nClusterROC; iClusterROC++) {
1067 AliTRDcluster *cluster = (AliTRDcluster *)
1068 RecPoints()->UncheckedAt(firstClusterROC+iClusterROC);
1069 cluster->SetLabel(-9999,0);
1070 cluster->SetLabel(-9999,1);
1071 cluster->SetLabel(-9999,2);
1073 cluster->AddTrackIndex(&idxTracks[iClusterROC*kNtrack]);
1077 delete [] idxTracks;
1083 //_____________________________________________________________________________
1084 Double_t AliTRDclusterizer::GetCOG(Double_t signal[5]) const
1088 // Used for clusters with more than 3 pads - where LUT not applicable
1091 Double_t sum = signal[0]
1097 Double_t res = (0.0 * (-signal[0] + signal[4])
1098 + (-signal[1] + signal[3])) / sum;
1104 //_____________________________________________________________________________
1105 Double_t AliTRDclusterizer::Unfold(Double_t eps, Int_t layer, Double_t *padSignal)
1108 // Method to unfold neighbouring maxima.
1109 // The charge ratio on the overlapping pad is calculated
1110 // until there is no more change within the range given by eps.
1111 // The resulting ratio is then returned to the calling method.
1114 AliTRDcalibDB *calibration = AliTRDcalibDB::Instance();
1116 AliError("No AliTRDcalibDB instance available\n");
1121 Int_t itStep = 0; // Count iteration steps
1123 Double_t ratio = 0.5; // Start value for ratio
1124 Double_t prevRatio = 0.0; // Store previous ratio
1126 Double_t newLeftSignal[3] = { 0.0, 0.0, 0.0 }; // Array to store left cluster signal
1127 Double_t newRightSignal[3] = { 0.0, 0.0, 0.0 }; // Array to store right cluster signal
1128 Double_t newSignal[3] = { 0.0, 0.0, 0.0 };
1130 // Start the iteration
1131 while ((TMath::Abs(prevRatio - ratio) > eps) && (itStep < 10)) {
1136 // Cluster position according to charge ratio
1137 Double_t maxLeft = (ratio*padSignal[2] - padSignal[0])
1138 / (padSignal[0] + padSignal[1] + ratio*padSignal[2]);
1139 Double_t maxRight = (padSignal[4] - (1-ratio)*padSignal[2])
1140 / ((1.0 - ratio)*padSignal[2] + padSignal[3] + padSignal[4]);
1142 // Set cluster charge ratio
1143 irc = calibration->PadResponse(1.0,maxLeft ,layer,newSignal);
1144 Double_t ampLeft = padSignal[1] / newSignal[1];
1145 irc = calibration->PadResponse(1.0,maxRight,layer,newSignal);
1146 Double_t ampRight = padSignal[3] / newSignal[1];
1148 // Apply pad response to parameters
1149 irc = calibration->PadResponse(ampLeft ,maxLeft ,layer,newLeftSignal );
1150 irc = calibration->PadResponse(ampRight,maxRight,layer,newRightSignal);
1152 // Calculate new overlapping ratio
1153 ratio = TMath::Min((Double_t) 1.0
1154 ,newLeftSignal[2] / (newLeftSignal[2] + newRightSignal[0]));
1162 //_____________________________________________________________________________
1163 void AliTRDclusterizer::TailCancelation(AliTRDdataArrayDigits *digitsIn
1164 , AliTRDdataArrayF *digitsOut
1165 , AliTRDSignalIndex *indexesIn
1166 , AliTRDSignalIndex *indexesOut
1168 , Float_t adcThreshold
1169 , AliTRDCalROC *calGainFactorROC
1170 , Float_t calGainFactorDetValue)
1173 // Applies the tail cancelation and gain factors:
1174 // Transform digitsIn to digitsOut
1181 Double_t *inADC = new Double_t[nTimeTotal]; // ADC data before tail cancellation
1182 Double_t *outADC = new Double_t[nTimeTotal]; // ADC data after tail cancellation
1183 indexesIn->ResetCounters();
1184 while (indexesIn->NextRCIndex(iRow, iCol))
1186 Float_t calGainFactorROCValue = calGainFactorROC->GetValue(iCol,iRow);
1187 Double_t gain = calGainFactorDetValue
1188 * calGainFactorROCValue;
1190 Bool_t corrupted = kFALSE;
1191 for (iTime = 0; iTime < nTimeTotal; iTime++)
1193 // Apply gain gain factor
1194 inADC[iTime] = digitsIn->GetDataUnchecked(iRow,iCol,iTime);
1195 if(digitsIn->GetPadStatus(iRow, iCol, iTime)) corrupted = kTRUE;
1196 inADC[iTime] /= gain;
1197 outADC[iTime] = inADC[iTime];
1201 // Apply the tail cancelation via the digital filter
1202 // (only for non-coorupted pads)
1203 if (AliTRDReconstructor::RecoParam()->IsTailCancelation())
1205 DeConvExp(inADC,outADC,nTimeTotal,AliTRDReconstructor::RecoParam()->GetTCnexp());
1209 indexesIn->ResetTbinCounter();
1210 while (indexesIn->NextTbinIndex(iTime))
1212 // Store the amplitude of the digit if above threshold
1213 if (outADC[iTime] > adcThreshold)
1215 digitsOut->SetDataUnchecked(iRow,iCol,iTime,outADC[iTime]);
1216 indexesOut->AddIndexTBin(iRow,iCol,iTime);
1220 } // while irow icol
1229 //_____________________________________________________________________________
1230 void AliTRDclusterizer::DeConvExp(Double_t *source, Double_t *target
1231 , Int_t n, Int_t nexp)
1234 // Tail cancellation by deconvolution for PASA v4 TRF
1238 Double_t coefficients[2];
1240 // Initialization (coefficient = alpha, rates = lambda)
1246 if (nexp == 1) { // 1 Exponentials
1252 if (nexp == 2) { // 2 Exponentials
1259 coefficients[0] = c1;
1260 coefficients[1] = c2;
1264 rates[0] = TMath::Exp(-dt/(r1));
1265 rates[1] = TMath::Exp(-dt/(r2));
1270 Double_t reminder[2];
1271 Double_t correction = 0.0;
1272 Double_t result = 0.0;
1274 // Attention: computation order is important
1275 for (k = 0; k < nexp; k++) {
1279 for (i = 0; i < n; i++) {
1281 result = (source[i] - correction); // No rescaling
1284 for (k = 0; k < nexp; k++) {
1285 reminder[k] = rates[k] * (reminder[k] + coefficients[k] * result);
1289 for (k = 0; k < nexp; k++) {
1290 correction += reminder[k];
1297 //_____________________________________________________________________________
1298 void AliTRDclusterizer::ResetRecPoints()
1301 // Resets the list of rec points
1305 fRecPoints->Delete();
1310 //_____________________________________________________________________________
1311 TObjArray *AliTRDclusterizer::RecPoints()
1314 // Returns the list of rec points
1318 fRecPoints = new TObjArray(400);
1325 //_____________________________________________________________________________
1326 void AliTRDclusterizer::FillLUT()
1332 const Int_t kNlut = 128;
1334 fLUTbin = AliTRDgeometry::kNlayer * kNlut;
1336 // The lookup table from Bogdan
1337 Float_t lut[AliTRDgeometry::kNlayer][kNlut] = {
1339 0.0070, 0.0150, 0.0224, 0.0298, 0.0374, 0.0454, 0.0533, 0.0611,
1340 0.0684, 0.0755, 0.0827, 0.0900, 0.0975, 0.1049, 0.1120, 0.1187,
1341 0.1253, 0.1318, 0.1385, 0.1453, 0.1519, 0.1584, 0.1646, 0.1704,
1342 0.1762, 0.1821, 0.1879, 0.1938, 0.1996, 0.2053, 0.2108, 0.2160,
1343 0.2210, 0.2260, 0.2310, 0.2361, 0.2411, 0.2461, 0.2509, 0.2557,
1344 0.2602, 0.2646, 0.2689, 0.2732, 0.2774, 0.2816, 0.2859, 0.2901,
1345 0.2942, 0.2983, 0.3022, 0.3061, 0.3099, 0.3136, 0.3172, 0.3207,
1346 0.3242, 0.3278, 0.3312, 0.3347, 0.3382, 0.3416, 0.3450, 0.3483,
1347 0.3515, 0.3547, 0.3579, 0.3609, 0.3639, 0.3669, 0.3698, 0.3727,
1348 0.3756, 0.3785, 0.3813, 0.3842, 0.3870, 0.3898, 0.3926, 0.3952,
1349 0.3979, 0.4005, 0.4032, 0.4057, 0.4082, 0.4108, 0.4132, 0.4157,
1350 0.4181, 0.4205, 0.4228, 0.4252, 0.4275, 0.4299, 0.4322, 0.4345,
1351 0.4367, 0.4390, 0.4412, 0.4434, 0.4456, 0.4478, 0.4499, 0.4520,
1352 0.4541, 0.4562, 0.4583, 0.4603, 0.4623, 0.4643, 0.4663, 0.4683,
1353 0.4702, 0.4722, 0.4741, 0.4758, 0.4774, 0.4790, 0.4805, 0.4824,
1354 0.4844, 0.4863, 0.4883, 0.4902, 0.4921, 0.4940, 0.4959, 0.4978
1357 0.0072, 0.0156, 0.0235, 0.0313, 0.0394, 0.0478, 0.0561, 0.0642,
1358 0.0718, 0.0792, 0.0868, 0.0947, 0.1025, 0.1101, 0.1172, 0.1241,
1359 0.1309, 0.1378, 0.1449, 0.1518, 0.1586, 0.1650, 0.1710, 0.1770,
1360 0.1830, 0.1891, 0.1952, 0.2011, 0.2070, 0.2125, 0.2177, 0.2229,
1361 0.2280, 0.2332, 0.2383, 0.2435, 0.2484, 0.2533, 0.2581, 0.2627,
1362 0.2670, 0.2714, 0.2757, 0.2799, 0.2842, 0.2884, 0.2927, 0.2968,
1363 0.3008, 0.3048, 0.3086, 0.3123, 0.3159, 0.3195, 0.3231, 0.3266,
1364 0.3301, 0.3335, 0.3370, 0.3404, 0.3438, 0.3471, 0.3504, 0.3536,
1365 0.3567, 0.3598, 0.3628, 0.3657, 0.3686, 0.3715, 0.3744, 0.3772,
1366 0.3800, 0.3828, 0.3856, 0.3884, 0.3911, 0.3938, 0.3965, 0.3991,
1367 0.4016, 0.4042, 0.4067, 0.4092, 0.4116, 0.4140, 0.4164, 0.4187,
1368 0.4211, 0.4234, 0.4257, 0.4280, 0.4302, 0.4325, 0.4347, 0.4369,
1369 0.4391, 0.4413, 0.4434, 0.4456, 0.4477, 0.4497, 0.4518, 0.4538,
1370 0.4558, 0.4578, 0.4598, 0.4618, 0.4637, 0.4656, 0.4675, 0.4694,
1371 0.4713, 0.4732, 0.4750, 0.4766, 0.4781, 0.4797, 0.4813, 0.4832,
1372 0.4851, 0.4870, 0.4888, 0.4906, 0.4925, 0.4942, 0.4960, 0.4978
1375 0.0075, 0.0163, 0.0246, 0.0328, 0.0415, 0.0504, 0.0592, 0.0674,
1376 0.0753, 0.0832, 0.0914, 0.0996, 0.1077, 0.1154, 0.1225, 0.1296,
1377 0.1369, 0.1442, 0.1515, 0.1585, 0.1652, 0.1714, 0.1776, 0.1839,
1378 0.1902, 0.1965, 0.2025, 0.2085, 0.2141, 0.2194, 0.2247, 0.2299,
1379 0.2352, 0.2405, 0.2457, 0.2507, 0.2557, 0.2604, 0.2649, 0.2693,
1380 0.2737, 0.2780, 0.2823, 0.2867, 0.2909, 0.2951, 0.2992, 0.3033,
1381 0.3072, 0.3110, 0.3146, 0.3182, 0.3218, 0.3253, 0.3288, 0.3323,
1382 0.3357, 0.3392, 0.3426, 0.3459, 0.3492, 0.3524, 0.3555, 0.3586,
1383 0.3616, 0.3645, 0.3674, 0.3703, 0.3731, 0.3759, 0.3787, 0.3815,
1384 0.3843, 0.3870, 0.3897, 0.3925, 0.3950, 0.3976, 0.4002, 0.4027,
1385 0.4052, 0.4076, 0.4101, 0.4124, 0.4148, 0.4171, 0.4194, 0.4217,
1386 0.4239, 0.4262, 0.4284, 0.4306, 0.4328, 0.4350, 0.4371, 0.4393,
1387 0.4414, 0.4435, 0.4455, 0.4476, 0.4496, 0.4516, 0.4536, 0.4555,
1388 0.4575, 0.4594, 0.4613, 0.4632, 0.4650, 0.4669, 0.4687, 0.4705,
1389 0.4723, 0.4741, 0.4758, 0.4773, 0.4789, 0.4804, 0.4821, 0.4839,
1390 0.4857, 0.4875, 0.4893, 0.4910, 0.4928, 0.4945, 0.4961, 0.4978
1393 0.0078, 0.0171, 0.0258, 0.0345, 0.0438, 0.0532, 0.0624, 0.0708,
1394 0.0791, 0.0875, 0.0962, 0.1048, 0.1130, 0.1206, 0.1281, 0.1356,
1395 0.1432, 0.1508, 0.1582, 0.1651, 0.1716, 0.1780, 0.1845, 0.1910,
1396 0.1975, 0.2038, 0.2099, 0.2155, 0.2210, 0.2263, 0.2317, 0.2371,
1397 0.2425, 0.2477, 0.2528, 0.2578, 0.2626, 0.2671, 0.2715, 0.2759,
1398 0.2803, 0.2846, 0.2890, 0.2933, 0.2975, 0.3016, 0.3056, 0.3095,
1399 0.3132, 0.3168, 0.3204, 0.3239, 0.3274, 0.3309, 0.3344, 0.3378,
1400 0.3412, 0.3446, 0.3479, 0.3511, 0.3543, 0.3574, 0.3603, 0.3633,
1401 0.3662, 0.3690, 0.3718, 0.3747, 0.3774, 0.3802, 0.3829, 0.3857,
1402 0.3883, 0.3910, 0.3936, 0.3962, 0.3987, 0.4012, 0.4037, 0.4061,
1403 0.4085, 0.4109, 0.4132, 0.4155, 0.4177, 0.4200, 0.4222, 0.4244,
1404 0.4266, 0.4288, 0.4309, 0.4331, 0.4352, 0.4373, 0.4394, 0.4414,
1405 0.4435, 0.4455, 0.4475, 0.4494, 0.4514, 0.4533, 0.4552, 0.4571,
1406 0.4590, 0.4608, 0.4626, 0.4645, 0.4662, 0.4680, 0.4698, 0.4715,
1407 0.4733, 0.4750, 0.4766, 0.4781, 0.4796, 0.4812, 0.4829, 0.4846,
1408 0.4863, 0.4880, 0.4897, 0.4914, 0.4930, 0.4946, 0.4963, 0.4979
1411 0.0081, 0.0178, 0.0270, 0.0364, 0.0463, 0.0562, 0.0656, 0.0744,
1412 0.0831, 0.0921, 0.1013, 0.1102, 0.1183, 0.1261, 0.1339, 0.1419,
1413 0.1499, 0.1576, 0.1648, 0.1715, 0.1782, 0.1849, 0.1917, 0.1984,
1414 0.2048, 0.2110, 0.2167, 0.2223, 0.2278, 0.2333, 0.2389, 0.2444,
1415 0.2497, 0.2548, 0.2598, 0.2645, 0.2691, 0.2735, 0.2780, 0.2824,
1416 0.2868, 0.2912, 0.2955, 0.2997, 0.3038, 0.3078, 0.3116, 0.3152,
1417 0.3188, 0.3224, 0.3259, 0.3294, 0.3329, 0.3364, 0.3398, 0.3432,
1418 0.3465, 0.3497, 0.3529, 0.3561, 0.3591, 0.3620, 0.3649, 0.3677,
1419 0.3705, 0.3733, 0.3761, 0.3788, 0.3816, 0.3843, 0.3869, 0.3896,
1420 0.3922, 0.3948, 0.3973, 0.3998, 0.4022, 0.4047, 0.4070, 0.4094,
1421 0.4117, 0.4139, 0.4162, 0.4184, 0.4206, 0.4227, 0.4249, 0.4270,
1422 0.4291, 0.4313, 0.4334, 0.4354, 0.4375, 0.4395, 0.4415, 0.4435,
1423 0.4455, 0.4474, 0.4493, 0.4512, 0.4531, 0.4550, 0.4568, 0.4586,
1424 0.4604, 0.4622, 0.4639, 0.4657, 0.4674, 0.4691, 0.4708, 0.4725,
1425 0.4742, 0.4758, 0.4773, 0.4788, 0.4803, 0.4819, 0.4836, 0.4852,
1426 0.4869, 0.4885, 0.4901, 0.4917, 0.4933, 0.4948, 0.4964, 0.4979
1429 0.0085, 0.0189, 0.0288, 0.0389, 0.0497, 0.0603, 0.0699, 0.0792,
1430 0.0887, 0.0985, 0.1082, 0.1170, 0.1253, 0.1336, 0.1421, 0.1505,
1431 0.1587, 0.1662, 0.1733, 0.1803, 0.1874, 0.1945, 0.2014, 0.2081,
1432 0.2143, 0.2201, 0.2259, 0.2316, 0.2374, 0.2431, 0.2487, 0.2541,
1433 0.2593, 0.2642, 0.2689, 0.2735, 0.2781, 0.2826, 0.2872, 0.2917,
1434 0.2961, 0.3003, 0.3045, 0.3086, 0.3125, 0.3162, 0.3198, 0.3235,
1435 0.3270, 0.3306, 0.3342, 0.3377, 0.3411, 0.3446, 0.3479, 0.3511,
1436 0.3543, 0.3575, 0.3605, 0.3634, 0.3663, 0.3691, 0.3720, 0.3748,
1437 0.3775, 0.3803, 0.3830, 0.3857, 0.3884, 0.3911, 0.3937, 0.3962,
1438 0.3987, 0.4012, 0.4036, 0.4060, 0.4084, 0.4107, 0.4129, 0.4152,
1439 0.4174, 0.4196, 0.4218, 0.4239, 0.4261, 0.4282, 0.4303, 0.4324,
1440 0.4344, 0.4365, 0.4385, 0.4405, 0.4425, 0.4445, 0.4464, 0.4483,
1441 0.4502, 0.4521, 0.4539, 0.4558, 0.4576, 0.4593, 0.4611, 0.4629,
1442 0.4646, 0.4663, 0.4680, 0.4697, 0.4714, 0.4730, 0.4747, 0.4759,
1443 0.4769, 0.4780, 0.4790, 0.4800, 0.4811, 0.4827, 0.4843, 0.4859,
1444 0.4874, 0.4889, 0.4905, 0.4920, 0.4935, 0.4950, 0.4965, 0.4979
1451 fLUT = new Double_t[fLUTbin];
1453 for (Int_t ilayer = 0; ilayer < AliTRDgeometry::kNlayer; ilayer++) {
1454 for (Int_t ilut = 0; ilut < kNlut; ilut++ ) {
1455 fLUT[ilayer*kNlut+ilut] = lut[ilayer][ilut];
1461 //_____________________________________________________________________________
1462 Double_t AliTRDclusterizer::LUTposition(Int_t ilayer, Double_t ampL
1463 , Double_t ampC, Double_t ampR) const
1466 // Calculates the cluster position using the lookup table.
1467 // Method provided by Bogdan Vulpescu.
1470 const Int_t kNlut = 128;
1481 Double_t xMin[AliTRDgeometry::kNlayer] = { 0.006492, 0.006377, 0.006258
1482 , 0.006144, 0.006030, 0.005980 };
1483 Double_t xMax[AliTRDgeometry::kNlayer] = { 0.960351, 0.965870, 0.970445
1484 , 0.974352, 0.977667, 0.996101 };
1487 x = (ampL - ampR) / ampC;
1490 else if (ampL < ampR) {
1491 x = (ampR - ampL) / ampC;
1497 xmin = xMin[ilayer] + 0.000005;
1498 xmax = xMax[ilayer] - 0.000005;
1499 xwid = (xmax - xmin) / 127.0;
1504 else if (x > xmax) {
1505 pos = side * 0.5000;
1508 ix = (Int_t) ((x - xmin) / xwid);
1509 pos = side * fLUT[ilayer*kNlut+ix];