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 "AliTRDgeometry.h"
40 #include "AliTRDdataArrayF.h"
41 #include "AliTRDdataArrayI.h"
42 #include "AliTRDdigitsManager.h"
43 #include "AliTRDrawData.h"
44 #include "AliTRDcalibDB.h"
45 #include "AliTRDSimParam.h"
46 #include "AliTRDRecParam.h"
47 #include "AliTRDCommonParam.h"
48 #include "AliTRDtransform.h"
49 #include "AliTRDSignalIndex.h"
50 #include "AliTRDRawStream.h"
51 #include "AliTRDRawStreamV2.h"
52 #include "AliTRDfeeParam.h"
54 #include "Cal/AliTRDCalROC.h"
55 #include "Cal/AliTRDCalDet.h"
57 ClassImp(AliTRDclusterizer)
59 //_____________________________________________________________________________
60 AliTRDclusterizer::AliTRDclusterizer()
73 // AliTRDclusterizer default constructor
76 fRawVersion = AliTRDfeeParam::Instance()->GetRAWversion();
80 //_____________________________________________________________________________
81 AliTRDclusterizer::AliTRDclusterizer(const Text_t *name, const Text_t *title)
86 ,fDigitsManager(new AliTRDdigitsManager())
91 ,fTransform(new AliTRDtransform(0))
94 // AliTRDclusterizer constructor
97 fDigitsManager->CreateArrays();
99 fRawVersion = AliTRDfeeParam::Instance()->GetRAWversion();
103 //_____________________________________________________________________________
104 AliTRDclusterizer::AliTRDclusterizer(const AliTRDclusterizer &c)
109 ,fDigitsManager(NULL)
113 ,fIndexesMaxima(NULL)
117 // AliTRDclusterizer copy constructor
122 //_____________________________________________________________________________
123 AliTRDclusterizer::~AliTRDclusterizer()
126 // AliTRDclusterizer destructor
131 fRecPoints->Delete();
137 delete fDigitsManager;
138 fDigitsManager = NULL;
149 delete fIndexesMaxima;
150 fIndexesMaxima = NULL;
161 //_____________________________________________________________________________
162 AliTRDclusterizer &AliTRDclusterizer::operator=(const AliTRDclusterizer &c)
165 // Assignment operator
170 ((AliTRDclusterizer &) c).Copy(*this);
176 //_____________________________________________________________________________
177 void AliTRDclusterizer::Copy(TObject &c) const
183 ((AliTRDclusterizer &) c).fClusterTree = NULL;
184 ((AliTRDclusterizer &) c).fRecPoints = NULL;
185 ((AliTRDclusterizer &) c).fDigitsManager = NULL;
186 ((AliTRDclusterizer &) c).fAddLabels = fAddLabels;
187 ((AliTRDclusterizer &) c).fRawVersion = fRawVersion;
188 ((AliTRDclusterizer &) c).fIndexesOut = NULL;
189 ((AliTRDclusterizer &) c).fIndexesMaxima = NULL;
190 ((AliTRDclusterizer &) c).fTransform = NULL;
194 //_____________________________________________________________________________
195 Bool_t AliTRDclusterizer::Open(const Char_t *name, Int_t nEvent)
198 // Opens the AliROOT file. Output and input are in the same file
201 TString evfoldname = AliConfig::GetDefaultEventFolderName();
202 fRunLoader = AliRunLoader::GetRunLoader(evfoldname);
205 fRunLoader = AliRunLoader::Open(name);
209 AliError(Form("Can not open session for file %s.",name));
220 //_____________________________________________________________________________
221 Bool_t AliTRDclusterizer::OpenOutput()
224 // Open the output file
227 TObjArray *ioArray = 0;
229 AliLoader* loader = fRunLoader->GetLoader("TRDLoader");
230 loader->MakeTree("R");
232 fClusterTree = loader->TreeR();
233 fClusterTree->Branch("TRDcluster","TObjArray",&ioArray,32000,0);
239 //_____________________________________________________________________________
240 Bool_t AliTRDclusterizer::OpenOutput(TTree *clusterTree)
243 // Connect the output tree
246 TObjArray *ioArray = 0;
248 fClusterTree = clusterTree;
249 fClusterTree->Branch("TRDcluster","TObjArray",&ioArray,32000,0);
255 //_____________________________________________________________________________
256 Bool_t AliTRDclusterizer::OpenInput(Int_t nEvent)
259 // Opens a ROOT-file with TRD-hits and reads in the digits-tree
262 // Import the Trees for the event nEvent in the file
263 fRunLoader->GetEvent(nEvent);
269 //_____________________________________________________________________________
270 Bool_t AliTRDclusterizer::WriteClusters(Int_t det)
273 // Fills TRDcluster branch in the tree with the clusters
274 // found in detector = det. For det=-1 writes the tree.
278 (det >= AliTRDgeometry::Ndet())) {
279 AliError(Form("Unexpected detector index %d.\n",det));
283 TBranch *branch = fClusterTree->GetBranch("TRDcluster");
285 TObjArray *ioArray = 0;
286 branch = fClusterTree->Branch("TRDcluster","TObjArray",&ioArray,32000,0);
290 (det < AliTRDgeometry::Ndet())) {
292 Int_t nRecPoints = RecPoints()->GetEntriesFast();
293 TObjArray *detRecPoints = new TObjArray(400);
295 for (Int_t i = 0; i < nRecPoints; i++) {
296 AliTRDcluster *c = (AliTRDcluster *) RecPoints()->UncheckedAt(i);
297 if (det == c->GetDetector()) {
298 detRecPoints->AddLast(c);
301 AliError(Form("Attempt to write a cluster with unexpected detector index: got=%d expected=%d\n"
307 branch->SetAddress(&detRecPoints);
308 fClusterTree->Fill();
318 AliInfo(Form("Writing the cluster tree %s for event %d."
319 ,fClusterTree->GetName(),fRunLoader->GetEventNumber()));
323 branch->SetAddress(&fRecPoints);
325 AliLoader *loader = fRunLoader->GetLoader("TRDLoader");
326 loader->WriteRecPoints("OVERWRITE");
331 AliError("Cluster tree does not exist. Cannot write clusters.\n");
340 AliError(Form("Unexpected detector index %d.\n",det));
346 //_____________________________________________________________________________
347 void AliTRDclusterizer::ResetHelperIndexes(AliTRDSignalIndex *indexesIn)
350 // Reset the helper indexes
355 // carefull here - we assume that only row number may change - most probable
356 if (indexesIn->GetNrow() <= fIndexesOut->GetNrow())
357 fIndexesOut->ResetContent();
359 fIndexesOut->ResetContentConditional(indexesIn->GetNrow()
360 , indexesIn->GetNcol()
361 , indexesIn->GetNtime());
365 fIndexesOut = new AliTRDSignalIndex(indexesIn->GetNrow()
366 , indexesIn->GetNcol()
367 , indexesIn->GetNtime());
372 // carefull here - we assume that only row number may change - most probable
373 if (indexesIn->GetNrow() <= fIndexesMaxima->GetNrow())
375 fIndexesMaxima->ResetContent();
379 fIndexesMaxima->ResetContentConditional(indexesIn->GetNrow()
380 , indexesIn->GetNcol()
381 , indexesIn->GetNtime());
386 fIndexesMaxima = new AliTRDSignalIndex(indexesIn->GetNrow()
387 , indexesIn->GetNcol()
388 , indexesIn->GetNtime());
393 //_____________________________________________________________________________
394 Bool_t AliTRDclusterizer::ReadDigits()
397 // Reads the digits arrays from the input aliroot file
401 AliError("No run loader available");
405 AliLoader* loader = fRunLoader->GetLoader("TRDLoader");
406 if (!loader->TreeD()) {
407 loader->LoadDigits();
410 // Read in the digit arrays
411 return (fDigitsManager->ReadDigits(loader->TreeD()));
415 //_____________________________________________________________________________
416 Bool_t AliTRDclusterizer::ReadDigits(TTree *digitsTree)
419 // Reads the digits arrays from the input tree
422 // Read in the digit arrays
423 return (fDigitsManager->ReadDigits(digitsTree));
427 //_____________________________________________________________________________
428 Bool_t AliTRDclusterizer::ReadDigits(AliRawReader *rawReader)
431 // Reads the digits arrays from the ddl file
435 fDigitsManager = raw.Raw2Digits(rawReader);
441 //_____________________________________________________________________________
442 Bool_t AliTRDclusterizer::MakeClusters()
445 // Creates clusters from digits
448 // Propagate info from the digits manager
449 if (fAddLabels == kTRUE)
451 fAddLabels = fDigitsManager->UsesDictionaries();
454 Bool_t fReturn = kTRUE;
455 for (Int_t i = 0; i < AliTRDgeometry::kNdet; i++)
458 AliTRDdataArrayI *digitsIn = fDigitsManager->GetDigits(i);
459 // This is to take care of switched off super modules
460 if (digitsIn->GetNtime() == 0)
465 AliTRDSignalIndex* indexes = fDigitsManager->GetIndexes(i);
466 if (indexes->IsAllocated() == kFALSE)
468 fDigitsManager->BuildIndexes(i);
472 if (indexes->HasEntry())
476 for (Int_t iDict = 0; iDict < AliTRDdigitsManager::kNDict; iDict++)
478 AliTRDdataArrayI *tracksIn = 0;
479 tracksIn = fDigitsManager->GetDictionary(i,iDict);
483 fR = MakeClusters(i);
484 fReturn = fR && fReturn;
493 // No compress just remove
494 fDigitsManager->RemoveDigits(i);
495 fDigitsManager->RemoveDictionaries(i);
496 fDigitsManager->ClearIndexes(i);
504 //_____________________________________________________________________________
505 Bool_t AliTRDclusterizer::Raw2Clusters(AliRawReader *rawReader)
508 // Creates clusters from raw data
511 AliTRDdataArrayI *digits = 0;
512 AliTRDdataArrayI *track0 = 0;
513 AliTRDdataArrayI *track1 = 0;
514 AliTRDdataArrayI *track2 = 0;
516 AliTRDSignalIndex *indexes = 0;
518 // Create the digits manager
521 fDigitsManager = new AliTRDdigitsManager();
522 fDigitsManager->CreateArrays();
525 AliTRDRawStreamV2 input(rawReader);
526 input.SetRawVersion( fRawVersion );
529 AliInfo(Form("Stream version: %s", input.IsA()->GetName()));
531 // Loop through the digits
538 det = input.GetDet();
545 digits = fDigitsManager->GetDigits(lastdet);
546 Bool_t iclusterBranch = kFALSE;
547 if (indexes->HasEntry())
548 iclusterBranch = MakeClusters(lastdet);
549 if (iclusterBranch == kFALSE)
551 WriteClusters(lastdet);
558 fDigitsManager->RemoveDigits(lastdet);
559 fDigitsManager->RemoveDictionaries(lastdet);
560 fDigitsManager->ClearIndexes(lastdet);
565 // Add a container for the digits of this detector
566 digits = fDigitsManager->GetDigits(det);
567 track0 = fDigitsManager->GetDictionary(det,0);
568 track1 = fDigitsManager->GetDictionary(det,1);
569 track2 = fDigitsManager->GetDictionary(det,2);
571 // Allocate memory space for the digits buffer
572 if (digits->GetNtime() == 0)
574 //AliDebug(5, Form("Alloc digits for det %d", det));
575 digits->Allocate(input.GetMaxRow(),input.GetMaxCol(), input.GetNumberOfTimeBins());
576 track0->Allocate(input.GetMaxRow(),input.GetMaxCol(), input.GetNumberOfTimeBins());
577 track1->Allocate(input.GetMaxRow(),input.GetMaxCol(), input.GetNumberOfTimeBins());
578 track2->Allocate(input.GetMaxRow(),input.GetMaxCol(), input.GetNumberOfTimeBins());
581 indexes = fDigitsManager->GetIndexes(det);
582 indexes->SetSM(input.GetSM());
583 indexes->SetStack(input.GetStack());
584 indexes->SetLayer(input.GetLayer());
585 indexes->SetDetNumber(det);
586 if (indexes->IsAllocated() == kFALSE)
588 indexes->Allocate(input.GetMaxRow(), input.GetMaxCol(), input.GetNumberOfTimeBins());
593 for (it = 0; it < 3; it++)
595 if ( input.GetTimeBin() + it < input.GetNumberOfTimeBins() )
597 if (input.GetSignals()[it] > 0)
599 digits->SetDataUnchecked(input.GetRow(), input.GetCol(),
600 input.GetTimeBin() + it, input.GetSignals()[it]);
602 indexes->AddIndexTBin(input.GetRow(), input.GetCol(),
603 input.GetTimeBin() + it);
604 track0->SetDataUnchecked(input.GetRow(), input.GetCol(),
605 input.GetTimeBin() + it, 0);
606 track1->SetDataUnchecked(input.GetRow(), input.GetCol(),
607 input.GetTimeBin() + it, 0);
608 track2->SetDataUnchecked(input.GetRow(), input.GetCol(),
609 input.GetTimeBin() + it, 0);
618 Bool_t iclusterBranch = kFALSE;
619 if (indexes->HasEntry())
621 iclusterBranch = MakeClusters(lastdet);
623 if (iclusterBranch == kFALSE)
625 WriteClusters(lastdet);
628 //MakeClusters(lastdet);
631 fDigitsManager->RemoveDigits(lastdet);
632 fDigitsManager->RemoveDictionaries(lastdet);
633 fDigitsManager->ClearIndexes(lastdet);
637 delete fDigitsManager;
638 fDigitsManager = NULL;
643 //_____________________________________________________________________________
644 Bool_t AliTRDclusterizer::Raw2ClustersChamber(AliRawReader *rawReader)
647 // Creates clusters from raw data
650 // Create the digits manager
653 fDigitsManager = new AliTRDdigitsManager();
654 fDigitsManager->CreateArrays();
657 fDigitsManager->SetUseDictionaries(fAddLabels);
659 AliTRDRawStreamV2 input(rawReader);
660 input.SetRawVersion( fRawVersion );
663 AliInfo(Form("Stream version: %s", input.IsA()->GetName()));
666 while ((det = input.NextChamber(fDigitsManager)) >= 0)
668 Bool_t iclusterBranch = kFALSE;
669 if (fDigitsManager->GetIndexes(det)->HasEntry())
671 iclusterBranch = MakeClusters(det);
673 if (iclusterBranch == kFALSE)
678 fDigitsManager->RemoveDigits(det);
679 fDigitsManager->RemoveDictionaries(det);
680 fDigitsManager->ClearIndexes(det);
683 delete fDigitsManager;
684 fDigitsManager = NULL;
689 //_____________________________________________________________________________
690 Bool_t AliTRDclusterizer::MakeClusters(Int_t det)
693 // Generates the cluster.
697 // digits should be expanded beforehand!
698 // digitsIn->Expand();
699 AliTRDdataArrayI *digitsIn = fDigitsManager->GetDigits(det);
701 // This is to take care of switched off super modules
702 if (digitsIn->GetNtime() == 0)
707 AliTRDSignalIndex *indexesIn = fDigitsManager->GetIndexes(det);
708 if (indexesIn->IsAllocated() == kFALSE)
710 AliError("Indexes do not exist!");
714 AliTRDcalibDB *calibration = AliTRDcalibDB::Instance();
717 AliFatal("No AliTRDcalibDB instance available\n");
721 AliTRDRecParam *recParam = AliTRDRecParam::Instance();
724 AliError("No AliTRDRecParam instance available\n");
729 // There is no ADC threshold anymore, and simParam should not be used in clusterizer. KO
730 Float_t ADCthreshold = 0;
732 // Threshold value for the maximum
733 Float_t maxThresh = recParam->GetClusMaxThresh();
734 // Threshold value for the digit signal
735 Float_t sigThresh = recParam->GetClusSigThresh();
737 // Iteration limit for unfolding procedure
738 const Float_t kEpsilon = 0.01;
739 const Int_t kNclus = 3;
740 const Int_t kNsig = 5;
743 Double_t ratioLeft = 1.0;
744 Double_t ratioRight = 1.0;
746 Double_t padSignal[kNsig];
747 Double_t clusterSignal[kNclus];
749 Int_t icham = indexesIn->GetChamber();
750 Int_t iplan = indexesIn->GetPlane();
751 Int_t isect = indexesIn->GetSM();
753 // Start clustering in the chamber
755 Int_t idet = AliTRDgeometry::GetDetector(iplan,icham,isect);
758 AliError("Strange Detector number Missmatch!");
762 // TRD space point transformation
763 fTransform->SetDetector(det);
765 Int_t ilayer = AliGeomManager::kTRD1 + iplan;
766 Int_t imodule = icham + AliTRDgeometry::Ncham() * isect;
767 UShort_t volid = AliGeomManager::LayerToVolUID(ilayer,imodule);
769 Int_t nColMax = digitsIn->GetNcol();
770 Int_t nTimeTotal = digitsIn->GetNtime();
772 // Detector wise calibration object for the gain factors
773 const AliTRDCalDet *calGainFactorDet = calibration->GetGainFactorDet();
774 // Calibration object with pad wise values for the gain factors
775 AliTRDCalROC *calGainFactorROC = calibration->GetGainFactorROC(idet);
776 // Calibration value for chamber wise gain factor
777 Float_t calGainFactorDetValue = calGainFactorDet->GetValue(idet);
781 AliTRDdataArrayF *digitsOut = new AliTRDdataArrayF(digitsIn->GetNrow()
783 ,digitsIn->GetNtime());
785 ResetHelperIndexes(indexesIn);
787 // Apply the gain and the tail cancelation via digital filter
788 TailCancelation(digitsIn
795 ,calGainFactorDetValue);
802 fIndexesOut->ResetCounters();
803 while (fIndexesOut->NextRCTbinIndex(row, col, time))
806 Float_t signalM = TMath::Abs(digitsOut->GetDataUnchecked(row,col,time));
808 // Look for the maximum
809 if (signalM >= maxThresh)
812 if (col + 1 >= nColMax || col-1 < 0)
815 Float_t signalL = TMath::Abs(digitsOut->GetDataUnchecked(row,col+1,time));
816 Float_t signalR = TMath::Abs(digitsOut->GetDataUnchecked(row,col-1,time));
818 if ((TMath::Abs(signalL) <= signalM) &&
819 (TMath::Abs(signalR) < signalM))
821 if ((TMath::Abs(signalL) >= sigThresh) ||
822 (TMath::Abs(signalR) >= sigThresh))
824 // Maximum found, mark the position by a negative signal
825 digitsOut->SetDataUnchecked(row,col,time,-signalM);
826 fIndexesMaxima->AddIndexTBin(row,col,time);
834 // The index to the first cluster of a given ROC
835 Int_t firstClusterROC = -1;
836 // The number of cluster in a given ROC
837 Int_t nClusterROC = 0;
839 // Now check the maxima and calculate the cluster position
840 fIndexesMaxima->ResetCounters();
841 while (fIndexesMaxima->NextRCTbinIndex(row, col, time))
845 if (digitsOut->GetDataUnchecked(row,col,time) < 0.0)
848 for (iPad = 0; iPad < kNclus; iPad++)
850 Int_t iPadCol = col - 1 + iPad;
851 clusterSignal[iPad] = TMath::Abs(digitsOut->GetDataUnchecked(row,iPadCol,time));
854 // Count the number of pads in the cluster
859 while (TMath::Abs(digitsOut->GetDataUnchecked(row,col-ii ,time)) >= sigThresh)
863 if (col-ii < 0) break;
867 while (TMath::Abs(digitsOut->GetDataUnchecked(row,col+ii+1,time)) >= sigThresh)
871 if (col+ii+1 >= nColMax) break;
875 // Look for 5 pad cluster with minimum in the middle
876 Bool_t fivePadCluster = kFALSE;
877 if (col < (nColMax - 3))
879 if (digitsOut->GetDataUnchecked(row,col+2,time) < 0)
881 fivePadCluster = kTRUE;
883 if ((fivePadCluster) && (col < (nColMax - 5)))
885 if (digitsOut->GetDataUnchecked(row,col+4,time) >= sigThresh)
887 fivePadCluster = kFALSE;
890 if ((fivePadCluster) && (col > 1))
892 if (digitsOut->GetDataUnchecked(row,col-2,time) >= sigThresh)
894 fivePadCluster = kFALSE;
900 // Modify the signal of the overlapping pad for the left part
901 // of the cluster which remains from a previous unfolding
904 clusterSignal[0] *= ratioLeft;
908 // Unfold the 5 pad cluster
911 for (iPad = 0; iPad < kNsig; iPad++)
913 padSignal[iPad] = TMath::Abs(digitsOut->GetDataUnchecked(row
917 // Unfold the two maxima and set the signal on
918 // the overlapping pad to the ratio
919 ratioRight = Unfold(kEpsilon,iplan,padSignal);
920 ratioLeft = 1.0 - ratioRight;
921 clusterSignal[2] *= ratioRight;
925 // The position of the cluster in COL direction relative to the center pad (pad units)
926 Double_t clusterPosCol = 0.0;
927 if (recParam->LUTOn())
929 // Calculate the position of the cluster by using the
930 // lookup table method
931 clusterPosCol = recParam->LUTposition(iplan
938 // Calculate the position of the cluster by using the
939 // center of gravity method
940 for (Int_t i = 0; i < kNsig; i++)
944 padSignal[2] = TMath::Abs(digitsOut->GetDataUnchecked(row,col ,time)); // Central pad
945 padSignal[1] = TMath::Abs(digitsOut->GetDataUnchecked(row,col-1,time)); // Left pad
946 padSignal[3] = TMath::Abs(digitsOut->GetDataUnchecked(row,col+1,time)); // Right pad
948 (TMath::Abs(digitsOut->GetDataUnchecked(row,col-2,time)) < padSignal[1]))
950 padSignal[0] = TMath::Abs(digitsOut->GetDataUnchecked(row,col-2,time));
952 if ((col < nColMax - 3) &&
953 (TMath::Abs(digitsOut->GetDataUnchecked(row,col+2,time)) < padSignal[3]))
955 padSignal[4] = TMath::Abs(digitsOut->GetDataUnchecked(row,col+2,time));
957 clusterPosCol = GetCOG(padSignal);
960 // Store the amplitudes of the pads in the cluster for later analysis
961 Short_t signals[7] = { 0, 0, 0, 0, 0, 0, 0 };
962 for (Int_t jPad = col-3; jPad <= col+3; jPad++)
969 signals[jPad-col+3] = TMath::Nint(TMath::Abs(digitsOut->GetDataUnchecked(row,jPad,time)));
972 // Transform the local cluster coordinates into calibrated
973 // space point positions defined in the local tracking system.
974 // Here the calibration for T0, Vdrift and ExB is applied as well.
975 Double_t clusterXYZ[6];
976 clusterXYZ[0] = clusterPosCol;
977 clusterXYZ[1] = clusterSignal[0];
978 clusterXYZ[2] = clusterSignal[1];
979 clusterXYZ[3] = clusterSignal[2];
986 fTransform->Transform(clusterXYZ,clusterRCT,((UInt_t) time),0);
988 // Add the cluster to the output array
989 // The track indices will be stored later
990 Float_t clusterPos[3];
991 clusterPos[0] = clusterXYZ[0];
992 clusterPos[1] = clusterXYZ[1];
993 clusterPos[2] = clusterXYZ[2];
994 Float_t clusterSig[2];
995 clusterSig[0] = clusterXYZ[4];
996 clusterSig[1] = clusterXYZ[5];
997 Double_t clusterCharge = clusterXYZ[3];
998 Char_t clusterTimeBin = ((Char_t) clusterRCT[2]);
999 AliTRDcluster *cluster = new AliTRDcluster(idet
1004 ,((Char_t) nPadCount)
1013 // Temporarily store the row, column and time bin of the center pad
1014 // Used to later on assign the track indices
1015 cluster->SetLabel( row,0);
1016 cluster->SetLabel( col,1);
1017 cluster->SetLabel(time,2);
1019 RecPoints()->Add(cluster);
1021 // Store the index of the first cluster in the current ROC
1022 if (firstClusterROC < 0)
1024 firstClusterROC = RecPoints()->GetEntriesFast() - 1;
1027 // Count the number of cluster in the current ROC
1030 } // if: Maximum found ?
1038 AddLabels(idet, firstClusterROC, nClusterROC);
1041 // Write the cluster and reset the array
1042 WriteClusters(idet);
1049 //_____________________________________________________________________________
1050 Bool_t AliTRDclusterizer::AddLabels(Int_t idet, Int_t firstClusterROC, Int_t nClusterROC)
1053 // Add the track indices to the found clusters
1056 const Int_t kNclus = 3;
1057 const Int_t kNdict = AliTRDdigitsManager::kNDict;
1058 const Int_t kNtrack = kNdict * kNclus;
1060 Int_t iClusterROC = 0;
1067 // Temporary array to collect the track indices
1068 Int_t *idxTracks = new Int_t[kNtrack*nClusterROC];
1070 // Loop through the dictionary arrays one-by-one
1071 // to keep memory consumption low
1072 AliTRDdataArrayI *tracksIn = 0;
1073 for (Int_t iDict = 0; iDict < kNdict; iDict++) {
1075 // tracksIn should be expanded beforehand!
1076 tracksIn = fDigitsManager->GetDictionary(idet,iDict);
1078 // Loop though the clusters found in this ROC
1079 for (iClusterROC = 0; iClusterROC < nClusterROC; iClusterROC++) {
1081 AliTRDcluster *cluster = (AliTRDcluster *)
1082 RecPoints()->UncheckedAt(firstClusterROC+iClusterROC);
1083 row = cluster->GetLabel(0);
1084 col = cluster->GetLabel(1);
1085 time = cluster->GetLabel(2);
1087 for (iPad = 0; iPad < kNclus; iPad++) {
1088 Int_t iPadCol = col - 1 + iPad;
1089 Int_t index = tracksIn->GetDataUnchecked(row,iPadCol,time) - 1;
1090 idxTracks[3*iPad+iDict + iClusterROC*kNtrack] = index;
1097 // Copy the track indices into the cluster
1098 // Loop though the clusters found in this ROC
1099 for (iClusterROC = 0; iClusterROC < nClusterROC; iClusterROC++) {
1101 AliTRDcluster *cluster = (AliTRDcluster *)
1102 RecPoints()->UncheckedAt(firstClusterROC+iClusterROC);
1103 cluster->SetLabel(-9999,0);
1104 cluster->SetLabel(-9999,1);
1105 cluster->SetLabel(-9999,2);
1107 cluster->AddTrackIndex(&idxTracks[iClusterROC*kNtrack]);
1111 delete [] idxTracks;
1117 //_____________________________________________________________________________
1118 Double_t AliTRDclusterizer::GetCOG(Double_t signal[5])
1122 // Used for clusters with more than 3 pads - where LUT not applicable
1125 Double_t sum = signal[0]
1131 Double_t res = (0.0 * (-signal[0] + signal[4])
1132 + (-signal[1] + signal[3])) / sum;
1138 //_____________________________________________________________________________
1139 Double_t AliTRDclusterizer::Unfold(Double_t eps, Int_t plane, Double_t *padSignal)
1142 // Method to unfold neighbouring maxima.
1143 // The charge ratio on the overlapping pad is calculated
1144 // until there is no more change within the range given by eps.
1145 // The resulting ratio is then returned to the calling method.
1148 AliTRDcalibDB *calibration = AliTRDcalibDB::Instance();
1150 AliError("No AliTRDcalibDB instance available\n");
1155 Int_t itStep = 0; // Count iteration steps
1157 Double_t ratio = 0.5; // Start value for ratio
1158 Double_t prevRatio = 0.0; // Store previous ratio
1160 Double_t newLeftSignal[3] = { 0.0, 0.0, 0.0 }; // Array to store left cluster signal
1161 Double_t newRightSignal[3] = { 0.0, 0.0, 0.0 }; // Array to store right cluster signal
1162 Double_t newSignal[3] = { 0.0, 0.0, 0.0 };
1164 // Start the iteration
1165 while ((TMath::Abs(prevRatio - ratio) > eps) && (itStep < 10)) {
1170 // Cluster position according to charge ratio
1171 Double_t maxLeft = (ratio*padSignal[2] - padSignal[0])
1172 / (padSignal[0] + padSignal[1] + ratio*padSignal[2]);
1173 Double_t maxRight = (padSignal[4] - (1-ratio)*padSignal[2])
1174 / ((1.0 - ratio)*padSignal[2] + padSignal[3] + padSignal[4]);
1176 // Set cluster charge ratio
1177 irc = calibration->PadResponse(1.0,maxLeft ,plane,newSignal);
1178 Double_t ampLeft = padSignal[1] / newSignal[1];
1179 irc = calibration->PadResponse(1.0,maxRight,plane,newSignal);
1180 Double_t ampRight = padSignal[3] / newSignal[1];
1182 // Apply pad response to parameters
1183 irc = calibration->PadResponse(ampLeft ,maxLeft ,plane,newLeftSignal );
1184 irc = calibration->PadResponse(ampRight,maxRight,plane,newRightSignal);
1186 // Calculate new overlapping ratio
1187 ratio = TMath::Min((Double_t) 1.0
1188 ,newLeftSignal[2] / (newLeftSignal[2] + newRightSignal[0]));
1196 //_____________________________________________________________________________
1197 void AliTRDclusterizer::TailCancelation(AliTRDdataArrayI *digitsIn
1198 , AliTRDdataArrayF *digitsOut
1199 , AliTRDSignalIndex *indexesIn
1200 , AliTRDSignalIndex *indexesOut
1202 , Float_t ADCthreshold
1203 , AliTRDCalROC *calGainFactorROC
1204 , Float_t calGainFactorDetValue)
1207 // Applies the tail cancelation and gain factors:
1208 // Transform digitsIn to digitsOut
1215 AliTRDRecParam *recParam = AliTRDRecParam::Instance();
1218 AliError("No AliTRDRecParam instance available\n");
1222 Double_t *inADC = new Double_t[nTimeTotal]; // ADC data before tail cancellation
1223 Double_t *outADC = new Double_t[nTimeTotal]; // ADC data after tail cancellation
1224 indexesIn->ResetCounters();
1225 while (indexesIn->NextRCIndex(iRow, iCol))
1227 Float_t calGainFactorROCValue = calGainFactorROC->GetValue(iCol,iRow);
1228 Double_t gain = calGainFactorDetValue
1229 * calGainFactorROCValue;
1231 for (iTime = 0; iTime < nTimeTotal; iTime++)
1233 // Apply gain gain factor
1234 inADC[iTime] = digitsIn->GetDataUnchecked(iRow,iCol,iTime);
1235 inADC[iTime] /= gain;
1236 outADC[iTime] = inADC[iTime];
1239 // Apply the tail cancelation via the digital filter
1240 if (recParam->TCOn())
1242 DeConvExp(inADC,outADC,nTimeTotal,recParam->GetTCnexp());
1245 indexesIn->ResetTbinCounter();
1246 while (indexesIn->NextTbinIndex(iTime))
1248 // Store the amplitude of the digit if above threshold
1249 if (outADC[iTime] > ADCthreshold)
1251 digitsOut->SetDataUnchecked(iRow,iCol,iTime,outADC[iTime]);
1252 indexesOut->AddIndexTBin(iRow,iCol,iTime);
1256 } // while irow icol
1265 //_____________________________________________________________________________
1266 void AliTRDclusterizer::DeConvExp(Double_t *source, Double_t *target
1267 , Int_t n, Int_t nexp)
1270 // Tail cancellation by deconvolution for PASA v4 TRF
1274 Double_t coefficients[2];
1276 // Initialization (coefficient = alpha, rates = lambda)
1282 if (nexp == 1) { // 1 Exponentials
1288 if (nexp == 2) { // 2 Exponentials
1295 coefficients[0] = c1;
1296 coefficients[1] = c2;
1300 rates[0] = TMath::Exp(-dt/(r1));
1301 rates[1] = TMath::Exp(-dt/(r2));
1306 Double_t reminder[2];
1307 Double_t correction = 0.0;
1308 Double_t result = 0.0;
1310 // Attention: computation order is important
1311 for (k = 0; k < nexp; k++) {
1315 for (i = 0; i < n; i++) {
1317 result = (source[i] - correction); // No rescaling
1320 for (k = 0; k < nexp; k++) {
1321 reminder[k] = rates[k] * (reminder[k] + coefficients[k] * result);
1325 for (k = 0; k < nexp; k++) {
1326 correction += reminder[k];
1333 //_____________________________________________________________________________
1334 void AliTRDclusterizer::ResetRecPoints()
1337 // Resets the list of rec points
1341 fRecPoints->Delete();
1346 //_____________________________________________________________________________
1347 TObjArray *AliTRDclusterizer::RecPoints()
1350 // Returns the list of rec points
1354 fRecPoints = new TObjArray(400);