]> git.uio.no Git - u/mrichter/AliRoot.git/blame - TRD/AliTRDclusterizer.cxx
Updating the main documentation page for new
[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
3fe61b77 24#include <TF1.h>
94de3818 25#include <TTree.h>
3fe61b77 26#include <TH1.h>
793ff80c 27#include <TFile.h>
66f6bfd9 28#include <TClonesArray.h>
6d50f529 29#include <TObjArray.h>
f7336fa3 30
88cb7938 31#include "AliRunLoader.h"
32#include "AliLoader.h"
3fe61b77 33#include "AliRawReader.h"
6d50f529 34#include "AliLog.h"
3fe61b77 35#include "AliAlignObj.h"
88cb7938 36
f7336fa3 37#include "AliTRDclusterizer.h"
3e1a3ad8 38#include "AliTRDcluster.h"
fc546d21 39#include "AliTRDReconstructor.h"
793ff80c 40#include "AliTRDgeometry.h"
b65e5048 41#include "AliTRDarraySignal.h"
42#include "AliTRDarrayDictionary.h"
43#include "AliTRDarrayADC.h"
3fe61b77 44#include "AliTRDdigitsManager.h"
45#include "AliTRDrawData.h"
3551db50 46#include "AliTRDcalibDB.h"
fc546d21 47#include "AliTRDrecoParam.h"
b43a3e17 48#include "AliTRDCommonParam.h"
3fe61b77 49#include "AliTRDtransform.h"
50#include "AliTRDSignalIndex.h"
dfbb4bb9 51#include "AliTRDrawStreamBase.h"
3fe61b77 52#include "AliTRDfeeParam.h"
53
29f95561 54#include "TTreeStream.h"
55
3fe61b77 56#include "Cal/AliTRDCalROC.h"
57#include "Cal/AliTRDCalDet.h"
0e09df31 58#include "Cal/AliTRDCalSingleChamberStatus.h"
f7336fa3 59
60ClassImp(AliTRDclusterizer)
61
62//_____________________________________________________________________________
3a039a31 63AliTRDclusterizer::AliTRDclusterizer(AliTRDReconstructor *rec)
6d50f529 64 :TNamed()
3a039a31 65 ,fReconstructor(rec)
6d50f529 66 ,fRunLoader(NULL)
67 ,fClusterTree(NULL)
68 ,fRecPoints(NULL)
9c7c9ec1 69 ,fTrackletTree(NULL)
3fe61b77 70 ,fDigitsManager(NULL)
9c7c9ec1 71 ,fTrackletContainer(NULL)
3fe61b77 72 ,fAddLabels(kTRUE)
73 ,fRawVersion(2)
74 ,fIndexesOut(NULL)
75 ,fIndexesMaxima(NULL)
dfbb4bb9 76 ,fTransform(new AliTRDtransform(0))
fc546d21 77 ,fLUTbin(0)
78 ,fLUT(NULL)
f7336fa3 79{
80 //
81 // AliTRDclusterizer default constructor
82 //
83
a7ac01d2 84 AliTRDcalibDB *trd = 0x0;
85 if (!(trd = AliTRDcalibDB::Instance())) {
86 AliFatal("Could not get calibration object");
87 }
88
3fe61b77 89 fRawVersion = AliTRDfeeParam::Instance()->GetRAWversion();
90
3a039a31 91 // Initialize debug stream
92 if(fReconstructor){
93 if(fReconstructor->GetStreamLevel(AliTRDReconstructor::kClusterizer) > 1){
94 TDirectory *savedir = gDirectory;
29f95561 95 //fgGetDebugStream = new TTreeSRedirector("TRD.ClusterizerDebug.root");
3a039a31 96 savedir->cd();
97 }
98 }
eb52b657 99
f7336fa3 100}
101
102//_____________________________________________________________________________
3a039a31 103AliTRDclusterizer::AliTRDclusterizer(const Text_t *name, const Text_t *title, AliTRDReconstructor *rec)
6d50f529 104 :TNamed(name,title)
3a039a31 105 ,fReconstructor(rec)
6d50f529 106 ,fRunLoader(NULL)
107 ,fClusterTree(NULL)
108 ,fRecPoints(NULL)
9c7c9ec1 109 ,fTrackletTree(NULL)
3fe61b77 110 ,fDigitsManager(new AliTRDdigitsManager())
9c7c9ec1 111 ,fTrackletContainer(NULL)
3fe61b77 112 ,fAddLabels(kTRUE)
113 ,fRawVersion(2)
114 ,fIndexesOut(NULL)
115 ,fIndexesMaxima(NULL)
116 ,fTransform(new AliTRDtransform(0))
fc546d21 117 ,fLUTbin(0)
118 ,fLUT(NULL)
f7336fa3 119{
120 //
6d50f529 121 // AliTRDclusterizer constructor
f7336fa3 122 //
123
a7ac01d2 124 AliTRDcalibDB *trd = 0x0;
125 if (!(trd = AliTRDcalibDB::Instance())) {
126 AliFatal("Could not get calibration object");
127 }
128
3fe61b77 129 fDigitsManager->CreateArrays();
130
131 fRawVersion = AliTRDfeeParam::Instance()->GetRAWversion();
132
fc546d21 133 FillLUT();
023b669c 134
f7336fa3 135}
136
8230f242 137//_____________________________________________________________________________
6d50f529 138AliTRDclusterizer::AliTRDclusterizer(const AliTRDclusterizer &c)
139 :TNamed(c)
3a039a31 140 ,fReconstructor(c.fReconstructor)
6d50f529 141 ,fRunLoader(NULL)
142 ,fClusterTree(NULL)
143 ,fRecPoints(NULL)
9c7c9ec1 144 ,fTrackletTree(NULL)
3fe61b77 145 ,fDigitsManager(NULL)
66f6bfd9 146 ,fTrackletContainer(NULL)
3fe61b77 147 ,fAddLabels(kTRUE)
148 ,fRawVersion(2)
149 ,fIndexesOut(NULL)
150 ,fIndexesMaxima(NULL)
151 ,fTransform(NULL)
fc546d21 152 ,fLUTbin(0)
153 ,fLUT(0)
8230f242 154{
155 //
156 // AliTRDclusterizer copy constructor
157 //
158
fc546d21 159 FillLUT();
160
8230f242 161}
162
f7336fa3 163//_____________________________________________________________________________
164AliTRDclusterizer::~AliTRDclusterizer()
165{
8230f242 166 //
167 // AliTRDclusterizer destructor
168 //
f7336fa3 169
48f8adf3 170 if (fRecPoints/* && IsClustersOwner()*/){
66f6bfd9 171 fRecPoints->Delete();
172 delete fRecPoints;
173 }
3fe61b77 174
66f6bfd9 175 if (fDigitsManager) {
176 delete fDigitsManager;
177 fDigitsManager = NULL;
178 }
9c7c9ec1 179
66f6bfd9 180 if (fTrackletContainer){
181 delete fTrackletContainer;
182 fTrackletContainer = NULL;
183 }
3fe61b77 184
66f6bfd9 185 if (fIndexesOut){
186 delete fIndexesOut;
187 fIndexesOut = NULL;
188 }
3fe61b77 189
66f6bfd9 190 if (fIndexesMaxima){
191 delete fIndexesMaxima;
192 fIndexesMaxima = NULL;
193 }
6d50f529 194
66f6bfd9 195 if (fTransform){
196 delete fTransform;
197 fTransform = NULL;
198 }
fc546d21 199
66f6bfd9 200 if (fLUT) {
201 delete [] fLUT;
202 fLUT = NULL;
203 }
eb52b657 204
f7336fa3 205}
206
8230f242 207//_____________________________________________________________________________
dd9a6ee3 208AliTRDclusterizer &AliTRDclusterizer::operator=(const AliTRDclusterizer &c)
209{
210 //
211 // Assignment operator
212 //
213
3fe61b77 214 if (this != &c)
215 {
216 ((AliTRDclusterizer &) c).Copy(*this);
217 }
053767a4 218
dd9a6ee3 219 return *this;
220
221}
222
223//_____________________________________________________________________________
e0d47c25 224void AliTRDclusterizer::Copy(TObject &c) const
8230f242 225{
226 //
227 // Copy function
228 //
229
3fe61b77 230 ((AliTRDclusterizer &) c).fClusterTree = NULL;
231 ((AliTRDclusterizer &) c).fRecPoints = NULL;
9c7c9ec1 232 ((AliTRDclusterizer &) c).fTrackletTree = NULL;
3fe61b77 233 ((AliTRDclusterizer &) c).fDigitsManager = NULL;
9c7c9ec1 234 ((AliTRDclusterizer &) c).fTrackletContainer = NULL;
3fe61b77 235 ((AliTRDclusterizer &) c).fAddLabels = fAddLabels;
236 ((AliTRDclusterizer &) c).fRawVersion = fRawVersion;
237 ((AliTRDclusterizer &) c).fIndexesOut = NULL;
238 ((AliTRDclusterizer &) c).fIndexesMaxima = NULL;
239 ((AliTRDclusterizer &) c).fTransform = NULL;
fc546d21 240 ((AliTRDclusterizer &) c).fLUTbin = 0;
241 ((AliTRDclusterizer &) c).fLUT = NULL;
8230f242 242
243}
244
f7336fa3 245//_____________________________________________________________________________
3e1a3ad8 246Bool_t AliTRDclusterizer::Open(const Char_t *name, Int_t nEvent)
f7336fa3 247{
248 //
3e1a3ad8 249 // Opens the AliROOT file. Output and input are in the same file
f7336fa3 250 //
6d50f529 251
e191bb57 252 TString evfoldname = AliConfig::GetDefaultEventFolderName();
6d50f529 253 fRunLoader = AliRunLoader::GetRunLoader(evfoldname);
254
255 if (!fRunLoader) {
19dd5b2f 256 fRunLoader = AliRunLoader::Open(name);
6d50f529 257 }
258
259 if (!fRunLoader) {
260 AliError(Form("Can not open session for file %s.",name));
261 return kFALSE;
262 }
88cb7938 263
264 OpenInput(nEvent);
265 OpenOutput();
6d50f529 266
3e1a3ad8 267 return kTRUE;
f7336fa3 268
6d50f529 269}
3e1a3ad8 270
271//_____________________________________________________________________________
88cb7938 272Bool_t AliTRDclusterizer::OpenOutput()
3e1a3ad8 273{
274 //
275 // Open the output file
276 //
277
66f6bfd9 278 if (!fReconstructor->IsWritingClusters()) return kTRUE;
279
280 TObjArray *ioArray = 0x0;
88cb7938 281
282 AliLoader* loader = fRunLoader->GetLoader("TRDLoader");
283 loader->MakeTree("R");
6d50f529 284
88cb7938 285 fClusterTree = loader->TreeR();
66f6bfd9 286 fClusterTree->Branch("TRDcluster", "TObjArray", &ioArray, 32000, 0);
3e1a3ad8 287
3e1a3ad8 288 return kTRUE;
289
290}
291
25ca55ce 292//_____________________________________________________________________________
293Bool_t AliTRDclusterizer::OpenOutput(TTree *clusterTree)
294{
295 //
296 // Connect the output tree
297 //
298
66f6bfd9 299 // clusters writing
300 if (fReconstructor->IsWritingClusters()){
301 TObjArray *ioArray = 0x0;
302 fClusterTree = clusterTree;
303 fClusterTree->Branch("TRDcluster", "TObjArray", &ioArray, 32000, 0);
304 }
9c7c9ec1 305
306 // tracklet writing
3a039a31 307 if (fReconstructor->IsWritingTracklets()){
9c7c9ec1 308 TString evfoldname = AliConfig::GetDefaultEventFolderName();
309 fRunLoader = AliRunLoader::GetRunLoader(evfoldname);
310
311 if (!fRunLoader) {
312 fRunLoader = AliRunLoader::Open("galice.root");
313 }
314 if (!fRunLoader) {
315 AliError(Form("Can not open session for file galice.root."));
316 return kFALSE;
317 }
318
319 UInt_t **leaves = new UInt_t *[2];
320 AliDataLoader *dl = fRunLoader->GetLoader("TRDLoader")->GetDataLoader("tracklets");
321 if (!dl) {
322 AliError("Could not get the tracklets data loader!");
90cf7133 323 dl = new AliDataLoader("TRD.Tracklets.root","tracklets", "tracklets");
9c7c9ec1 324 fRunLoader->GetLoader("TRDLoader")->AddDataLoader(dl);
325 }
326 else {
327 fTrackletTree = dl->Tree();
328 if (!fTrackletTree)
329 {
317b5644 330 dl->MakeTree();
331 fTrackletTree = dl->Tree();
9c7c9ec1 332 }
333 TBranch *trkbranch = fTrackletTree->GetBranch("trkbranch");
334 if (!trkbranch)
335 fTrackletTree->Branch("trkbranch",leaves[0],"det/i:side/i:tracklets[256]/i");
336 }
337 }
338
25ca55ce 339 return kTRUE;
340
341}
342
3e1a3ad8 343//_____________________________________________________________________________
88cb7938 344Bool_t AliTRDclusterizer::OpenInput(Int_t nEvent)
f7336fa3 345{
346 //
347 // Opens a ROOT-file with TRD-hits and reads in the digits-tree
348 //
349
f7336fa3 350 // Import the Trees for the event nEvent in the file
bdbb05bb 351 fRunLoader->GetEvent(nEvent);
88cb7938 352
f7336fa3 353 return kTRUE;
354
355}
356
357//_____________________________________________________________________________
793ff80c 358Bool_t AliTRDclusterizer::WriteClusters(Int_t det)
f7336fa3 359{
360 //
3e1a3ad8 361 // Fills TRDcluster branch in the tree with the clusters
793ff80c 362 // found in detector = det. For det=-1 writes the tree.
a3c76cdc 363 //
793ff80c 364
6d50f529 365 if ((det < -1) ||
366 (det >= AliTRDgeometry::Ndet())) {
367 AliError(Form("Unexpected detector index %d.\n",det));
3e1a3ad8 368 return kFALSE;
793ff80c 369 }
317b5644 370
66f6bfd9 371 TObjArray *ioArray = new TObjArray(400);
3e1a3ad8 372 TBranch *branch = fClusterTree->GetBranch("TRDcluster");
373 if (!branch) {
3e1a3ad8 374 branch = fClusterTree->Branch("TRDcluster","TObjArray",&ioArray,32000,0);
66f6bfd9 375 } else branch->SetAddress(&ioArray);
66f6bfd9 376
377 Int_t nRecPoints = RecPoints()->GetEntriesFast();
378 if(det >= 0){
3e1a3ad8 379 for (Int_t i = 0; i < nRecPoints; i++) {
bdbb05bb 380 AliTRDcluster *c = (AliTRDcluster *) RecPoints()->UncheckedAt(i);
66f6bfd9 381 if(det != c->GetDetector()) continue;
382 ioArray->AddLast(c);
793ff80c 383 }
3e1a3ad8 384 fClusterTree->Fill();
66f6bfd9 385 } else {
eb52b657 386
66f6bfd9 387 Int_t detOld = -1;
388 for (Int_t i = 0; i < nRecPoints; i++) {
389 AliTRDcluster *c = (AliTRDcluster *) RecPoints()->UncheckedAt(i);
390 if(c->GetDetector() != detOld){
391 fClusterTree->Fill();
392 ioArray->Clear();
393 detOld = c->GetDetector();
394 }
395 ioArray->AddLast(c);
a6dd11e9 396 }
793ff80c 397 }
66f6bfd9 398 delete ioArray;
6d50f529 399
66f6bfd9 400 return kTRUE;
eb52b657 401
f7336fa3 402}
793ff80c 403
9c7c9ec1 404//_____________________________________________________________________________
405Bool_t AliTRDclusterizer::WriteTracklets(Int_t det)
406{
eb52b657 407 //
408 // Write the raw data tracklets into seperate file
409 //
9c7c9ec1 410
411 UInt_t **leaves = new UInt_t *[2];
412 for (Int_t i=0; i<2 ;i++){
317b5644 413 leaves[i] = new UInt_t[258];
414 leaves[i][0] = det; // det
415 leaves[i][1] = i; // side
416 memcpy(leaves[i]+2, fTrackletContainer[i], sizeof(UInt_t) * 256);
9c7c9ec1 417 }
418
9c7c9ec1 419 if (!fTrackletTree){
420 AliDataLoader *dl = fRunLoader->GetLoader("TRDLoader")->GetDataLoader("tracklets");
421 dl->MakeTree();
422 fTrackletTree = dl->Tree();
423 }
424
425 TBranch *trkbranch = fTrackletTree->GetBranch("trkbranch");
426 if (!trkbranch) {
427 trkbranch = fTrackletTree->Branch("trkbranch",leaves[0],"det/i:side/i:tracklets[256]/i");
428 }
429
430 for (Int_t i=0; i<2; i++){
317b5644 431 if (leaves[i][2]>0) {
432 trkbranch->SetAddress(leaves[i]);
433 fTrackletTree->Fill();
434 }
9c7c9ec1 435 }
436
437 AliDataLoader *dl = fRunLoader->GetLoader("TRDLoader")->GetDataLoader("tracklets");
438 dl->WriteData("OVERWRITE");
439 //dl->Unload();
440 delete [] leaves;
441
eb52b657 442 return kTRUE;
443
9c7c9ec1 444}
445
3551db50 446//_____________________________________________________________________________
3fe61b77 447void AliTRDclusterizer::ResetHelperIndexes(AliTRDSignalIndex *indexesIn)
448{
449 //
450 // Reset the helper indexes
451 //
452
453 if (fIndexesOut)
454 {
455 // carefull here - we assume that only row number may change - most probable
456 if (indexesIn->GetNrow() <= fIndexesOut->GetNrow())
317b5644 457 fIndexesOut->ResetContent();
3fe61b77 458 else
317b5644 459 fIndexesOut->ResetContentConditional(indexesIn->GetNrow()
460 , indexesIn->GetNcol()
461 , indexesIn->GetNtime());
3fe61b77 462 }
463 else
464 {
465 fIndexesOut = new AliTRDSignalIndex(indexesIn->GetNrow()
466 , indexesIn->GetNcol()
467 , indexesIn->GetNtime());
468 }
469
470 if (fIndexesMaxima)
471 {
472 // carefull here - we assume that only row number may change - most probable
473 if (indexesIn->GetNrow() <= fIndexesMaxima->GetNrow())
474 {
317b5644 475 fIndexesMaxima->ResetContent();
476 }
3fe61b77 477 else
317b5644 478 {
479 fIndexesMaxima->ResetContentConditional(indexesIn->GetNrow()
3fe61b77 480 , indexesIn->GetNcol()
481 , indexesIn->GetNtime());
317b5644 482 }
3fe61b77 483 }
484 else
485 {
486 fIndexesMaxima = new AliTRDSignalIndex(indexesIn->GetNrow()
317b5644 487 , indexesIn->GetNcol()
488 , indexesIn->GetNtime());
3fe61b77 489 }
490
491}
492
493//_____________________________________________________________________________
494Bool_t AliTRDclusterizer::ReadDigits()
495{
496 //
497 // Reads the digits arrays from the input aliroot file
498 //
499
500 if (!fRunLoader) {
501 AliError("No run loader available");
502 return kFALSE;
503 }
504
505 AliLoader* loader = fRunLoader->GetLoader("TRDLoader");
506 if (!loader->TreeD()) {
507 loader->LoadDigits();
508 }
509
510 // Read in the digit arrays
511 return (fDigitsManager->ReadDigits(loader->TreeD()));
512
513}
514
515//_____________________________________________________________________________
516Bool_t AliTRDclusterizer::ReadDigits(TTree *digitsTree)
517{
518 //
519 // Reads the digits arrays from the input tree
520 //
521
522 // Read in the digit arrays
523 return (fDigitsManager->ReadDigits(digitsTree));
524
525}
526
527//_____________________________________________________________________________
528Bool_t AliTRDclusterizer::ReadDigits(AliRawReader *rawReader)
529{
530 //
531 // Reads the digits arrays from the ddl file
532 //
533
534 AliTRDrawData raw;
535 fDigitsManager = raw.Raw2Digits(rawReader);
536
537 return kTRUE;
538
539}
540
541//_____________________________________________________________________________
542Bool_t AliTRDclusterizer::MakeClusters()
543{
544 //
545 // Creates clusters from digits
546 //
547
548 // Propagate info from the digits manager
66f6bfd9 549 if (fAddLabels == kTRUE){
550 fAddLabels = fDigitsManager->UsesDictionaries();
551 }
552
3fe61b77 553 Bool_t fReturn = kTRUE;
66f6bfd9 554 for (Int_t i = 0; i < AliTRDgeometry::kNdet; i++){
555
b65e5048 556 AliTRDarrayADC *digitsIn = (AliTRDarrayADC*) fDigitsManager->GetDigits(i); //mod
66f6bfd9 557 // This is to take care of switched off super modules
558 if (!digitsIn->HasData()) continue;
559 digitsIn->Expand();
0d64b05f 560 digitsIn->DeleteNegatives(); // Restore digits array to >=0 values
66f6bfd9 561 AliTRDSignalIndex* indexes = fDigitsManager->GetIndexes(i);
562 if (indexes->IsAllocated() == kFALSE){
563 fDigitsManager->BuildIndexes(i);
564 }
565
566 Bool_t fR = kFALSE;
567 if (indexes->HasEntry()){
568 if (fAddLabels){
569 for (Int_t iDict = 0; iDict < AliTRDdigitsManager::kNDict; iDict++){
b65e5048 570 AliTRDarrayDictionary *tracksIn = 0; //mod
571 tracksIn = (AliTRDarrayDictionary *) fDigitsManager->GetDictionary(i,iDict); //mod
66f6bfd9 572 tracksIn->Expand();
3fe61b77 573 }
66f6bfd9 574 }
575 fR = MakeClusters(i);
576 fReturn = fR && fReturn;
3fe61b77 577 }
66f6bfd9 578
579 //if (fR == kFALSE){
580 // if(IsWritingClusters()) WriteClusters(i);
581 // ResetRecPoints();
582 //}
583
584 // No compress just remove
585 fDigitsManager->RemoveDigits(i);
586 fDigitsManager->RemoveDictionaries(i);
587 fDigitsManager->ClearIndexes(i);
588 }
589
590 if(fReconstructor->IsWritingClusters()) WriteClusters(-1);
3fe61b77 591
66f6bfd9 592 AliInfo(Form("Number of found clusters : %d", RecPoints()->GetEntriesFast()));
3fe61b77 593
66f6bfd9 594 return fReturn;
eb52b657 595
3fe61b77 596}
597
598//_____________________________________________________________________________
599Bool_t AliTRDclusterizer::Raw2Clusters(AliRawReader *rawReader)
600{
601 //
602 // Creates clusters from raw data
603 //
604
fc546d21 605 return Raw2ClustersChamber(rawReader);
3fe61b77 606
3fe61b77 607}
608
609//_____________________________________________________________________________
610Bool_t AliTRDclusterizer::Raw2ClustersChamber(AliRawReader *rawReader)
611{
612 //
613 // Creates clusters from raw data
614 //
615
616 // Create the digits manager
66f6bfd9 617 if (!fDigitsManager){
618 fDigitsManager = new AliTRDdigitsManager();
619 fDigitsManager->CreateArrays();
620 }
3fe61b77 621
622 fDigitsManager->SetUseDictionaries(fAddLabels);
623
317b5644 624 // tracklet container for raw tracklet writing
625 if (!fTrackletContainer && fReconstructor->IsWritingTracklets()) {
626 // maximum tracklets for one HC
627 const Int_t kTrackletChmb=256;
628 fTrackletContainer = new UInt_t *[2];
629 fTrackletContainer[0] = new UInt_t[kTrackletChmb];
630 fTrackletContainer[1] = new UInt_t[kTrackletChmb];
631 }
632
633
dfbb4bb9 634 AliTRDrawStreamBase *pinput = AliTRDrawStreamBase::GetRawStream(rawReader);
635 AliTRDrawStreamBase &input = *pinput;
3fe61b77 636
637 AliInfo(Form("Stream version: %s", input.IsA()->GetName()));
638
639 Int_t det = 0;
317b5644 640 while ((det = input.NextChamber(fDigitsManager,fTrackletContainer)) >= 0){
66f6bfd9 641 Bool_t iclusterBranch = kFALSE;
642 if (fDigitsManager->GetIndexes(det)->HasEntry()){
643 iclusterBranch = MakeClusters(det);
3fe61b77 644 }
66f6bfd9 645
646 fDigitsManager->RemoveDigits(det);
647 fDigitsManager->RemoveDictionaries(det);
648 fDigitsManager->ClearIndexes(det);
317b5644 649
650 if (!fReconstructor->IsWritingTracklets()) continue;
651 if (*(fTrackletContainer[0]) > 0 || *(fTrackletContainer[1]) > 0) WriteTracklets(det);
9c7c9ec1 652 }
317b5644 653 if (fReconstructor->IsWritingTracklets()){
654 delete [] fTrackletContainer[0];
655 delete [] fTrackletContainer[1];
656 delete [] fTrackletContainer;
657 fTrackletContainer = NULL;
658 }
659
66f6bfd9 660 if(fReconstructor->IsWritingClusters()) WriteClusters(-1);
3fe61b77 661
662 delete fDigitsManager;
663 fDigitsManager = NULL;
dfbb4bb9 664
665 delete pinput;
666 pinput = NULL;
3fe61b77 667
66f6bfd9 668 AliInfo(Form("Number of found clusters : %d", RecPoints()->GetEntriesFast()));
669 return kTRUE;
eb52b657 670
3fe61b77 671}
672
fa7427d0 673//_____________________________________________________________________________
674UChar_t AliTRDclusterizer::GetStatus(Short_t &signal)
675{
023b669c 676 //
677 // Check if a pad is masked
678 //
679
317b5644 680 UChar_t status = 0;
681
682 if(signal>0 && TESTBIT(signal, 10)){
683 CLRBIT(signal, 10);
684 for(int ibit=0; ibit<4; ibit++){
685 if(TESTBIT(signal, 11+ibit)){
686 SETBIT(status, ibit);
687 CLRBIT(signal, 11+ibit);
688 }
689 }
690 }
691 return status;
fa7427d0 692}
693
6d9e79cc 694//_____________________________________________________________________________
695void AliTRDclusterizer::SetPadStatus(UChar_t status, UChar_t &out){
696 //
697 // Set the pad status into out
698 // First three bits are needed for the position encoding
699 //
700 status = status << 3;
701 out |= status;
702}
703
704//_____________________________________________________________________________
705UChar_t AliTRDclusterizer::GetPadStatus(UChar_t encoding){
706 //
707 // return the staus encoding of the corrupted pad
708 //
709 return static_cast<UChar_t>(encoding >> 3);
710}
711
712//_____________________________________________________________________________
713Int_t AliTRDclusterizer::GetCorruption(UChar_t encoding){
714 //
715 // Return the position of the corruption
716 //
717 return encoding & 7;
718}
719
3fe61b77 720//_____________________________________________________________________________
721Bool_t AliTRDclusterizer::MakeClusters(Int_t det)
722{
723 //
724 // Generates the cluster.
725 //
726
727 // Get the digits
728 // digits should be expanded beforehand!
729 // digitsIn->Expand();
b65e5048 730 AliTRDarrayADC *digitsIn = (AliTRDarrayADC *) fDigitsManager->GetDigits(det); //mod
f5375dcb 731
3fe61b77 732 // This is to take care of switched off super modules
625f5260 733 if (!digitsIn->HasData())
3fe61b77 734 {
735 return kFALSE;
736 }
737
738 AliTRDSignalIndex *indexesIn = fDigitsManager->GetIndexes(det);
739 if (indexesIn->IsAllocated() == kFALSE)
740 {
741 AliError("Indexes do not exist!");
742 return kFALSE;
743 }
744
745 AliTRDcalibDB *calibration = AliTRDcalibDB::Instance();
746 if (!calibration)
747 {
748 AliFatal("No AliTRDcalibDB instance available\n");
749 return kFALSE;
750 }
751
3fe61b77 752 // ADC thresholds
753 // There is no ADC threshold anymore, and simParam should not be used in clusterizer. KO
acc49af9 754 Float_t adcThreshold = 0;
3fe61b77 755
3a039a31 756 if (!fReconstructor){
757 AliError("Reconstructor not set\n");
758 return kFALSE;
759 }
c5f589b9 760
29f95561 761 TTreeSRedirector *fDebugStream = fReconstructor->GetDebugStream(AliTRDReconstructor::kClusterizer);
762
3fe61b77 763 // Threshold value for the maximum
eb52b657 764 Float_t maxThresh = fReconstructor->GetRecoParam()->GetClusMaxThresh();
3fe61b77 765 // Threshold value for the digit signal
eb52b657 766 Float_t sigThresh = fReconstructor->GetRecoParam()->GetClusSigThresh();
3fe61b77 767
df83a620 768 // Threshold value for the maximum ( cut noise)
eb52b657 769 Float_t minMaxCutSigma = fReconstructor->GetRecoParam()->GetMinMaxCutSigma();
df83a620 770 // Threshold value for the sum pad ( cut noise)
eb52b657 771 Float_t minLeftRightCutSigma = fReconstructor->GetRecoParam()->GetMinLeftRightCutSigma();
df83a620 772
3fe61b77 773 // Iteration limit for unfolding procedure
774 const Float_t kEpsilon = 0.01;
775 const Int_t kNclus = 3;
776 const Int_t kNsig = 5;
777
778 Int_t iUnfold = 0;
779 Double_t ratioLeft = 1.0;
780 Double_t ratioRight = 1.0;
781
782 Double_t padSignal[kNsig];
783 Double_t clusterSignal[kNclus];
784
053767a4 785 Int_t istack = indexesIn->GetStack();
786 Int_t ilayer = indexesIn->GetLayer();
787 Int_t isector = indexesIn->GetSM();
3fe61b77 788
789 // Start clustering in the chamber
790
053767a4 791 Int_t idet = AliTRDgeometry::GetDetector(ilayer,istack,isector);
b65e5048 792 if (idet != det) {
793 AliError("Strange Detector number Missmatch!");
794 return kFALSE;
795 }
3fe61b77 796
797 // TRD space point transformation
798 fTransform->SetDetector(det);
799
053767a4 800 Int_t iGeoLayer = AliGeomManager::kTRD1 + ilayer;
801 Int_t iGeoModule = istack + AliTRDgeometry::Nstack() * isector;
802 UShort_t volid = AliGeomManager::LayerToVolUID(iGeoLayer,iGeoModule);
3fe61b77 803
804 Int_t nColMax = digitsIn->GetNcol();
fa7427d0 805 Int_t nRowMax = digitsIn->GetNrow();
3fe61b77 806 Int_t nTimeTotal = digitsIn->GetNtime();
807
808 // Detector wise calibration object for the gain factors
0e09df31 809 const AliTRDCalDet *calGainFactorDet = calibration->GetGainFactorDet();
3fe61b77 810 // Calibration object with pad wise values for the gain factors
0e09df31 811 AliTRDCalROC *calGainFactorROC = calibration->GetGainFactorROC(idet);
3fe61b77 812 // Calibration value for chamber wise gain factor
0e09df31 813 Float_t calGainFactorDetValue = calGainFactorDet->GetValue(idet);
814
df83a620 815 // Detector wise calibration object for the noise
816 const AliTRDCalDet *calNoiseDet = calibration->GetNoiseDet();
817 // Calibration object with pad wise values for the noise
818 AliTRDCalROC *calNoiseROC = calibration->GetNoiseROC(idet);
819 // Calibration value for chamber wise noise
820 Float_t calNoiseDetValue = calNoiseDet->GetValue(idet);
821
3fe61b77 822 Int_t nClusters = 0;
823
b65e5048 824 AliTRDarraySignal *digitsOut = new AliTRDarraySignal(nRowMax, nColMax, nTimeTotal);
825 AliTRDarrayADC padStatus(nRowMax, nColMax, nTimeTotal);
3fe61b77 826
827 ResetHelperIndexes(indexesIn);
828
829 // Apply the gain and the tail cancelation via digital filter
830 TailCancelation(digitsIn
b65e5048 831 ,digitsOut
832 ,indexesIn
833 ,fIndexesOut
834 ,nTimeTotal
835 ,adcThreshold
836 ,calGainFactorROC
837 ,calGainFactorDetValue);
317b5644 838
3fe61b77 839 Int_t row = 0;
840 Int_t col = 0;
841 Int_t time = 0;
842 Int_t iPad = 0;
843
f5375dcb 844 UChar_t status[3]={0, 0, 0}, ipos = 0;
3fe61b77 845 fIndexesOut->ResetCounters();
29f95561 846 Int_t nMaximas = 0, nCorrupted = 0;
eb52b657 847 while (fIndexesOut->NextRCTbinIndex(row, col, time)) {
49451fe0 848 // reset pad status
849 ipos = 0; for(Int_t is=3; is--;) status[is] = 0;
023b669c 850
b65e5048 851 Float_t signalM = TMath::Abs(digitsOut->GetData(row,col,time));
f5375dcb 852 status[1] = digitsIn->GetPadStatus(row,col,time);
853 if(status[1]) SETBIT(ipos, AliTRDcluster::kMaskedCenter);
854
df83a620 855 if(signalM < maxThresh) continue;
856
857 Float_t noiseMiddleThresh = minMaxCutSigma*calNoiseDetValue*calNoiseROC->GetValue(col,row);
858 if (signalM < noiseMiddleThresh) continue;
859
860 if (col + 1 >= nColMax || col-1 < 0) continue;
f5375dcb 861
b65e5048 862 Float_t signalL = TMath::Abs(digitsOut->GetData(row,col+1,time));
df83a620 863 status[0] = digitsIn->GetPadStatus(row,col+1,time);
864 if(status[0]) SETBIT(ipos, AliTRDcluster::kMaskedLeft);
f5375dcb 865
b65e5048 866 Float_t signalR = TMath::Abs(digitsOut->GetData(row,col-1,time));
df83a620 867 status[2] = digitsIn->GetPadStatus(row,col-1,time);
868 if(status[2]) SETBIT(ipos, AliTRDcluster::kMaskedRight);
f5375dcb 869
df83a620 870 // reject candidates with more than 1 problematic pad
871 if(ipos == 3 || ipos > 4) continue;
f5375dcb 872
b65e5048 873 if (!status[1]) { // good central pad
874 if (!ipos) { // all pads are OK
875 if ((signalL <= signalM) && (signalR < signalM)) {
876 if ((signalL >= sigThresh) || (signalR >= sigThresh)) {
877 Float_t noiseSumThresh = minLeftRightCutSigma
878 * calNoiseDetValue
879 * calNoiseROC->GetValue(col,row);
880 if ((signalL+signalR+signalM) >= noiseSumThresh) {
881 // Maximum found, mark the position by a negative signal
882 digitsOut->SetData(row,col,time,-signalM);
883 fIndexesMaxima->AddIndexTBin(row,col,time);
6d9e79cc 884 padStatus.SetData(row, col, time, ipos); // No corruption
b65e5048 885 }
886 }
887 }
49451fe0 888 } else { // one of the neighbouring pads are bad
b65e5048 889 if (status[0] && signalR < signalM && signalR >= sigThresh) {
890 digitsOut->SetData(row,col,time,-signalM);
891 digitsOut->SetData(row, col, time+1, 0.);
023b669c 892 fIndexesMaxima->AddIndexTBin(row,col,time);
6d9e79cc 893 SetPadStatus(status[0], ipos);
b65e5048 894 padStatus.SetData(row, col, time, ipos);
895 }
896 else if (status[2] && signalL <= signalM && signalL >= sigThresh) {
897 digitsOut->SetData(row,col,time,-signalM);
898 digitsOut->SetData(row, col, time-1, 0.);
899 fIndexesMaxima->AddIndexTBin(row,col,time);
6d9e79cc 900 SetPadStatus(status[2], ipos);
b65e5048 901 padStatus.SetData(row, col, time, ipos);
902 }
df83a620 903 }
b65e5048 904 }
905 else { // wrong maximum pad
df83a620 906 if ((signalL >= sigThresh) || (signalR >= sigThresh)) {
b65e5048 907 // Maximum found, mark the position by a negative signal
49451fe0 908 digitsOut->SetData(row,col,time,-maxThresh);
909 fIndexesMaxima->AddIndexTBin(row,col,time);
6d9e79cc 910 SetPadStatus(status[1], ipos);
49451fe0 911 padStatus.SetData(row, col, time, ipos);
f5375dcb 912 }
913 }
df83a620 914 }
f5375dcb 915
eb52b657 916 // The index to the first cluster of a given ROC
df83a620 917 Int_t firstClusterROC = -1;
eb52b657 918 // The number of cluster in a given ROC
919 Int_t nClusterROC = 0;
f5375dcb 920
eb52b657 921 // Now check the maxima and calculate the cluster position
922 fIndexesMaxima->ResetCounters();
923 while (fIndexesMaxima->NextRCTbinIndex(row, col, time)) {
3fe61b77 924
eb52b657 925 // Maximum found ?
b65e5048 926 if (digitsOut->GetData(row,col,time) < 0.0) {
023b669c 927
eb52b657 928 for (iPad = 0; iPad < kNclus; iPad++) {
929 Int_t iPadCol = col - 1 + iPad;
b65e5048 930 clusterSignal[iPad] = TMath::Abs(digitsOut->GetData(row,iPadCol,time));
eb52b657 931 }
3fe61b77 932
eb52b657 933 // Count the number of pads in the cluster
934 Int_t nPadCount = 0;
935 Int_t ii;
936 // Look to the right
937 ii = 0;
b65e5048 938 while (TMath::Abs(digitsOut->GetData(row,col-ii ,time)) >= sigThresh) {
eb52b657 939 nPadCount++;
940 ii++;
941 if (col-ii < 0) break;
942 }
943 // Look to the left
944 ii = 0;
b65e5048 945 while (TMath::Abs(digitsOut->GetData(row,col+ii+1,time)) >= sigThresh) {
eb52b657 946 nPadCount++;
947 ii++;
948 if (col+ii+1 >= nColMax) break;
949 }
950 nClusters++;
f5375dcb 951
eb52b657 952 // Look for 5 pad cluster with minimum in the middle
953 Bool_t fivePadCluster = kFALSE;
954 if (col < (nColMax - 3)){
b65e5048 955 if (digitsOut->GetData(row,col+2,time) < 0) {
eb52b657 956 fivePadCluster = kTRUE;
957 }
958 if ((fivePadCluster) && (col < (nColMax - 5))) {
b65e5048 959 if (digitsOut->GetData(row,col+4,time) >= sigThresh) {
eb52b657 960 fivePadCluster = kFALSE;
f5375dcb 961 }
eb52b657 962 }
963 if ((fivePadCluster) && (col > 1)) {
b65e5048 964 if (digitsOut->GetData(row,col-2,time) >= sigThresh) {
eb52b657 965 fivePadCluster = kFALSE;
f5375dcb 966 }
967 }
eb52b657 968 }
3fe61b77 969
eb52b657 970 // 5 pad cluster
971 // Modify the signal of the overlapping pad for the left part
972 // of the cluster which remains from a previous unfolding
973 if (iUnfold) {
974 clusterSignal[0] *= ratioLeft;
975 iUnfold = 0;
976 }
3fe61b77 977
eb52b657 978 // Unfold the 5 pad cluster
b65e5048 979 if (fivePadCluster) {
eb52b657 980 for (iPad = 0; iPad < kNsig; iPad++) {
b65e5048 981 padSignal[iPad] = TMath::Abs(digitsOut->GetData(row
982 ,col-1+iPad
983 ,time));
f5375dcb 984 }
eb52b657 985 // Unfold the two maxima and set the signal on
986 // the overlapping pad to the ratio
987 ratioRight = Unfold(kEpsilon,ilayer,padSignal);
988 ratioLeft = 1.0 - ratioRight;
989 clusterSignal[2] *= ratioRight;
990 iUnfold = 1;
991 }
3fe61b77 992
eb52b657 993 // The position of the cluster in COL direction relative to the center pad (pad units)
994 Double_t clusterPosCol = 0.0;
995 if (fReconstructor->GetRecoParam()->IsLUT()) {
996 // Calculate the position of the cluster by using the
997 // lookup table method
998 clusterPosCol = LUTposition(ilayer,clusterSignal[0]
999 ,clusterSignal[1]
1000 ,clusterSignal[2]);
1001 }
1002 else {
1003 // Calculate the position of the cluster by using the
1004 // center of gravity method
1005 for (Int_t i = 0; i < kNsig; i++) {
1006 padSignal[i] = 0.0;
1007 }
b65e5048 1008 padSignal[2] = TMath::Abs(digitsOut->GetData(row,col ,time)); // Central pad
1009 padSignal[3] = TMath::Abs(digitsOut->GetData(row,col+1,time)); // Left pad
1010 padSignal[1] = TMath::Abs(digitsOut->GetData(row,col-1,time)); // Right pad
eb52b657 1011 if ((col > 2) &&
b65e5048 1012 (TMath::Abs(digitsOut->GetData(row,col-2,time)) < padSignal[1])) {
1013 padSignal[4] = TMath::Abs(digitsOut->GetData(row,col-2,time));
f5375dcb 1014 }
eb52b657 1015 if ((col < nColMax - 3) &&
b65e5048 1016 (TMath::Abs(digitsOut->GetData(row,col+2,time)) < padSignal[3])) {
1017 padSignal[0] = TMath::Abs(digitsOut->GetData(row,col+2,time));
eb52b657 1018 }
1019 clusterPosCol = GetCOG(padSignal);
1020 }
3fe61b77 1021
eb52b657 1022 // Store the amplitudes of the pads in the cluster for later analysis
1023 // and check whether one of these pads is masked in the database
1024 Short_t signals[7] = { 0, 0, 0, 0, 0, 0, 0 };
1025 for (Int_t jPad = col-3; jPad <= col+3; jPad++) {
1026 if ((jPad < 0) ||
1027 (jPad >= nColMax-1)) {
1028 continue;
f5375dcb 1029 }
b65e5048 1030 signals[jPad-col+3] = TMath::Nint(TMath::Abs(digitsOut->GetData(row,jPad,time)));
eb52b657 1031 }
3fe61b77 1032
eb52b657 1033 // Transform the local cluster coordinates into calibrated
1034 // space point positions defined in the local tracking system.
1035 // Here the calibration for T0, Vdrift and ExB is applied as well.
1036 Double_t clusterXYZ[6];
1037 clusterXYZ[0] = clusterPosCol;
1038 clusterXYZ[1] = clusterSignal[2];
1039 clusterXYZ[2] = clusterSignal[1];
1040 clusterXYZ[3] = clusterSignal[0];
1041 clusterXYZ[4] = 0.0;
1042 clusterXYZ[5] = 0.0;
1043 Int_t clusterRCT[3];
1044 clusterRCT[0] = row;
1045 clusterRCT[1] = col;
1046 clusterRCT[2] = 0;
1047
1048 Bool_t out = kTRUE;
1049 if (fTransform->Transform(clusterXYZ,clusterRCT,((UInt_t) time),out,0)) {
f5375dcb 1050
1051 // Add the cluster to the output array
1052 // The track indices will be stored later
1053 Float_t clusterPos[3];
1054 clusterPos[0] = clusterXYZ[0];
1055 clusterPos[1] = clusterXYZ[1];
1056 clusterPos[2] = clusterXYZ[2];
1057 Float_t clusterSig[2];
1058 clusterSig[0] = clusterXYZ[4];
1059 clusterSig[1] = clusterXYZ[5];
1060 Double_t clusterCharge = clusterXYZ[3];
1061 Char_t clusterTimeBin = ((Char_t) clusterRCT[2]);
66f6bfd9 1062
1063 Int_t n = RecPoints()->GetEntriesFast();
49451fe0 1064 AliTRDcluster *cluster = new((*RecPoints())[n]) AliTRDcluster(
1065 idet,
1066 clusterCharge, clusterPos, clusterSig,
1067 0x0,
1068 ((Char_t) nPadCount),
1069 signals,
1070 ((UChar_t) col), ((UChar_t) row), ((UChar_t) time),
1071 clusterTimeBin, clusterPosCol,
1072 volid);
f5375dcb 1073 cluster->SetInChamber(!out);
023b669c 1074
6d9e79cc 1075 UChar_t maskPosition = GetCorruption(padStatus.GetData(row, col, time));
1076 UChar_t padstatus = GetPadStatus(padStatus.GetData(row, col, time));
023b669c 1077 if (maskPosition) {
f5375dcb 1078 cluster->SetPadMaskedPosition(maskPosition);
6d9e79cc 1079 cluster->SetPadMaskedStatus(padstatus);
f5375dcb 1080 }
3fe61b77 1081
f5375dcb 1082 // Temporarily store the row, column and time bin of the center pad
1083 // Used to later on assign the track indices
1084 cluster->SetLabel( row,0);
1085 cluster->SetLabel( col,1);
1086 cluster->SetLabel(time,2);
3fe61b77 1087
f5375dcb 1088 // Store the index of the first cluster in the current ROC
1089 if (firstClusterROC < 0) {
1090 firstClusterROC = RecPoints()->GetEntriesFast() - 1;
1091 }
1092
1093 // Count the number of cluster in the current ROC
1094 nClusterROC++;
1095
1096 } // if: Transform ok ?
eb52b657 1097
f5375dcb 1098 } // if: Maximum found ?
eb52b657 1099
f5375dcb 1100 }
3fe61b77 1101
29f95561 1102 if(fReconstructor->GetStreamLevel(AliTRDReconstructor::kClusterizer) > 2){
1103 (*fDebugStream) << "MakeClusters"
1104 << "Detector=" << det
1105 << "NMaxima=" << nMaximas
1106 << "NClusters=" << nClusterROC
1107 << "NCorrupted=" << nCorrupted
1108 << "\n";
1109 }
1110
3fe61b77 1111 delete digitsOut;
1112
eb52b657 1113 if (fAddLabels) {
1114 AddLabels(idet,firstClusterROC,nClusterROC);
1115 }
3fe61b77 1116
1117 return kTRUE;
1118
1119}
1120
1121//_____________________________________________________________________________
1122Bool_t AliTRDclusterizer::AddLabels(Int_t idet, Int_t firstClusterROC, Int_t nClusterROC)
3551db50 1123{
1124 //
3fe61b77 1125 // Add the track indices to the found clusters
3551db50 1126 //
1127
3fe61b77 1128 const Int_t kNclus = 3;
1129 const Int_t kNdict = AliTRDdigitsManager::kNDict;
1130 const Int_t kNtrack = kNdict * kNclus;
1131
1132 Int_t iClusterROC = 0;
1133
1134 Int_t row = 0;
1135 Int_t col = 0;
1136 Int_t time = 0;
1137 Int_t iPad = 0;
1138
1139 // Temporary array to collect the track indices
1140 Int_t *idxTracks = new Int_t[kNtrack*nClusterROC];
1141
1142 // Loop through the dictionary arrays one-by-one
1143 // to keep memory consumption low
b65e5048 1144 AliTRDarrayDictionary *tracksIn = 0; //mod
3fe61b77 1145 for (Int_t iDict = 0; iDict < kNdict; iDict++) {
1146
1147 // tracksIn should be expanded beforehand!
b65e5048 1148 tracksIn = (AliTRDarrayDictionary *) fDigitsManager->GetDictionary(idet,iDict);
3fe61b77 1149
1150 // Loop though the clusters found in this ROC
1151 for (iClusterROC = 0; iClusterROC < nClusterROC; iClusterROC++) {
317b5644 1152
3fe61b77 1153 AliTRDcluster *cluster = (AliTRDcluster *)
b65e5048 1154 RecPoints()->UncheckedAt(firstClusterROC+iClusterROC);
3fe61b77 1155 row = cluster->GetLabel(0);
1156 col = cluster->GetLabel(1);
1157 time = cluster->GetLabel(2);
1158
1159 for (iPad = 0; iPad < kNclus; iPad++) {
b65e5048 1160 Int_t iPadCol = col - 1 + iPad;
1161 Int_t index = tracksIn->GetData(row,iPadCol,time); //Modification of -1 in Track
1162 idxTracks[3*iPad+iDict + iClusterROC*kNtrack] = index;
3fe61b77 1163 }
1164
1165 }
1166
1167 }
1168
1169 // Copy the track indices into the cluster
1170 // Loop though the clusters found in this ROC
1171 for (iClusterROC = 0; iClusterROC < nClusterROC; iClusterROC++) {
317b5644 1172
3fe61b77 1173 AliTRDcluster *cluster = (AliTRDcluster *)
1174 RecPoints()->UncheckedAt(firstClusterROC+iClusterROC);
1175 cluster->SetLabel(-9999,0);
1176 cluster->SetLabel(-9999,1);
1177 cluster->SetLabel(-9999,2);
1178
1179 cluster->AddTrackIndex(&idxTracks[iClusterROC*kNtrack]);
1180
1181 }
1182
1183 delete [] idxTracks;
1184
1185 return kTRUE;
1186
1187}
1188
1189//_____________________________________________________________________________
acc49af9 1190Double_t AliTRDclusterizer::GetCOG(Double_t signal[5]) const
3fe61b77 1191{
1192 //
1193 // Get COG position
1194 // Used for clusters with more than 3 pads - where LUT not applicable
1195 //
1196
1197 Double_t sum = signal[0]
317b5644 1198 + signal[1]
1199 + signal[2]
1200 + signal[3]
1201 + signal[4];
3fe61b77 1202
eb52b657 1203 // ???????????? CBL
1204 // Go to 3 pad COG ????
023b669c 1205 // ???????????? CBL
3fe61b77 1206 Double_t res = (0.0 * (-signal[0] + signal[4])
1207 + (-signal[1] + signal[3])) / sum;
1208
1209 return res;
1210
1211}
1212
1213//_____________________________________________________________________________
053767a4 1214Double_t AliTRDclusterizer::Unfold(Double_t eps, Int_t layer, Double_t *padSignal)
3fe61b77 1215{
1216 //
1217 // Method to unfold neighbouring maxima.
1218 // The charge ratio on the overlapping pad is calculated
1219 // until there is no more change within the range given by eps.
1220 // The resulting ratio is then returned to the calling method.
1221 //
1222
1223 AliTRDcalibDB *calibration = AliTRDcalibDB::Instance();
6d50f529 1224 if (!calibration) {
3fe61b77 1225 AliError("No AliTRDcalibDB instance available\n");
1226 return kFALSE;
6d50f529 1227 }
3fe61b77 1228
1229 Int_t irc = 0;
1230 Int_t itStep = 0; // Count iteration steps
1231
1232 Double_t ratio = 0.5; // Start value for ratio
1233 Double_t prevRatio = 0.0; // Store previous ratio
1234
1235 Double_t newLeftSignal[3] = { 0.0, 0.0, 0.0 }; // Array to store left cluster signal
1236 Double_t newRightSignal[3] = { 0.0, 0.0, 0.0 }; // Array to store right cluster signal
1237 Double_t newSignal[3] = { 0.0, 0.0, 0.0 };
1238
1239 // Start the iteration
1240 while ((TMath::Abs(prevRatio - ratio) > eps) && (itStep < 10)) {
1241
1242 itStep++;
1243 prevRatio = ratio;
1244
1245 // Cluster position according to charge ratio
1246 Double_t maxLeft = (ratio*padSignal[2] - padSignal[0])
1247 / (padSignal[0] + padSignal[1] + ratio*padSignal[2]);
1248 Double_t maxRight = (padSignal[4] - (1-ratio)*padSignal[2])
1249 / ((1.0 - ratio)*padSignal[2] + padSignal[3] + padSignal[4]);
1250
1251 // Set cluster charge ratio
053767a4 1252 irc = calibration->PadResponse(1.0,maxLeft ,layer,newSignal);
3fe61b77 1253 Double_t ampLeft = padSignal[1] / newSignal[1];
053767a4 1254 irc = calibration->PadResponse(1.0,maxRight,layer,newSignal);
3fe61b77 1255 Double_t ampRight = padSignal[3] / newSignal[1];
1256
1257 // Apply pad response to parameters
053767a4 1258 irc = calibration->PadResponse(ampLeft ,maxLeft ,layer,newLeftSignal );
1259 irc = calibration->PadResponse(ampRight,maxRight,layer,newRightSignal);
3fe61b77 1260
1261 // Calculate new overlapping ratio
1262 ratio = TMath::Min((Double_t) 1.0
1263 ,newLeftSignal[2] / (newLeftSignal[2] + newRightSignal[0]));
1264
b43a3e17 1265 }
88719a08 1266
3fe61b77 1267 return ratio;
1268
1269}
88719a08 1270
3fe61b77 1271//_____________________________________________________________________________
b65e5048 1272void AliTRDclusterizer::TailCancelation(AliTRDarrayADC *digitsIn
1273 , AliTRDarraySignal *digitsOut
1274 , AliTRDSignalIndex *indexesIn
1275 , AliTRDSignalIndex *indexesOut
1276 , Int_t nTimeTotal
1277 , Float_t adcThreshold
1278 , AliTRDCalROC *calGainFactorROC
1279 , Float_t calGainFactorDetValue)
3fe61b77 1280{
1281 //
1282 // Applies the tail cancelation and gain factors:
1283 // Transform digitsIn to digitsOut
1284 //
1285
1286 Int_t iRow = 0;
1287 Int_t iCol = 0;
1288 Int_t iTime = 0;
1289
3fe61b77 1290 Double_t *inADC = new Double_t[nTimeTotal]; // ADC data before tail cancellation
1291 Double_t *outADC = new Double_t[nTimeTotal]; // ADC data after tail cancellation
1292 indexesIn->ResetCounters();
29f95561 1293 TTreeSRedirector *fDebugStream = fReconstructor->GetDebugStream(AliTRDReconstructor::kClusterizer);
3fe61b77 1294 while (indexesIn->NextRCIndex(iRow, iCol))
1295 {
1296 Float_t calGainFactorROCValue = calGainFactorROC->GetValue(iCol,iRow);
1297 Double_t gain = calGainFactorDetValue
317b5644 1298 * calGainFactorROCValue;
3fe61b77 1299
f5375dcb 1300 Bool_t corrupted = kFALSE;
3fe61b77 1301 for (iTime = 0; iTime < nTimeTotal; iTime++)
b65e5048 1302 {
1303 // Apply gain gain factor
ce1fb7da 1304 inADC[iTime] = digitsIn->GetDataB(iRow,iCol,iTime);
b65e5048 1305 if (digitsIn->GetPadStatus(iRow, iCol, iTime)) corrupted = kTRUE;
1306 inADC[iTime] /= gain;
1307 outADC[iTime] = inADC[iTime];
29f95561 1308 if(fReconstructor->GetStreamLevel(AliTRDReconstructor::kClusterizer) > 7){
1309 (*fDebugStream) << "TailCancellation"
1310 << "col=" << iCol
1311 << "row=" << iRow
1312 << "time=" << iTime
1313 << "inADC=" << inADC[iTime]
1314 << "gain=" << gain
1315 << "outADC=" << outADC[iTime]
1316 << "corrupted=" << corrupted
1317 << "\n";
1318 }
b65e5048 1319 }
1320 if (!corrupted)
1321 {
1322 // Apply the tail cancelation via the digital filter
1323 // (only for non-coorupted pads)
1324 if (fReconstructor->GetRecoParam() ->IsTailCancelation())
1325 {
1326 DeConvExp(inADC,outADC,nTimeTotal,fReconstructor->GetRecoParam() ->GetTCnexp());
ce1fb7da 1327 }
b65e5048 1328 }
3fe61b77 1329
1330 indexesIn->ResetTbinCounter();
b65e5048 1331
3fe61b77 1332 while (indexesIn->NextTbinIndex(iTime))
b65e5048 1333 {
1334 // Store the amplitude of the digit if above threshold
1335 if (outADC[iTime] > adcThreshold)
1336 {
1337 digitsOut->SetData(iRow,iCol,iTime,outADC[iTime]);
1338 indexesOut->AddIndexTBin(iRow,iCol,iTime);
1339 }
1340 } // while itime
3fe61b77 1341
1342 } // while irow icol
1343
1344 delete [] inADC;
1345 delete [] outADC;
1346
1347 return;
1348
1349}
1350
1351//_____________________________________________________________________________
1352void AliTRDclusterizer::DeConvExp(Double_t *source, Double_t *target
b65e5048 1353 , Int_t n, Int_t nexp)
3fe61b77 1354{
1355 //
1356 // Tail cancellation by deconvolution for PASA v4 TRF
1357 //
1358
1359 Double_t rates[2];
1360 Double_t coefficients[2];
1361
1362 // Initialization (coefficient = alpha, rates = lambda)
1363 Double_t r1 = 1.0;
1364 Double_t r2 = 1.0;
1365 Double_t c1 = 0.5;
1366 Double_t c2 = 0.5;
1367
1368 if (nexp == 1) { // 1 Exponentials
1369 r1 = 1.156;
1370 r2 = 0.130;
1371 c1 = 0.066;
1372 c2 = 0.000;
1373 }
1374 if (nexp == 2) { // 2 Exponentials
181c7f7e 1375 Double_t par[4];
1376 fReconstructor->GetTCParams(par);
1377 r1 = par[0];//1.156;
1378 r2 = par[1];//0.130;
1379 c1 = par[2];//0.114;
1380 c2 = par[3];//0.624;
3fe61b77 1381 }
1382
1383 coefficients[0] = c1;
1384 coefficients[1] = c2;
1385
1386 Double_t dt = 0.1;
1387
1388 rates[0] = TMath::Exp(-dt/(r1));
1389 rates[1] = TMath::Exp(-dt/(r2));
1390
1391 Int_t i = 0;
1392 Int_t k = 0;
1393
1394 Double_t reminder[2];
1395 Double_t correction = 0.0;
1396 Double_t result = 0.0;
1397
1398 // Attention: computation order is important
1399 for (k = 0; k < nexp; k++) {
1400 reminder[k] = 0.0;
1401 }
1402
1403 for (i = 0; i < n; i++) {
1404
1405 result = (source[i] - correction); // No rescaling
1406 target[i] = result;
1407
1408 for (k = 0; k < nexp; k++) {
1409 reminder[k] = rates[k] * (reminder[k] + coefficients[k] * result);
1410 }
1411
1412 correction = 0.0;
1413 for (k = 0; k < nexp; k++) {
1414 correction += reminder[k];
1415 }
1416
1417 }
6d50f529 1418
1419}
1420
1421//_____________________________________________________________________________
1422void AliTRDclusterizer::ResetRecPoints()
1423{
1424 //
1425 // Resets the list of rec points
1426 //
1427
1428 if (fRecPoints) {
1429 fRecPoints->Delete();
48f8adf3 1430 delete fRecPoints;
6d50f529 1431 }
6d50f529 1432}
1433
1434//_____________________________________________________________________________
66f6bfd9 1435TClonesArray *AliTRDclusterizer::RecPoints()
6d50f529 1436{
1437 //
1438 // Returns the list of rec points
1439 //
1440
1441 if (!fRecPoints) {
48f8adf3 1442 if(!(fRecPoints = AliTRDReconstructor::GetClusters())){
8ae98148 1443 // determine number of clusters which has to be allocated
1444 Float_t nclusters = fReconstructor->GetRecoParam()->GetNClusters();
1445 if(fReconstructor->IsHLT()) nclusters /= AliTRDgeometry::kNsector;
1446
1447 fRecPoints = new TClonesArray("AliTRDcluster", Int_t(nclusters));
48f8adf3 1448 }
1449 //SetClustersOwner(kTRUE);
1450 AliTRDReconstructor::SetClusters(0x0);
6d50f529 1451 }
6d50f529 1452 return fRecPoints;
eb52b657 1453
3551db50 1454}
fc546d21 1455
1456//_____________________________________________________________________________
1457void AliTRDclusterizer::FillLUT()
1458{
1459 //
1460 // Create the LUT
1461 //
1462
1463 const Int_t kNlut = 128;
1464
053767a4 1465 fLUTbin = AliTRDgeometry::kNlayer * kNlut;
fc546d21 1466
1467 // The lookup table from Bogdan
053767a4 1468 Float_t lut[AliTRDgeometry::kNlayer][kNlut] = {
fc546d21 1469 {
1470 0.0070, 0.0150, 0.0224, 0.0298, 0.0374, 0.0454, 0.0533, 0.0611,
1471 0.0684, 0.0755, 0.0827, 0.0900, 0.0975, 0.1049, 0.1120, 0.1187,
1472 0.1253, 0.1318, 0.1385, 0.1453, 0.1519, 0.1584, 0.1646, 0.1704,
1473 0.1762, 0.1821, 0.1879, 0.1938, 0.1996, 0.2053, 0.2108, 0.2160,
1474 0.2210, 0.2260, 0.2310, 0.2361, 0.2411, 0.2461, 0.2509, 0.2557,
1475 0.2602, 0.2646, 0.2689, 0.2732, 0.2774, 0.2816, 0.2859, 0.2901,
1476 0.2942, 0.2983, 0.3022, 0.3061, 0.3099, 0.3136, 0.3172, 0.3207,
1477 0.3242, 0.3278, 0.3312, 0.3347, 0.3382, 0.3416, 0.3450, 0.3483,
1478 0.3515, 0.3547, 0.3579, 0.3609, 0.3639, 0.3669, 0.3698, 0.3727,
1479 0.3756, 0.3785, 0.3813, 0.3842, 0.3870, 0.3898, 0.3926, 0.3952,
1480 0.3979, 0.4005, 0.4032, 0.4057, 0.4082, 0.4108, 0.4132, 0.4157,
1481 0.4181, 0.4205, 0.4228, 0.4252, 0.4275, 0.4299, 0.4322, 0.4345,
1482 0.4367, 0.4390, 0.4412, 0.4434, 0.4456, 0.4478, 0.4499, 0.4520,
1483 0.4541, 0.4562, 0.4583, 0.4603, 0.4623, 0.4643, 0.4663, 0.4683,
1484 0.4702, 0.4722, 0.4741, 0.4758, 0.4774, 0.4790, 0.4805, 0.4824,
1485 0.4844, 0.4863, 0.4883, 0.4902, 0.4921, 0.4940, 0.4959, 0.4978
1486 },
1487 {
1488 0.0072, 0.0156, 0.0235, 0.0313, 0.0394, 0.0478, 0.0561, 0.0642,
1489 0.0718, 0.0792, 0.0868, 0.0947, 0.1025, 0.1101, 0.1172, 0.1241,
1490 0.1309, 0.1378, 0.1449, 0.1518, 0.1586, 0.1650, 0.1710, 0.1770,
1491 0.1830, 0.1891, 0.1952, 0.2011, 0.2070, 0.2125, 0.2177, 0.2229,
1492 0.2280, 0.2332, 0.2383, 0.2435, 0.2484, 0.2533, 0.2581, 0.2627,
1493 0.2670, 0.2714, 0.2757, 0.2799, 0.2842, 0.2884, 0.2927, 0.2968,
1494 0.3008, 0.3048, 0.3086, 0.3123, 0.3159, 0.3195, 0.3231, 0.3266,
1495 0.3301, 0.3335, 0.3370, 0.3404, 0.3438, 0.3471, 0.3504, 0.3536,
1496 0.3567, 0.3598, 0.3628, 0.3657, 0.3686, 0.3715, 0.3744, 0.3772,
1497 0.3800, 0.3828, 0.3856, 0.3884, 0.3911, 0.3938, 0.3965, 0.3991,
1498 0.4016, 0.4042, 0.4067, 0.4092, 0.4116, 0.4140, 0.4164, 0.4187,
1499 0.4211, 0.4234, 0.4257, 0.4280, 0.4302, 0.4325, 0.4347, 0.4369,
1500 0.4391, 0.4413, 0.4434, 0.4456, 0.4477, 0.4497, 0.4518, 0.4538,
1501 0.4558, 0.4578, 0.4598, 0.4618, 0.4637, 0.4656, 0.4675, 0.4694,
1502 0.4713, 0.4732, 0.4750, 0.4766, 0.4781, 0.4797, 0.4813, 0.4832,
1503 0.4851, 0.4870, 0.4888, 0.4906, 0.4925, 0.4942, 0.4960, 0.4978
1504 },
1505 {
1506 0.0075, 0.0163, 0.0246, 0.0328, 0.0415, 0.0504, 0.0592, 0.0674,
1507 0.0753, 0.0832, 0.0914, 0.0996, 0.1077, 0.1154, 0.1225, 0.1296,
1508 0.1369, 0.1442, 0.1515, 0.1585, 0.1652, 0.1714, 0.1776, 0.1839,
1509 0.1902, 0.1965, 0.2025, 0.2085, 0.2141, 0.2194, 0.2247, 0.2299,
1510 0.2352, 0.2405, 0.2457, 0.2507, 0.2557, 0.2604, 0.2649, 0.2693,
1511 0.2737, 0.2780, 0.2823, 0.2867, 0.2909, 0.2951, 0.2992, 0.3033,
1512 0.3072, 0.3110, 0.3146, 0.3182, 0.3218, 0.3253, 0.3288, 0.3323,
1513 0.3357, 0.3392, 0.3426, 0.3459, 0.3492, 0.3524, 0.3555, 0.3586,
1514 0.3616, 0.3645, 0.3674, 0.3703, 0.3731, 0.3759, 0.3787, 0.3815,
1515 0.3843, 0.3870, 0.3897, 0.3925, 0.3950, 0.3976, 0.4002, 0.4027,
1516 0.4052, 0.4076, 0.4101, 0.4124, 0.4148, 0.4171, 0.4194, 0.4217,
1517 0.4239, 0.4262, 0.4284, 0.4306, 0.4328, 0.4350, 0.4371, 0.4393,
1518 0.4414, 0.4435, 0.4455, 0.4476, 0.4496, 0.4516, 0.4536, 0.4555,
1519 0.4575, 0.4594, 0.4613, 0.4632, 0.4650, 0.4669, 0.4687, 0.4705,
1520 0.4723, 0.4741, 0.4758, 0.4773, 0.4789, 0.4804, 0.4821, 0.4839,
1521 0.4857, 0.4875, 0.4893, 0.4910, 0.4928, 0.4945, 0.4961, 0.4978
1522 },
1523 {
1524 0.0078, 0.0171, 0.0258, 0.0345, 0.0438, 0.0532, 0.0624, 0.0708,
1525 0.0791, 0.0875, 0.0962, 0.1048, 0.1130, 0.1206, 0.1281, 0.1356,
1526 0.1432, 0.1508, 0.1582, 0.1651, 0.1716, 0.1780, 0.1845, 0.1910,
1527 0.1975, 0.2038, 0.2099, 0.2155, 0.2210, 0.2263, 0.2317, 0.2371,
1528 0.2425, 0.2477, 0.2528, 0.2578, 0.2626, 0.2671, 0.2715, 0.2759,
1529 0.2803, 0.2846, 0.2890, 0.2933, 0.2975, 0.3016, 0.3056, 0.3095,
1530 0.3132, 0.3168, 0.3204, 0.3239, 0.3274, 0.3309, 0.3344, 0.3378,
1531 0.3412, 0.3446, 0.3479, 0.3511, 0.3543, 0.3574, 0.3603, 0.3633,
1532 0.3662, 0.3690, 0.3718, 0.3747, 0.3774, 0.3802, 0.3829, 0.3857,
1533 0.3883, 0.3910, 0.3936, 0.3962, 0.3987, 0.4012, 0.4037, 0.4061,
1534 0.4085, 0.4109, 0.4132, 0.4155, 0.4177, 0.4200, 0.4222, 0.4244,
1535 0.4266, 0.4288, 0.4309, 0.4331, 0.4352, 0.4373, 0.4394, 0.4414,
1536 0.4435, 0.4455, 0.4475, 0.4494, 0.4514, 0.4533, 0.4552, 0.4571,
1537 0.4590, 0.4608, 0.4626, 0.4645, 0.4662, 0.4680, 0.4698, 0.4715,
1538 0.4733, 0.4750, 0.4766, 0.4781, 0.4796, 0.4812, 0.4829, 0.4846,
1539 0.4863, 0.4880, 0.4897, 0.4914, 0.4930, 0.4946, 0.4963, 0.4979
1540 },
1541 {
1542 0.0081, 0.0178, 0.0270, 0.0364, 0.0463, 0.0562, 0.0656, 0.0744,
1543 0.0831, 0.0921, 0.1013, 0.1102, 0.1183, 0.1261, 0.1339, 0.1419,
1544 0.1499, 0.1576, 0.1648, 0.1715, 0.1782, 0.1849, 0.1917, 0.1984,
1545 0.2048, 0.2110, 0.2167, 0.2223, 0.2278, 0.2333, 0.2389, 0.2444,
1546 0.2497, 0.2548, 0.2598, 0.2645, 0.2691, 0.2735, 0.2780, 0.2824,
1547 0.2868, 0.2912, 0.2955, 0.2997, 0.3038, 0.3078, 0.3116, 0.3152,
1548 0.3188, 0.3224, 0.3259, 0.3294, 0.3329, 0.3364, 0.3398, 0.3432,
1549 0.3465, 0.3497, 0.3529, 0.3561, 0.3591, 0.3620, 0.3649, 0.3677,
1550 0.3705, 0.3733, 0.3761, 0.3788, 0.3816, 0.3843, 0.3869, 0.3896,
1551 0.3922, 0.3948, 0.3973, 0.3998, 0.4022, 0.4047, 0.4070, 0.4094,
1552 0.4117, 0.4139, 0.4162, 0.4184, 0.4206, 0.4227, 0.4249, 0.4270,
1553 0.4291, 0.4313, 0.4334, 0.4354, 0.4375, 0.4395, 0.4415, 0.4435,
1554 0.4455, 0.4474, 0.4493, 0.4512, 0.4531, 0.4550, 0.4568, 0.4586,
1555 0.4604, 0.4622, 0.4639, 0.4657, 0.4674, 0.4691, 0.4708, 0.4725,
1556 0.4742, 0.4758, 0.4773, 0.4788, 0.4803, 0.4819, 0.4836, 0.4852,
1557 0.4869, 0.4885, 0.4901, 0.4917, 0.4933, 0.4948, 0.4964, 0.4979
1558 },
1559 {
1560 0.0085, 0.0189, 0.0288, 0.0389, 0.0497, 0.0603, 0.0699, 0.0792,
1561 0.0887, 0.0985, 0.1082, 0.1170, 0.1253, 0.1336, 0.1421, 0.1505,
1562 0.1587, 0.1662, 0.1733, 0.1803, 0.1874, 0.1945, 0.2014, 0.2081,
1563 0.2143, 0.2201, 0.2259, 0.2316, 0.2374, 0.2431, 0.2487, 0.2541,
1564 0.2593, 0.2642, 0.2689, 0.2735, 0.2781, 0.2826, 0.2872, 0.2917,
1565 0.2961, 0.3003, 0.3045, 0.3086, 0.3125, 0.3162, 0.3198, 0.3235,
1566 0.3270, 0.3306, 0.3342, 0.3377, 0.3411, 0.3446, 0.3479, 0.3511,
1567 0.3543, 0.3575, 0.3605, 0.3634, 0.3663, 0.3691, 0.3720, 0.3748,
1568 0.3775, 0.3803, 0.3830, 0.3857, 0.3884, 0.3911, 0.3937, 0.3962,
1569 0.3987, 0.4012, 0.4036, 0.4060, 0.4084, 0.4107, 0.4129, 0.4152,
1570 0.4174, 0.4196, 0.4218, 0.4239, 0.4261, 0.4282, 0.4303, 0.4324,
1571 0.4344, 0.4365, 0.4385, 0.4405, 0.4425, 0.4445, 0.4464, 0.4483,
1572 0.4502, 0.4521, 0.4539, 0.4558, 0.4576, 0.4593, 0.4611, 0.4629,
1573 0.4646, 0.4663, 0.4680, 0.4697, 0.4714, 0.4730, 0.4747, 0.4759,
1574 0.4769, 0.4780, 0.4790, 0.4800, 0.4811, 0.4827, 0.4843, 0.4859,
1575 0.4874, 0.4889, 0.4905, 0.4920, 0.4935, 0.4950, 0.4965, 0.4979
1576 }
1577 };
1578
1579 if (fLUT) {
1580 delete [] fLUT;
1581 }
1582 fLUT = new Double_t[fLUTbin];
1583
053767a4 1584 for (Int_t ilayer = 0; ilayer < AliTRDgeometry::kNlayer; ilayer++) {
fc546d21 1585 for (Int_t ilut = 0; ilut < kNlut; ilut++ ) {
053767a4 1586 fLUT[ilayer*kNlut+ilut] = lut[ilayer][ilut];
fc546d21 1587 }
1588 }
1589
1590}
1591
1592//_____________________________________________________________________________
eb52b657 1593Double_t AliTRDclusterizer::LUTposition(Int_t ilayer
1594 , Double_t ampL
1595 , Double_t ampC
1596 , Double_t ampR) const
fc546d21 1597{
1598 //
1599 // Calculates the cluster position using the lookup table.
1600 // Method provided by Bogdan Vulpescu.
1601 //
1602
1603 const Int_t kNlut = 128;
1604
1605 Double_t pos;
1606 Double_t x = 0.0;
1607 Double_t xmin;
1608 Double_t xmax;
1609 Double_t xwid;
1610
1611 Int_t side = 0;
1612 Int_t ix;
1613
053767a4 1614 Double_t xMin[AliTRDgeometry::kNlayer] = { 0.006492, 0.006377, 0.006258
317b5644 1615 , 0.006144, 0.006030, 0.005980 };
053767a4 1616 Double_t xMax[AliTRDgeometry::kNlayer] = { 0.960351, 0.965870, 0.970445
317b5644 1617 , 0.974352, 0.977667, 0.996101 };
fc546d21 1618
1619 if (ampL > ampR) {
1620 x = (ampL - ampR) / ampC;
1621 side = -1;
1622 }
1623 else if (ampL < ampR) {
1624 x = (ampR - ampL) / ampC;
1625 side = +1;
1626 }
1627
1628 if (ampL != ampR) {
1629
053767a4 1630 xmin = xMin[ilayer] + 0.000005;
1631 xmax = xMax[ilayer] - 0.000005;
fc546d21 1632 xwid = (xmax - xmin) / 127.0;
1633
1634 if (x < xmin) {
1635 pos = 0.0000;
1636 }
1637 else if (x > xmax) {
1638 pos = side * 0.5000;
1639 }
1640 else {
1641 ix = (Int_t) ((x - xmin) / xwid);
053767a4 1642 pos = side * fLUT[ilayer*kNlut+ix];
fc546d21 1643 }
317b5644 1644
fc546d21 1645 }
1646 else {
1647
1648 pos = 0.0;
1649
1650 }
1651
1652 return pos;
1653
1654}