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 "AliTRDdigitsManager.h"
45 #include "AliTRDrawData.h"
46 #include "AliTRDcalibDB.h"
47 #include "AliTRDrecoParam.h"
48 #include "AliTRDCommonParam.h"
49 #include "AliTRDtransform.h"
50 #include "AliTRDSignalIndex.h"
51 #include "AliTRDrawStreamBase.h"
52 #include "AliTRDfeeParam.h"
54 #include "Cal/AliTRDCalROC.h"
55 #include "Cal/AliTRDCalDet.h"
56 #include "Cal/AliTRDCalSingleChamberStatus.h"
58 ClassImp(AliTRDclusterizer)
60 //_____________________________________________________________________________
61 AliTRDclusterizer::AliTRDclusterizer()
71 ,fTransform(new AliTRDtransform(0))
76 // AliTRDclusterizer default constructor
79 fRawVersion = AliTRDfeeParam::Instance()->GetRAWversion();
83 //_____________________________________________________________________________
84 AliTRDclusterizer::AliTRDclusterizer(const Text_t *name, const Text_t *title)
89 ,fDigitsManager(new AliTRDdigitsManager())
94 ,fTransform(new AliTRDtransform(0))
99 // AliTRDclusterizer constructor
102 fDigitsManager->CreateArrays();
104 fRawVersion = AliTRDfeeParam::Instance()->GetRAWversion();
110 //_____________________________________________________________________________
111 AliTRDclusterizer::AliTRDclusterizer(const AliTRDclusterizer &c)
116 ,fDigitsManager(NULL)
120 ,fIndexesMaxima(NULL)
126 // AliTRDclusterizer copy constructor
133 //_____________________________________________________________________________
134 AliTRDclusterizer::~AliTRDclusterizer()
137 // AliTRDclusterizer destructor
142 fRecPoints->Delete();
148 delete fDigitsManager;
149 fDigitsManager = NULL;
160 delete fIndexesMaxima;
161 fIndexesMaxima = NULL;
178 //_____________________________________________________________________________
179 AliTRDclusterizer &AliTRDclusterizer::operator=(const AliTRDclusterizer &c)
182 // Assignment operator
187 ((AliTRDclusterizer &) c).Copy(*this);
193 //_____________________________________________________________________________
194 void AliTRDclusterizer::Copy(TObject &c) const
200 ((AliTRDclusterizer &) c).fClusterTree = NULL;
201 ((AliTRDclusterizer &) c).fRecPoints = NULL;
202 ((AliTRDclusterizer &) c).fDigitsManager = NULL;
203 ((AliTRDclusterizer &) c).fAddLabels = fAddLabels;
204 ((AliTRDclusterizer &) c).fRawVersion = fRawVersion;
205 ((AliTRDclusterizer &) c).fIndexesOut = NULL;
206 ((AliTRDclusterizer &) c).fIndexesMaxima = NULL;
207 ((AliTRDclusterizer &) c).fTransform = NULL;
208 ((AliTRDclusterizer &) c).fLUTbin = 0;
209 ((AliTRDclusterizer &) c).fLUT = NULL;
213 //_____________________________________________________________________________
214 Bool_t AliTRDclusterizer::Open(const Char_t *name, Int_t nEvent)
217 // Opens the AliROOT file. Output and input are in the same file
220 TString evfoldname = AliConfig::GetDefaultEventFolderName();
221 fRunLoader = AliRunLoader::GetRunLoader(evfoldname);
224 fRunLoader = AliRunLoader::Open(name);
228 AliError(Form("Can not open session for file %s.",name));
239 //_____________________________________________________________________________
240 Bool_t AliTRDclusterizer::OpenOutput()
243 // Open the output file
246 TObjArray *ioArray = 0;
248 AliLoader* loader = fRunLoader->GetLoader("TRDLoader");
249 loader->MakeTree("R");
251 fClusterTree = loader->TreeR();
252 fClusterTree->Branch("TRDcluster","TObjArray",&ioArray,32000,0);
258 //_____________________________________________________________________________
259 Bool_t AliTRDclusterizer::OpenOutput(TTree *clusterTree)
262 // Connect the output tree
265 TObjArray *ioArray = 0;
267 fClusterTree = clusterTree;
268 fClusterTree->Branch("TRDcluster","TObjArray",&ioArray,32000,0);
274 //_____________________________________________________________________________
275 Bool_t AliTRDclusterizer::OpenInput(Int_t nEvent)
278 // Opens a ROOT-file with TRD-hits and reads in the digits-tree
281 // Import the Trees for the event nEvent in the file
282 fRunLoader->GetEvent(nEvent);
288 //_____________________________________________________________________________
289 Bool_t AliTRDclusterizer::WriteClusters(Int_t det)
292 // Fills TRDcluster branch in the tree with the clusters
293 // found in detector = det. For det=-1 writes the tree.
297 (det >= AliTRDgeometry::Ndet())) {
298 AliError(Form("Unexpected detector index %d.\n",det));
302 TBranch *branch = fClusterTree->GetBranch("TRDcluster");
304 TObjArray *ioArray = 0;
305 branch = fClusterTree->Branch("TRDcluster","TObjArray",&ioArray,32000,0);
309 (det < AliTRDgeometry::Ndet())) {
311 Int_t nRecPoints = RecPoints()->GetEntriesFast();
312 TObjArray *detRecPoints = new TObjArray(400);
314 for (Int_t i = 0; i < nRecPoints; i++) {
315 AliTRDcluster *c = (AliTRDcluster *) RecPoints()->UncheckedAt(i);
316 if (det == c->GetDetector()) {
317 detRecPoints->AddLast(c);
320 AliError(Form("Attempt to write a cluster with unexpected detector index: got=%d expected=%d\n"
326 branch->SetAddress(&detRecPoints);
327 fClusterTree->Fill();
337 AliInfo(Form("Writing the cluster tree %s for event %d."
338 ,fClusterTree->GetName(),fRunLoader->GetEventNumber()));
342 branch->SetAddress(&fRecPoints);
344 AliLoader *loader = fRunLoader->GetLoader("TRDLoader");
345 loader->WriteRecPoints("OVERWRITE");
350 AliError("Cluster tree does not exist. Cannot write clusters.\n");
359 AliError(Form("Unexpected detector index %d.\n",det));
365 //_____________________________________________________________________________
366 void AliTRDclusterizer::ResetHelperIndexes(AliTRDSignalIndex *indexesIn)
369 // Reset the helper indexes
374 // carefull here - we assume that only row number may change - most probable
375 if (indexesIn->GetNrow() <= fIndexesOut->GetNrow())
376 fIndexesOut->ResetContent();
378 fIndexesOut->ResetContentConditional(indexesIn->GetNrow()
379 , indexesIn->GetNcol()
380 , indexesIn->GetNtime());
384 fIndexesOut = new AliTRDSignalIndex(indexesIn->GetNrow()
385 , indexesIn->GetNcol()
386 , indexesIn->GetNtime());
391 // carefull here - we assume that only row number may change - most probable
392 if (indexesIn->GetNrow() <= fIndexesMaxima->GetNrow())
394 fIndexesMaxima->ResetContent();
398 fIndexesMaxima->ResetContentConditional(indexesIn->GetNrow()
399 , indexesIn->GetNcol()
400 , indexesIn->GetNtime());
405 fIndexesMaxima = new AliTRDSignalIndex(indexesIn->GetNrow()
406 , indexesIn->GetNcol()
407 , indexesIn->GetNtime());
412 //_____________________________________________________________________________
413 Bool_t AliTRDclusterizer::ReadDigits()
416 // Reads the digits arrays from the input aliroot file
420 AliError("No run loader available");
424 AliLoader* loader = fRunLoader->GetLoader("TRDLoader");
425 if (!loader->TreeD()) {
426 loader->LoadDigits();
429 // Read in the digit arrays
430 return (fDigitsManager->ReadDigits(loader->TreeD()));
434 //_____________________________________________________________________________
435 Bool_t AliTRDclusterizer::ReadDigits(TTree *digitsTree)
438 // Reads the digits arrays from the input tree
441 // Read in the digit arrays
442 return (fDigitsManager->ReadDigits(digitsTree));
446 //_____________________________________________________________________________
447 Bool_t AliTRDclusterizer::ReadDigits(AliRawReader *rawReader)
450 // Reads the digits arrays from the ddl file
454 fDigitsManager = raw.Raw2Digits(rawReader);
460 //_____________________________________________________________________________
461 Bool_t AliTRDclusterizer::MakeClusters()
464 // Creates clusters from digits
467 // Propagate info from the digits manager
468 if (fAddLabels == kTRUE)
470 fAddLabels = fDigitsManager->UsesDictionaries();
473 Bool_t fReturn = kTRUE;
474 for (Int_t i = 0; i < AliTRDgeometry::kNdet; i++)
477 AliTRDdataArrayS *digitsIn = (AliTRDdataArrayS *) fDigitsManager->GetDigits(i);
478 // This is to take care of switched off super modules
479 if (!digitsIn->HasData())
484 AliTRDSignalIndex* indexes = fDigitsManager->GetIndexes(i);
485 if (indexes->IsAllocated() == kFALSE)
487 fDigitsManager->BuildIndexes(i);
491 if (indexes->HasEntry())
495 for (Int_t iDict = 0; iDict < AliTRDdigitsManager::kNDict; iDict++)
497 AliTRDdataArrayI *tracksIn = 0;
498 tracksIn = (AliTRDdataArrayI *) fDigitsManager->GetDictionary(i,iDict);
502 fR = MakeClusters(i);
503 fReturn = fR && fReturn;
512 // No compress just remove
513 fDigitsManager->RemoveDigits(i);
514 fDigitsManager->RemoveDictionaries(i);
515 fDigitsManager->ClearIndexes(i);
523 //_____________________________________________________________________________
524 Bool_t AliTRDclusterizer::Raw2Clusters(AliRawReader *rawReader)
527 // Creates clusters from raw data
530 return Raw2ClustersChamber(rawReader);
534 //_____________________________________________________________________________
535 Bool_t AliTRDclusterizer::Raw2ClustersChamber(AliRawReader *rawReader)
538 // Creates clusters from raw data
541 // Create the digits manager
544 fDigitsManager = new AliTRDdigitsManager();
545 fDigitsManager->CreateArrays();
548 fDigitsManager->SetUseDictionaries(fAddLabels);
550 AliTRDrawStreamBase *pinput = AliTRDrawStreamBase::GetRawStream(rawReader);
551 AliTRDrawStreamBase &input = *pinput;
553 AliInfo(Form("Stream version: %s", input.IsA()->GetName()));
556 while ((det = input.NextChamber(fDigitsManager)) >= 0)
558 Bool_t iclusterBranch = kFALSE;
559 if (fDigitsManager->GetIndexes(det)->HasEntry())
561 iclusterBranch = MakeClusters(det);
563 if (iclusterBranch == kFALSE)
568 fDigitsManager->RemoveDigits(det);
569 fDigitsManager->RemoveDictionaries(det);
570 fDigitsManager->ClearIndexes(det);
573 delete fDigitsManager;
574 fDigitsManager = NULL;
582 //_____________________________________________________________________________
583 UChar_t AliTRDclusterizer::GetStatus(Short_t &signal)
586 // check if pad is masked
587 if(signal>0 && TESTBIT(signal, 10)){
589 for(int ibit=0; ibit<4; ibit++){
590 if(TESTBIT(signal, 11+ibit)){
591 SETBIT(status, ibit);
592 CLRBIT(signal, 11+ibit);
599 //_____________________________________________________________________________
600 Bool_t AliTRDclusterizer::MakeClusters(Int_t det)
603 // Generates the cluster.
607 // digits should be expanded beforehand!
608 // digitsIn->Expand();
609 AliTRDdataArrayS *digitsIn = (AliTRDdataArrayS *) fDigitsManager->GetDigits(det);
611 // This is to take care of switched off super modules
612 if (!digitsIn->HasData())
617 AliTRDSignalIndex *indexesIn = fDigitsManager->GetIndexes(det);
618 if (indexesIn->IsAllocated() == kFALSE)
620 AliError("Indexes do not exist!");
624 AliTRDcalibDB *calibration = AliTRDcalibDB::Instance();
627 AliFatal("No AliTRDcalibDB instance available\n");
632 // There is no ADC threshold anymore, and simParam should not be used in clusterizer. KO
633 Float_t adcThreshold = 0;
635 if (!AliTRDReconstructor::RecoParam())
637 AliError("RecoParam does not exist\n");
641 // Threshold value for the maximum
642 Float_t maxThresh = AliTRDReconstructor::RecoParam()->GetClusMaxThresh();
643 // Threshold value for the digit signal
644 Float_t sigThresh = AliTRDReconstructor::RecoParam()->GetClusSigThresh();
646 // Iteration limit for unfolding procedure
647 const Float_t kEpsilon = 0.01;
648 const Int_t kNclus = 3;
649 const Int_t kNsig = 5;
652 Double_t ratioLeft = 1.0;
653 Double_t ratioRight = 1.0;
655 Double_t padSignal[kNsig];
656 Double_t clusterSignal[kNclus];
658 Int_t icham = indexesIn->GetChamber();
659 Int_t iplan = indexesIn->GetPlane();
660 Int_t isect = indexesIn->GetSM();
662 // Start clustering in the chamber
664 Int_t idet = AliTRDgeometry::GetDetector(iplan,icham,isect);
667 AliError("Strange Detector number Missmatch!");
671 // TRD space point transformation
672 fTransform->SetDetector(det);
674 Int_t ilayer = AliGeomManager::kTRD1 + iplan;
675 Int_t imodule = icham + AliTRDgeometry::Ncham() * isect;
676 UShort_t volid = AliGeomManager::LayerToVolUID(ilayer,imodule);
678 Int_t nColMax = digitsIn->GetNcol();
679 Int_t nRowMax = digitsIn->GetNrow();
680 Int_t nTimeTotal = digitsIn->GetNtime();
682 // Detector wise calibration object for the gain factors
683 const AliTRDCalDet *calGainFactorDet = calibration->GetGainFactorDet();
684 // Calibration object with pad wise values for the gain factors
685 AliTRDCalROC *calGainFactorROC = calibration->GetGainFactorROC(idet);
686 // Calibration value for chamber wise gain factor
687 Float_t calGainFactorDetValue = calGainFactorDet->GetValue(idet);
691 AliTRDdataArrayF *digitsOut = new AliTRDdataArrayF(nRowMax, nColMax, nTimeTotal);
692 AliTRDdataArrayS padStatus(nRowMax, nColMax, nTimeTotal);
694 ResetHelperIndexes(indexesIn);
696 // Apply the gain and the tail cancelation via digital filter
697 TailCancelation(digitsIn
704 ,calGainFactorDetValue);
711 UChar_t status[3], ipos;
713 fIndexesOut->ResetCounters();
714 while (fIndexesOut->NextRCTbinIndex(row, col, time)){
715 Float_t signalM = TMath::Abs(digitsOut->GetDataUnchecked(row,col,time));
716 signal = digitsIn->GetDataUnchecked(row,col,time);
717 status[1] = GetStatus(signal);
718 ipos = status[1] ? 2 : 0;
720 // Look for the maximum
721 if (signalM >= maxThresh) {
722 if (col + 1 >= nColMax || col-1 < 0) continue;
724 Float_t signalL = TMath::Abs(digitsOut->GetDataUnchecked(row,col+1,time));
725 signal = digitsIn->GetDataUnchecked(row,col+1,time);
726 status[0] = GetStatus(signal);
727 ipos += status[0] ? 1 : 0;
729 Float_t signalR = TMath::Abs(digitsOut->GetDataUnchecked(row,col-1,time));
730 signal = digitsIn->GetDataUnchecked(row,col-1,time);
731 status[2] = GetStatus(signal);
732 ipos += status[0] ? 4 : 0;
734 // reject candidates with more than 1 problematic pad
735 if(ipos == 3 || ipos > 4) continue;
737 if(!status[1]){ // good central pad
738 if(!ipos){ // all pads are OK
739 if ((signalL <= signalM) && (signalR < signalM)) {
740 if ((signalL >= sigThresh) || (signalR >= sigThresh)) {
741 // Maximum found, mark the position by a negative signal
742 digitsOut->SetDataUnchecked(row,col,time,-signalM);
743 fIndexesMaxima->AddIndexTBin(row,col,time);
744 padStatus.SetDataUnchecked(row, col, time, ipos);
747 } else { // one of the neighbouring pads are bad
748 if(status[0] && signalR < signalM && signalR >= sigThresh){
749 digitsOut->SetDataUnchecked(row,col,time,-signalM);
750 digitsOut->SetDataUnchecked(row, col, time+1, 0.);
751 fIndexesMaxima->AddIndexTBin(row,col,time);
752 padStatus.SetDataUnchecked(row, col, time, ipos);
753 } else if(status[2] && signalL <= signalM && signalL >= sigThresh){
754 digitsOut->SetDataUnchecked(row,col,time,-signalM);
755 digitsOut->SetDataUnchecked(row, col, time-1, 0.);
756 fIndexesMaxima->AddIndexTBin(row,col,time);
757 padStatus.SetDataUnchecked(row, col, time, ipos);
760 } else { // wrong maximum pad
761 if ((signalL >= sigThresh) || (signalR >= sigThresh)) {
762 // Maximum found, mark the position by a negative signal
763 digitsOut->SetDataUnchecked(row,col,time,-maxThresh);
764 fIndexesMaxima->AddIndexTBin(row,col,time);
765 padStatus.SetDataUnchecked(row, col, time, ipos);
771 // The index to the first cluster of a given ROC
772 Int_t firstClusterROC = -1;
773 // The number of cluster in a given ROC
774 Int_t nClusterROC = 0;
776 // Now check the maxima and calculate the cluster position
777 fIndexesMaxima->ResetCounters();
778 while (fIndexesMaxima->NextRCTbinIndex(row, col, time))
782 if (digitsOut->GetDataUnchecked(row,col,time) < 0.0)
785 for (iPad = 0; iPad < kNclus; iPad++)
787 Int_t iPadCol = col - 1 + iPad;
788 clusterSignal[iPad] = TMath::Abs(digitsOut->GetDataUnchecked(row,iPadCol,time));
791 // Count the number of pads in the cluster
796 while (TMath::Abs(digitsOut->GetDataUnchecked(row,col-ii ,time)) >= sigThresh)
800 if (col-ii < 0) break;
804 while (TMath::Abs(digitsOut->GetDataUnchecked(row,col+ii+1,time)) >= sigThresh)
808 if (col+ii+1 >= nColMax) break;
812 // Look for 5 pad cluster with minimum in the middle
813 Bool_t fivePadCluster = kFALSE;
814 if (col < (nColMax - 3))
816 if (digitsOut->GetDataUnchecked(row,col+2,time) < 0)
818 fivePadCluster = kTRUE;
820 if ((fivePadCluster) && (col < (nColMax - 5)))
822 if (digitsOut->GetDataUnchecked(row,col+4,time) >= sigThresh)
824 fivePadCluster = kFALSE;
827 if ((fivePadCluster) && (col > 1))
829 if (digitsOut->GetDataUnchecked(row,col-2,time) >= sigThresh)
831 fivePadCluster = kFALSE;
837 // Modify the signal of the overlapping pad for the left part
838 // of the cluster which remains from a previous unfolding
841 clusterSignal[0] *= ratioLeft;
845 // Unfold the 5 pad cluster
848 for (iPad = 0; iPad < kNsig; iPad++)
850 padSignal[iPad] = TMath::Abs(digitsOut->GetDataUnchecked(row
854 // Unfold the two maxima and set the signal on
855 // the overlapping pad to the ratio
856 ratioRight = Unfold(kEpsilon,iplan,padSignal);
857 ratioLeft = 1.0 - ratioRight;
858 clusterSignal[2] *= ratioRight;
862 // The position of the cluster in COL direction relative to the center pad (pad units)
863 Double_t clusterPosCol = 0.0;
864 if (AliTRDReconstructor::RecoParam()->LUTOn())
866 // Calculate the position of the cluster by using the
867 // lookup table method
868 clusterPosCol = LUTposition(iplan,clusterSignal[0]
874 // Calculate the position of the cluster by using the
875 // center of gravity method
876 for (Int_t i = 0; i < kNsig; i++)
880 padSignal[2] = TMath::Abs(digitsOut->GetDataUnchecked(row,col ,time)); // Central pad
881 padSignal[1] = TMath::Abs(digitsOut->GetDataUnchecked(row,col-1,time)); // Left pad
882 padSignal[3] = TMath::Abs(digitsOut->GetDataUnchecked(row,col+1,time)); // Right pad
884 (TMath::Abs(digitsOut->GetDataUnchecked(row,col-2,time)) < padSignal[1]))
886 padSignal[0] = TMath::Abs(digitsOut->GetDataUnchecked(row,col-2,time));
888 if ((col < nColMax - 3) &&
889 (TMath::Abs(digitsOut->GetDataUnchecked(row,col+2,time)) < padSignal[3]))
891 padSignal[4] = TMath::Abs(digitsOut->GetDataUnchecked(row,col+2,time));
893 clusterPosCol = GetCOG(padSignal);
896 // Store the amplitudes of the pads in the cluster for later analysis
897 // and check whether one of these pads is masked in the database
898 Short_t signals[7] = { 0, 0, 0, 0, 0, 0, 0 };
899 for (Int_t jPad = col-3; jPad <= col+3; jPad++)
906 signals[jPad-col+3] = TMath::Nint(TMath::Abs(digitsOut->GetDataUnchecked(row,jPad,time)));
909 // Transform the local cluster coordinates into calibrated
910 // space point positions defined in the local tracking system.
911 // Here the calibration for T0, Vdrift and ExB is applied as well.
912 Double_t clusterXYZ[6];
913 clusterXYZ[0] = clusterPosCol;
914 clusterXYZ[1] = clusterSignal[0];
915 clusterXYZ[2] = clusterSignal[1];
916 clusterXYZ[3] = clusterSignal[2];
925 if (fTransform->Transform(clusterXYZ, clusterRCT, ((UInt_t) time), out, 0)) {
927 // Add the cluster to the output array
928 // The track indices will be stored later
929 Float_t clusterPos[3];
930 clusterPos[0] = clusterXYZ[0];
931 clusterPos[1] = clusterXYZ[1];
932 clusterPos[2] = clusterXYZ[2];
933 Float_t clusterSig[2];
934 clusterSig[0] = clusterXYZ[4];
935 clusterSig[1] = clusterXYZ[5];
936 Double_t clusterCharge = clusterXYZ[3];
937 Char_t clusterTimeBin = ((Char_t) clusterRCT[2]);
938 AliTRDcluster *cluster = new AliTRDcluster(idet
943 ,((Char_t) nPadCount)
951 cluster->SetInChamber(!out);
952 if(padStatus.GetDataUnchecked(row, col, time)){
953 cluster->SetMaskedPad(kTRUE);
954 //cluster->SetPadMasked(center/side);
955 //cluster->SetPadMaskedStatus(status);
958 // Temporarily store the row, column and time bin of the center pad
959 // Used to later on assign the track indices
960 cluster->SetLabel( row,0);
961 cluster->SetLabel( col,1);
962 cluster->SetLabel(time,2);
964 RecPoints()->Add(cluster);
966 // Store the index of the first cluster in the current ROC
967 if (firstClusterROC < 0)
969 firstClusterROC = RecPoints()->GetEntriesFast() - 1;
972 // Count the number of cluster in the current ROC
975 } // if: Transform ok ?
977 } // if: Maximum found ?
985 AddLabels(idet, firstClusterROC, nClusterROC);
988 // Write the cluster and reset the array
996 //_____________________________________________________________________________
997 Bool_t AliTRDclusterizer::AddLabels(Int_t idet, Int_t firstClusterROC, Int_t nClusterROC)
1000 // Add the track indices to the found clusters
1003 const Int_t kNclus = 3;
1004 const Int_t kNdict = AliTRDdigitsManager::kNDict;
1005 const Int_t kNtrack = kNdict * kNclus;
1007 Int_t iClusterROC = 0;
1014 // Temporary array to collect the track indices
1015 Int_t *idxTracks = new Int_t[kNtrack*nClusterROC];
1017 // Loop through the dictionary arrays one-by-one
1018 // to keep memory consumption low
1019 AliTRDdataArrayI *tracksIn = 0;
1020 for (Int_t iDict = 0; iDict < kNdict; iDict++) {
1022 // tracksIn should be expanded beforehand!
1023 tracksIn = (AliTRDdataArrayI *) fDigitsManager->GetDictionary(idet,iDict);
1025 // Loop though the clusters found in this ROC
1026 for (iClusterROC = 0; iClusterROC < nClusterROC; iClusterROC++) {
1028 AliTRDcluster *cluster = (AliTRDcluster *)
1029 RecPoints()->UncheckedAt(firstClusterROC+iClusterROC);
1030 row = cluster->GetLabel(0);
1031 col = cluster->GetLabel(1);
1032 time = cluster->GetLabel(2);
1034 for (iPad = 0; iPad < kNclus; iPad++) {
1035 Int_t iPadCol = col - 1 + iPad;
1036 Int_t index = tracksIn->GetDataUnchecked(row,iPadCol,time) - 1;
1037 idxTracks[3*iPad+iDict + iClusterROC*kNtrack] = index;
1044 // Copy the track indices into the cluster
1045 // Loop though the clusters found in this ROC
1046 for (iClusterROC = 0; iClusterROC < nClusterROC; iClusterROC++) {
1048 AliTRDcluster *cluster = (AliTRDcluster *)
1049 RecPoints()->UncheckedAt(firstClusterROC+iClusterROC);
1050 cluster->SetLabel(-9999,0);
1051 cluster->SetLabel(-9999,1);
1052 cluster->SetLabel(-9999,2);
1054 cluster->AddTrackIndex(&idxTracks[iClusterROC*kNtrack]);
1058 delete [] idxTracks;
1064 //_____________________________________________________________________________
1065 Double_t AliTRDclusterizer::GetCOG(Double_t signal[5]) const
1069 // Used for clusters with more than 3 pads - where LUT not applicable
1072 Double_t sum = signal[0]
1078 Double_t res = (0.0 * (-signal[0] + signal[4])
1079 + (-signal[1] + signal[3])) / sum;
1085 //_____________________________________________________________________________
1086 Double_t AliTRDclusterizer::Unfold(Double_t eps, Int_t plane, Double_t *padSignal)
1089 // Method to unfold neighbouring maxima.
1090 // The charge ratio on the overlapping pad is calculated
1091 // until there is no more change within the range given by eps.
1092 // The resulting ratio is then returned to the calling method.
1095 AliTRDcalibDB *calibration = AliTRDcalibDB::Instance();
1097 AliError("No AliTRDcalibDB instance available\n");
1102 Int_t itStep = 0; // Count iteration steps
1104 Double_t ratio = 0.5; // Start value for ratio
1105 Double_t prevRatio = 0.0; // Store previous ratio
1107 Double_t newLeftSignal[3] = { 0.0, 0.0, 0.0 }; // Array to store left cluster signal
1108 Double_t newRightSignal[3] = { 0.0, 0.0, 0.0 }; // Array to store right cluster signal
1109 Double_t newSignal[3] = { 0.0, 0.0, 0.0 };
1111 // Start the iteration
1112 while ((TMath::Abs(prevRatio - ratio) > eps) && (itStep < 10)) {
1117 // Cluster position according to charge ratio
1118 Double_t maxLeft = (ratio*padSignal[2] - padSignal[0])
1119 / (padSignal[0] + padSignal[1] + ratio*padSignal[2]);
1120 Double_t maxRight = (padSignal[4] - (1-ratio)*padSignal[2])
1121 / ((1.0 - ratio)*padSignal[2] + padSignal[3] + padSignal[4]);
1123 // Set cluster charge ratio
1124 irc = calibration->PadResponse(1.0,maxLeft ,plane,newSignal);
1125 Double_t ampLeft = padSignal[1] / newSignal[1];
1126 irc = calibration->PadResponse(1.0,maxRight,plane,newSignal);
1127 Double_t ampRight = padSignal[3] / newSignal[1];
1129 // Apply pad response to parameters
1130 irc = calibration->PadResponse(ampLeft ,maxLeft ,plane,newLeftSignal );
1131 irc = calibration->PadResponse(ampRight,maxRight,plane,newRightSignal);
1133 // Calculate new overlapping ratio
1134 ratio = TMath::Min((Double_t) 1.0
1135 ,newLeftSignal[2] / (newLeftSignal[2] + newRightSignal[0]));
1143 //_____________________________________________________________________________
1144 void AliTRDclusterizer::TailCancelation(AliTRDdataArrayS *digitsIn
1145 , AliTRDdataArrayF *digitsOut
1146 , AliTRDSignalIndex *indexesIn
1147 , AliTRDSignalIndex *indexesOut
1149 , Float_t adcThreshold
1150 , AliTRDCalROC *calGainFactorROC
1151 , Float_t calGainFactorDetValue)
1154 // Applies the tail cancelation and gain factors:
1155 // Transform digitsIn to digitsOut
1162 Double_t *inADC = new Double_t[nTimeTotal]; // ADC data before tail cancellation
1163 Double_t *outADC = new Double_t[nTimeTotal]; // ADC data after tail cancellation
1164 indexesIn->ResetCounters();
1165 while (indexesIn->NextRCIndex(iRow, iCol))
1167 Float_t calGainFactorROCValue = calGainFactorROC->GetValue(iCol,iRow);
1168 Double_t gain = calGainFactorDetValue
1169 * calGainFactorROCValue;
1171 for (iTime = 0; iTime < nTimeTotal; iTime++)
1173 // Apply gain gain factor
1174 inADC[iTime] = digitsIn->GetDataUnchecked(iRow,iCol,iTime);
1175 inADC[iTime] /= gain;
1176 outADC[iTime] = inADC[iTime];
1179 // Apply the tail cancelation via the digital filter
1180 if (AliTRDReconstructor::RecoParam()->TCOn())
1182 DeConvExp(inADC,outADC,nTimeTotal,AliTRDReconstructor::RecoParam()->GetTCnexp());
1185 indexesIn->ResetTbinCounter();
1186 while (indexesIn->NextTbinIndex(iTime))
1188 // Store the amplitude of the digit if above threshold
1189 if (outADC[iTime] > adcThreshold)
1191 digitsOut->SetDataUnchecked(iRow,iCol,iTime,outADC[iTime]);
1192 indexesOut->AddIndexTBin(iRow,iCol,iTime);
1196 } // while irow icol
1205 //_____________________________________________________________________________
1206 void AliTRDclusterizer::DeConvExp(Double_t *source, Double_t *target
1207 , Int_t n, Int_t nexp)
1210 // Tail cancellation by deconvolution for PASA v4 TRF
1214 Double_t coefficients[2];
1216 // Initialization (coefficient = alpha, rates = lambda)
1222 if (nexp == 1) { // 1 Exponentials
1228 if (nexp == 2) { // 2 Exponentials
1235 coefficients[0] = c1;
1236 coefficients[1] = c2;
1240 rates[0] = TMath::Exp(-dt/(r1));
1241 rates[1] = TMath::Exp(-dt/(r2));
1246 Double_t reminder[2];
1247 Double_t correction = 0.0;
1248 Double_t result = 0.0;
1250 // Attention: computation order is important
1251 for (k = 0; k < nexp; k++) {
1255 for (i = 0; i < n; i++) {
1257 result = (source[i] - correction); // No rescaling
1260 for (k = 0; k < nexp; k++) {
1261 reminder[k] = rates[k] * (reminder[k] + coefficients[k] * result);
1265 for (k = 0; k < nexp; k++) {
1266 correction += reminder[k];
1273 //_____________________________________________________________________________
1274 void AliTRDclusterizer::ResetRecPoints()
1277 // Resets the list of rec points
1281 fRecPoints->Delete();
1286 //_____________________________________________________________________________
1287 TObjArray *AliTRDclusterizer::RecPoints()
1290 // Returns the list of rec points
1294 fRecPoints = new TObjArray(400);
1301 //_____________________________________________________________________________
1302 void AliTRDclusterizer::FillLUT()
1308 const Int_t kNlut = 128;
1310 fLUTbin = AliTRDgeometry::kNplan * kNlut;
1312 // The lookup table from Bogdan
1313 Float_t lut[AliTRDgeometry::kNplan][kNlut] = {
1315 0.0070, 0.0150, 0.0224, 0.0298, 0.0374, 0.0454, 0.0533, 0.0611,
1316 0.0684, 0.0755, 0.0827, 0.0900, 0.0975, 0.1049, 0.1120, 0.1187,
1317 0.1253, 0.1318, 0.1385, 0.1453, 0.1519, 0.1584, 0.1646, 0.1704,
1318 0.1762, 0.1821, 0.1879, 0.1938, 0.1996, 0.2053, 0.2108, 0.2160,
1319 0.2210, 0.2260, 0.2310, 0.2361, 0.2411, 0.2461, 0.2509, 0.2557,
1320 0.2602, 0.2646, 0.2689, 0.2732, 0.2774, 0.2816, 0.2859, 0.2901,
1321 0.2942, 0.2983, 0.3022, 0.3061, 0.3099, 0.3136, 0.3172, 0.3207,
1322 0.3242, 0.3278, 0.3312, 0.3347, 0.3382, 0.3416, 0.3450, 0.3483,
1323 0.3515, 0.3547, 0.3579, 0.3609, 0.3639, 0.3669, 0.3698, 0.3727,
1324 0.3756, 0.3785, 0.3813, 0.3842, 0.3870, 0.3898, 0.3926, 0.3952,
1325 0.3979, 0.4005, 0.4032, 0.4057, 0.4082, 0.4108, 0.4132, 0.4157,
1326 0.4181, 0.4205, 0.4228, 0.4252, 0.4275, 0.4299, 0.4322, 0.4345,
1327 0.4367, 0.4390, 0.4412, 0.4434, 0.4456, 0.4478, 0.4499, 0.4520,
1328 0.4541, 0.4562, 0.4583, 0.4603, 0.4623, 0.4643, 0.4663, 0.4683,
1329 0.4702, 0.4722, 0.4741, 0.4758, 0.4774, 0.4790, 0.4805, 0.4824,
1330 0.4844, 0.4863, 0.4883, 0.4902, 0.4921, 0.4940, 0.4959, 0.4978
1333 0.0072, 0.0156, 0.0235, 0.0313, 0.0394, 0.0478, 0.0561, 0.0642,
1334 0.0718, 0.0792, 0.0868, 0.0947, 0.1025, 0.1101, 0.1172, 0.1241,
1335 0.1309, 0.1378, 0.1449, 0.1518, 0.1586, 0.1650, 0.1710, 0.1770,
1336 0.1830, 0.1891, 0.1952, 0.2011, 0.2070, 0.2125, 0.2177, 0.2229,
1337 0.2280, 0.2332, 0.2383, 0.2435, 0.2484, 0.2533, 0.2581, 0.2627,
1338 0.2670, 0.2714, 0.2757, 0.2799, 0.2842, 0.2884, 0.2927, 0.2968,
1339 0.3008, 0.3048, 0.3086, 0.3123, 0.3159, 0.3195, 0.3231, 0.3266,
1340 0.3301, 0.3335, 0.3370, 0.3404, 0.3438, 0.3471, 0.3504, 0.3536,
1341 0.3567, 0.3598, 0.3628, 0.3657, 0.3686, 0.3715, 0.3744, 0.3772,
1342 0.3800, 0.3828, 0.3856, 0.3884, 0.3911, 0.3938, 0.3965, 0.3991,
1343 0.4016, 0.4042, 0.4067, 0.4092, 0.4116, 0.4140, 0.4164, 0.4187,
1344 0.4211, 0.4234, 0.4257, 0.4280, 0.4302, 0.4325, 0.4347, 0.4369,
1345 0.4391, 0.4413, 0.4434, 0.4456, 0.4477, 0.4497, 0.4518, 0.4538,
1346 0.4558, 0.4578, 0.4598, 0.4618, 0.4637, 0.4656, 0.4675, 0.4694,
1347 0.4713, 0.4732, 0.4750, 0.4766, 0.4781, 0.4797, 0.4813, 0.4832,
1348 0.4851, 0.4870, 0.4888, 0.4906, 0.4925, 0.4942, 0.4960, 0.4978
1351 0.0075, 0.0163, 0.0246, 0.0328, 0.0415, 0.0504, 0.0592, 0.0674,
1352 0.0753, 0.0832, 0.0914, 0.0996, 0.1077, 0.1154, 0.1225, 0.1296,
1353 0.1369, 0.1442, 0.1515, 0.1585, 0.1652, 0.1714, 0.1776, 0.1839,
1354 0.1902, 0.1965, 0.2025, 0.2085, 0.2141, 0.2194, 0.2247, 0.2299,
1355 0.2352, 0.2405, 0.2457, 0.2507, 0.2557, 0.2604, 0.2649, 0.2693,
1356 0.2737, 0.2780, 0.2823, 0.2867, 0.2909, 0.2951, 0.2992, 0.3033,
1357 0.3072, 0.3110, 0.3146, 0.3182, 0.3218, 0.3253, 0.3288, 0.3323,
1358 0.3357, 0.3392, 0.3426, 0.3459, 0.3492, 0.3524, 0.3555, 0.3586,
1359 0.3616, 0.3645, 0.3674, 0.3703, 0.3731, 0.3759, 0.3787, 0.3815,
1360 0.3843, 0.3870, 0.3897, 0.3925, 0.3950, 0.3976, 0.4002, 0.4027,
1361 0.4052, 0.4076, 0.4101, 0.4124, 0.4148, 0.4171, 0.4194, 0.4217,
1362 0.4239, 0.4262, 0.4284, 0.4306, 0.4328, 0.4350, 0.4371, 0.4393,
1363 0.4414, 0.4435, 0.4455, 0.4476, 0.4496, 0.4516, 0.4536, 0.4555,
1364 0.4575, 0.4594, 0.4613, 0.4632, 0.4650, 0.4669, 0.4687, 0.4705,
1365 0.4723, 0.4741, 0.4758, 0.4773, 0.4789, 0.4804, 0.4821, 0.4839,
1366 0.4857, 0.4875, 0.4893, 0.4910, 0.4928, 0.4945, 0.4961, 0.4978
1369 0.0078, 0.0171, 0.0258, 0.0345, 0.0438, 0.0532, 0.0624, 0.0708,
1370 0.0791, 0.0875, 0.0962, 0.1048, 0.1130, 0.1206, 0.1281, 0.1356,
1371 0.1432, 0.1508, 0.1582, 0.1651, 0.1716, 0.1780, 0.1845, 0.1910,
1372 0.1975, 0.2038, 0.2099, 0.2155, 0.2210, 0.2263, 0.2317, 0.2371,
1373 0.2425, 0.2477, 0.2528, 0.2578, 0.2626, 0.2671, 0.2715, 0.2759,
1374 0.2803, 0.2846, 0.2890, 0.2933, 0.2975, 0.3016, 0.3056, 0.3095,
1375 0.3132, 0.3168, 0.3204, 0.3239, 0.3274, 0.3309, 0.3344, 0.3378,
1376 0.3412, 0.3446, 0.3479, 0.3511, 0.3543, 0.3574, 0.3603, 0.3633,
1377 0.3662, 0.3690, 0.3718, 0.3747, 0.3774, 0.3802, 0.3829, 0.3857,
1378 0.3883, 0.3910, 0.3936, 0.3962, 0.3987, 0.4012, 0.4037, 0.4061,
1379 0.4085, 0.4109, 0.4132, 0.4155, 0.4177, 0.4200, 0.4222, 0.4244,
1380 0.4266, 0.4288, 0.4309, 0.4331, 0.4352, 0.4373, 0.4394, 0.4414,
1381 0.4435, 0.4455, 0.4475, 0.4494, 0.4514, 0.4533, 0.4552, 0.4571,
1382 0.4590, 0.4608, 0.4626, 0.4645, 0.4662, 0.4680, 0.4698, 0.4715,
1383 0.4733, 0.4750, 0.4766, 0.4781, 0.4796, 0.4812, 0.4829, 0.4846,
1384 0.4863, 0.4880, 0.4897, 0.4914, 0.4930, 0.4946, 0.4963, 0.4979
1387 0.0081, 0.0178, 0.0270, 0.0364, 0.0463, 0.0562, 0.0656, 0.0744,
1388 0.0831, 0.0921, 0.1013, 0.1102, 0.1183, 0.1261, 0.1339, 0.1419,
1389 0.1499, 0.1576, 0.1648, 0.1715, 0.1782, 0.1849, 0.1917, 0.1984,
1390 0.2048, 0.2110, 0.2167, 0.2223, 0.2278, 0.2333, 0.2389, 0.2444,
1391 0.2497, 0.2548, 0.2598, 0.2645, 0.2691, 0.2735, 0.2780, 0.2824,
1392 0.2868, 0.2912, 0.2955, 0.2997, 0.3038, 0.3078, 0.3116, 0.3152,
1393 0.3188, 0.3224, 0.3259, 0.3294, 0.3329, 0.3364, 0.3398, 0.3432,
1394 0.3465, 0.3497, 0.3529, 0.3561, 0.3591, 0.3620, 0.3649, 0.3677,
1395 0.3705, 0.3733, 0.3761, 0.3788, 0.3816, 0.3843, 0.3869, 0.3896,
1396 0.3922, 0.3948, 0.3973, 0.3998, 0.4022, 0.4047, 0.4070, 0.4094,
1397 0.4117, 0.4139, 0.4162, 0.4184, 0.4206, 0.4227, 0.4249, 0.4270,
1398 0.4291, 0.4313, 0.4334, 0.4354, 0.4375, 0.4395, 0.4415, 0.4435,
1399 0.4455, 0.4474, 0.4493, 0.4512, 0.4531, 0.4550, 0.4568, 0.4586,
1400 0.4604, 0.4622, 0.4639, 0.4657, 0.4674, 0.4691, 0.4708, 0.4725,
1401 0.4742, 0.4758, 0.4773, 0.4788, 0.4803, 0.4819, 0.4836, 0.4852,
1402 0.4869, 0.4885, 0.4901, 0.4917, 0.4933, 0.4948, 0.4964, 0.4979
1405 0.0085, 0.0189, 0.0288, 0.0389, 0.0497, 0.0603, 0.0699, 0.0792,
1406 0.0887, 0.0985, 0.1082, 0.1170, 0.1253, 0.1336, 0.1421, 0.1505,
1407 0.1587, 0.1662, 0.1733, 0.1803, 0.1874, 0.1945, 0.2014, 0.2081,
1408 0.2143, 0.2201, 0.2259, 0.2316, 0.2374, 0.2431, 0.2487, 0.2541,
1409 0.2593, 0.2642, 0.2689, 0.2735, 0.2781, 0.2826, 0.2872, 0.2917,
1410 0.2961, 0.3003, 0.3045, 0.3086, 0.3125, 0.3162, 0.3198, 0.3235,
1411 0.3270, 0.3306, 0.3342, 0.3377, 0.3411, 0.3446, 0.3479, 0.3511,
1412 0.3543, 0.3575, 0.3605, 0.3634, 0.3663, 0.3691, 0.3720, 0.3748,
1413 0.3775, 0.3803, 0.3830, 0.3857, 0.3884, 0.3911, 0.3937, 0.3962,
1414 0.3987, 0.4012, 0.4036, 0.4060, 0.4084, 0.4107, 0.4129, 0.4152,
1415 0.4174, 0.4196, 0.4218, 0.4239, 0.4261, 0.4282, 0.4303, 0.4324,
1416 0.4344, 0.4365, 0.4385, 0.4405, 0.4425, 0.4445, 0.4464, 0.4483,
1417 0.4502, 0.4521, 0.4539, 0.4558, 0.4576, 0.4593, 0.4611, 0.4629,
1418 0.4646, 0.4663, 0.4680, 0.4697, 0.4714, 0.4730, 0.4747, 0.4759,
1419 0.4769, 0.4780, 0.4790, 0.4800, 0.4811, 0.4827, 0.4843, 0.4859,
1420 0.4874, 0.4889, 0.4905, 0.4920, 0.4935, 0.4950, 0.4965, 0.4979
1427 fLUT = new Double_t[fLUTbin];
1429 for (Int_t iplan = 0; iplan < AliTRDgeometry::kNplan; iplan++) {
1430 for (Int_t ilut = 0; ilut < kNlut; ilut++ ) {
1431 fLUT[iplan*kNlut+ilut] = lut[iplan][ilut];
1437 //_____________________________________________________________________________
1438 Double_t AliTRDclusterizer::LUTposition(Int_t iplane, Double_t ampL
1439 , Double_t ampC, Double_t ampR) const
1442 // Calculates the cluster position using the lookup table.
1443 // Method provided by Bogdan Vulpescu.
1446 const Int_t kNlut = 128;
1457 Double_t xMin[AliTRDgeometry::kNplan] = { 0.006492, 0.006377, 0.006258
1458 , 0.006144, 0.006030, 0.005980 };
1459 Double_t xMax[AliTRDgeometry::kNplan] = { 0.960351, 0.965870, 0.970445
1460 , 0.974352, 0.977667, 0.996101 };
1463 x = (ampL - ampR) / ampC;
1466 else if (ampL < ampR) {
1467 x = (ampR - ampL) / ampC;
1473 xmin = xMin[iplane] + 0.000005;
1474 xmax = xMax[iplane] - 0.000005;
1475 xwid = (xmax - xmin) / 127.0;
1480 else if (x > xmax) {
1481 pos = side * 0.5000;
1484 ix = (Int_t) ((x - xmin) / xwid);
1485 pos = side * fLUT[iplane*kNlut+ix];