]> git.uio.no Git - u/mrichter/AliRoot.git/blob - TRD/AliTRDclusterizer.cxx
- use only one array in DeConvExp
[u/mrichter/AliRoot.git] / TRD / AliTRDclusterizer.cxx
1 /**************************************************************************
2 * Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
3 *                                                                        *
4 * Author: The ALICE Off-line Project.                                    *
5 * Contributors are mentioned in the code where appropriate.              *
6 *                                                                        *
7 * Permission to use, copy, modify and distribute this software and its   *
8 * documentation strictly for non-commercial purposes is hereby granted   *
9 * without fee, provided that the above copyright notice appears in all   *
10 * copies and that both the copyright notice and this permission notice   *
11 * appear in the supporting documentation. The authors make no claims     *
12 * about the suitability of this software for any purpose. It is          *
13 * provided "as is" without express or implied warranty.                  *
14 **************************************************************************/
15
16 /* $Id$ */
17
18 ///////////////////////////////////////////////////////////////////////////////
19 //                                                                           //
20 // TRD cluster finder                                                        //
21 //                                                                           //
22 ///////////////////////////////////////////////////////////////////////////////
23
24 #include <TClonesArray.h>
25 #include <TObjArray.h>
26
27 #include "AliRunLoader.h"
28 #include "AliLoader.h"
29 #include "AliAlignObj.h"
30
31 #include "AliTRDclusterizer.h"
32 #include "AliTRDcluster.h"
33 #include "AliTRDReconstructor.h"
34 #include "AliTRDgeometry.h"
35 #include "AliTRDarrayDictionary.h"
36 #include "AliTRDarrayADC.h"
37 #include "AliTRDdigitsManager.h"
38 #include "AliTRDdigitsParam.h"
39 #include "AliTRDrawData.h"
40 #include "AliTRDcalibDB.h"
41 #include "AliTRDtransform.h"
42 #include "AliTRDSignalIndex.h"
43 #include "AliTRDrawStreamBase.h"
44 #include "AliTRDfeeParam.h"
45 #include "AliTRDtrackletWord.h"
46
47 #include "TTreeStream.h"
48
49 #include "Cal/AliTRDCalROC.h"
50 #include "Cal/AliTRDCalDet.h"
51 #include "Cal/AliTRDCalSingleChamberStatus.h"
52
53 ClassImp(AliTRDclusterizer)
54
55 //_____________________________________________________________________________
56 AliTRDclusterizer::AliTRDclusterizer(const AliTRDReconstructor *const rec)
57   :TNamed()
58   ,fReconstructor(rec)  
59   ,fRunLoader(NULL)
60   ,fClusterTree(NULL)
61   ,fRecPoints(NULL)
62   ,fTracklets(NULL)
63   ,fTrackletTree(NULL)
64   ,fDigitsManager(new AliTRDdigitsManager())
65   ,fTrackletContainer(NULL)
66   ,fRawVersion(2)
67   ,fTransform(new AliTRDtransform(0))
68   ,fDigits(NULL)
69   ,fIndexes(NULL)
70   ,fMaxThresh(0)
71   ,fSigThresh(0)
72   ,fMinMaxCutSigma(0)
73   ,fMinLeftRightCutSigma(0)
74   ,fLayer(0)
75   ,fDet(0)
76   ,fVolid(0)
77   ,fColMax(0)
78   ,fTimeTotal(0)
79   ,fCalGainFactorROC(NULL)
80   ,fCalGainFactorDetValue(0)
81   ,fCalNoiseROC(NULL)
82   ,fCalNoiseDetValue(0)
83   ,fCalPadStatusROC(NULL)
84   ,fClusterROC(0)
85   ,firstClusterROC(0)
86   ,fNoOfClusters(0)
87   ,fBaseline(0)
88   ,fRawStream(NULL)
89 {
90   //
91   // AliTRDclusterizer default constructor
92   //
93
94   SetBit(kLabels, kTRUE);
95   SetBit(knewDM, kFALSE);
96
97   AliTRDcalibDB *trd = 0x0;
98   if (!(trd = AliTRDcalibDB::Instance())) {
99     AliFatal("Could not get calibration object");
100   }
101
102   fRawVersion = AliTRDfeeParam::Instance()->GetRAWversion();
103
104   // Initialize debug stream
105   if(fReconstructor){
106     if(fReconstructor->GetRecoParam()->GetStreamLevel(AliTRDrecoParam::kClusterizer) > 1){
107       TDirectory *savedir = gDirectory; 
108       //fgGetDebugStream    = new TTreeSRedirector("TRD.ClusterizerDebug.root");
109       savedir->cd();
110     }
111   }
112
113 }
114
115 //_____________________________________________________________________________
116 AliTRDclusterizer::AliTRDclusterizer(const Text_t *name, const Text_t *title, const AliTRDReconstructor *const rec)
117   :TNamed(name,title)
118   ,fReconstructor(rec)
119   ,fRunLoader(NULL)
120   ,fClusterTree(NULL)
121   ,fRecPoints(NULL)
122   ,fTracklets(NULL)
123   ,fTrackletTree(NULL)
124   ,fDigitsManager(new AliTRDdigitsManager())
125   ,fTrackletContainer(NULL)
126   ,fRawVersion(2)
127   ,fTransform(new AliTRDtransform(0))
128   ,fDigits(NULL)
129   ,fIndexes(NULL)
130   ,fMaxThresh(0)
131   ,fSigThresh(0)
132   ,fMinMaxCutSigma(0)
133   ,fMinLeftRightCutSigma(0)
134   ,fLayer(0)
135   ,fDet(0)
136   ,fVolid(0)
137   ,fColMax(0)
138   ,fTimeTotal(0)
139   ,fCalGainFactorROC(NULL)
140   ,fCalGainFactorDetValue(0)
141   ,fCalNoiseROC(NULL)
142   ,fCalNoiseDetValue(0)
143   ,fCalPadStatusROC(NULL)
144   ,fClusterROC(0)
145   ,firstClusterROC(0)
146   ,fNoOfClusters(0)
147   ,fBaseline(0)
148   ,fRawStream(NULL)
149 {
150   //
151   // AliTRDclusterizer constructor
152   //
153
154   SetBit(kLabels, kTRUE);
155   SetBit(knewDM, kFALSE);
156
157   AliTRDcalibDB *trd = 0x0;
158   if (!(trd = AliTRDcalibDB::Instance())) {
159     AliFatal("Could not get calibration object");
160   }
161
162   fDigitsManager->CreateArrays();
163
164   fRawVersion = AliTRDfeeParam::Instance()->GetRAWversion();
165
166   //FillLUT();
167
168 }
169
170 //_____________________________________________________________________________
171 AliTRDclusterizer::AliTRDclusterizer(const AliTRDclusterizer &c)
172   :TNamed(c)
173   ,fReconstructor(c.fReconstructor)
174   ,fRunLoader(NULL)
175   ,fClusterTree(NULL)
176   ,fRecPoints(NULL)
177   ,fTracklets(NULL)
178   ,fTrackletTree(NULL)
179   ,fDigitsManager(NULL)
180   ,fTrackletContainer(NULL)
181   ,fRawVersion(2)
182   ,fTransform(NULL)
183   ,fDigits(NULL)
184   ,fIndexes(NULL)
185   ,fMaxThresh(0)
186   ,fSigThresh(0)
187   ,fMinMaxCutSigma(0)
188   ,fMinLeftRightCutSigma(0)
189   ,fLayer(0)
190   ,fDet(0)
191   ,fVolid(0)
192   ,fColMax(0)
193   ,fTimeTotal(0)
194   ,fCalGainFactorROC(NULL)
195   ,fCalGainFactorDetValue(0)
196   ,fCalNoiseROC(NULL)
197   ,fCalNoiseDetValue(0)
198   ,fCalPadStatusROC(NULL)
199   ,fClusterROC(0)
200   ,firstClusterROC(0)
201   ,fNoOfClusters(0)
202   ,fBaseline(0)
203   ,fRawStream(NULL)
204 {
205   //
206   // AliTRDclusterizer copy constructor
207   //
208
209   SetBit(kLabels, kTRUE);
210   SetBit(knewDM, kFALSE);
211
212   //FillLUT();
213
214 }
215
216 //_____________________________________________________________________________
217 AliTRDclusterizer::~AliTRDclusterizer()
218 {
219   //
220   // AliTRDclusterizer destructor
221   //
222
223   if (fRecPoints/* && IsClustersOwner()*/){
224     fRecPoints->Delete();
225     delete fRecPoints;
226   }
227
228   if (fTracklets){
229     fTracklets->Delete();
230     delete fTracklets;
231   }
232
233   if (fDigitsManager) {
234     delete fDigitsManager;
235     fDigitsManager = NULL;
236   }
237
238   if (fTrackletContainer){
239     delete [] fTrackletContainer[0];
240     delete [] fTrackletContainer[1];
241     delete [] fTrackletContainer;
242     fTrackletContainer = NULL;
243   }
244
245   if (fTransform){
246     delete fTransform;
247     fTransform = NULL;
248   }
249
250   if (fRawStream){
251     delete fRawStream;
252     fRawStream = NULL;
253   }
254
255 }
256
257 //_____________________________________________________________________________
258 AliTRDclusterizer &AliTRDclusterizer::operator=(const AliTRDclusterizer &c)
259 {
260   //
261   // Assignment operator
262   //
263
264   if (this != &c) 
265     {
266       ((AliTRDclusterizer &) c).Copy(*this);
267     }
268
269   return *this;
270
271 }
272
273 //_____________________________________________________________________________
274 void AliTRDclusterizer::Copy(TObject &c) const
275 {
276   //
277   // Copy function
278   //
279
280   ((AliTRDclusterizer &) c).fClusterTree   = NULL;
281   ((AliTRDclusterizer &) c).fRecPoints     = NULL;  
282   ((AliTRDclusterizer &) c).fTrackletTree  = NULL;
283   ((AliTRDclusterizer &) c).fDigitsManager = NULL;
284   ((AliTRDclusterizer &) c).fTrackletContainer = NULL;
285   ((AliTRDclusterizer &) c).fRawVersion    = fRawVersion;
286   ((AliTRDclusterizer &) c).fTransform     = NULL;
287   ((AliTRDclusterizer &) c).fDigits      = NULL;
288   ((AliTRDclusterizer &) c).fIndexes       = NULL;
289   ((AliTRDclusterizer &) c).fMaxThresh     = 0;
290   ((AliTRDclusterizer &) c).fSigThresh     = 0;
291   ((AliTRDclusterizer &) c).fMinMaxCutSigma= 0;
292   ((AliTRDclusterizer &) c).fMinLeftRightCutSigma = 0;
293   ((AliTRDclusterizer &) c).fLayer         = 0;
294   ((AliTRDclusterizer &) c).fDet           = 0;
295   ((AliTRDclusterizer &) c).fVolid         = 0;
296   ((AliTRDclusterizer &) c).fColMax        = 0;
297   ((AliTRDclusterizer &) c).fTimeTotal     = 0;
298   ((AliTRDclusterizer &) c).fCalGainFactorROC = NULL;
299   ((AliTRDclusterizer &) c).fCalGainFactorDetValue = 0;
300   ((AliTRDclusterizer &) c).fCalNoiseROC   = NULL;
301   ((AliTRDclusterizer &) c).fCalNoiseDetValue = 0;
302   ((AliTRDclusterizer &) c).fCalPadStatusROC = NULL;
303   ((AliTRDclusterizer &) c).fClusterROC    = 0;
304   ((AliTRDclusterizer &) c).firstClusterROC= 0;
305   ((AliTRDclusterizer &) c).fNoOfClusters  = 0;
306   ((AliTRDclusterizer &) c).fBaseline      = 0;
307   ((AliTRDclusterizer &) c).fRawStream     = NULL;
308   
309 }
310
311 //_____________________________________________________________________________
312 Bool_t AliTRDclusterizer::Open(const Char_t *name, Int_t nEvent)
313 {
314   //
315   // Opens the AliROOT file. Output and input are in the same file
316   //
317
318   TString evfoldname = AliConfig::GetDefaultEventFolderName();
319   fRunLoader         = AliRunLoader::GetRunLoader(evfoldname);
320
321   if (!fRunLoader) {
322     fRunLoader = AliRunLoader::Open(name);
323   }
324
325   if (!fRunLoader) {
326     AliError(Form("Can not open session for file %s.",name));
327     return kFALSE;
328   }
329
330   OpenInput(nEvent);
331   OpenOutput();
332
333   return kTRUE;
334
335 }
336
337 //_____________________________________________________________________________
338 Bool_t AliTRDclusterizer::OpenOutput()
339 {
340   //
341   // Open the output file
342   //
343
344   if (!fReconstructor->IsWritingClusters()) return kTRUE;
345
346   TObjArray *ioArray = 0x0; 
347
348   AliLoader* loader = fRunLoader->GetLoader("TRDLoader");
349   loader->MakeTree("R");
350
351   fClusterTree = loader->TreeR();
352   fClusterTree->Branch("TRDcluster", "TObjArray", &ioArray, 32000, 0);
353
354   return kTRUE;
355
356 }
357
358 //_____________________________________________________________________________
359 Bool_t AliTRDclusterizer::OpenOutput(TTree *const clusterTree)
360 {
361   //
362   // Connect the output tree
363   //
364
365   // clusters writing
366   if (fReconstructor->IsWritingClusters()){
367     TObjArray *ioArray = 0x0;
368     fClusterTree = clusterTree;
369     fClusterTree->Branch("TRDcluster", "TObjArray", &ioArray, 32000, 0);
370   }
371   return kTRUE;
372 }
373
374 //_____________________________________________________________________________
375 Bool_t AliTRDclusterizer::OpenTrackletOutput()
376 {
377   //
378   // Tracklet writing
379   //
380
381   if (fReconstructor->IsWritingTracklets()){
382     TString evfoldname = AliConfig::GetDefaultEventFolderName();
383     fRunLoader         = AliRunLoader::GetRunLoader(evfoldname);
384
385     if (!fRunLoader) {
386       fRunLoader = AliRunLoader::Open("galice.root");
387     }
388     if (!fRunLoader) {
389       AliError(Form("Can not open session for file galice.root."));
390       return kFALSE;
391     }
392
393     UInt_t **leaves = new UInt_t *[2];
394     AliDataLoader *dl = fRunLoader->GetLoader("TRDLoader")->GetDataLoader("tracklets");
395     if (!dl) {
396       AliError("Could not get the tracklets data loader!");
397       dl = new AliDataLoader("TRD.Tracklets.root","tracklets", "tracklets");
398       fRunLoader->GetLoader("TRDLoader")->AddDataLoader(dl);
399     }
400     fTrackletTree = dl->Tree();
401     if (!fTrackletTree)
402       {
403        dl->MakeTree();
404        fTrackletTree = dl->Tree();
405       }
406     TBranch *trkbranch = fTrackletTree->GetBranch("trkbranch");
407     if (!trkbranch)
408       fTrackletTree->Branch("trkbranch",leaves[0],"det/i:side/i:tracklets[256]/i");
409   }
410
411   return kTRUE;
412 }
413
414 //_____________________________________________________________________________
415 Bool_t AliTRDclusterizer::OpenInput(Int_t nEvent)
416 {
417   //
418   // Opens a ROOT-file with TRD-hits and reads in the digits-tree
419   //
420
421   // Import the Trees for the event nEvent in the file
422   fRunLoader->GetEvent(nEvent);
423   
424   return kTRUE;
425
426 }
427
428 //_____________________________________________________________________________
429 Bool_t AliTRDclusterizer::WriteClusters(Int_t det)
430 {
431   //
432   // Fills TRDcluster branch in the tree with the clusters 
433   // found in detector = det. For det=-1 writes the tree. 
434   //
435
436   if ((det <                      -1) || 
437       (det >= AliTRDgeometry::Ndet())) {
438     AliError(Form("Unexpected detector index %d.\n",det));
439     return kFALSE;
440   }
441
442   TObjArray *ioArray = new TObjArray(400);
443   TBranch *branch = fClusterTree->GetBranch("TRDcluster");
444   if (!branch) {
445     branch = fClusterTree->Branch("TRDcluster","TObjArray",&ioArray,32000,0);
446   } else branch->SetAddress(&ioArray);
447   
448   Int_t nRecPoints = RecPoints()->GetEntriesFast();
449   if(det >= 0){
450     for (Int_t i = 0; i < nRecPoints; i++) {
451       AliTRDcluster *c = (AliTRDcluster *) RecPoints()->UncheckedAt(i);
452       if(det != c->GetDetector()) continue;
453       ioArray->AddLast(c);
454     }
455     fClusterTree->Fill();
456     ioArray->Clear();
457   } else {
458     Int_t detOld = -1, nw(0);
459     for (Int_t i = 0; i < nRecPoints; i++) {
460       AliTRDcluster *c = (AliTRDcluster *) RecPoints()->UncheckedAt(i);
461       if(c->GetDetector() != detOld){
462         nw += ioArray->GetEntriesFast();
463         fClusterTree->Fill();
464         ioArray->Clear();
465         detOld = c->GetDetector();
466       } 
467       ioArray->AddLast(c);
468     }
469     if(ioArray->GetEntriesFast()){
470       nw += ioArray->GetEntriesFast();
471       fClusterTree->Fill();
472       ioArray->Clear();
473     }
474     AliDebug(2, Form("Clusters FOUND[%d] WRITTEN[%d] STATUS[%s]", nRecPoints, nw, nw==nRecPoints?"OK":"FAILED"));
475   }
476   delete ioArray;
477
478   return kTRUE;  
479 }
480
481 //_____________________________________________________________________________
482 Bool_t AliTRDclusterizer::WriteTracklets(Int_t det)
483 {
484   //
485   // Write the raw data tracklets into seperate file
486   //
487
488   UInt_t **leaves = new UInt_t *[2];
489   for (Int_t i=0; i<2 ;i++){
490     leaves[i] = new UInt_t[258];
491     leaves[i][0] = det; // det
492     leaves[i][1] = i;   // side
493     memcpy(leaves[i]+2, fTrackletContainer[i], sizeof(UInt_t) * 256);
494   }
495
496   if (!fTrackletTree){
497     AliDataLoader *dl = fRunLoader->GetLoader("TRDLoader")->GetDataLoader("tracklets");
498     dl->MakeTree();
499     fTrackletTree = dl->Tree();
500   }
501
502   TBranch *trkbranch = fTrackletTree->GetBranch("trkbranch");
503   if (!trkbranch) {
504     trkbranch = fTrackletTree->Branch("trkbranch",leaves[0],"det/i:side/i:tracklets[256]/i");
505   }
506
507   for (Int_t i=0; i<2; i++){
508     if (leaves[i][2]>0) {
509       trkbranch->SetAddress(leaves[i]);
510       fTrackletTree->Fill();
511     }
512   }
513
514   AliDataLoader *dl = fRunLoader->GetLoader("TRDLoader")->GetDataLoader("tracklets");
515   dl->WriteData("OVERWRITE");
516   //dl->Unload();
517   delete [] leaves;
518
519   return kTRUE;
520
521 }
522
523 //_____________________________________________________________________________
524 Bool_t AliTRDclusterizer::ReadDigits()
525 {
526   //
527   // Reads the digits arrays from the input aliroot file
528   //
529
530   if (!fRunLoader) {
531     AliError("No run loader available");
532     return kFALSE;
533   }
534
535   AliLoader* loader = fRunLoader->GetLoader("TRDLoader");
536   if (!loader->TreeD()) {
537     loader->LoadDigits();
538   }
539
540   // Read in the digit arrays
541   return (fDigitsManager->ReadDigits(loader->TreeD()));
542
543 }
544
545 //_____________________________________________________________________________
546 Bool_t AliTRDclusterizer::ReadDigits(TTree *digitsTree)
547 {
548   //
549   // Reads the digits arrays from the input tree
550   //
551
552   // Read in the digit arrays
553   return (fDigitsManager->ReadDigits(digitsTree));
554
555 }
556
557 //_____________________________________________________________________________
558 Bool_t AliTRDclusterizer::ReadDigits(AliRawReader *rawReader)
559 {
560   //
561   // Reads the digits arrays from the ddl file
562   //
563
564   AliTRDrawData raw;
565   fDigitsManager = raw.Raw2Digits(rawReader);
566
567   return kTRUE;
568
569 }
570
571 //_____________________________________________________________________________
572 Bool_t AliTRDclusterizer::MakeClusters()
573 {
574   //
575   // Creates clusters from digits
576   //
577
578   // Propagate info from the digits manager
579   if (TestBit(kLabels)){
580     SetBit(kLabels, fDigitsManager->UsesDictionaries());
581   }
582   
583   Bool_t fReturn = kTRUE;
584   for (Int_t i = 0; i < AliTRDgeometry::kNdet; i++){
585   
586     AliTRDarrayADC *digitsIn = (AliTRDarrayADC*) fDigitsManager->GetDigits(i); //mod     
587     // This is to take care of switched off super modules
588     if (!digitsIn->HasData()) continue;
589     digitsIn->Expand();
590     digitsIn->DeleteNegatives();  // Restore digits array to >=0 values
591     AliTRDSignalIndex* indexes = fDigitsManager->GetIndexes(i);
592     if (indexes->IsAllocated() == kFALSE){
593       fDigitsManager->BuildIndexes(i);
594     }
595   
596     Bool_t fR = kFALSE;
597     if (indexes->HasEntry()){
598       if (TestBit(kLabels)){
599         for (Int_t iDict = 0; iDict < AliTRDdigitsManager::kNDict; iDict++){
600           AliTRDarrayDictionary *tracksIn = 0; //mod
601           tracksIn = (AliTRDarrayDictionary *) fDigitsManager->GetDictionary(i,iDict);  //mod
602           tracksIn->Expand();
603         }
604       }
605       fR = MakeClusters(i);
606       fReturn = fR && fReturn;
607     }
608   
609     //if (fR == kFALSE){
610     //  if(IsWritingClusters()) WriteClusters(i);
611     //  ResetRecPoints();
612     //}
613         
614     // No compress just remove
615     fDigitsManager->RemoveDigits(i);
616     fDigitsManager->RemoveDictionaries(i);      
617     fDigitsManager->ClearIndexes(i);  
618   }
619   fReconstructor->SetDigitsParam(fDigitsManager->GetDigitsParam());
620   
621   if(fReconstructor->IsWritingClusters()) WriteClusters(-1);
622
623   AliInfo(Form("Number of found clusters : %d", RecPoints()->GetEntriesFast())); 
624
625   return fReturn;
626
627 }
628
629 //_____________________________________________________________________________
630 Bool_t AliTRDclusterizer::Raw2Clusters(AliRawReader *rawReader)
631 {
632   //
633   // Creates clusters from raw data
634   //
635
636   return Raw2ClustersChamber(rawReader);
637
638 }
639
640 //_____________________________________________________________________________
641 Bool_t AliTRDclusterizer::Raw2ClustersChamber(AliRawReader *rawReader)
642 {
643   //
644   // Creates clusters from raw data
645   //
646
647   // Create the digits manager
648   if (!fDigitsManager){
649     SetBit(knewDM, kTRUE);
650     fDigitsManager = new AliTRDdigitsManager(kTRUE);
651     fDigitsManager->CreateArrays();
652   }
653
654   fDigitsManager->SetUseDictionaries(TestBit(kLabels));
655
656   // tracklet container for raw tracklet writing
657   if (!fTrackletContainer && ( fReconstructor->IsWritingTracklets() || fReconstructor->IsProcessingTracklets() )) {
658     // maximum tracklets for one HC
659     const Int_t kTrackletChmb=256;
660     fTrackletContainer = new UInt_t *[2];
661     fTrackletContainer[0] = new UInt_t[kTrackletChmb]; 
662     fTrackletContainer[1] = new UInt_t[kTrackletChmb]; 
663   }
664
665   if(!fRawStream)
666     fRawStream = AliTRDrawStreamBase::GetRawStream(rawReader);
667   else
668     fRawStream->SetReader(rawReader);
669
670   if(fReconstructor->IsHLT()){
671     fRawStream->SetSharedPadReadout(kFALSE);
672     fRawStream->SetNoErrorWarning();
673   }
674
675   AliDebug(1,Form("Stream version: %s", fRawStream->IsA()->GetName()));
676   
677   Int_t det    = 0;
678   while ((det = fRawStream->NextChamber(fDigitsManager,fTrackletContainer)) >= 0){
679     Bool_t iclusterBranch = kFALSE;
680     if (fDigitsManager->GetIndexes(det)->HasEntry()){
681       iclusterBranch = MakeClusters(det);
682     }
683
684     fDigitsManager->ClearArrays(det);
685
686     if (!fReconstructor->IsWritingTracklets()) continue;
687     if (*(fTrackletContainer[0]) > 0 || *(fTrackletContainer[1]) > 0) WriteTracklets(det);
688   }
689   fReconstructor->SetDigitsParam(fDigitsManager->GetDigitsParam());
690   
691   if (fTrackletContainer){
692     delete [] fTrackletContainer[0];
693     delete [] fTrackletContainer[1];
694     delete [] fTrackletContainer;
695     fTrackletContainer = NULL;
696   }
697
698   if(fReconstructor->IsWritingClusters()) WriteClusters(-1);
699
700   if(!TestBit(knewDM)){
701     delete fDigitsManager;
702     fDigitsManager = NULL;
703     delete fRawStream;
704     fRawStream = NULL;
705   }
706
707   AliInfo(Form("Number of found clusters : %d", fNoOfClusters)); 
708   return kTRUE;
709
710 }
711
712 //_____________________________________________________________________________
713 UChar_t AliTRDclusterizer::GetStatus(Short_t &signal)
714 {
715   //
716   // Check if a pad is masked
717   //
718
719   UChar_t status = 0;
720
721   if(signal>0 && TESTBIT(signal, 10)){
722     CLRBIT(signal, 10);
723     for(int ibit=0; ibit<4; ibit++){
724       if(TESTBIT(signal, 11+ibit)){
725         SETBIT(status, ibit);
726         CLRBIT(signal, 11+ibit);
727       } 
728     }
729   }
730   return status;
731 }
732
733 //_____________________________________________________________________________
734 void AliTRDclusterizer::SetPadStatus(const UChar_t status, UChar_t &out) const {
735   //
736   // Set the pad status into out
737   // First three bits are needed for the position encoding
738   //
739   out |= status << 3;
740 }
741
742 //_____________________________________________________________________________
743 UChar_t AliTRDclusterizer::GetPadStatus(UChar_t encoding) const {
744   //
745   // return the staus encoding of the corrupted pad
746   //
747   return static_cast<UChar_t>(encoding >> 3);
748 }
749
750 //_____________________________________________________________________________
751 Int_t AliTRDclusterizer::GetCorruption(UChar_t encoding) const {
752   //
753   // Return the position of the corruption
754   //
755   return encoding & 7;
756 }
757
758 //_____________________________________________________________________________
759 Bool_t AliTRDclusterizer::MakeClusters(Int_t det)
760 {
761   //
762   // Generates the cluster.
763   //
764
765   // Get the digits
766   fDigits = (AliTRDarrayADC *) fDigitsManager->GetDigits(det); //mod
767   fBaseline = fDigitsManager->GetDigitsParam()->GetADCbaseline();
768   
769   // This is to take care of switched off super modules
770   if (!fDigits->HasData()) return kFALSE;
771
772   fIndexes = fDigitsManager->GetIndexes(det);
773   if (fIndexes->IsAllocated() == kFALSE) {
774     AliError("Indexes do not exist!");
775     return kFALSE;      
776   }
777
778   AliTRDcalibDB  *calibration = AliTRDcalibDB::Instance();
779   if (!calibration) {
780     AliFatal("No AliTRDcalibDB instance available\n");
781     return kFALSE;  
782   }
783
784   if (!fReconstructor){
785     AliError("Reconstructor not set\n");
786     return kFALSE;
787   }
788
789   fMaxThresh            = fReconstructor->GetRecoParam()->GetClusMaxThresh();
790   fSigThresh            = fReconstructor->GetRecoParam()->GetClusSigThresh();
791   fMinMaxCutSigma       = fReconstructor->GetRecoParam()->GetMinMaxCutSigma();
792   fMinLeftRightCutSigma = fReconstructor->GetRecoParam()->GetMinLeftRightCutSigma();
793
794   Int_t istack  = fIndexes->GetStack();
795   fLayer  = fIndexes->GetLayer();
796   Int_t isector = fIndexes->GetSM();
797
798   // Start clustering in the chamber
799
800   fDet  = AliTRDgeometry::GetDetector(fLayer,istack,isector);
801   if (fDet != det) {
802     AliError("Strange Detector number Missmatch!");
803     return kFALSE;
804   }
805
806   AliDebug(2, Form("Det[%d] @ Sec[%d] Stk[%d] Ly[%d]", fDet, isector, istack, fLayer));
807
808   // TRD space point transformation
809   fTransform->SetDetector(det);
810
811   Int_t    iGeoLayer  = AliGeomManager::kTRD1 + fLayer;
812   Int_t    iGeoModule = istack + AliTRDgeometry::Nstack() * isector;
813   fVolid      = AliGeomManager::LayerToVolUID(iGeoLayer,iGeoModule); 
814
815   if(fReconstructor->IsProcessingTracklets() && fTrackletContainer)
816     AddTrackletsToArray();
817
818   fColMax    = fDigits->GetNcol();
819   //Int_t nRowMax    = fDigits->GetNrow();
820   fTimeTotal = fDigits->GetNtime();
821
822   // Check consistency between OCDB and raw data
823   Int_t nTimeOCDB = calibration->GetNumberOfTimeBinsDCS();
824   if ((nTimeOCDB  >         -1) &&
825       (fTimeTotal != nTimeOCDB)) {
826     AliError(Form("Number of timebins does not match OCDB value (RAW[%d] OCDB[%d])"
827                 ,fTimeTotal,calibration->GetNumberOfTimeBinsDCS()));
828   }
829
830   // Detector wise calibration object for the gain factors
831   const AliTRDCalDet *calGainFactorDet = calibration->GetGainFactorDet();
832   // Calibration object with pad wise values for the gain factors
833   fCalGainFactorROC      = calibration->GetGainFactorROC(fDet);
834   // Calibration value for chamber wise gain factor
835   fCalGainFactorDetValue = calGainFactorDet->GetValue(fDet);
836
837   // Detector wise calibration object for the noise
838   const AliTRDCalDet *calNoiseDet = calibration->GetNoiseDet();
839   // Calibration object with pad wise values for the noise
840   fCalNoiseROC           = calibration->GetNoiseROC(fDet);
841   // Calibration value for chamber wise noise
842   fCalNoiseDetValue      = calNoiseDet->GetValue(fDet);
843   
844   // Calibration object with the pad status
845   fCalPadStatusROC       = calibration->GetPadStatusROC(fDet);
846
847   SetBit(kLUT, fReconstructor->GetRecoParam()->UseLUT());
848   SetBit(kGAUS, fReconstructor->GetRecoParam()->UseGAUS());
849   SetBit(kHLT, fReconstructor->IsHLT());
850   
851   firstClusterROC = -1;
852   fClusterROC     =  0;
853
854   // Apply the gain and the tail cancelation via digital filter
855   if(fReconstructor->GetRecoParam()->UseTailCancelation()) TailCancelation();
856
857   MaxStruct curr, last;
858   Int_t nMaximas = 0, nCorrupted = 0;
859
860   // Here the clusterfining is happening
861   
862   for(curr.time = 0; curr.time < fTimeTotal; curr.time++){
863     while(fIndexes->NextRCIndex(curr.row, curr.col)){
864       if(IsMaximum(curr, curr.padStatus, &curr.signals[0])){
865         if(last.row>-1){
866           if(curr.time==last.time && curr.row==last.row && curr.col==last.col+2) FivePadCluster(last, curr);
867           CreateCluster(last);
868         }
869         last=curr; curr.fivePad=kFALSE;
870       }
871     }
872   }
873   if(last.row>-1) CreateCluster(last);
874
875   if(fReconstructor->GetRecoParam()->GetStreamLevel(AliTRDrecoParam::kClusterizer) > 2 && fReconstructor->IsDebugStreaming()){
876     TTreeSRedirector* fDebugStream = fReconstructor->GetDebugStream(AliTRDrecoParam::kClusterizer);
877     (*fDebugStream) << "MakeClusters"
878       << "Detector="   << det
879       << "NMaxima="    << nMaximas
880       << "NClusters="  << fClusterROC
881       << "NCorrupted=" << nCorrupted
882       << "\n";
883   }
884   if (TestBit(kLabels)) AddLabels();
885
886   return kTRUE;
887
888 }
889
890 //_____________________________________________________________________________
891 Bool_t AliTRDclusterizer::IsMaximum(const MaxStruct &Max, UChar_t &padStatus, Short_t *const Signals) 
892 {
893   //
894   // Returns true if this row,col,time combination is a maximum. 
895   // Gives back the padStatus and the signals of the center pad and the two neighbouring pads.
896   //
897
898   Float_t gain = fCalGainFactorDetValue * fCalGainFactorROC->GetValue(Max.col,Max.row);
899   Signals[1] = (Short_t)((fDigits->GetData(Max.row, Max.col, Max.time) - fBaseline) / gain + 0.5f);
900   if(Signals[1] < fMaxThresh) return kFALSE;
901
902   Float_t  noiseMiddleThresh = fMinMaxCutSigma*fCalNoiseDetValue*fCalNoiseROC->GetValue(Max.col, Max.row);
903   if (Signals[1] < noiseMiddleThresh) return kFALSE;
904
905   if (Max.col + 1 >= fColMax || Max.col < 1) return kFALSE;
906
907   UChar_t status[3]={
908     fCalPadStatusROC->GetStatus(Max.col-1, Max.row)
909    ,fCalPadStatusROC->GetStatus(Max.col,   Max.row)
910    ,fCalPadStatusROC->GetStatus(Max.col+1, Max.row)
911   };
912
913   gain = fCalGainFactorDetValue * fCalGainFactorROC->GetValue(Max.col-1,Max.row);
914   Signals[0] = (Short_t)((fDigits->GetData(Max.row, Max.col-1, Max.time) - fBaseline) / gain + 0.5f);
915   gain = fCalGainFactorDetValue * fCalGainFactorROC->GetValue(Max.col+1,Max.row);
916   Signals[2] = (Short_t)((fDigits->GetData(Max.row, Max.col+1, Max.time) - fBaseline) / gain + 0.5f);
917
918   if(!(status[0] | status[1] | status[2])) {//all pads are good
919     if ((Signals[2] <= Signals[1]) && (Signals[0] <  Signals[1])) {
920       if ((Signals[2] >= fSigThresh) || (Signals[0] >= fSigThresh)) {
921         if(Signals[0]<0)Signals[0]=0;
922         if(Signals[2]<0)Signals[2]=0;
923         Float_t  noiseSumThresh = fMinLeftRightCutSigma
924           * fCalNoiseDetValue
925           * fCalNoiseROC->GetValue(Max.col, Max.row);
926         if ((Signals[2]+Signals[0]+Signals[1]) < noiseSumThresh) return kFALSE;
927         padStatus = 0;
928         return kTRUE;
929       }
930     }
931   } else { // at least one of the pads is bad, and reject candidates with more than 1 problematic pad
932     if(Signals[0]<0)Signals[0]=0;
933     if(Signals[2]<0)Signals[2]=0;
934     if (status[2] && (!(status[0] || status[1])) && Signals[1] > Signals[0] && Signals[0] >= fSigThresh) { 
935       Signals[2]=0;
936       SetPadStatus(status[2], padStatus);
937       return kTRUE;
938     } 
939     else if (status[0] && (!(status[1] || status[2])) && Signals[1] >= Signals[2] && Signals[2] >= fSigThresh) {
940       Signals[0]=0;
941       SetPadStatus(status[0], padStatus);
942       return kTRUE;
943     }
944     else if (status[1] && (!(status[0] || status[2])) && ((Signals[2] >= fSigThresh) || (Signals[0] >= fSigThresh))) {
945       Signals[1] = (Short_t)(fMaxThresh + 0.5f);
946       SetPadStatus(status[1], padStatus);
947       return kTRUE;
948     }
949   }
950   return kFALSE;
951 }
952
953 //_____________________________________________________________________________
954 Bool_t AliTRDclusterizer::FivePadCluster(MaxStruct &ThisMax, MaxStruct &NeighbourMax)
955 {
956   //
957   // Look for 5 pad cluster with minimum in the middle
958   // Gives back the ratio
959   //
960   
961   if (ThisMax.col >= fColMax - 3) return kFALSE;
962   Float_t gain;
963   if (ThisMax.col < fColMax - 5){
964     gain = fCalGainFactorDetValue * fCalGainFactorROC->GetValue(ThisMax.col+4,ThisMax.row);
965     if (fDigits->GetData(ThisMax.row, ThisMax.col+4, ThisMax.time) - fBaseline >= fSigThresh * gain)
966       return kFALSE;
967   }
968   if (ThisMax.col > 1) {
969     gain = fCalGainFactorDetValue * fCalGainFactorROC->GetValue(ThisMax.col-2,ThisMax.row);
970     if (fDigits->GetData(ThisMax.row, ThisMax.col-2, ThisMax.time) - fBaseline >= fSigThresh * gain)
971       return kFALSE;
972   }
973   
974   const Float_t kEpsilon = 0.01;
975   Double_t padSignal[5] = {ThisMax.signals[0], ThisMax.signals[1], ThisMax.signals[2],
976       NeighbourMax.signals[1], NeighbourMax.signals[2]};
977   
978   // Unfold the two maxima and set the signal on 
979   // the overlapping pad to the ratio
980   Float_t ratio = Unfold(kEpsilon,fLayer,padSignal);
981   ThisMax.signals[2] = (Short_t)(ThisMax.signals[2]*ratio + 0.5f);
982   NeighbourMax.signals[0] = (Short_t)(NeighbourMax.signals[0]*(1-ratio) + 0.5f);
983   ThisMax.fivePad=kTRUE;
984   NeighbourMax.fivePad=kTRUE;
985   return kTRUE;
986
987 }
988
989 //_____________________________________________________________________________
990 void AliTRDclusterizer::CreateCluster(const MaxStruct &Max)
991 {
992   //
993   // Creates a cluster at the given position and saves it in fRecPoints
994   //
995
996   Int_t nPadCount = 1;
997   Short_t signals[7] = { 0, 0, Max.signals[0], Max.signals[1], Max.signals[2], 0, 0 };
998   if(!TestBit(kHLT)) CalcAdditionalInfo(Max, signals, nPadCount);
999
1000   AliTRDcluster cluster(fDet, ((UChar_t) Max.col), ((UChar_t) Max.row), ((UChar_t) Max.time), signals, fVolid);
1001   cluster.SetNPads(nPadCount);
1002   if(TestBit(kLUT)) cluster.SetRPhiMethod(AliTRDcluster::kLUT);
1003   else if(TestBit(kGAUS)) cluster.SetRPhiMethod(AliTRDcluster::kGAUS);
1004   else cluster.SetRPhiMethod(AliTRDcluster::kCOG);
1005
1006   cluster.SetFivePad(Max.fivePad);
1007   // set pads status for the cluster
1008   UChar_t maskPosition = GetCorruption(Max.padStatus);
1009   if (maskPosition) { 
1010     cluster.SetPadMaskedPosition(maskPosition);
1011     cluster.SetPadMaskedStatus(GetPadStatus(Max.padStatus));
1012   }
1013
1014   // Transform the local cluster coordinates into calibrated 
1015   // space point positions defined in the local tracking system.
1016   // Here the calibration for T0, Vdrift and ExB is applied as well.
1017   if(!fTransform->Transform(&cluster)) return;
1018   // Temporarily store the Max.Row, column and time bin of the center pad
1019   // Used to later on assign the track indices
1020   cluster.SetLabel(Max.row, 0);
1021   cluster.SetLabel(Max.col, 1);
1022   cluster.SetLabel(Max.time,2);
1023
1024   //needed for HLT reconstruction
1025   AddClusterToArray(&cluster); 
1026
1027   // Store the index of the first cluster in the current ROC
1028   if (firstClusterROC < 0) firstClusterROC = fNoOfClusters;
1029   
1030   fNoOfClusters++;
1031   fClusterROC++;
1032 }
1033
1034 //_____________________________________________________________________________
1035 void AliTRDclusterizer::CalcAdditionalInfo(const MaxStruct &Max, Short_t *const signals, Int_t &nPadCount)
1036 {
1037   // Look to the right
1038   Int_t ii = 1;
1039   while (fDigits->GetData(Max.row, Max.col-ii, Max.time) >= fSigThresh) {
1040     nPadCount++;
1041     ii++;
1042     if (Max.col < ii) break;
1043   }
1044   // Look to the left
1045   ii = 1;
1046   while (fDigits->GetData(Max.row, Max.col+ii, Max.time) >= fSigThresh) {
1047     nPadCount++;
1048     ii++;
1049     if (Max.col+ii >= fColMax) break;
1050   }
1051
1052   // Store the amplitudes of the pads in the cluster for later analysis
1053   // and check whether one of these pads is masked in the database
1054   signals[2]=Max.signals[0];
1055   signals[3]=Max.signals[1];
1056   signals[4]=Max.signals[2];
1057   Float_t gain;
1058   for(Int_t i = 0; i<2; i++)
1059     {
1060       if(Max.col+i >= 3){
1061         gain = fCalGainFactorDetValue * fCalGainFactorROC->GetValue(Max.col-3+i,Max.row);
1062         signals[i] = (Short_t)((fDigits->GetData(Max.row, Max.col-3+i, Max.time) - fBaseline) / gain + 0.5f);
1063       }
1064       if(Max.col+3-i < fColMax){
1065         gain = fCalGainFactorDetValue * fCalGainFactorROC->GetValue(Max.col+3-i,Max.row);
1066         signals[6-i] = (Short_t)((fDigits->GetData(Max.row, Max.col+3-i, Max.time) - fBaseline) / gain + 0.5f);
1067       }
1068     }
1069   /*for (Int_t jPad = Max.Col-3; jPad <= Max.Col+3; jPad++) {
1070     if ((jPad >= 0) && (jPad < fColMax))
1071       signals[jPad-Max.Col+3] = TMath::Nint(fDigits->GetData(Max.Row,jPad,Max.Time));
1072       }*/
1073 }
1074
1075 //_____________________________________________________________________________
1076 void AliTRDclusterizer::AddClusterToArray(AliTRDcluster* cluster)
1077 {
1078   //
1079   // Add a cluster to the array
1080   //
1081
1082   Int_t n = RecPoints()->GetEntriesFast();
1083   if(n!=fNoOfClusters)AliError(Form("fNoOfClusters != RecPoints()->GetEntriesFast %i != %i \n", fNoOfClusters, n));
1084   new((*RecPoints())[n]) AliTRDcluster(*cluster);
1085 }
1086
1087 //_____________________________________________________________________________
1088 void AliTRDclusterizer::AddTrackletsToArray()
1089 {
1090   //
1091   // Add the online tracklets of this chamber to the array
1092   //
1093
1094   UInt_t* trackletword;
1095   for(Int_t side=0; side<2; side++)
1096     {
1097       Int_t trkl=0;
1098       trackletword=fTrackletContainer[side];
1099       while(trackletword[trkl]>0){
1100         Int_t n = TrackletsArray()->GetEntriesFast();
1101         AliTRDtrackletWord tmp(trackletword[trkl]);
1102         new((*TrackletsArray())[n]) AliTRDcluster(&tmp,fDet,fVolid);
1103         trkl++;
1104       }
1105     }
1106 }
1107
1108 //_____________________________________________________________________________
1109 Bool_t AliTRDclusterizer::AddLabels()
1110 {
1111   //
1112   // Add the track indices to the found clusters
1113   //
1114   
1115   const Int_t   kNclus  = 3;  
1116   const Int_t   kNdict  = AliTRDdigitsManager::kNDict;
1117   const Int_t   kNtrack = kNdict * kNclus;
1118
1119   Int_t iClusterROC = 0;
1120
1121   Int_t row  = 0;
1122   Int_t col  = 0;
1123   Int_t time = 0;
1124   Int_t iPad = 0;
1125
1126   // Temporary array to collect the track indices
1127   Int_t *idxTracks = new Int_t[kNtrack*fClusterROC];
1128
1129   // Loop through the dictionary arrays one-by-one
1130   // to keep memory consumption low
1131   AliTRDarrayDictionary *tracksIn = 0;  //mod
1132   for (Int_t iDict = 0; iDict < kNdict; iDict++) {
1133
1134     // tracksIn should be expanded beforehand!
1135     tracksIn = (AliTRDarrayDictionary *) fDigitsManager->GetDictionary(fDet,iDict);
1136
1137     // Loop though the clusters found in this ROC
1138     for (iClusterROC = 0; iClusterROC < fClusterROC; iClusterROC++) {
1139
1140       AliTRDcluster *cluster = (AliTRDcluster *)
1141                                RecPoints()->UncheckedAt(firstClusterROC+iClusterROC);
1142       row  = cluster->GetLabel(0);
1143       col  = cluster->GetLabel(1);
1144       time = cluster->GetLabel(2);
1145
1146       for (iPad = 0; iPad < kNclus; iPad++) {
1147         Int_t iPadCol = col - 1 + iPad;
1148         Int_t index   = tracksIn->GetData(row,iPadCol,time);  //Modification of -1 in Track
1149         idxTracks[3*iPad+iDict + iClusterROC*kNtrack] = index;     
1150       }
1151
1152     }
1153
1154   }
1155
1156   // Copy the track indices into the cluster
1157   // Loop though the clusters found in this ROC
1158   for (iClusterROC = 0; iClusterROC < fClusterROC; iClusterROC++) {
1159
1160     AliTRDcluster *cluster = (AliTRDcluster *)
1161       RecPoints()->UncheckedAt(firstClusterROC+iClusterROC);
1162     cluster->SetLabel(-9999,0);
1163     cluster->SetLabel(-9999,1);
1164     cluster->SetLabel(-9999,2);
1165   
1166     cluster->AddTrackIndex(&idxTracks[iClusterROC*kNtrack]);
1167
1168   }
1169
1170   delete [] idxTracks;
1171
1172   return kTRUE;
1173
1174 }
1175
1176 //_____________________________________________________________________________
1177 Float_t AliTRDclusterizer::Unfold(Double_t eps, Int_t layer, const Double_t *const padSignal) const
1178 {
1179   //
1180   // Method to unfold neighbouring maxima.
1181   // The charge ratio on the overlapping pad is calculated
1182   // until there is no more change within the range given by eps.
1183   // The resulting ratio is then returned to the calling method.
1184   //
1185
1186   AliTRDcalibDB *calibration = AliTRDcalibDB::Instance();
1187   if (!calibration) {
1188     AliError("No AliTRDcalibDB instance available\n");
1189     return kFALSE;  
1190   }
1191   
1192   Int_t   irc                = 0;
1193   Int_t   itStep             = 0;                 // Count iteration steps
1194
1195   Double_t ratio             = 0.5;               // Start value for ratio
1196   Double_t prevRatio         = 0.0;               // Store previous ratio
1197
1198   Double_t newLeftSignal[3]  = { 0.0, 0.0, 0.0 }; // Array to store left cluster signal
1199   Double_t newRightSignal[3] = { 0.0, 0.0, 0.0 }; // Array to store right cluster signal
1200   Double_t newSignal[3]      = { 0.0, 0.0, 0.0 };
1201
1202   // Start the iteration
1203   while ((TMath::Abs(prevRatio - ratio) > eps) && (itStep < 10)) {
1204
1205     itStep++;
1206     prevRatio = ratio;
1207
1208     // Cluster position according to charge ratio
1209     Double_t maxLeft  = (ratio*padSignal[2] - padSignal[0]) 
1210                       / (padSignal[0] + padSignal[1] + ratio * padSignal[2]);
1211     Double_t maxRight = (padSignal[4] - (1-ratio)*padSignal[2]) 
1212                       / ((1.0 - ratio)*padSignal[2] + padSignal[3] + padSignal[4]);
1213
1214     // Set cluster charge ratio
1215     irc = calibration->PadResponse(1.0, maxLeft, layer, newSignal);
1216     Double_t ampLeft  = padSignal[1] / newSignal[1];
1217     irc = calibration->PadResponse(1.0, maxRight, layer, newSignal);
1218     Double_t ampRight = padSignal[3] / newSignal[1];
1219
1220     // Apply pad response to parameters
1221     irc = calibration->PadResponse(ampLeft ,maxLeft ,layer,newLeftSignal );
1222     irc = calibration->PadResponse(ampRight,maxRight,layer,newRightSignal);
1223
1224     // Calculate new overlapping ratio
1225     ratio = TMath::Min((Double_t) 1.0
1226                       ,newLeftSignal[2] / (newLeftSignal[2] + newRightSignal[0]));
1227
1228   }
1229
1230   return ratio;
1231
1232 }
1233
1234 //_____________________________________________________________________________
1235 void AliTRDclusterizer::TailCancelation()
1236 {
1237   //
1238   // Applies the tail cancelation and gain factors: 
1239   // Transform fDigits to fDigits
1240   //
1241
1242   Int_t iRow  = 0;
1243   Int_t iCol  = 0;
1244   Int_t iTime = 0;
1245
1246   Float_t *arr = new Float_t[fTimeTotal];  // temp array containing the ADC signals
1247
1248   TTreeSRedirector *fDebugStream = fReconstructor->GetDebugStream(AliTRDrecoParam::kClusterizer);
1249   Bool_t debugStreaming = fReconstructor->GetRecoParam()->GetStreamLevel(AliTRDrecoParam::kClusterizer) > 7 && fReconstructor->IsDebugStreaming();
1250   Int_t nexp = fReconstructor->GetRecoParam()->GetTCnexp();
1251   while(fIndexes->NextRCIndex(iRow, iCol))
1252     {
1253       // if corrupted then don't make the tail cancallation
1254       if (fCalPadStatusROC->GetStatus(iCol, iRow)) continue;
1255
1256       // Save data into the temporary processing array and substract the baseline,
1257       // since DeConvExp does not expect a baseline
1258       for (iTime = 0; iTime < fTimeTotal; iTime++) 
1259         arr[iTime] = fDigits->GetData(iRow,iCol,iTime)-fBaseline;
1260           
1261       if(debugStreaming){
1262         for (iTime = 0; iTime < fTimeTotal; iTime++) 
1263           (*fDebugStream) << "TailCancellation"
1264                           << "col="  << iCol
1265                           << "row="  << iRow
1266                           << "time=" << iTime
1267                           << "arr=" << arr[iTime]
1268                           << "\n";
1269       }
1270       
1271       // Apply the tail cancelation via the digital filter
1272       DeConvExp(arr,fTimeTotal,nexp);
1273
1274       // Save tailcancalled data and add the baseline
1275       for(iTime = 0; iTime < fTimeTotal; iTime++)
1276         fDigits->SetData(iRow,iCol,iTime,(Short_t)(arr[iTime] + fBaseline + 0.5f));
1277       
1278     } // while irow icol
1279
1280   delete [] arr;
1281
1282   return;
1283
1284 }
1285
1286 //_____________________________________________________________________________
1287 void AliTRDclusterizer::DeConvExp(Float_t *const arr, const Int_t n, const Int_t nexp) 
1288 {
1289   //
1290   // Tail cancellation by deconvolution for PASA v4 TRF
1291   //
1292
1293   Float_t rates[2];
1294   Float_t coefficients[2];
1295
1296   // Initialization (coefficient = alpha, rates = lambda)
1297   Float_t r1 = 1.0;
1298   Float_t r2 = 1.0;
1299   Float_t c1 = 0.5;
1300   Float_t c2 = 0.5;
1301
1302   if (nexp == 1) {   // 1 Exponentials
1303     r1 = 1.156;
1304     r2 = 0.130;
1305     c1 = 0.066;
1306     c2 = 0.000;
1307   }
1308   if (nexp == 2) {   // 2 Exponentials
1309     Double_t par[4];
1310     fReconstructor->GetRecoParam()->GetTCParams(par);
1311     r1 = par[0];//1.156;
1312     r2 = par[1];//0.130;
1313     c1 = par[2];//0.114;
1314     c2 = par[3];//0.624;
1315   }
1316
1317   coefficients[0] = c1;
1318   coefficients[1] = c2;
1319
1320   Float_t dt = 0.1;
1321
1322   rates[0] = TMath::Exp(-dt/(r1));
1323   rates[1] = TMath::Exp(-dt/(r2));
1324   
1325   Int_t i = 0;
1326   Int_t k = 0;
1327
1328   Float_t reminder[2];
1329   Float_t correction = 0.0;
1330   Float_t result     = 0.0;
1331
1332   // Attention: computation order is important
1333   for (k = 0; k < nexp; k++) {
1334     reminder[k] = 0.0;
1335   }
1336
1337   for (i = 0; i < n; i++) {
1338
1339     result = (arr[i] - correction);    // No rescaling
1340     arr[i] = result;
1341
1342     for (k = 0; k < nexp; k++) {
1343       reminder[k] = rates[k] * (reminder[k] + coefficients[k] * result);
1344     }
1345
1346     correction = 0.0;
1347     for (k = 0; k < nexp; k++) {
1348       correction += reminder[k];
1349     }
1350
1351   }
1352
1353 }
1354
1355 //_____________________________________________________________________________
1356 void AliTRDclusterizer::ResetRecPoints() 
1357 {
1358   //
1359   // Resets the list of rec points
1360   //
1361
1362   if (fRecPoints) {
1363     fRecPoints->Delete();
1364     delete fRecPoints;
1365   }
1366 }
1367
1368 //_____________________________________________________________________________
1369 TClonesArray *AliTRDclusterizer::RecPoints() 
1370 {
1371   //
1372   // Returns the list of rec points
1373   //
1374
1375   if (!fRecPoints) {
1376     if(!(fRecPoints = AliTRDReconstructor::GetClusters())){
1377       // determine number of clusters which has to be allocated
1378       Float_t nclusters = fReconstructor->GetRecoParam()->GetNClusters();
1379
1380       fRecPoints = new TClonesArray("AliTRDcluster", Int_t(nclusters));
1381     }
1382     //SetClustersOwner(kTRUE);
1383     AliTRDReconstructor::SetClusters(0x0);
1384   }
1385   return fRecPoints;
1386
1387 }
1388
1389 //_____________________________________________________________________________
1390 TClonesArray *AliTRDclusterizer::TrackletsArray() 
1391 {
1392   //
1393   // Returns the list of rec points
1394   //
1395
1396   if (!fTracklets && fReconstructor->IsProcessingTracklets()) {
1397     fTracklets = new TClonesArray("AliTRDcluster", 2*MAXTRACKLETSPERHC);
1398     //SetClustersOwner(kTRUE);
1399     //AliTRDReconstructor::SetTracklets(0x0);
1400   }
1401   return fTracklets;
1402
1403 }
1404