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);
194 //_____________________________________________________________________________
195 void AliTRDclusterizer::Copy(TObject &c) const
201 ((AliTRDclusterizer &) c).fClusterTree = NULL;
202 ((AliTRDclusterizer &) c).fRecPoints = NULL;
203 ((AliTRDclusterizer &) c).fDigitsManager = NULL;
204 ((AliTRDclusterizer &) c).fAddLabels = fAddLabels;
205 ((AliTRDclusterizer &) c).fRawVersion = fRawVersion;
206 ((AliTRDclusterizer &) c).fIndexesOut = NULL;
207 ((AliTRDclusterizer &) c).fIndexesMaxima = NULL;
208 ((AliTRDclusterizer &) c).fTransform = NULL;
209 ((AliTRDclusterizer &) c).fLUTbin = 0;
210 ((AliTRDclusterizer &) c).fLUT = NULL;
214 //_____________________________________________________________________________
215 Bool_t AliTRDclusterizer::Open(const Char_t *name, Int_t nEvent)
218 // Opens the AliROOT file. Output and input are in the same file
221 TString evfoldname = AliConfig::GetDefaultEventFolderName();
222 fRunLoader = AliRunLoader::GetRunLoader(evfoldname);
225 fRunLoader = AliRunLoader::Open(name);
229 AliError(Form("Can not open session for file %s.",name));
240 //_____________________________________________________________________________
241 Bool_t AliTRDclusterizer::OpenOutput()
244 // Open the output file
247 TObjArray *ioArray = 0;
249 AliLoader* loader = fRunLoader->GetLoader("TRDLoader");
250 loader->MakeTree("R");
252 fClusterTree = loader->TreeR();
253 fClusterTree->Branch("TRDcluster","TObjArray",&ioArray,32000,0);
259 //_____________________________________________________________________________
260 Bool_t AliTRDclusterizer::OpenOutput(TTree *clusterTree)
263 // Connect the output tree
266 TObjArray *ioArray = 0;
268 fClusterTree = clusterTree;
269 fClusterTree->Branch("TRDcluster","TObjArray",&ioArray,32000,0);
275 //_____________________________________________________________________________
276 Bool_t AliTRDclusterizer::OpenInput(Int_t nEvent)
279 // Opens a ROOT-file with TRD-hits and reads in the digits-tree
282 // Import the Trees for the event nEvent in the file
283 fRunLoader->GetEvent(nEvent);
289 //_____________________________________________________________________________
290 Bool_t AliTRDclusterizer::WriteClusters(Int_t det)
293 // Fills TRDcluster branch in the tree with the clusters
294 // found in detector = det. For det=-1 writes the tree.
298 (det >= AliTRDgeometry::Ndet())) {
299 AliError(Form("Unexpected detector index %d.\n",det));
303 TBranch *branch = fClusterTree->GetBranch("TRDcluster");
305 TObjArray *ioArray = 0;
306 branch = fClusterTree->Branch("TRDcluster","TObjArray",&ioArray,32000,0);
310 (det < AliTRDgeometry::Ndet())) {
312 Int_t nRecPoints = RecPoints()->GetEntriesFast();
313 TObjArray *detRecPoints = new TObjArray(400);
315 for (Int_t i = 0; i < nRecPoints; i++) {
316 AliTRDcluster *c = (AliTRDcluster *) RecPoints()->UncheckedAt(i);
317 if (det == c->GetDetector()) {
318 detRecPoints->AddLast(c);
321 AliError(Form("Attempt to write a cluster with unexpected detector index: got=%d expected=%d\n"
327 branch->SetAddress(&detRecPoints);
328 fClusterTree->Fill();
338 AliInfo(Form("Writing the cluster tree %s for event %d."
339 ,fClusterTree->GetName(),fRunLoader->GetEventNumber()));
343 branch->SetAddress(&fRecPoints);
345 AliLoader *loader = fRunLoader->GetLoader("TRDLoader");
346 loader->WriteRecPoints("OVERWRITE");
351 AliError("Cluster tree does not exist. Cannot write clusters.\n");
360 AliError(Form("Unexpected detector index %d.\n",det));
366 //_____________________________________________________________________________
367 void AliTRDclusterizer::ResetHelperIndexes(AliTRDSignalIndex *indexesIn)
370 // Reset the helper indexes
375 // carefull here - we assume that only row number may change - most probable
376 if (indexesIn->GetNrow() <= fIndexesOut->GetNrow())
377 fIndexesOut->ResetContent();
379 fIndexesOut->ResetContentConditional(indexesIn->GetNrow()
380 , indexesIn->GetNcol()
381 , indexesIn->GetNtime());
385 fIndexesOut = new AliTRDSignalIndex(indexesIn->GetNrow()
386 , indexesIn->GetNcol()
387 , indexesIn->GetNtime());
392 // carefull here - we assume that only row number may change - most probable
393 if (indexesIn->GetNrow() <= fIndexesMaxima->GetNrow())
395 fIndexesMaxima->ResetContent();
399 fIndexesMaxima->ResetContentConditional(indexesIn->GetNrow()
400 , indexesIn->GetNcol()
401 , indexesIn->GetNtime());
406 fIndexesMaxima = new AliTRDSignalIndex(indexesIn->GetNrow()
407 , indexesIn->GetNcol()
408 , indexesIn->GetNtime());
413 //_____________________________________________________________________________
414 Bool_t AliTRDclusterizer::ReadDigits()
417 // Reads the digits arrays from the input aliroot file
421 AliError("No run loader available");
425 AliLoader* loader = fRunLoader->GetLoader("TRDLoader");
426 if (!loader->TreeD()) {
427 loader->LoadDigits();
430 // Read in the digit arrays
431 return (fDigitsManager->ReadDigits(loader->TreeD()));
435 //_____________________________________________________________________________
436 Bool_t AliTRDclusterizer::ReadDigits(TTree *digitsTree)
439 // Reads the digits arrays from the input tree
442 // Read in the digit arrays
443 return (fDigitsManager->ReadDigits(digitsTree));
447 //_____________________________________________________________________________
448 Bool_t AliTRDclusterizer::ReadDigits(AliRawReader *rawReader)
451 // Reads the digits arrays from the ddl file
455 fDigitsManager = raw.Raw2Digits(rawReader);
461 //_____________________________________________________________________________
462 Bool_t AliTRDclusterizer::MakeClusters()
465 // Creates clusters from digits
468 // Propagate info from the digits manager
469 if (fAddLabels == kTRUE)
471 fAddLabels = fDigitsManager->UsesDictionaries();
474 Bool_t fReturn = kTRUE;
475 for (Int_t i = 0; i < AliTRDgeometry::kNdet; i++)
478 AliTRDdataArrayDigits *digitsIn = (AliTRDdataArrayDigits*) fDigitsManager->GetDigits(i);
479 // This is to take care of switched off super modules
480 if (!digitsIn->HasData())
485 AliTRDSignalIndex* indexes = fDigitsManager->GetIndexes(i);
486 if (indexes->IsAllocated() == kFALSE)
488 fDigitsManager->BuildIndexes(i);
492 if (indexes->HasEntry())
496 for (Int_t iDict = 0; iDict < AliTRDdigitsManager::kNDict; iDict++)
498 AliTRDdataArrayI *tracksIn = 0;
499 tracksIn = (AliTRDdataArrayI *) fDigitsManager->GetDictionary(i,iDict);
503 fR = MakeClusters(i);
504 fReturn = fR && fReturn;
513 // No compress just remove
514 fDigitsManager->RemoveDigits(i);
515 fDigitsManager->RemoveDictionaries(i);
516 fDigitsManager->ClearIndexes(i);
524 //_____________________________________________________________________________
525 Bool_t AliTRDclusterizer::Raw2Clusters(AliRawReader *rawReader)
528 // Creates clusters from raw data
531 return Raw2ClustersChamber(rawReader);
535 //_____________________________________________________________________________
536 Bool_t AliTRDclusterizer::Raw2ClustersChamber(AliRawReader *rawReader)
539 // Creates clusters from raw data
542 // Create the digits manager
545 fDigitsManager = new AliTRDdigitsManager();
546 fDigitsManager->CreateArrays();
549 fDigitsManager->SetUseDictionaries(fAddLabels);
551 AliTRDrawStreamBase *pinput = AliTRDrawStreamBase::GetRawStream(rawReader);
552 AliTRDrawStreamBase &input = *pinput;
554 AliInfo(Form("Stream version: %s", input.IsA()->GetName()));
557 while ((det = input.NextChamber(fDigitsManager)) >= 0)
559 Bool_t iclusterBranch = kFALSE;
560 if (fDigitsManager->GetIndexes(det)->HasEntry())
562 iclusterBranch = MakeClusters(det);
564 if (iclusterBranch == kFALSE)
569 fDigitsManager->RemoveDigits(det);
570 fDigitsManager->RemoveDictionaries(det);
571 fDigitsManager->ClearIndexes(det);
574 delete fDigitsManager;
575 fDigitsManager = NULL;
583 //_____________________________________________________________________________
584 UChar_t AliTRDclusterizer::GetStatus(Short_t &signal)
587 // check if pad is masked
588 if(signal>0 && TESTBIT(signal, 10)){
590 for(int ibit=0; ibit<4; ibit++){
591 if(TESTBIT(signal, 11+ibit)){
592 SETBIT(status, ibit);
593 CLRBIT(signal, 11+ibit);
600 //_____________________________________________________________________________
601 Bool_t AliTRDclusterizer::MakeClusters(Int_t det)
604 // Generates the cluster.
608 // digits should be expanded beforehand!
609 // digitsIn->Expand();
610 AliTRDdataArrayDigits *digitsIn = (AliTRDdataArrayDigits *) fDigitsManager->GetDigits(det);
612 // This is to take care of switched off super modules
613 if (!digitsIn->HasData())
618 AliTRDSignalIndex *indexesIn = fDigitsManager->GetIndexes(det);
619 if (indexesIn->IsAllocated() == kFALSE)
621 AliError("Indexes do not exist!");
625 AliTRDcalibDB *calibration = AliTRDcalibDB::Instance();
628 AliFatal("No AliTRDcalibDB instance available\n");
633 // There is no ADC threshold anymore, and simParam should not be used in clusterizer. KO
634 Float_t adcThreshold = 0;
636 if (!AliTRDReconstructor::RecoParam())
638 AliError("RecoParam does not exist\n");
642 // Threshold value for the maximum
643 Float_t maxThresh = AliTRDReconstructor::RecoParam()->GetClusMaxThresh();
644 // Threshold value for the digit signal
645 Float_t sigThresh = AliTRDReconstructor::RecoParam()->GetClusSigThresh();
647 // Iteration limit for unfolding procedure
648 const Float_t kEpsilon = 0.01;
649 const Int_t kNclus = 3;
650 const Int_t kNsig = 5;
653 Double_t ratioLeft = 1.0;
654 Double_t ratioRight = 1.0;
656 Double_t padSignal[kNsig];
657 Double_t clusterSignal[kNclus];
659 Int_t icham = indexesIn->GetChamber();
660 Int_t iplan = indexesIn->GetPlane();
661 Int_t isect = indexesIn->GetSM();
663 // Start clustering in the chamber
665 Int_t idet = AliTRDgeometry::GetDetector(iplan,icham,isect);
668 AliError("Strange Detector number Missmatch!");
672 // TRD space point transformation
673 fTransform->SetDetector(det);
675 Int_t ilayer = AliGeomManager::kTRD1 + iplan;
676 Int_t imodule = icham + AliTRDgeometry::Ncham() * isect;
677 UShort_t volid = AliGeomManager::LayerToVolUID(ilayer,imodule);
679 Int_t nColMax = digitsIn->GetNcol();
680 Int_t nRowMax = digitsIn->GetNrow();
681 Int_t nTimeTotal = digitsIn->GetNtime();
683 // Detector wise calibration object for the gain factors
684 const AliTRDCalDet *calGainFactorDet = calibration->GetGainFactorDet();
685 // Calibration object with pad wise values for the gain factors
686 AliTRDCalROC *calGainFactorROC = calibration->GetGainFactorROC(idet);
687 // Calibration value for chamber wise gain factor
688 Float_t calGainFactorDetValue = calGainFactorDet->GetValue(idet);
692 AliTRDdataArrayF *digitsOut = new AliTRDdataArrayF(nRowMax, nColMax, nTimeTotal);
693 AliTRDdataArrayS padStatus(nRowMax, nColMax, nTimeTotal);
695 ResetHelperIndexes(indexesIn);
697 // Apply the gain and the tail cancelation via digital filter
698 TailCancelation(digitsIn
705 ,calGainFactorDetValue);
712 UChar_t status[3]={0, 0, 0}, ipos = 0;
713 fIndexesOut->ResetCounters();
714 while (fIndexesOut->NextRCTbinIndex(row, col, time)){
715 Float_t signalM = TMath::Abs(digitsOut->GetDataUnchecked(row,col,time));
716 status[1] = digitsIn->GetPadStatus(row,col,time);
717 if(status[1]) SETBIT(ipos, AliTRDcluster::kMaskedCenter);
719 // Look for the maximum
720 if (signalM >= maxThresh) {
721 if (col + 1 >= nColMax || col-1 < 0) continue;
723 Float_t signalL = TMath::Abs(digitsOut->GetDataUnchecked(row,col+1,time));
724 status[0] = digitsIn->GetPadStatus(row,col+1,time);
725 if(status[0]) SETBIT(ipos, AliTRDcluster::kMaskedLeft);
727 Float_t signalR = TMath::Abs(digitsOut->GetDataUnchecked(row,col-1,time));
728 status[2] = digitsIn->GetPadStatus(row,col-1,time);
729 if(status[2]) SETBIT(ipos, AliTRDcluster::kMaskedRight);
731 // reject candidates with more than 1 problematic pad
732 if(ipos == 3 || ipos > 4) continue;
734 if(!status[1]){ // good central pad
735 if(!ipos){ // all pads are OK
736 if ((signalL <= signalM) && (signalR < signalM)) {
737 if ((signalL >= sigThresh) || (signalR >= sigThresh)) {
738 // Maximum found, mark the position by a negative signal
739 digitsOut->SetDataUnchecked(row,col,time,-signalM);
740 fIndexesMaxima->AddIndexTBin(row,col,time);
741 padStatus.SetDataUnchecked(row, col, time, ipos);
744 } else { // one of the neighbouring pads are bad
745 if(status[0] && signalR < signalM && signalR >= sigThresh){
746 digitsOut->SetDataUnchecked(row,col,time,-signalM);
747 digitsOut->SetDataUnchecked(row, col, time+1, 0.);
748 fIndexesMaxima->AddIndexTBin(row,col,time);
749 padStatus.SetDataUnchecked(row, col, time, ipos);
750 } else if(status[2] && signalL <= signalM && signalL >= sigThresh){
751 digitsOut->SetDataUnchecked(row,col,time,-signalM);
752 digitsOut->SetDataUnchecked(row, col, time-1, 0.);
753 fIndexesMaxima->AddIndexTBin(row,col,time);
754 padStatus.SetDataUnchecked(row, col, time, ipos);
757 } else { // wrong maximum pad
758 if ((signalL >= sigThresh) || (signalR >= sigThresh)) {
759 // Maximum found, mark the position by a negative signal
760 digitsOut->SetDataUnchecked(row,col,time,-maxThresh);
761 fIndexesMaxima->AddIndexTBin(row,col,time);
762 padStatus.SetDataUnchecked(row, col, time, ipos);
768 // The index to the first cluster of a given ROC
769 Int_t firstClusterROC = -1;
770 // The number of cluster in a given ROC
771 Int_t nClusterROC = 0;
773 // Now check the maxima and calculate the cluster position
774 fIndexesMaxima->ResetCounters();
775 while (fIndexesMaxima->NextRCTbinIndex(row, col, time)) {
778 if (digitsOut->GetDataUnchecked(row,col,time) < 0.0) {
779 for (iPad = 0; iPad < kNclus; iPad++) {
780 Int_t iPadCol = col - 1 + iPad;
781 clusterSignal[iPad] = TMath::Abs(digitsOut->GetDataUnchecked(row,iPadCol,time));
784 // Count the number of pads in the cluster
789 while (TMath::Abs(digitsOut->GetDataUnchecked(row,col-ii ,time)) >= sigThresh) {
792 if (col-ii < 0) break;
796 while (TMath::Abs(digitsOut->GetDataUnchecked(row,col+ii+1,time)) >= sigThresh){
799 if (col+ii+1 >= nColMax) break;
803 // Look for 5 pad cluster with minimum in the middle
804 Bool_t fivePadCluster = kFALSE;
805 if (col < (nColMax - 3)){
806 if (digitsOut->GetDataUnchecked(row,col+2,time) < 0) {
807 fivePadCluster = kTRUE;
809 if ((fivePadCluster) && (col < (nColMax - 5))) {
810 if (digitsOut->GetDataUnchecked(row,col+4,time) >= sigThresh){
811 fivePadCluster = kFALSE;
814 if ((fivePadCluster) && (col > 1)){
815 if (digitsOut->GetDataUnchecked(row,col-2,time) >= sigThresh){
816 fivePadCluster = kFALSE;
822 // Modify the signal of the overlapping pad for the left part
823 // of the cluster which remains from a previous unfolding
825 clusterSignal[0] *= ratioLeft;
829 // Unfold the 5 pad cluster
831 for (iPad = 0; iPad < kNsig; iPad++) {
832 padSignal[iPad] = TMath::Abs(digitsOut->GetDataUnchecked(row
836 // Unfold the two maxima and set the signal on
837 // the overlapping pad to the ratio
838 ratioRight = Unfold(kEpsilon,iplan,padSignal);
839 ratioLeft = 1.0 - ratioRight;
840 clusterSignal[2] *= ratioRight;
844 // The position of the cluster in COL direction relative to the center pad (pad units)
845 Double_t clusterPosCol = 0.0;
846 if (AliTRDReconstructor::RecoParam()->LUTOn()) {
847 // Calculate the position of the cluster by using the
848 // lookup table method
849 clusterPosCol = LUTposition(iplan,clusterSignal[0]
853 // Calculate the position of the cluster by using the
854 // center of gravity method
855 for (Int_t i = 0; i < kNsig; i++) {
858 padSignal[2] = TMath::Abs(digitsOut->GetDataUnchecked(row,col ,time)); // Central pad
859 padSignal[1] = TMath::Abs(digitsOut->GetDataUnchecked(row,col-1,time)); // Left pad
860 padSignal[3] = TMath::Abs(digitsOut->GetDataUnchecked(row,col+1,time)); // Right pad
863 (TMath::Abs(digitsOut->GetDataUnchecked(row,col-2,time)) < padSignal[1])) {
864 padSignal[0] = TMath::Abs(digitsOut->GetDataUnchecked(row,col-2,time));
866 if ((col < nColMax - 3) &&
867 (TMath::Abs(digitsOut->GetDataUnchecked(row,col+2,time)) < padSignal[3])){
868 padSignal[4] = TMath::Abs(digitsOut->GetDataUnchecked(row,col+2,time));
870 clusterPosCol = GetCOG(padSignal);
873 // Store the amplitudes of the pads in the cluster for later analysis
874 // and check whether one of these pads is masked in the database
875 Short_t signals[7] = { 0, 0, 0, 0, 0, 0, 0 };
876 for (Int_t jPad = col-3; jPad <= col+3; jPad++) {
878 (jPad >= nColMax-1)) {
881 signals[jPad-col+3] = TMath::Nint(TMath::Abs(digitsOut->GetDataUnchecked(row,jPad,time)));
884 // Transform the local cluster coordinates into calibrated
885 // space point positions defined in the local tracking system.
886 // Here the calibration for T0, Vdrift and ExB is applied as well.
887 Double_t clusterXYZ[6];
888 clusterXYZ[0] = clusterPosCol;
889 clusterXYZ[1] = clusterSignal[0];
890 clusterXYZ[2] = clusterSignal[1];
891 clusterXYZ[3] = clusterSignal[2];
900 if (fTransform->Transform(clusterXYZ, clusterRCT, ((UInt_t) time), out, 0)) {
902 // Add the cluster to the output array
903 // The track indices will be stored later
904 Float_t clusterPos[3];
905 clusterPos[0] = clusterXYZ[0];
906 clusterPos[1] = clusterXYZ[1];
907 clusterPos[2] = clusterXYZ[2];
908 Float_t clusterSig[2];
909 clusterSig[0] = clusterXYZ[4];
910 clusterSig[1] = clusterXYZ[5];
911 Double_t clusterCharge = clusterXYZ[3];
912 Char_t clusterTimeBin = ((Char_t) clusterRCT[2]);
913 AliTRDcluster *cluster = new AliTRDcluster(idet
918 ,((Char_t) nPadCount)
926 cluster->SetInChamber(!out);
927 UChar_t maskPosition = padStatus.GetDataUnchecked(row, col, time);
929 cluster->SetPadMaskedPosition(maskPosition);
931 if(maskPosition & AliTRDcluster::kMaskedLeft) cluster->SetPadMaskedStatus(status[0]);
932 else if(maskPosition & AliTRDcluster::kMaskedCenter) cluster->SetPadMaskedStatus(status[1]);
933 else cluster->SetPadMaskedStatus(status[2]);
936 // Temporarily store the row, column and time bin of the center pad
937 // Used to later on assign the track indices
938 cluster->SetLabel( row,0);
939 cluster->SetLabel( col,1);
940 cluster->SetLabel(time,2);
942 RecPoints()->Add(cluster);
944 // Store the index of the first cluster in the current ROC
945 if (firstClusterROC < 0) {
946 firstClusterROC = RecPoints()->GetEntriesFast() - 1;
949 // Count the number of cluster in the current ROC
952 } // if: Transform ok ?
953 } // if: Maximum found ?
958 if (fAddLabels) AddLabels(idet, firstClusterROC, nClusterROC);
960 // Write the cluster and reset the array
968 //_____________________________________________________________________________
969 Bool_t AliTRDclusterizer::AddLabels(Int_t idet, Int_t firstClusterROC, Int_t nClusterROC)
972 // Add the track indices to the found clusters
975 const Int_t kNclus = 3;
976 const Int_t kNdict = AliTRDdigitsManager::kNDict;
977 const Int_t kNtrack = kNdict * kNclus;
979 Int_t iClusterROC = 0;
986 // Temporary array to collect the track indices
987 Int_t *idxTracks = new Int_t[kNtrack*nClusterROC];
989 // Loop through the dictionary arrays one-by-one
990 // to keep memory consumption low
991 AliTRDdataArrayI *tracksIn = 0;
992 for (Int_t iDict = 0; iDict < kNdict; iDict++) {
994 // tracksIn should be expanded beforehand!
995 tracksIn = (AliTRDdataArrayI *) fDigitsManager->GetDictionary(idet,iDict);
997 // Loop though the clusters found in this ROC
998 for (iClusterROC = 0; iClusterROC < nClusterROC; iClusterROC++) {
1000 AliTRDcluster *cluster = (AliTRDcluster *)
1001 RecPoints()->UncheckedAt(firstClusterROC+iClusterROC);
1002 row = cluster->GetLabel(0);
1003 col = cluster->GetLabel(1);
1004 time = cluster->GetLabel(2);
1006 for (iPad = 0; iPad < kNclus; iPad++) {
1007 Int_t iPadCol = col - 1 + iPad;
1008 Int_t index = tracksIn->GetDataUnchecked(row,iPadCol,time) - 1;
1009 idxTracks[3*iPad+iDict + iClusterROC*kNtrack] = index;
1016 // Copy the track indices into the cluster
1017 // Loop though the clusters found in this ROC
1018 for (iClusterROC = 0; iClusterROC < nClusterROC; iClusterROC++) {
1020 AliTRDcluster *cluster = (AliTRDcluster *)
1021 RecPoints()->UncheckedAt(firstClusterROC+iClusterROC);
1022 cluster->SetLabel(-9999,0);
1023 cluster->SetLabel(-9999,1);
1024 cluster->SetLabel(-9999,2);
1026 cluster->AddTrackIndex(&idxTracks[iClusterROC*kNtrack]);
1030 delete [] idxTracks;
1036 //_____________________________________________________________________________
1037 Double_t AliTRDclusterizer::GetCOG(Double_t signal[5]) const
1041 // Used for clusters with more than 3 pads - where LUT not applicable
1044 Double_t sum = signal[0]
1050 Double_t res = (0.0 * (-signal[0] + signal[4])
1051 + (-signal[1] + signal[3])) / sum;
1057 //_____________________________________________________________________________
1058 Double_t AliTRDclusterizer::Unfold(Double_t eps, Int_t plane, Double_t *padSignal)
1061 // Method to unfold neighbouring maxima.
1062 // The charge ratio on the overlapping pad is calculated
1063 // until there is no more change within the range given by eps.
1064 // The resulting ratio is then returned to the calling method.
1067 AliTRDcalibDB *calibration = AliTRDcalibDB::Instance();
1069 AliError("No AliTRDcalibDB instance available\n");
1074 Int_t itStep = 0; // Count iteration steps
1076 Double_t ratio = 0.5; // Start value for ratio
1077 Double_t prevRatio = 0.0; // Store previous ratio
1079 Double_t newLeftSignal[3] = { 0.0, 0.0, 0.0 }; // Array to store left cluster signal
1080 Double_t newRightSignal[3] = { 0.0, 0.0, 0.0 }; // Array to store right cluster signal
1081 Double_t newSignal[3] = { 0.0, 0.0, 0.0 };
1083 // Start the iteration
1084 while ((TMath::Abs(prevRatio - ratio) > eps) && (itStep < 10)) {
1089 // Cluster position according to charge ratio
1090 Double_t maxLeft = (ratio*padSignal[2] - padSignal[0])
1091 / (padSignal[0] + padSignal[1] + ratio*padSignal[2]);
1092 Double_t maxRight = (padSignal[4] - (1-ratio)*padSignal[2])
1093 / ((1.0 - ratio)*padSignal[2] + padSignal[3] + padSignal[4]);
1095 // Set cluster charge ratio
1096 irc = calibration->PadResponse(1.0,maxLeft ,plane,newSignal);
1097 Double_t ampLeft = padSignal[1] / newSignal[1];
1098 irc = calibration->PadResponse(1.0,maxRight,plane,newSignal);
1099 Double_t ampRight = padSignal[3] / newSignal[1];
1101 // Apply pad response to parameters
1102 irc = calibration->PadResponse(ampLeft ,maxLeft ,plane,newLeftSignal );
1103 irc = calibration->PadResponse(ampRight,maxRight,plane,newRightSignal);
1105 // Calculate new overlapping ratio
1106 ratio = TMath::Min((Double_t) 1.0
1107 ,newLeftSignal[2] / (newLeftSignal[2] + newRightSignal[0]));
1115 //_____________________________________________________________________________
1116 void AliTRDclusterizer::TailCancelation(AliTRDdataArrayDigits *digitsIn
1117 , AliTRDdataArrayF *digitsOut
1118 , AliTRDSignalIndex *indexesIn
1119 , AliTRDSignalIndex *indexesOut
1121 , Float_t adcThreshold
1122 , AliTRDCalROC *calGainFactorROC
1123 , Float_t calGainFactorDetValue)
1126 // Applies the tail cancelation and gain factors:
1127 // Transform digitsIn to digitsOut
1134 Double_t *inADC = new Double_t[nTimeTotal]; // ADC data before tail cancellation
1135 Double_t *outADC = new Double_t[nTimeTotal]; // ADC data after tail cancellation
1136 indexesIn->ResetCounters();
1137 while (indexesIn->NextRCIndex(iRow, iCol))
1139 Float_t calGainFactorROCValue = calGainFactorROC->GetValue(iCol,iRow);
1140 Double_t gain = calGainFactorDetValue
1141 * calGainFactorROCValue;
1143 Bool_t corrupted = kFALSE;
1144 for (iTime = 0; iTime < nTimeTotal; iTime++)
1146 // Apply gain gain factor
1147 inADC[iTime] = digitsIn->GetDataUnchecked(iRow,iCol,iTime);
1148 if(digitsIn->GetPadStatus(iRow, iCol, iTime)) corrupted = kTRUE;
1149 inADC[iTime] /= gain;
1150 outADC[iTime] = inADC[iTime];
1154 // Apply the tail cancelation via the digital filter
1155 // (only for non-coorupted pads)
1156 if (AliTRDReconstructor::RecoParam()->TCOn())
1158 DeConvExp(inADC,outADC,nTimeTotal,AliTRDReconstructor::RecoParam()->GetTCnexp());
1162 indexesIn->ResetTbinCounter();
1163 while (indexesIn->NextTbinIndex(iTime))
1165 // Store the amplitude of the digit if above threshold
1166 if (outADC[iTime] > adcThreshold)
1168 digitsOut->SetDataUnchecked(iRow,iCol,iTime,outADC[iTime]);
1169 indexesOut->AddIndexTBin(iRow,iCol,iTime);
1173 } // while irow icol
1182 //_____________________________________________________________________________
1183 void AliTRDclusterizer::DeConvExp(Double_t *source, Double_t *target
1184 , Int_t n, Int_t nexp)
1187 // Tail cancellation by deconvolution for PASA v4 TRF
1191 Double_t coefficients[2];
1193 // Initialization (coefficient = alpha, rates = lambda)
1199 if (nexp == 1) { // 1 Exponentials
1205 if (nexp == 2) { // 2 Exponentials
1212 coefficients[0] = c1;
1213 coefficients[1] = c2;
1217 rates[0] = TMath::Exp(-dt/(r1));
1218 rates[1] = TMath::Exp(-dt/(r2));
1223 Double_t reminder[2];
1224 Double_t correction = 0.0;
1225 Double_t result = 0.0;
1227 // Attention: computation order is important
1228 for (k = 0; k < nexp; k++) {
1232 for (i = 0; i < n; i++) {
1234 result = (source[i] - correction); // No rescaling
1237 for (k = 0; k < nexp; k++) {
1238 reminder[k] = rates[k] * (reminder[k] + coefficients[k] * result);
1242 for (k = 0; k < nexp; k++) {
1243 correction += reminder[k];
1250 //_____________________________________________________________________________
1251 void AliTRDclusterizer::ResetRecPoints()
1254 // Resets the list of rec points
1258 fRecPoints->Delete();
1263 //_____________________________________________________________________________
1264 TObjArray *AliTRDclusterizer::RecPoints()
1267 // Returns the list of rec points
1271 fRecPoints = new TObjArray(400);
1278 //_____________________________________________________________________________
1279 void AliTRDclusterizer::FillLUT()
1285 const Int_t kNlut = 128;
1287 fLUTbin = AliTRDgeometry::kNplan * kNlut;
1289 // The lookup table from Bogdan
1290 Float_t lut[AliTRDgeometry::kNplan][kNlut] = {
1292 0.0070, 0.0150, 0.0224, 0.0298, 0.0374, 0.0454, 0.0533, 0.0611,
1293 0.0684, 0.0755, 0.0827, 0.0900, 0.0975, 0.1049, 0.1120, 0.1187,
1294 0.1253, 0.1318, 0.1385, 0.1453, 0.1519, 0.1584, 0.1646, 0.1704,
1295 0.1762, 0.1821, 0.1879, 0.1938, 0.1996, 0.2053, 0.2108, 0.2160,
1296 0.2210, 0.2260, 0.2310, 0.2361, 0.2411, 0.2461, 0.2509, 0.2557,
1297 0.2602, 0.2646, 0.2689, 0.2732, 0.2774, 0.2816, 0.2859, 0.2901,
1298 0.2942, 0.2983, 0.3022, 0.3061, 0.3099, 0.3136, 0.3172, 0.3207,
1299 0.3242, 0.3278, 0.3312, 0.3347, 0.3382, 0.3416, 0.3450, 0.3483,
1300 0.3515, 0.3547, 0.3579, 0.3609, 0.3639, 0.3669, 0.3698, 0.3727,
1301 0.3756, 0.3785, 0.3813, 0.3842, 0.3870, 0.3898, 0.3926, 0.3952,
1302 0.3979, 0.4005, 0.4032, 0.4057, 0.4082, 0.4108, 0.4132, 0.4157,
1303 0.4181, 0.4205, 0.4228, 0.4252, 0.4275, 0.4299, 0.4322, 0.4345,
1304 0.4367, 0.4390, 0.4412, 0.4434, 0.4456, 0.4478, 0.4499, 0.4520,
1305 0.4541, 0.4562, 0.4583, 0.4603, 0.4623, 0.4643, 0.4663, 0.4683,
1306 0.4702, 0.4722, 0.4741, 0.4758, 0.4774, 0.4790, 0.4805, 0.4824,
1307 0.4844, 0.4863, 0.4883, 0.4902, 0.4921, 0.4940, 0.4959, 0.4978
1310 0.0072, 0.0156, 0.0235, 0.0313, 0.0394, 0.0478, 0.0561, 0.0642,
1311 0.0718, 0.0792, 0.0868, 0.0947, 0.1025, 0.1101, 0.1172, 0.1241,
1312 0.1309, 0.1378, 0.1449, 0.1518, 0.1586, 0.1650, 0.1710, 0.1770,
1313 0.1830, 0.1891, 0.1952, 0.2011, 0.2070, 0.2125, 0.2177, 0.2229,
1314 0.2280, 0.2332, 0.2383, 0.2435, 0.2484, 0.2533, 0.2581, 0.2627,
1315 0.2670, 0.2714, 0.2757, 0.2799, 0.2842, 0.2884, 0.2927, 0.2968,
1316 0.3008, 0.3048, 0.3086, 0.3123, 0.3159, 0.3195, 0.3231, 0.3266,
1317 0.3301, 0.3335, 0.3370, 0.3404, 0.3438, 0.3471, 0.3504, 0.3536,
1318 0.3567, 0.3598, 0.3628, 0.3657, 0.3686, 0.3715, 0.3744, 0.3772,
1319 0.3800, 0.3828, 0.3856, 0.3884, 0.3911, 0.3938, 0.3965, 0.3991,
1320 0.4016, 0.4042, 0.4067, 0.4092, 0.4116, 0.4140, 0.4164, 0.4187,
1321 0.4211, 0.4234, 0.4257, 0.4280, 0.4302, 0.4325, 0.4347, 0.4369,
1322 0.4391, 0.4413, 0.4434, 0.4456, 0.4477, 0.4497, 0.4518, 0.4538,
1323 0.4558, 0.4578, 0.4598, 0.4618, 0.4637, 0.4656, 0.4675, 0.4694,
1324 0.4713, 0.4732, 0.4750, 0.4766, 0.4781, 0.4797, 0.4813, 0.4832,
1325 0.4851, 0.4870, 0.4888, 0.4906, 0.4925, 0.4942, 0.4960, 0.4978
1328 0.0075, 0.0163, 0.0246, 0.0328, 0.0415, 0.0504, 0.0592, 0.0674,
1329 0.0753, 0.0832, 0.0914, 0.0996, 0.1077, 0.1154, 0.1225, 0.1296,
1330 0.1369, 0.1442, 0.1515, 0.1585, 0.1652, 0.1714, 0.1776, 0.1839,
1331 0.1902, 0.1965, 0.2025, 0.2085, 0.2141, 0.2194, 0.2247, 0.2299,
1332 0.2352, 0.2405, 0.2457, 0.2507, 0.2557, 0.2604, 0.2649, 0.2693,
1333 0.2737, 0.2780, 0.2823, 0.2867, 0.2909, 0.2951, 0.2992, 0.3033,
1334 0.3072, 0.3110, 0.3146, 0.3182, 0.3218, 0.3253, 0.3288, 0.3323,
1335 0.3357, 0.3392, 0.3426, 0.3459, 0.3492, 0.3524, 0.3555, 0.3586,
1336 0.3616, 0.3645, 0.3674, 0.3703, 0.3731, 0.3759, 0.3787, 0.3815,
1337 0.3843, 0.3870, 0.3897, 0.3925, 0.3950, 0.3976, 0.4002, 0.4027,
1338 0.4052, 0.4076, 0.4101, 0.4124, 0.4148, 0.4171, 0.4194, 0.4217,
1339 0.4239, 0.4262, 0.4284, 0.4306, 0.4328, 0.4350, 0.4371, 0.4393,
1340 0.4414, 0.4435, 0.4455, 0.4476, 0.4496, 0.4516, 0.4536, 0.4555,
1341 0.4575, 0.4594, 0.4613, 0.4632, 0.4650, 0.4669, 0.4687, 0.4705,
1342 0.4723, 0.4741, 0.4758, 0.4773, 0.4789, 0.4804, 0.4821, 0.4839,
1343 0.4857, 0.4875, 0.4893, 0.4910, 0.4928, 0.4945, 0.4961, 0.4978
1346 0.0078, 0.0171, 0.0258, 0.0345, 0.0438, 0.0532, 0.0624, 0.0708,
1347 0.0791, 0.0875, 0.0962, 0.1048, 0.1130, 0.1206, 0.1281, 0.1356,
1348 0.1432, 0.1508, 0.1582, 0.1651, 0.1716, 0.1780, 0.1845, 0.1910,
1349 0.1975, 0.2038, 0.2099, 0.2155, 0.2210, 0.2263, 0.2317, 0.2371,
1350 0.2425, 0.2477, 0.2528, 0.2578, 0.2626, 0.2671, 0.2715, 0.2759,
1351 0.2803, 0.2846, 0.2890, 0.2933, 0.2975, 0.3016, 0.3056, 0.3095,
1352 0.3132, 0.3168, 0.3204, 0.3239, 0.3274, 0.3309, 0.3344, 0.3378,
1353 0.3412, 0.3446, 0.3479, 0.3511, 0.3543, 0.3574, 0.3603, 0.3633,
1354 0.3662, 0.3690, 0.3718, 0.3747, 0.3774, 0.3802, 0.3829, 0.3857,
1355 0.3883, 0.3910, 0.3936, 0.3962, 0.3987, 0.4012, 0.4037, 0.4061,
1356 0.4085, 0.4109, 0.4132, 0.4155, 0.4177, 0.4200, 0.4222, 0.4244,
1357 0.4266, 0.4288, 0.4309, 0.4331, 0.4352, 0.4373, 0.4394, 0.4414,
1358 0.4435, 0.4455, 0.4475, 0.4494, 0.4514, 0.4533, 0.4552, 0.4571,
1359 0.4590, 0.4608, 0.4626, 0.4645, 0.4662, 0.4680, 0.4698, 0.4715,
1360 0.4733, 0.4750, 0.4766, 0.4781, 0.4796, 0.4812, 0.4829, 0.4846,
1361 0.4863, 0.4880, 0.4897, 0.4914, 0.4930, 0.4946, 0.4963, 0.4979
1364 0.0081, 0.0178, 0.0270, 0.0364, 0.0463, 0.0562, 0.0656, 0.0744,
1365 0.0831, 0.0921, 0.1013, 0.1102, 0.1183, 0.1261, 0.1339, 0.1419,
1366 0.1499, 0.1576, 0.1648, 0.1715, 0.1782, 0.1849, 0.1917, 0.1984,
1367 0.2048, 0.2110, 0.2167, 0.2223, 0.2278, 0.2333, 0.2389, 0.2444,
1368 0.2497, 0.2548, 0.2598, 0.2645, 0.2691, 0.2735, 0.2780, 0.2824,
1369 0.2868, 0.2912, 0.2955, 0.2997, 0.3038, 0.3078, 0.3116, 0.3152,
1370 0.3188, 0.3224, 0.3259, 0.3294, 0.3329, 0.3364, 0.3398, 0.3432,
1371 0.3465, 0.3497, 0.3529, 0.3561, 0.3591, 0.3620, 0.3649, 0.3677,
1372 0.3705, 0.3733, 0.3761, 0.3788, 0.3816, 0.3843, 0.3869, 0.3896,
1373 0.3922, 0.3948, 0.3973, 0.3998, 0.4022, 0.4047, 0.4070, 0.4094,
1374 0.4117, 0.4139, 0.4162, 0.4184, 0.4206, 0.4227, 0.4249, 0.4270,
1375 0.4291, 0.4313, 0.4334, 0.4354, 0.4375, 0.4395, 0.4415, 0.4435,
1376 0.4455, 0.4474, 0.4493, 0.4512, 0.4531, 0.4550, 0.4568, 0.4586,
1377 0.4604, 0.4622, 0.4639, 0.4657, 0.4674, 0.4691, 0.4708, 0.4725,
1378 0.4742, 0.4758, 0.4773, 0.4788, 0.4803, 0.4819, 0.4836, 0.4852,
1379 0.4869, 0.4885, 0.4901, 0.4917, 0.4933, 0.4948, 0.4964, 0.4979
1382 0.0085, 0.0189, 0.0288, 0.0389, 0.0497, 0.0603, 0.0699, 0.0792,
1383 0.0887, 0.0985, 0.1082, 0.1170, 0.1253, 0.1336, 0.1421, 0.1505,
1384 0.1587, 0.1662, 0.1733, 0.1803, 0.1874, 0.1945, 0.2014, 0.2081,
1385 0.2143, 0.2201, 0.2259, 0.2316, 0.2374, 0.2431, 0.2487, 0.2541,
1386 0.2593, 0.2642, 0.2689, 0.2735, 0.2781, 0.2826, 0.2872, 0.2917,
1387 0.2961, 0.3003, 0.3045, 0.3086, 0.3125, 0.3162, 0.3198, 0.3235,
1388 0.3270, 0.3306, 0.3342, 0.3377, 0.3411, 0.3446, 0.3479, 0.3511,
1389 0.3543, 0.3575, 0.3605, 0.3634, 0.3663, 0.3691, 0.3720, 0.3748,
1390 0.3775, 0.3803, 0.3830, 0.3857, 0.3884, 0.3911, 0.3937, 0.3962,
1391 0.3987, 0.4012, 0.4036, 0.4060, 0.4084, 0.4107, 0.4129, 0.4152,
1392 0.4174, 0.4196, 0.4218, 0.4239, 0.4261, 0.4282, 0.4303, 0.4324,
1393 0.4344, 0.4365, 0.4385, 0.4405, 0.4425, 0.4445, 0.4464, 0.4483,
1394 0.4502, 0.4521, 0.4539, 0.4558, 0.4576, 0.4593, 0.4611, 0.4629,
1395 0.4646, 0.4663, 0.4680, 0.4697, 0.4714, 0.4730, 0.4747, 0.4759,
1396 0.4769, 0.4780, 0.4790, 0.4800, 0.4811, 0.4827, 0.4843, 0.4859,
1397 0.4874, 0.4889, 0.4905, 0.4920, 0.4935, 0.4950, 0.4965, 0.4979
1404 fLUT = new Double_t[fLUTbin];
1406 for (Int_t iplan = 0; iplan < AliTRDgeometry::kNplan; iplan++) {
1407 for (Int_t ilut = 0; ilut < kNlut; ilut++ ) {
1408 fLUT[iplan*kNlut+ilut] = lut[iplan][ilut];
1414 //_____________________________________________________________________________
1415 Double_t AliTRDclusterizer::LUTposition(Int_t iplane, Double_t ampL
1416 , Double_t ampC, Double_t ampR) const
1419 // Calculates the cluster position using the lookup table.
1420 // Method provided by Bogdan Vulpescu.
1423 const Int_t kNlut = 128;
1434 Double_t xMin[AliTRDgeometry::kNplan] = { 0.006492, 0.006377, 0.006258
1435 , 0.006144, 0.006030, 0.005980 };
1436 Double_t xMax[AliTRDgeometry::kNplan] = { 0.960351, 0.965870, 0.970445
1437 , 0.974352, 0.977667, 0.996101 };
1440 x = (ampL - ampR) / ampC;
1443 else if (ampL < ampR) {
1444 x = (ampR - ampL) / ampC;
1450 xmin = xMin[iplane] + 0.000005;
1451 xmax = xMax[iplane] - 0.000005;
1452 xwid = (xmax - xmin) / 127.0;
1457 else if (x > xmax) {
1458 pos = side * 0.5000;
1461 ix = (Int_t) ((x - xmin) / xwid);
1462 pos = side * fLUT[iplane*kNlut+ix];