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