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