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