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 fRawVersion = AliTRDfeeParam::Instance()->GetRAWversion();
84 //_____________________________________________________________________________
85 AliTRDclusterizer::AliTRDclusterizer(const Text_t *name, const Text_t *title)
90 ,fDigitsManager(new AliTRDdigitsManager())
95 ,fTransform(new AliTRDtransform(0))
100 // AliTRDclusterizer constructor
103 fDigitsManager->CreateArrays();
105 fRawVersion = AliTRDfeeParam::Instance()->GetRAWversion();
111 //_____________________________________________________________________________
112 AliTRDclusterizer::AliTRDclusterizer(const AliTRDclusterizer &c)
117 ,fDigitsManager(NULL)
121 ,fIndexesMaxima(NULL)
127 // AliTRDclusterizer copy constructor
134 //_____________________________________________________________________________
135 AliTRDclusterizer::~AliTRDclusterizer()
138 // AliTRDclusterizer destructor
143 fRecPoints->Delete();
149 delete fDigitsManager;
150 fDigitsManager = NULL;
161 delete fIndexesMaxima;
162 fIndexesMaxima = NULL;
179 //_____________________________________________________________________________
180 AliTRDclusterizer &AliTRDclusterizer::operator=(const AliTRDclusterizer &c)
183 // Assignment operator
188 ((AliTRDclusterizer &) c).Copy(*this);
195 //_____________________________________________________________________________
196 void AliTRDclusterizer::Copy(TObject &c) const
202 ((AliTRDclusterizer &) c).fClusterTree = NULL;
203 ((AliTRDclusterizer &) c).fRecPoints = NULL;
204 ((AliTRDclusterizer &) c).fDigitsManager = NULL;
205 ((AliTRDclusterizer &) c).fAddLabels = fAddLabels;
206 ((AliTRDclusterizer &) c).fRawVersion = fRawVersion;
207 ((AliTRDclusterizer &) c).fIndexesOut = NULL;
208 ((AliTRDclusterizer &) c).fIndexesMaxima = NULL;
209 ((AliTRDclusterizer &) c).fTransform = NULL;
210 ((AliTRDclusterizer &) c).fLUTbin = 0;
211 ((AliTRDclusterizer &) c).fLUT = NULL;
215 //_____________________________________________________________________________
216 Bool_t AliTRDclusterizer::Open(const Char_t *name, Int_t nEvent)
219 // Opens the AliROOT file. Output and input are in the same file
222 TString evfoldname = AliConfig::GetDefaultEventFolderName();
223 fRunLoader = AliRunLoader::GetRunLoader(evfoldname);
226 fRunLoader = AliRunLoader::Open(name);
230 AliError(Form("Can not open session for file %s.",name));
241 //_____________________________________________________________________________
242 Bool_t AliTRDclusterizer::OpenOutput()
245 // Open the output file
248 TObjArray *ioArray = 0;
250 AliLoader* loader = fRunLoader->GetLoader("TRDLoader");
251 loader->MakeTree("R");
253 fClusterTree = loader->TreeR();
254 fClusterTree->Branch("TRDcluster","TObjArray",&ioArray,32000,0);
260 //_____________________________________________________________________________
261 Bool_t AliTRDclusterizer::OpenOutput(TTree *clusterTree)
264 // Connect the output tree
267 TObjArray *ioArray = 0;
269 fClusterTree = clusterTree;
270 fClusterTree->Branch("TRDcluster","TObjArray",&ioArray,32000,0);
276 //_____________________________________________________________________________
277 Bool_t AliTRDclusterizer::OpenInput(Int_t nEvent)
280 // Opens a ROOT-file with TRD-hits and reads in the digits-tree
283 // Import the Trees for the event nEvent in the file
284 fRunLoader->GetEvent(nEvent);
290 //_____________________________________________________________________________
291 Bool_t AliTRDclusterizer::WriteClusters(Int_t det)
294 // Fills TRDcluster branch in the tree with the clusters
295 // found in detector = det. For det=-1 writes the tree.
299 (det >= AliTRDgeometry::Ndet())) {
300 AliError(Form("Unexpected detector index %d.\n",det));
304 TBranch *branch = fClusterTree->GetBranch("TRDcluster");
306 TObjArray *ioArray = 0;
307 branch = fClusterTree->Branch("TRDcluster","TObjArray",&ioArray,32000,0);
311 (det < AliTRDgeometry::Ndet())) {
313 Int_t nRecPoints = RecPoints()->GetEntriesFast();
314 TObjArray *detRecPoints = new TObjArray(400);
316 for (Int_t i = 0; i < nRecPoints; i++) {
317 AliTRDcluster *c = (AliTRDcluster *) RecPoints()->UncheckedAt(i);
318 if (det == c->GetDetector()) {
319 detRecPoints->AddLast(c);
322 AliError(Form("Attempt to write a cluster with unexpected detector index: got=%d expected=%d\n"
328 branch->SetAddress(&detRecPoints);
329 fClusterTree->Fill();
339 AliInfo(Form("Writing the cluster tree %s for event %d."
340 ,fClusterTree->GetName(),fRunLoader->GetEventNumber()));
344 branch->SetAddress(&fRecPoints);
346 AliLoader *loader = fRunLoader->GetLoader("TRDLoader");
347 loader->WriteRecPoints("OVERWRITE");
352 AliError("Cluster tree does not exist. Cannot write clusters.\n");
361 AliError(Form("Unexpected detector index %d.\n",det));
367 //_____________________________________________________________________________
368 void AliTRDclusterizer::ResetHelperIndexes(AliTRDSignalIndex *indexesIn)
371 // Reset the helper indexes
376 // carefull here - we assume that only row number may change - most probable
377 if (indexesIn->GetNrow() <= fIndexesOut->GetNrow())
378 fIndexesOut->ResetContent();
380 fIndexesOut->ResetContentConditional(indexesIn->GetNrow()
381 , indexesIn->GetNcol()
382 , indexesIn->GetNtime());
386 fIndexesOut = new AliTRDSignalIndex(indexesIn->GetNrow()
387 , indexesIn->GetNcol()
388 , indexesIn->GetNtime());
393 // carefull here - we assume that only row number may change - most probable
394 if (indexesIn->GetNrow() <= fIndexesMaxima->GetNrow())
396 fIndexesMaxima->ResetContent();
400 fIndexesMaxima->ResetContentConditional(indexesIn->GetNrow()
401 , indexesIn->GetNcol()
402 , indexesIn->GetNtime());
407 fIndexesMaxima = new AliTRDSignalIndex(indexesIn->GetNrow()
408 , indexesIn->GetNcol()
409 , indexesIn->GetNtime());
414 //_____________________________________________________________________________
415 Bool_t AliTRDclusterizer::ReadDigits()
418 // Reads the digits arrays from the input aliroot file
422 AliError("No run loader available");
426 AliLoader* loader = fRunLoader->GetLoader("TRDLoader");
427 if (!loader->TreeD()) {
428 loader->LoadDigits();
431 // Read in the digit arrays
432 return (fDigitsManager->ReadDigits(loader->TreeD()));
436 //_____________________________________________________________________________
437 Bool_t AliTRDclusterizer::ReadDigits(TTree *digitsTree)
440 // Reads the digits arrays from the input tree
443 // Read in the digit arrays
444 return (fDigitsManager->ReadDigits(digitsTree));
448 //_____________________________________________________________________________
449 Bool_t AliTRDclusterizer::ReadDigits(AliRawReader *rawReader)
452 // Reads the digits arrays from the ddl file
456 fDigitsManager = raw.Raw2Digits(rawReader);
462 //_____________________________________________________________________________
463 Bool_t AliTRDclusterizer::MakeClusters()
466 // Creates clusters from digits
469 // Propagate info from the digits manager
470 if (fAddLabels == kTRUE)
472 fAddLabels = fDigitsManager->UsesDictionaries();
475 Bool_t fReturn = kTRUE;
476 for (Int_t i = 0; i < AliTRDgeometry::kNdet; i++)
479 AliTRDdataArrayDigits *digitsIn = (AliTRDdataArrayDigits*) fDigitsManager->GetDigits(i);
480 // This is to take care of switched off super modules
481 if (!digitsIn->HasData())
486 AliTRDSignalIndex* indexes = fDigitsManager->GetIndexes(i);
487 if (indexes->IsAllocated() == kFALSE)
489 fDigitsManager->BuildIndexes(i);
493 if (indexes->HasEntry())
497 for (Int_t iDict = 0; iDict < AliTRDdigitsManager::kNDict; iDict++)
499 AliTRDdataArrayI *tracksIn = 0;
500 tracksIn = (AliTRDdataArrayI *) fDigitsManager->GetDictionary(i,iDict);
504 fR = MakeClusters(i);
505 fReturn = fR && fReturn;
514 // No compress just remove
515 fDigitsManager->RemoveDigits(i);
516 fDigitsManager->RemoveDictionaries(i);
517 fDigitsManager->ClearIndexes(i);
525 //_____________________________________________________________________________
526 Bool_t AliTRDclusterizer::Raw2Clusters(AliRawReader *rawReader)
529 // Creates clusters from raw data
532 return Raw2ClustersChamber(rawReader);
536 //_____________________________________________________________________________
537 Bool_t AliTRDclusterizer::Raw2ClustersChamber(AliRawReader *rawReader)
540 // Creates clusters from raw data
543 // Create the digits manager
546 fDigitsManager = new AliTRDdigitsManager();
547 fDigitsManager->CreateArrays();
550 fDigitsManager->SetUseDictionaries(fAddLabels);
552 AliTRDrawStreamBase *pinput = AliTRDrawStreamBase::GetRawStream(rawReader);
553 AliTRDrawStreamBase &input = *pinput;
555 AliInfo(Form("Stream version: %s", input.IsA()->GetName()));
558 while ((det = input.NextChamber(fDigitsManager)) >= 0)
560 Bool_t iclusterBranch = kFALSE;
561 if (fDigitsManager->GetIndexes(det)->HasEntry())
563 iclusterBranch = MakeClusters(det);
565 if (iclusterBranch == kFALSE)
570 fDigitsManager->RemoveDigits(det);
571 fDigitsManager->RemoveDictionaries(det);
572 fDigitsManager->ClearIndexes(det);
575 delete fDigitsManager;
576 fDigitsManager = NULL;
584 //_____________________________________________________________________________
585 UChar_t AliTRDclusterizer::GetStatus(Short_t &signal)
588 // check if pad is masked
589 if(signal>0 && TESTBIT(signal, 10)){
591 for(int ibit=0; ibit<4; ibit++){
592 if(TESTBIT(signal, 11+ibit)){
593 SETBIT(status, ibit);
594 CLRBIT(signal, 11+ibit);
601 //_____________________________________________________________________________
602 Bool_t AliTRDclusterizer::MakeClusters(Int_t det)
605 // Generates the cluster.
609 // digits should be expanded beforehand!
610 // digitsIn->Expand();
611 AliTRDdataArrayDigits *digitsIn = (AliTRDdataArrayDigits *) fDigitsManager->GetDigits(det);
613 // This is to take care of switched off super modules
614 if (!digitsIn->HasData())
619 AliTRDSignalIndex *indexesIn = fDigitsManager->GetIndexes(det);
620 if (indexesIn->IsAllocated() == kFALSE)
622 AliError("Indexes do not exist!");
626 AliTRDcalibDB *calibration = AliTRDcalibDB::Instance();
629 AliFatal("No AliTRDcalibDB instance available\n");
634 // There is no ADC threshold anymore, and simParam should not be used in clusterizer. KO
635 Float_t adcThreshold = 0;
637 if (!AliTRDReconstructor::RecoParam())
639 AliError("RecoParam does not exist\n");
643 // Threshold value for the maximum
644 Float_t maxThresh = AliTRDReconstructor::RecoParam()->GetClusMaxThresh();
645 // Threshold value for the digit signal
646 Float_t sigThresh = AliTRDReconstructor::RecoParam()->GetClusSigThresh();
648 // Threshold value for the maximum ( cut noise)
649 Float_t minMaxCutSigma = AliTRDReconstructor::RecoParam()->GetMinMaxCutSigma();
650 // Threshold value for the sum pad ( cut noise)
651 Float_t minLeftRightCutSigma = AliTRDReconstructor::RecoParam()->GetMinLeftRightCutSigma();
653 // Iteration limit for unfolding procedure
654 const Float_t kEpsilon = 0.01;
655 const Int_t kNclus = 3;
656 const Int_t kNsig = 5;
659 Double_t ratioLeft = 1.0;
660 Double_t ratioRight = 1.0;
662 Double_t padSignal[kNsig];
663 Double_t clusterSignal[kNclus];
665 Int_t istack = indexesIn->GetStack();
666 Int_t ilayer = indexesIn->GetLayer();
667 Int_t isector = indexesIn->GetSM();
669 // Start clustering in the chamber
671 Int_t idet = AliTRDgeometry::GetDetector(ilayer,istack,isector);
674 AliError("Strange Detector number Missmatch!");
678 // TRD space point transformation
679 fTransform->SetDetector(det);
681 Int_t iGeoLayer = AliGeomManager::kTRD1 + ilayer;
682 Int_t iGeoModule = istack + AliTRDgeometry::Nstack() * isector;
683 UShort_t volid = AliGeomManager::LayerToVolUID(iGeoLayer,iGeoModule);
685 Int_t nColMax = digitsIn->GetNcol();
686 Int_t nRowMax = digitsIn->GetNrow();
687 Int_t nTimeTotal = digitsIn->GetNtime();
689 // Detector wise calibration object for the gain factors
690 const AliTRDCalDet *calGainFactorDet = calibration->GetGainFactorDet();
691 // Calibration object with pad wise values for the gain factors
692 AliTRDCalROC *calGainFactorROC = calibration->GetGainFactorROC(idet);
693 // Calibration value for chamber wise gain factor
694 Float_t calGainFactorDetValue = calGainFactorDet->GetValue(idet);
697 // Detector wise calibration object for the noise
698 const AliTRDCalDet *calNoiseDet = calibration->GetNoiseDet();
699 // Calibration object with pad wise values for the noise
700 AliTRDCalROC *calNoiseROC = calibration->GetNoiseROC(idet);
701 // Calibration value for chamber wise noise
702 Float_t calNoiseDetValue = calNoiseDet->GetValue(idet);
706 AliTRDdataArrayF *digitsOut = new AliTRDdataArrayF(nRowMax, nColMax, nTimeTotal);
707 AliTRDdataArrayS padStatus(nRowMax, nColMax, nTimeTotal);
709 ResetHelperIndexes(indexesIn);
711 // Apply the gain and the tail cancelation via digital filter
712 TailCancelation(digitsIn
719 ,calGainFactorDetValue);
726 UChar_t status[3]={0, 0, 0}, ipos = 0;
727 fIndexesOut->ResetCounters();
728 while (fIndexesOut->NextRCTbinIndex(row, col, time)){
729 Float_t signalM = TMath::Abs(digitsOut->GetDataUnchecked(row,col,time));
730 status[1] = digitsIn->GetPadStatus(row,col,time);
731 if(status[1]) SETBIT(ipos, AliTRDcluster::kMaskedCenter);
733 if(signalM < maxThresh) continue;
735 Float_t noiseMiddleThresh = minMaxCutSigma*calNoiseDetValue*calNoiseROC->GetValue(col,row);
736 if (signalM < noiseMiddleThresh) continue;
738 if (col + 1 >= nColMax || col-1 < 0) continue;
740 Float_t signalL = TMath::Abs(digitsOut->GetDataUnchecked(row,col+1,time));
741 status[0] = digitsIn->GetPadStatus(row,col+1,time);
742 if(status[0]) SETBIT(ipos, AliTRDcluster::kMaskedLeft);
744 Float_t signalR = TMath::Abs(digitsOut->GetDataUnchecked(row,col-1,time));
745 status[2] = digitsIn->GetPadStatus(row,col-1,time);
746 if(status[2]) SETBIT(ipos, AliTRDcluster::kMaskedRight);
748 // reject candidates with more than 1 problematic pad
749 if(ipos == 3 || ipos > 4) continue;
751 if(!status[1]){ // good central pad
752 if(!ipos){ // all pads are OK
753 if ((signalL <= signalM) && (signalR < signalM)) {
754 if ((signalL >= sigThresh) || (signalR >= sigThresh)) {
755 Float_t noiseSumThresh = minLeftRightCutSigma*calNoiseDetValue*calNoiseROC->GetValue(col,row);
756 if((signalL+signalR+signalM) >= noiseSumThresh){
757 // Maximum found, mark the position by a negative signal
758 digitsOut->SetDataUnchecked(row,col,time,-signalM);
759 fIndexesMaxima->AddIndexTBin(row,col,time);
760 padStatus.SetDataUnchecked(row, col, time, ipos);
764 } else { // one of the neighbouring pads are bad
765 if(status[0] && signalR < signalM && signalR >= sigThresh){
766 digitsOut->SetDataUnchecked(row,col,time,-signalM);
767 digitsOut->SetDataUnchecked(row, col, time+1, 0.);
768 fIndexesMaxima->AddIndexTBin(row,col,time);
769 padStatus.SetDataUnchecked(row, col, time, ipos);
770 } else if(status[2] && signalL <= signalM && signalL >= sigThresh){
771 digitsOut->SetDataUnchecked(row,col,time,-signalM);
772 digitsOut->SetDataUnchecked(row, col, time-1, 0.);
773 fIndexesMaxima->AddIndexTBin(row,col,time);
774 padStatus.SetDataUnchecked(row, col, time, ipos);
777 } else { // wrong maximum pad
778 if ((signalL >= sigThresh) || (signalR >= sigThresh)) {
779 // Maximum found, mark the position by a negative signal
780 digitsOut->SetDataUnchecked(row,col,time,-maxThresh);
781 fIndexesMaxima->AddIndexTBin(row,col,time);
782 padStatus.SetDataUnchecked(row, col, time, ipos);
787 // The index to the first cluster of a given ROC
788 Int_t firstClusterROC = -1;
789 // The number of cluster in a given ROC
790 Int_t nClusterROC = 0;
792 // Now check the maxima and calculate the cluster position
793 fIndexesMaxima->ResetCounters();
794 while (fIndexesMaxima->NextRCTbinIndex(row, col, time)) {
797 if (digitsOut->GetDataUnchecked(row,col,time) < 0.0) {
798 for (iPad = 0; iPad < kNclus; iPad++) {
799 Int_t iPadCol = col - 1 + iPad;
800 clusterSignal[iPad] = TMath::Abs(digitsOut->GetDataUnchecked(row,iPadCol,time));
803 // Count the number of pads in the cluster
808 while (TMath::Abs(digitsOut->GetDataUnchecked(row,col-ii ,time)) >= sigThresh) {
811 if (col-ii < 0) break;
815 while (TMath::Abs(digitsOut->GetDataUnchecked(row,col+ii+1,time)) >= sigThresh){
818 if (col+ii+1 >= nColMax) break;
822 // Look for 5 pad cluster with minimum in the middle
823 Bool_t fivePadCluster = kFALSE;
824 if (col < (nColMax - 3)){
825 if (digitsOut->GetDataUnchecked(row,col+2,time) < 0) {
826 fivePadCluster = kTRUE;
828 if ((fivePadCluster) && (col < (nColMax - 5))) {
829 if (digitsOut->GetDataUnchecked(row,col+4,time) >= sigThresh){
830 fivePadCluster = kFALSE;
833 if ((fivePadCluster) && (col > 1)){
834 if (digitsOut->GetDataUnchecked(row,col-2,time) >= sigThresh){
835 fivePadCluster = kFALSE;
841 // Modify the signal of the overlapping pad for the left part
842 // of the cluster which remains from a previous unfolding
844 clusterSignal[0] *= ratioLeft;
848 // Unfold the 5 pad cluster
850 for (iPad = 0; iPad < kNsig; iPad++) {
851 padSignal[iPad] = TMath::Abs(digitsOut->GetDataUnchecked(row
855 // Unfold the two maxima and set the signal on
856 // the overlapping pad to the ratio
857 ratioRight = Unfold(kEpsilon,ilayer,padSignal);
858 ratioLeft = 1.0 - ratioRight;
859 clusterSignal[2] *= ratioRight;
863 // The position of the cluster in COL direction relative to the center pad (pad units)
864 Double_t clusterPosCol = 0.0;
865 if (AliTRDReconstructor::RecoParam()->LUTOn()) {
866 // Calculate the position of the cluster by using the
867 // lookup table method
868 clusterPosCol = LUTposition(ilayer,clusterSignal[0]
872 // Calculate the position of the cluster by using the
873 // center of gravity method
874 for (Int_t i = 0; i < kNsig; i++) {
877 padSignal[2] = TMath::Abs(digitsOut->GetDataUnchecked(row,col ,time)); // Central pad
878 padSignal[1] = TMath::Abs(digitsOut->GetDataUnchecked(row,col-1,time)); // Left pad
879 padSignal[3] = TMath::Abs(digitsOut->GetDataUnchecked(row,col+1,time)); // Right pad
882 (TMath::Abs(digitsOut->GetDataUnchecked(row,col-2,time)) < padSignal[1])) {
883 padSignal[0] = TMath::Abs(digitsOut->GetDataUnchecked(row,col-2,time));
885 if ((col < nColMax - 3) &&
886 (TMath::Abs(digitsOut->GetDataUnchecked(row,col+2,time)) < padSignal[3])){
887 padSignal[4] = TMath::Abs(digitsOut->GetDataUnchecked(row,col+2,time));
889 clusterPosCol = GetCOG(padSignal);
892 // Store the amplitudes of the pads in the cluster for later analysis
893 // and check whether one of these pads is masked in the database
894 Short_t signals[7] = { 0, 0, 0, 0, 0, 0, 0 };
895 for (Int_t jPad = col-3; jPad <= col+3; jPad++) {
897 (jPad >= nColMax-1)) {
900 signals[jPad-col+3] = TMath::Nint(TMath::Abs(digitsOut->GetDataUnchecked(row,jPad,time)));
903 // Transform the local cluster coordinates into calibrated
904 // space point positions defined in the local tracking system.
905 // Here the calibration for T0, Vdrift and ExB is applied as well.
906 Double_t clusterXYZ[6];
907 clusterXYZ[0] = clusterPosCol;
908 clusterXYZ[1] = clusterSignal[0];
909 clusterXYZ[2] = clusterSignal[1];
910 clusterXYZ[3] = clusterSignal[2];
919 if (fTransform->Transform(clusterXYZ, clusterRCT, ((UInt_t) time), out, 0)) {
921 // Add the cluster to the output array
922 // The track indices will be stored later
923 Float_t clusterPos[3];
924 clusterPos[0] = clusterXYZ[0];
925 clusterPos[1] = clusterXYZ[1];
926 clusterPos[2] = clusterXYZ[2];
927 Float_t clusterSig[2];
928 clusterSig[0] = clusterXYZ[4];
929 clusterSig[1] = clusterXYZ[5];
930 Double_t clusterCharge = clusterXYZ[3];
931 Char_t clusterTimeBin = ((Char_t) clusterRCT[2]);
932 AliTRDcluster *cluster = new AliTRDcluster(idet
937 ,((Char_t) nPadCount)
945 cluster->SetInChamber(!out);
946 UChar_t maskPosition = padStatus.GetDataUnchecked(row, col, time);
948 cluster->SetPadMaskedPosition(maskPosition);
950 if(maskPosition & AliTRDcluster::kMaskedLeft) cluster->SetPadMaskedStatus(status[0]);
951 else if(maskPosition & AliTRDcluster::kMaskedCenter) cluster->SetPadMaskedStatus(status[1]);
952 else cluster->SetPadMaskedStatus(status[2]);
955 // Temporarily store the row, column and time bin of the center pad
956 // Used to later on assign the track indices
957 cluster->SetLabel( row,0);
958 cluster->SetLabel( col,1);
959 cluster->SetLabel(time,2);
961 RecPoints()->Add(cluster);
963 // Store the index of the first cluster in the current ROC
964 if (firstClusterROC < 0) {
965 firstClusterROC = RecPoints()->GetEntriesFast() - 1;
968 // Count the number of cluster in the current ROC
971 } // if: Transform ok ?
972 } // if: Maximum found ?
977 if (fAddLabels) AddLabels(idet, firstClusterROC, nClusterROC);
979 // Write the cluster and reset the array
987 //_____________________________________________________________________________
988 Bool_t AliTRDclusterizer::AddLabels(Int_t idet, Int_t firstClusterROC, Int_t nClusterROC)
991 // Add the track indices to the found clusters
994 const Int_t kNclus = 3;
995 const Int_t kNdict = AliTRDdigitsManager::kNDict;
996 const Int_t kNtrack = kNdict * kNclus;
998 Int_t iClusterROC = 0;
1005 // Temporary array to collect the track indices
1006 Int_t *idxTracks = new Int_t[kNtrack*nClusterROC];
1008 // Loop through the dictionary arrays one-by-one
1009 // to keep memory consumption low
1010 AliTRDdataArrayI *tracksIn = 0;
1011 for (Int_t iDict = 0; iDict < kNdict; iDict++) {
1013 // tracksIn should be expanded beforehand!
1014 tracksIn = (AliTRDdataArrayI *) fDigitsManager->GetDictionary(idet,iDict);
1016 // Loop though the clusters found in this ROC
1017 for (iClusterROC = 0; iClusterROC < nClusterROC; iClusterROC++) {
1019 AliTRDcluster *cluster = (AliTRDcluster *)
1020 RecPoints()->UncheckedAt(firstClusterROC+iClusterROC);
1021 row = cluster->GetLabel(0);
1022 col = cluster->GetLabel(1);
1023 time = cluster->GetLabel(2);
1025 for (iPad = 0; iPad < kNclus; iPad++) {
1026 Int_t iPadCol = col - 1 + iPad;
1027 Int_t index = tracksIn->GetDataUnchecked(row,iPadCol,time) - 1;
1028 idxTracks[3*iPad+iDict + iClusterROC*kNtrack] = index;
1035 // Copy the track indices into the cluster
1036 // Loop though the clusters found in this ROC
1037 for (iClusterROC = 0; iClusterROC < nClusterROC; iClusterROC++) {
1039 AliTRDcluster *cluster = (AliTRDcluster *)
1040 RecPoints()->UncheckedAt(firstClusterROC+iClusterROC);
1041 cluster->SetLabel(-9999,0);
1042 cluster->SetLabel(-9999,1);
1043 cluster->SetLabel(-9999,2);
1045 cluster->AddTrackIndex(&idxTracks[iClusterROC*kNtrack]);
1049 delete [] idxTracks;
1055 //_____________________________________________________________________________
1056 Double_t AliTRDclusterizer::GetCOG(Double_t signal[5]) const
1060 // Used for clusters with more than 3 pads - where LUT not applicable
1063 Double_t sum = signal[0]
1069 Double_t res = (0.0 * (-signal[0] + signal[4])
1070 + (-signal[1] + signal[3])) / sum;
1076 //_____________________________________________________________________________
1077 Double_t AliTRDclusterizer::Unfold(Double_t eps, Int_t layer, Double_t *padSignal)
1080 // Method to unfold neighbouring maxima.
1081 // The charge ratio on the overlapping pad is calculated
1082 // until there is no more change within the range given by eps.
1083 // The resulting ratio is then returned to the calling method.
1086 AliTRDcalibDB *calibration = AliTRDcalibDB::Instance();
1088 AliError("No AliTRDcalibDB instance available\n");
1093 Int_t itStep = 0; // Count iteration steps
1095 Double_t ratio = 0.5; // Start value for ratio
1096 Double_t prevRatio = 0.0; // Store previous ratio
1098 Double_t newLeftSignal[3] = { 0.0, 0.0, 0.0 }; // Array to store left cluster signal
1099 Double_t newRightSignal[3] = { 0.0, 0.0, 0.0 }; // Array to store right cluster signal
1100 Double_t newSignal[3] = { 0.0, 0.0, 0.0 };
1102 // Start the iteration
1103 while ((TMath::Abs(prevRatio - ratio) > eps) && (itStep < 10)) {
1108 // Cluster position according to charge ratio
1109 Double_t maxLeft = (ratio*padSignal[2] - padSignal[0])
1110 / (padSignal[0] + padSignal[1] + ratio*padSignal[2]);
1111 Double_t maxRight = (padSignal[4] - (1-ratio)*padSignal[2])
1112 / ((1.0 - ratio)*padSignal[2] + padSignal[3] + padSignal[4]);
1114 // Set cluster charge ratio
1115 irc = calibration->PadResponse(1.0,maxLeft ,layer,newSignal);
1116 Double_t ampLeft = padSignal[1] / newSignal[1];
1117 irc = calibration->PadResponse(1.0,maxRight,layer,newSignal);
1118 Double_t ampRight = padSignal[3] / newSignal[1];
1120 // Apply pad response to parameters
1121 irc = calibration->PadResponse(ampLeft ,maxLeft ,layer,newLeftSignal );
1122 irc = calibration->PadResponse(ampRight,maxRight,layer,newRightSignal);
1124 // Calculate new overlapping ratio
1125 ratio = TMath::Min((Double_t) 1.0
1126 ,newLeftSignal[2] / (newLeftSignal[2] + newRightSignal[0]));
1134 //_____________________________________________________________________________
1135 void AliTRDclusterizer::TailCancelation(AliTRDdataArrayDigits *digitsIn
1136 , AliTRDdataArrayF *digitsOut
1137 , AliTRDSignalIndex *indexesIn
1138 , AliTRDSignalIndex *indexesOut
1140 , Float_t adcThreshold
1141 , AliTRDCalROC *calGainFactorROC
1142 , Float_t calGainFactorDetValue)
1145 // Applies the tail cancelation and gain factors:
1146 // Transform digitsIn to digitsOut
1153 Double_t *inADC = new Double_t[nTimeTotal]; // ADC data before tail cancellation
1154 Double_t *outADC = new Double_t[nTimeTotal]; // ADC data after tail cancellation
1155 indexesIn->ResetCounters();
1156 while (indexesIn->NextRCIndex(iRow, iCol))
1158 Float_t calGainFactorROCValue = calGainFactorROC->GetValue(iCol,iRow);
1159 Double_t gain = calGainFactorDetValue
1160 * calGainFactorROCValue;
1162 Bool_t corrupted = kFALSE;
1163 for (iTime = 0; iTime < nTimeTotal; iTime++)
1165 // Apply gain gain factor
1166 inADC[iTime] = digitsIn->GetDataUnchecked(iRow,iCol,iTime);
1167 if(digitsIn->GetPadStatus(iRow, iCol, iTime)) corrupted = kTRUE;
1168 inADC[iTime] /= gain;
1169 outADC[iTime] = inADC[iTime];
1173 // Apply the tail cancelation via the digital filter
1174 // (only for non-coorupted pads)
1175 if (AliTRDReconstructor::RecoParam()->TCOn())
1177 DeConvExp(inADC,outADC,nTimeTotal,AliTRDReconstructor::RecoParam()->GetTCnexp());
1181 indexesIn->ResetTbinCounter();
1182 while (indexesIn->NextTbinIndex(iTime))
1184 // Store the amplitude of the digit if above threshold
1185 if (outADC[iTime] > adcThreshold)
1187 digitsOut->SetDataUnchecked(iRow,iCol,iTime,outADC[iTime]);
1188 indexesOut->AddIndexTBin(iRow,iCol,iTime);
1192 } // while irow icol
1201 //_____________________________________________________________________________
1202 void AliTRDclusterizer::DeConvExp(Double_t *source, Double_t *target
1203 , Int_t n, Int_t nexp)
1206 // Tail cancellation by deconvolution for PASA v4 TRF
1210 Double_t coefficients[2];
1212 // Initialization (coefficient = alpha, rates = lambda)
1218 if (nexp == 1) { // 1 Exponentials
1224 if (nexp == 2) { // 2 Exponentials
1231 coefficients[0] = c1;
1232 coefficients[1] = c2;
1236 rates[0] = TMath::Exp(-dt/(r1));
1237 rates[1] = TMath::Exp(-dt/(r2));
1242 Double_t reminder[2];
1243 Double_t correction = 0.0;
1244 Double_t result = 0.0;
1246 // Attention: computation order is important
1247 for (k = 0; k < nexp; k++) {
1251 for (i = 0; i < n; i++) {
1253 result = (source[i] - correction); // No rescaling
1256 for (k = 0; k < nexp; k++) {
1257 reminder[k] = rates[k] * (reminder[k] + coefficients[k] * result);
1261 for (k = 0; k < nexp; k++) {
1262 correction += reminder[k];
1269 //_____________________________________________________________________________
1270 void AliTRDclusterizer::ResetRecPoints()
1273 // Resets the list of rec points
1277 fRecPoints->Delete();
1282 //_____________________________________________________________________________
1283 TObjArray *AliTRDclusterizer::RecPoints()
1286 // Returns the list of rec points
1290 fRecPoints = new TObjArray(400);
1297 //_____________________________________________________________________________
1298 void AliTRDclusterizer::FillLUT()
1304 const Int_t kNlut = 128;
1306 fLUTbin = AliTRDgeometry::kNlayer * kNlut;
1308 // The lookup table from Bogdan
1309 Float_t lut[AliTRDgeometry::kNlayer][kNlut] = {
1311 0.0070, 0.0150, 0.0224, 0.0298, 0.0374, 0.0454, 0.0533, 0.0611,
1312 0.0684, 0.0755, 0.0827, 0.0900, 0.0975, 0.1049, 0.1120, 0.1187,
1313 0.1253, 0.1318, 0.1385, 0.1453, 0.1519, 0.1584, 0.1646, 0.1704,
1314 0.1762, 0.1821, 0.1879, 0.1938, 0.1996, 0.2053, 0.2108, 0.2160,
1315 0.2210, 0.2260, 0.2310, 0.2361, 0.2411, 0.2461, 0.2509, 0.2557,
1316 0.2602, 0.2646, 0.2689, 0.2732, 0.2774, 0.2816, 0.2859, 0.2901,
1317 0.2942, 0.2983, 0.3022, 0.3061, 0.3099, 0.3136, 0.3172, 0.3207,
1318 0.3242, 0.3278, 0.3312, 0.3347, 0.3382, 0.3416, 0.3450, 0.3483,
1319 0.3515, 0.3547, 0.3579, 0.3609, 0.3639, 0.3669, 0.3698, 0.3727,
1320 0.3756, 0.3785, 0.3813, 0.3842, 0.3870, 0.3898, 0.3926, 0.3952,
1321 0.3979, 0.4005, 0.4032, 0.4057, 0.4082, 0.4108, 0.4132, 0.4157,
1322 0.4181, 0.4205, 0.4228, 0.4252, 0.4275, 0.4299, 0.4322, 0.4345,
1323 0.4367, 0.4390, 0.4412, 0.4434, 0.4456, 0.4478, 0.4499, 0.4520,
1324 0.4541, 0.4562, 0.4583, 0.4603, 0.4623, 0.4643, 0.4663, 0.4683,
1325 0.4702, 0.4722, 0.4741, 0.4758, 0.4774, 0.4790, 0.4805, 0.4824,
1326 0.4844, 0.4863, 0.4883, 0.4902, 0.4921, 0.4940, 0.4959, 0.4978
1329 0.0072, 0.0156, 0.0235, 0.0313, 0.0394, 0.0478, 0.0561, 0.0642,
1330 0.0718, 0.0792, 0.0868, 0.0947, 0.1025, 0.1101, 0.1172, 0.1241,
1331 0.1309, 0.1378, 0.1449, 0.1518, 0.1586, 0.1650, 0.1710, 0.1770,
1332 0.1830, 0.1891, 0.1952, 0.2011, 0.2070, 0.2125, 0.2177, 0.2229,
1333 0.2280, 0.2332, 0.2383, 0.2435, 0.2484, 0.2533, 0.2581, 0.2627,
1334 0.2670, 0.2714, 0.2757, 0.2799, 0.2842, 0.2884, 0.2927, 0.2968,
1335 0.3008, 0.3048, 0.3086, 0.3123, 0.3159, 0.3195, 0.3231, 0.3266,
1336 0.3301, 0.3335, 0.3370, 0.3404, 0.3438, 0.3471, 0.3504, 0.3536,
1337 0.3567, 0.3598, 0.3628, 0.3657, 0.3686, 0.3715, 0.3744, 0.3772,
1338 0.3800, 0.3828, 0.3856, 0.3884, 0.3911, 0.3938, 0.3965, 0.3991,
1339 0.4016, 0.4042, 0.4067, 0.4092, 0.4116, 0.4140, 0.4164, 0.4187,
1340 0.4211, 0.4234, 0.4257, 0.4280, 0.4302, 0.4325, 0.4347, 0.4369,
1341 0.4391, 0.4413, 0.4434, 0.4456, 0.4477, 0.4497, 0.4518, 0.4538,
1342 0.4558, 0.4578, 0.4598, 0.4618, 0.4637, 0.4656, 0.4675, 0.4694,
1343 0.4713, 0.4732, 0.4750, 0.4766, 0.4781, 0.4797, 0.4813, 0.4832,
1344 0.4851, 0.4870, 0.4888, 0.4906, 0.4925, 0.4942, 0.4960, 0.4978
1347 0.0075, 0.0163, 0.0246, 0.0328, 0.0415, 0.0504, 0.0592, 0.0674,
1348 0.0753, 0.0832, 0.0914, 0.0996, 0.1077, 0.1154, 0.1225, 0.1296,
1349 0.1369, 0.1442, 0.1515, 0.1585, 0.1652, 0.1714, 0.1776, 0.1839,
1350 0.1902, 0.1965, 0.2025, 0.2085, 0.2141, 0.2194, 0.2247, 0.2299,
1351 0.2352, 0.2405, 0.2457, 0.2507, 0.2557, 0.2604, 0.2649, 0.2693,
1352 0.2737, 0.2780, 0.2823, 0.2867, 0.2909, 0.2951, 0.2992, 0.3033,
1353 0.3072, 0.3110, 0.3146, 0.3182, 0.3218, 0.3253, 0.3288, 0.3323,
1354 0.3357, 0.3392, 0.3426, 0.3459, 0.3492, 0.3524, 0.3555, 0.3586,
1355 0.3616, 0.3645, 0.3674, 0.3703, 0.3731, 0.3759, 0.3787, 0.3815,
1356 0.3843, 0.3870, 0.3897, 0.3925, 0.3950, 0.3976, 0.4002, 0.4027,
1357 0.4052, 0.4076, 0.4101, 0.4124, 0.4148, 0.4171, 0.4194, 0.4217,
1358 0.4239, 0.4262, 0.4284, 0.4306, 0.4328, 0.4350, 0.4371, 0.4393,
1359 0.4414, 0.4435, 0.4455, 0.4476, 0.4496, 0.4516, 0.4536, 0.4555,
1360 0.4575, 0.4594, 0.4613, 0.4632, 0.4650, 0.4669, 0.4687, 0.4705,
1361 0.4723, 0.4741, 0.4758, 0.4773, 0.4789, 0.4804, 0.4821, 0.4839,
1362 0.4857, 0.4875, 0.4893, 0.4910, 0.4928, 0.4945, 0.4961, 0.4978
1365 0.0078, 0.0171, 0.0258, 0.0345, 0.0438, 0.0532, 0.0624, 0.0708,
1366 0.0791, 0.0875, 0.0962, 0.1048, 0.1130, 0.1206, 0.1281, 0.1356,
1367 0.1432, 0.1508, 0.1582, 0.1651, 0.1716, 0.1780, 0.1845, 0.1910,
1368 0.1975, 0.2038, 0.2099, 0.2155, 0.2210, 0.2263, 0.2317, 0.2371,
1369 0.2425, 0.2477, 0.2528, 0.2578, 0.2626, 0.2671, 0.2715, 0.2759,
1370 0.2803, 0.2846, 0.2890, 0.2933, 0.2975, 0.3016, 0.3056, 0.3095,
1371 0.3132, 0.3168, 0.3204, 0.3239, 0.3274, 0.3309, 0.3344, 0.3378,
1372 0.3412, 0.3446, 0.3479, 0.3511, 0.3543, 0.3574, 0.3603, 0.3633,
1373 0.3662, 0.3690, 0.3718, 0.3747, 0.3774, 0.3802, 0.3829, 0.3857,
1374 0.3883, 0.3910, 0.3936, 0.3962, 0.3987, 0.4012, 0.4037, 0.4061,
1375 0.4085, 0.4109, 0.4132, 0.4155, 0.4177, 0.4200, 0.4222, 0.4244,
1376 0.4266, 0.4288, 0.4309, 0.4331, 0.4352, 0.4373, 0.4394, 0.4414,
1377 0.4435, 0.4455, 0.4475, 0.4494, 0.4514, 0.4533, 0.4552, 0.4571,
1378 0.4590, 0.4608, 0.4626, 0.4645, 0.4662, 0.4680, 0.4698, 0.4715,
1379 0.4733, 0.4750, 0.4766, 0.4781, 0.4796, 0.4812, 0.4829, 0.4846,
1380 0.4863, 0.4880, 0.4897, 0.4914, 0.4930, 0.4946, 0.4963, 0.4979
1383 0.0081, 0.0178, 0.0270, 0.0364, 0.0463, 0.0562, 0.0656, 0.0744,
1384 0.0831, 0.0921, 0.1013, 0.1102, 0.1183, 0.1261, 0.1339, 0.1419,
1385 0.1499, 0.1576, 0.1648, 0.1715, 0.1782, 0.1849, 0.1917, 0.1984,
1386 0.2048, 0.2110, 0.2167, 0.2223, 0.2278, 0.2333, 0.2389, 0.2444,
1387 0.2497, 0.2548, 0.2598, 0.2645, 0.2691, 0.2735, 0.2780, 0.2824,
1388 0.2868, 0.2912, 0.2955, 0.2997, 0.3038, 0.3078, 0.3116, 0.3152,
1389 0.3188, 0.3224, 0.3259, 0.3294, 0.3329, 0.3364, 0.3398, 0.3432,
1390 0.3465, 0.3497, 0.3529, 0.3561, 0.3591, 0.3620, 0.3649, 0.3677,
1391 0.3705, 0.3733, 0.3761, 0.3788, 0.3816, 0.3843, 0.3869, 0.3896,
1392 0.3922, 0.3948, 0.3973, 0.3998, 0.4022, 0.4047, 0.4070, 0.4094,
1393 0.4117, 0.4139, 0.4162, 0.4184, 0.4206, 0.4227, 0.4249, 0.4270,
1394 0.4291, 0.4313, 0.4334, 0.4354, 0.4375, 0.4395, 0.4415, 0.4435,
1395 0.4455, 0.4474, 0.4493, 0.4512, 0.4531, 0.4550, 0.4568, 0.4586,
1396 0.4604, 0.4622, 0.4639, 0.4657, 0.4674, 0.4691, 0.4708, 0.4725,
1397 0.4742, 0.4758, 0.4773, 0.4788, 0.4803, 0.4819, 0.4836, 0.4852,
1398 0.4869, 0.4885, 0.4901, 0.4917, 0.4933, 0.4948, 0.4964, 0.4979
1401 0.0085, 0.0189, 0.0288, 0.0389, 0.0497, 0.0603, 0.0699, 0.0792,
1402 0.0887, 0.0985, 0.1082, 0.1170, 0.1253, 0.1336, 0.1421, 0.1505,
1403 0.1587, 0.1662, 0.1733, 0.1803, 0.1874, 0.1945, 0.2014, 0.2081,
1404 0.2143, 0.2201, 0.2259, 0.2316, 0.2374, 0.2431, 0.2487, 0.2541,
1405 0.2593, 0.2642, 0.2689, 0.2735, 0.2781, 0.2826, 0.2872, 0.2917,
1406 0.2961, 0.3003, 0.3045, 0.3086, 0.3125, 0.3162, 0.3198, 0.3235,
1407 0.3270, 0.3306, 0.3342, 0.3377, 0.3411, 0.3446, 0.3479, 0.3511,
1408 0.3543, 0.3575, 0.3605, 0.3634, 0.3663, 0.3691, 0.3720, 0.3748,
1409 0.3775, 0.3803, 0.3830, 0.3857, 0.3884, 0.3911, 0.3937, 0.3962,
1410 0.3987, 0.4012, 0.4036, 0.4060, 0.4084, 0.4107, 0.4129, 0.4152,
1411 0.4174, 0.4196, 0.4218, 0.4239, 0.4261, 0.4282, 0.4303, 0.4324,
1412 0.4344, 0.4365, 0.4385, 0.4405, 0.4425, 0.4445, 0.4464, 0.4483,
1413 0.4502, 0.4521, 0.4539, 0.4558, 0.4576, 0.4593, 0.4611, 0.4629,
1414 0.4646, 0.4663, 0.4680, 0.4697, 0.4714, 0.4730, 0.4747, 0.4759,
1415 0.4769, 0.4780, 0.4790, 0.4800, 0.4811, 0.4827, 0.4843, 0.4859,
1416 0.4874, 0.4889, 0.4905, 0.4920, 0.4935, 0.4950, 0.4965, 0.4979
1423 fLUT = new Double_t[fLUTbin];
1425 for (Int_t ilayer = 0; ilayer < AliTRDgeometry::kNlayer; ilayer++) {
1426 for (Int_t ilut = 0; ilut < kNlut; ilut++ ) {
1427 fLUT[ilayer*kNlut+ilut] = lut[ilayer][ilut];
1433 //_____________________________________________________________________________
1434 Double_t AliTRDclusterizer::LUTposition(Int_t ilayer, Double_t ampL
1435 , Double_t ampC, Double_t ampR) const
1438 // Calculates the cluster position using the lookup table.
1439 // Method provided by Bogdan Vulpescu.
1442 const Int_t kNlut = 128;
1453 Double_t xMin[AliTRDgeometry::kNlayer] = { 0.006492, 0.006377, 0.006258
1454 , 0.006144, 0.006030, 0.005980 };
1455 Double_t xMax[AliTRDgeometry::kNlayer] = { 0.960351, 0.965870, 0.970445
1456 , 0.974352, 0.977667, 0.996101 };
1459 x = (ampL - ampR) / ampC;
1462 else if (ampL < ampR) {
1463 x = (ampR - ampL) / ampC;
1469 xmin = xMin[ilayer] + 0.000005;
1470 xmax = xMax[ilayer] - 0.000005;
1471 xwid = (xmax - xmin) / 127.0;
1476 else if (x > xmax) {
1477 pos = side * 0.5000;
1480 ix = (Int_t) ((x - xmin) / xwid);
1481 pos = side * fLUT[ilayer*kNlut+ix];