]> git.uio.no Git - u/mrichter/AliRoot.git/blame - MUON/AliMUONDigitizerV3.cxx
- We now save in MUON ESD both track parameters extrapolated to vertex
[u/mrichter/AliRoot.git] / MUON / AliMUONDigitizerV3.cxx
CommitLineData
92aeef15 1/**************************************************************************
2* Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
3* *
4* Author: The ALICE Off-line Project. *
5* Contributors are mentioned in the code where appropriate. *
6* *
7* Permission to use, copy, modify and distribute this software and its *
8* documentation strictly for non-commercial purposes is hereby granted *
9* without fee, provided that the above copyright notice appears in all *
10* copies and that both the copyright notice and this permission notice *
11* appear in the supporting documentation. The authors make no claims *
12* about the suitability of this software for any purpose. It is *
13* provided "as is" without express or implied warranty. *
14**************************************************************************/
15
16// $Id$
17
9edefa04 18
92aeef15 19#include "AliMUONDigitizerV3.h"
20
4ce497c4 21#include "AliMUON.h"
92aeef15 22#include "AliMUONCalibrationData.h"
ad26d4f6 23#include "AliCDBManager.h"
92aeef15 24#include "AliMUONConstants.h"
25#include "AliMUONData.h"
4ce497c4 26#include "AliMUONDataIterator.h"
92aeef15 27#include "AliMUONDigit.h"
ad26d4f6 28#include "AliMUONLogger.h"
4ce497c4 29#include "AliMUONSegmentation.h"
4ce497c4 30#include "AliMUONTriggerEfficiencyCells.h"
4f8a3d8b 31#include "AliMUONTriggerElectronics.h"
05314992 32#include "AliMUONVCalibParam.h"
9265505b 33
4ce497c4 34#include "AliMpDEIterator.h"
92aeef15 35#include "AliMpDEManager.h"
4ce497c4 36#include "AliMpIntPair.h"
37#include "AliMpPad.h"
92aeef15 38#include "AliMpStationType.h"
9265505b 39#include "AliMpSegmentation.h"
4ce497c4 40#include "AliMpVSegmentation.h"
66f4c572 41#include "AliMpDEManager.h"
866c3232 42#include "AliMpCathodType.h"
9265505b 43
92aeef15 44#include "AliRun.h"
45#include "AliRunDigitizer.h"
46#include "AliRunLoader.h"
9265505b 47#include "AliLog.h"
48
866c3232 49#include <Riostream.h>
50#include <TF1.h>
51#include <TMath.h>
52#include <TRandom.h>
53#include <TString.h>
4ce497c4 54///
9265505b 55/// \class AliMUONDigitizerV3
4ce497c4 56/// The digitizer is performing the transformation to go from SDigits (digits
57/// w/o any electronic noise) to Digits (w/ electronic noise, and decalibration)
58///
59/// The decalibration is performed by doing the reverse operation of the
60/// calibration, that is we do (Signal+pedestal)/gain -> ADC
61///
62/// Note also that the digitizer takes care of merging sdigits that belongs
63/// to the same pad, either because we're merging several input sdigit files
64/// or with a single file because the sdigitizer does not merge sdigits itself
65/// (for performance reason mainly, and because anyway we know we have to do it
66/// here, at the digitization level).
67///
68
69namespace
70{
71 AliMUON* muon()
72 {
73 return static_cast<AliMUON*>(gAlice->GetModule("MUON"));
74 }
4ce497c4 75}
76
77const Double_t AliMUONDigitizerV3::fgkNSigmas=3;
78
9265505b 79/// \cond CLASSIMP
92aeef15 80ClassImp(AliMUONDigitizerV3)
9265505b 81/// \endcond
92aeef15 82
83//_____________________________________________________________________________
84AliMUONDigitizerV3::AliMUONDigitizerV3(AliRunDigitizer* manager,
4ce497c4 85 Bool_t generateNoisyDigits)
92aeef15 86: AliDigitizer(manager),
92aeef15 87fIsInitialized(kFALSE),
88fOutputData(0x0),
89fCalibrationData(0x0),
90fTriggerProcessor(0x0),
4ce497c4 91fTriggerEfficiency(0x0),
ccea41d4 92fFindDigitIndexTimer(),
93fGenerateNoisyDigitsTimer(),
94fExecTimer(),
4ce497c4 95fNoiseFunction(0x0),
ad26d4f6 96 fGenerateNoisyDigits(generateNoisyDigits),
97 fLogger(new AliMUONLogger(1000))
92aeef15 98{
9265505b 99 /// Ctor.
100
92aeef15 101 AliDebug(1,Form("AliRunDigitizer=%p",fManager));
4ce497c4 102 fGenerateNoisyDigitsTimer.Start(kTRUE); fGenerateNoisyDigitsTimer.Stop();
103 fExecTimer.Start(kTRUE); fExecTimer.Stop();
104 fFindDigitIndexTimer.Start(kTRUE); fFindDigitIndexTimer.Stop();
92aeef15 105}
106
107//_____________________________________________________________________________
108AliMUONDigitizerV3::~AliMUONDigitizerV3()
109{
9265505b 110 /// Dtor. Note we're the owner of some pointers.
111
92aeef15 112 AliDebug(1,"dtor");
4ce497c4 113
92aeef15 114 delete fOutputData;
115 delete fCalibrationData;
116 delete fTriggerProcessor;
4ce497c4 117 delete fNoiseFunction;
118
a7b01aa5 119 AliDebug(1, Form("Execution time for FindDigitIndex() : R:%.2fs C:%.2fs",
4ce497c4 120 fFindDigitIndexTimer.RealTime(),fFindDigitIndexTimer.CpuTime()));
121 if ( fGenerateNoisyDigits )
122 {
a7b01aa5 123 AliDebug(1, Form("Execution time for GenerateNoisyDigits() : R:%.2fs C:%.2fs",
4ce497c4 124 fGenerateNoisyDigitsTimer.RealTime(),
125 fGenerateNoisyDigitsTimer.CpuTime()));
126 }
a7b01aa5 127 AliDebug(1, Form("Execution time for Exec() : R:%.2fs C:%.2fs",
4ce497c4 128 fExecTimer.RealTime(),fExecTimer.CpuTime()));
ad26d4f6 129
130 AliInfo("Summary of messages");
131 fLogger->Print();
4ce497c4 132
ad26d4f6 133 delete fLogger;
92aeef15 134}
135
136//_____________________________________________________________________________
137void
4ce497c4 138AliMUONDigitizerV3::ApplyResponseToTrackerDigit(AliMUONDigit& digit, Bool_t addNoise)
92aeef15 139{
9265505b 140 /// For tracking digits, starting from an ideal digit's charge, we :
141 ///
142 /// - add some noise (thus leading to a realistic charge), if requested to do so
143 /// - divide by a gain (thus decalibrating the digit)
144 /// - add a pedestal (thus decalibrating the digit)
145 /// - sets the signal to zero if below 3*sigma of the noise
59b91539 146
4ce497c4 147 static const Int_t kMaxADC = (1<<12)-1; // We code the charge on a 12 bits ADC.
ad26d4f6 148
4ce497c4 149 Float_t signal = digit.Signal();
ad26d4f6 150
59b91539 151 if ( !addNoise )
ad26d4f6 152 {
153 digit.SetADC(TMath::Nint(signal));
154 return;
155 }
92aeef15 156
4ce497c4 157 Int_t detElemId = digit.DetElemId();
92aeef15 158
159 Int_t manuId = digit.ManuId();
160 Int_t manuChannel = digit.ManuChannel();
161
4ce497c4 162 AliMUONVCalibParam* pedestal = fCalibrationData->Pedestals(detElemId,manuId);
92aeef15 163 if (!pedestal)
ad26d4f6 164 {
165 fLogger->Log(Form("%s:%d:Could not get pedestal for DE=%4d manuId=%4d. Disabling.",
166 __FILE__,__LINE__,
167 detElemId,manuId));
168 digit.SetPhysicsSignal(0);
169 digit.SetSignal(0);
170 digit.SetADC(0);
171 return;
172 }
05314992 173 Float_t pedestalMean = pedestal->ValueAsFloat(manuChannel,0);
174 Float_t pedestalSigma = pedestal->ValueAsFloat(manuChannel,1);
59b91539 175
4ce497c4 176 AliMUONVCalibParam* gain = fCalibrationData->Gains(detElemId,manuId);
92aeef15 177 if (!gain)
ad26d4f6 178 {
179 fLogger->Log(Form("%s:%d:Could not get gain for DE=%4d manuId=%4d. Disabling.",
180 __FILE__,__LINE__,
181 detElemId,manuId));
182 digit.SetPhysicsSignal(0);
183 digit.SetSignal(0);
184 digit.SetADC(0);
185 return;
186 }
05314992 187 Float_t gainMean = gain->ValueAsFloat(manuChannel,0);
ad26d4f6 188
59b91539 189 Float_t adcNoise = gRandom->Gaus(0.0,pedestalSigma);
ad26d4f6 190
92aeef15 191 Int_t adc;
ad26d4f6 192
05314992 193 if ( gainMean < 1E-6 )
ad26d4f6 194 {
195 AliError(Form("Got a too small gain %e for DE=%d manuId=%d manuChannel=%d. "
196 "Setting signal to 0.",
197 gainMean,detElemId,manuId,manuChannel));
198 adc = 0;
199 }
59b91539 200 else
ad26d4f6 201 {
202 adc = TMath::Nint( signal / gainMean + pedestalMean + adcNoise);///
203
204 if ( adc <= pedestalMean + fgkNSigmas*pedestalSigma )
59b91539 205 {
ad26d4f6 206 adc = 0;
59b91539 207 }
ad26d4f6 208 }
59b91539 209
05314992 210 // be sure we stick to 12 bits.
4ce497c4 211 if ( adc > kMaxADC )
ad26d4f6 212 {
213 adc = kMaxADC;
214 }
59b91539 215
92aeef15 216 digit.SetPhysicsSignal(TMath::Nint(signal));
217 digit.SetSignal(adc);
218 digit.SetADC(adc);
219}
220
4ce497c4 221//_____________________________________________________________________________
222void
ad26d4f6 223AliMUONDigitizerV3::ApplyResponseToTriggerDigit(AliMUONDigit& digit)
4ce497c4 224{
9265505b 225 /// \todo add comment
226
4ce497c4 227 if ( !fTriggerEfficiency ) return;
228
ad26d4f6 229 if (digit.IsEfficiencyApplied()) return;
4ce497c4 230
ad26d4f6 231 AliMUONDigit* correspondingDigit = FindCorrespondingDigit(digit);
232
233 if (!correspondingDigit) return; //reject bad correspondences
a0dc51a6 234
4ce497c4 235 Int_t detElemId = digit.DetElemId();
9265505b 236
237 AliMpSegmentation* segmentation = AliMpSegmentation::Instance();
4ce497c4 238 const AliMpVSegmentation* segment[2] =
239 {
866c3232 240 segmentation->GetMpSegmentation(detElemId,AliMp::GetCathodType(digit.Cathode())),
241 segmentation->GetMpSegmentation(detElemId,AliMp::GetCathodType(correspondingDigit->Cathode()))
4ce497c4 242 };
243
244 AliMpPad pad[2] =
245 {
246 segment[0]->PadByIndices(AliMpIntPair(digit.PadX(),digit.PadY()),kTRUE),
247 segment[1]->PadByIndices(AliMpIntPair(correspondingDigit->PadX(),correspondingDigit->PadY()),kTRUE)
248 };
249
081d3361 250 Int_t p0(1);
ad26d4f6 251 if (digit.Cathode()==0) p0=0;
081d3361 252
253 AliMpIntPair location = pad[p0].GetLocation(0);
254 Int_t nboard = location.GetFirst();
4ce497c4 255
4ce497c4 256 Bool_t isTrig[2];
081d3361 257
258 fTriggerEfficiency->IsTriggered(detElemId, nboard-1,
4ce497c4 259 isTrig[0], isTrig[1]);
ad26d4f6 260 digit.EfficiencyApplied(kTRUE);
261 correspondingDigit->EfficiencyApplied(kTRUE);
081d3361 262
4ce497c4 263 if (!isTrig[digit.Cathode()])
264 {
265 digit.SetSignal(0);
266 }
267
268 if ( &digit != correspondingDigit )
269 {
270 if (!isTrig[correspondingDigit->Cathode()])
271 {
272 correspondingDigit->SetSignal(0);
273 }
274 }
275}
276
92aeef15 277//_____________________________________________________________________________
278void
279AliMUONDigitizerV3::ApplyResponse()
280{
9265505b 281 /// Loop over all chamber digits, and apply the response to them
282 /// Note that this method may remove digits.
283
4ce497c4 284 const Bool_t kAddNoise = kTRUE;
285
92aeef15 286 for ( Int_t ich = 0; ich < AliMUONConstants::NCh(); ++ich )
4ce497c4 287 {
92aeef15 288 TClonesArray* digits = fOutputData->Digits(ich);
289 Int_t n = digits->GetEntriesFast();
4ce497c4 290 Bool_t trackingChamber = ( ich < AliMUONConstants::NTrackingCh() );
92aeef15 291 for ( Int_t i = 0; i < n; ++i )
292 {
293 AliMUONDigit* d = static_cast<AliMUONDigit*>(digits->UncheckedAt(i));
ad26d4f6 294 if ( !d ) continue; // that digit might have been removed
4ce497c4 295 if ( trackingChamber )
296 {
297 ApplyResponseToTrackerDigit(*d,kAddNoise);
298 }
299 else
300 {
ad26d4f6 301 ApplyResponseToTriggerDigit(*d);
4ce497c4 302 }
92aeef15 303 if ( d->Signal() <= 0 )
304 {
305 digits->RemoveAt(i);
306 }
307 }
ad26d4f6 308 digits->Compress(); // only do the compress at the end in order not to
309 // change the n = digits->GetEntriesFast()
92aeef15 310 }
4ce497c4 311
312// The version below, using iterator, does not yet work (as the iterator
313// assumes it is reading digits from the tree, while in this case it's
314// writing...)
315//
316// AliMUONDigit* digit(0x0);
317//
318// // First loop on tracker digits
319// AliMUONDataIterator tracker(fOutputData,"D",AliMUONDataIterator::kTrackingChambers);
320//
321// while ( ( digit = static_cast<AliMUONDigit*>(tracker.Next()) ) )
322// {
323// ApplyResponseToTrackerDigit(*digit);
324// if ( digit->Signal() <= 0 )
325// {
326// tracker.Remove();
327// }
328//
329// }
330//
331// // Then loop on trigger digits
332// AliMUONDataIterator trigger(fOutputData,"D",AliMUONDataIterator::kTriggerChambers);
333//
334// while ( ( digit = static_cast<AliMUONDigit*>(trigger.Next()) ) )
335// {
336// ApplyResponseToTriggerDigit(*digit,fOutputData);
337// if ( digit->Signal() <= 0 )
338// {
339// trigger.Remove();
340// }
341// }
92aeef15 342}
343
344//_____________________________________________________________________________
345void
346AliMUONDigitizerV3::AddOrUpdateDigit(TClonesArray& array,
347 const AliMUONDigit& digit)
348{
9265505b 349 /// Add or update a digit, depending on whether there's already a digit
350 /// for the corresponding channel.
351
92aeef15 352 Int_t ix = FindDigitIndex(array,digit);
353
354 if (ix>=0)
355 {
356 AliMUONDigit* d = static_cast<AliMUONDigit*>(array.UncheckedAt(ix));
357 Bool_t ok = MergeDigits(digit,*d);
358 if (!ok)
359 {
360 AliError("Digits are not mergeable !");
361 }
92aeef15 362 }
363 else
364 {
365 ix = array.GetLast() + 1;
366 new(array[ix]) AliMUONDigit(digit);
367 }
368
369}
370
371//_____________________________________________________________________________
372void
373AliMUONDigitizerV3::Exec(Option_t*)
374{
9265505b 375 /// Main method.
376 /// We first loop over input files, and merge the sdigits we found there.
377 /// Second, we digitize all the resulting sdigits
378 /// Then we generate noise-only digits (for tracker only)
379 /// And we finally generate the trigger outputs.
4ce497c4 380
92aeef15 381 AliDebug(1, "Running digitizer.");
382
383 if ( fManager->GetNinputs() == 0 )
384 {
385 AliWarning("No input set. Nothing to do.");
386 return;
387 }
388
389 if ( !fIsInitialized )
390 {
391 AliError("Not initialized. Cannot perform the work. Sorry");
392 return;
393 }
394
4ce497c4 395 fExecTimer.Start(kFALSE);
396
92aeef15 397 Int_t nInputFiles = fManager->GetNinputs();
398
399 if ( fOutputData->TreeD() == 0x0 )
400 {
ad26d4f6 401 AliDebug(2,"Calling MakeDigitsContainer");
92aeef15 402 fOutputData->GetLoader()->MakeDigitsContainer();
403 }
404 fOutputData->MakeBranch("D,GLT");
405 fOutputData->SetTreeAddress("D,GLT");
406
407 // Loop over all the input files, and merge the sdigits found in those
408 // files.
409 for ( Int_t iFile = 0; iFile < nInputFiles; ++iFile )
410 {
411 AliMUONData* inputData = GetDataAccess(fManager->GetInputFolderName(iFile));
412 if (!inputData)
413 {
414 AliFatal(Form("Could not get access to input file #%d",iFile));
415 }
05314992 416
92aeef15 417 inputData->GetLoader()->LoadSDigits("READ");
92aeef15 418 inputData->SetTreeAddress("S");
419 inputData->GetSDigits();
05314992 420
421 MergeWithSDigits(*fOutputData,*inputData,fManager->GetMask(iFile));
422
92aeef15 423 inputData->ResetSDigits();
424 inputData->GetLoader()->UnloadSDigits();
425 delete inputData;
426 }
427
428 // At this point, we do have digit arrays (one per chamber) which contains
429 // the merging of all the sdigits of the input file(s).
430 // We now massage them to apply the detector response, i.e. this
431 // is here that we do the "digitization" work.
432
433 ApplyResponse();
4ce497c4 434
435 if ( fGenerateNoisyDigits )
436 {
437 // Generate noise-only digits for tracker.
438 GenerateNoisyDigits();
439 }
440
92aeef15 441 // We generate the global and local trigger decisions.
442 fTriggerProcessor->ExecuteTask();
443
444 // Fill the output treeD
445 fOutputData->Fill("D,GLT");
446
447 // Write to the output tree(D).
448 // Please note that as GlobalTrigger, LocalTrigger and Digits are in the same
449 // tree (=TreeD) in different branches, this WriteDigits in fact writes all of
450 // the 3 branches.
451 fOutputData->GetLoader()->WriteDigits("OVERWRITE");
452
453 // Finally, we clean up after ourselves.
454 fOutputData->ResetDigits();
455 fOutputData->ResetTrigger();
456 fOutputData->GetLoader()->UnloadDigits();
4ce497c4 457
458 fExecTimer.Stop();
92aeef15 459}
460
4ce497c4 461//_____________________________________________________________________________
462AliMUONDigit*
ad26d4f6 463AliMUONDigitizerV3::FindCorrespondingDigit(AliMUONDigit& digit) const
4ce497c4 464{
ad26d4f6 465 /// Find, if it exists, the digit corresponding to digit.Hit(), in the
466 /// other cathode
9265505b 467
ad26d4f6 468// Iterator does not yet work when writing digits (only works when reading,
469// which is not the case here)
470//
471// AliMUONDataIterator it(data,"D",AliMUONDataIterator::kTriggerChambers);
472// AliMUONDigit* cd;
473//
474// while ( ( cd = static_cast<AliMUONDigit*>(it.Next()) ) )
475// {
476// if ( cd->DetElemId() == digit.DetElemId() &&
477// cd->Hit() == digit.Hit() &&
478// cd->Cathode() != digit.Cathode() )
479// {
480// break;
481// }
482// }
4ce497c4 483
ad26d4f6 484 Int_t ich = AliMpDEManager::GetChamberId(digit.DetElemId());
485 TClonesArray* digits = fOutputData->Digits(ich);
486 Int_t n = digits->GetEntriesFast();
487 for ( Int_t i = 0; i < n; ++i )
4ce497c4 488 {
ad26d4f6 489 AliMUONDigit* d = static_cast<AliMUONDigit*>(digits->UncheckedAt(i));
490 if ( d &&
491 d->DetElemId() == digit.DetElemId() &&
492 d->Hit() == digit.Hit() &&
493 d->Cathode() != digit.Cathode() )
4ce497c4 494 {
ad26d4f6 495 return d;
496 }
497 }
498
4ce497c4 499 return 0x0;
500}
501
502
92aeef15 503//_____________________________________________________________________________
504Int_t
4ce497c4 505AliMUONDigitizerV3::FindDigitIndex(TClonesArray& array,
506 const AliMUONDigit& digit) const
92aeef15 507{
9265505b 508 /// Return the index of digit within array, if that digit is there,
509 /// otherwise returns -1
510 ///
511 /// \todo FIXME: this is of course not the best implementation you can think of.
512 /// Reconsider the use of hit/digit map... ? (but be sure it's needed!)
4ce497c4 513
514 fFindDigitIndexTimer.Start(kFALSE);
515
92aeef15 516 Int_t n = array.GetEntriesFast();
517 for ( Int_t i = 0; i < n; ++i )
518 {
519 AliMUONDigit* d = static_cast<AliMUONDigit*>(array.UncheckedAt(i));
520 if ( d->DetElemId() == digit.DetElemId() &&
521 d->PadX() == digit.PadX() &&
522 d->PadY() == digit.PadY() &&
523 d->Cathode() == digit.Cathode() )
524 {
4ce497c4 525 fFindDigitIndexTimer.Stop();
92aeef15 526 return i;
527 }
528 }
4ce497c4 529 fFindDigitIndexTimer.Stop();
92aeef15 530 return -1;
531}
532
4ce497c4 533//_____________________________________________________________________________
534void
535AliMUONDigitizerV3::GenerateNoisyDigits()
536{
9265505b 537 /// According to a given probability, generate digits that
538 /// have a signal above the noise cut (ped+n*sigma_ped), i.e. digits
539 /// that are "only noise".
4ce497c4 540
541 if ( !fNoiseFunction )
542 {
543 fNoiseFunction = new TF1("AliMUONDigitizerV3::fNoiseFunction","gaus",
544 fgkNSigmas,fgkNSigmas*10);
545
546 fNoiseFunction->SetParameters(1,0,1);
547 }
548
549 fGenerateNoisyDigitsTimer.Start(kFALSE);
550
551 for ( Int_t i = 0; i < AliMUONConstants::NTrackingCh(); ++i )
552 {
553 AliMpDEIterator it;
554
555 it.First(i);
556
557 while ( !it.IsDone() )
558 {
559 for ( Int_t cathode = 0; cathode < 2; ++cathode )
560 {
866c3232 561 GenerateNoisyDigitsForOneCathode(it.CurrentDEId(),cathode);
4ce497c4 562 }
563 it.Next();
564 }
565 }
566
567 fGenerateNoisyDigitsTimer.Stop();
568}
569
570//_____________________________________________________________________________
571void
572AliMUONDigitizerV3::GenerateNoisyDigitsForOneCathode(Int_t detElemId, Int_t cathode)
573{
9265505b 574 /// Generate noise-only digits for one cathode of one detection element.
575 /// Called by GenerateNoisyDigits()
4ce497c4 576
66f4c572 577 Int_t chamberId = AliMpDEManager::GetChamberId(detElemId);
578 TClonesArray* digits = fOutputData->Digits(chamberId);
4ce497c4 579
9265505b 580 const AliMpVSegmentation* seg
866c3232 581 = AliMpSegmentation::Instance()->GetMpSegmentation(detElemId,AliMp::GetCathodType(cathode));
4ce497c4 582 Int_t nofPads = seg->NofPads();
583
584 Int_t maxIx = seg->MaxPadIndexX();
585 Int_t maxIy = seg->MaxPadIndexY();
586
cdea095e 587 static const Double_t kProbToBeOutsideNsigmas = TMath::Erfc(fgkNSigmas/TMath::Sqrt(2.0)) / 2. ;
4ce497c4 588
84aac932 589 Int_t nofNoisyPads = TMath::Nint(kProbToBeOutsideNsigmas*nofPads);
4ce497c4 590 if ( !nofNoisyPads ) return;
591
592 nofNoisyPads =
593 TMath::Nint(gRandom->Gaus(nofNoisyPads,
594 nofNoisyPads/TMath::Sqrt(nofNoisyPads)));
595
596 AliDebug(3,Form("DE %d cath %d nofNoisyPads %d",detElemId,cathode,nofNoisyPads));
597
598 for ( Int_t i = 0; i < nofNoisyPads; ++i )
599 {
600 Int_t ix(-1);
601 Int_t iy(-1);
602 do {
603 ix = gRandom->Integer(maxIx+1);
604 iy = gRandom->Integer(maxIy+1);
605 } while ( !seg->HasPad(AliMpIntPair(ix,iy)) );
606 AliMUONDigit d;
607 d.SetDetElemId(detElemId);
608 d.SetCathode(cathode);
609 d.SetPadX(ix);
610 d.SetPadY(iy);
611 if ( FindDigitIndex(*digits,d) >= 0 )
612 {
613 // this digit is already there, and not noise-only, we simply skip it
614 continue;
615 }
616 AliMpPad pad = seg->PadByIndices(AliMpIntPair(ix,iy));
617 Int_t manuId = pad.GetLocation().GetFirst();
618 Int_t manuChannel = pad.GetLocation().GetSecond();
619
620 d.SetElectronics(manuId,manuChannel);
621
622 AliMUONVCalibParam* pedestals = fCalibrationData->Pedestals(detElemId,manuId);
623
ad26d4f6 624 if (!pedestals)
625 {
626 // no pedestal available for this channel, simply give up
627 return;
628 }
629
4ce497c4 630 Float_t pedestalMean = pedestals->ValueAsFloat(manuChannel,0);
631 Float_t pedestalSigma = pedestals->ValueAsFloat(manuChannel,1);
632
633 Double_t ped = fNoiseFunction->GetRandom()*pedestalSigma;
59b91539 634
4ce497c4 635 d.SetSignal(TMath::Nint(ped+pedestalMean+0.5));
59b91539 636 d.SetPhysicsSignal(0);
4ce497c4 637 d.NoiseOnly(kTRUE);
638 AliDebug(3,Form("Adding a pure noise digit :"));
ad26d4f6 639// StdoutToAliDebug(3,cout << "Before Response: " << endl;
640// d.Print(););
4ce497c4 641 ApplyResponseToTrackerDigit(d,kFALSE);
642 if ( d.Signal() > 0 )
643 {
644 AddOrUpdateDigit(*digits,d);
645 }
646 else
647 {
648 AliError("Pure noise below threshold. This should not happen. Not adding "
649 "this digit.");
650 }
ad26d4f6 651// StdoutToAliDebug(3,cout << "After Response: " << endl;
652// d.Print(););
4ce497c4 653 }
654}
655
92aeef15 656//_____________________________________________________________________________
657AliMUONData*
658AliMUONDigitizerV3::GetDataAccess(const TString& folderName)
659{
9265505b 660 /// Create an AliMUONData to deal with data found in folderName.
661
ad26d4f6 662 AliDebug(2,Form("Getting access to folder %s",folderName.Data()));
92aeef15 663 AliRunLoader* runLoader = AliRunLoader::GetRunLoader(folderName);
664 if (!runLoader)
665 {
666 AliError(Form("Could not get RunLoader from folder %s",folderName.Data()));
667 return 0x0;
668 }
669 AliLoader* loader = static_cast<AliLoader*>(runLoader->GetLoader("MUONLoader"));
670 if (!loader)
671 {
672 AliError(Form("Could not get MuonLoader from folder %s",folderName.Data()));
673 return 0x0;
674 }
675 AliMUONData* data = new AliMUONData(loader,"MUON","MUONDataForDigitOutput");
ad26d4f6 676 AliDebug(2,Form("AliMUONData=%p loader=%p",data,loader));
92aeef15 677 return data;
678}
679
680//_____________________________________________________________________________
681Bool_t
682AliMUONDigitizerV3::Init()
683{
9265505b 684 /// Initialization of the TTask :
685 /// a) set the outputData pointer
686 /// b) create the calibrationData, according to run number
687 /// c) create the trigger processing task
688
ad26d4f6 689 AliDebug(2,"");
92aeef15 690
691 if ( fIsInitialized )
692 {
693 AliError("Object already initialized.");
694 return kFALSE;
695 }
696
697 if (!fManager)
698 {
699 AliError("fManager is null !");
700 return kFALSE;
701 }
702
703 fOutputData = GetDataAccess(fManager->GetOutputFolderName());
704 if (!fOutputData)
705 {
706 AliError("Can not perform digitization. I'm sorry");
707 return kFALSE;
708 }
ad26d4f6 709 AliDebug(2,Form("fOutputData=%p",fOutputData));
92aeef15 710
ad26d4f6 711 Int_t runnumber = AliCDBManager::Instance()->GetRun();
92aeef15 712
713 fCalibrationData = new AliMUONCalibrationData(runnumber);
ad26d4f6 714 if ( !fCalibrationData->Pedestals() )
715 {
716 AliFatal("Could not access pedestals from OCDB !");
717 }
718 if ( !fCalibrationData->Gains() )
719 {
720 AliFatal("Could not access gains from OCDB !");
721 }
eb5d708c 722 fTriggerProcessor = new AliMUONTriggerElectronics(fOutputData,fCalibrationData);
4ce497c4 723
afb3ccf0 724 if ( muon()->GetTriggerEffCells() )
4ce497c4 725 {
726 fTriggerEfficiency = fCalibrationData->TriggerEfficiency();
727 if ( fTriggerEfficiency )
728 {
a7b01aa5 729 AliDebug(1, "Will apply trigger efficiency");
4ce497c4 730 }
731 else
732 {
ad26d4f6 733 AliFatal("I was requested to apply trigger efficiency, but I could "
4ce497c4 734 "not get it !");
735 }
736 }
737
ad26d4f6 738 AliDebug(1, Form("Will %s generate noise-only digits for tracker",
739 (fGenerateNoisyDigits ? "":"NOT")));
740
92aeef15 741 fIsInitialized = kTRUE;
742 return kTRUE;
743}
744
745//_____________________________________________________________________________
746Bool_t
05314992 747AliMUONDigitizerV3::MergeDigits(const AliMUONDigit& src,
748 AliMUONDigit& srcAndDest)
92aeef15 749{
9265505b 750 /// Merge 2 digits (src and srcAndDest) into srcAndDest.
751
ad26d4f6 752 AliDebug(2,"Merging the following digits:");
753// StdoutToAliDebug(2,src.Print("tracks"););
754// StdoutToAliDebug(2,srcAndDest.Print("tracks"););
92aeef15 755
756 Bool_t check = ( src.DetElemId() == srcAndDest.DetElemId() &&
757 src.PadX() == srcAndDest.PadX() &&
758 src.PadY() == srcAndDest.PadY() &&
759 src.Cathode() == srcAndDest.Cathode() );
760 if (!check)
761 {
762 return kFALSE;
763 }
764
92aeef15 765 srcAndDest.AddSignal(src.Signal());
766 srcAndDest.AddPhysicsSignal(src.Physics());
05314992 767 for ( Int_t i = 0; i < src.Ntracks(); ++i )
768 {
769 srcAndDest.AddTrack(src.Track(i),src.TrackCharge(i));
770 }
ad26d4f6 771// StdoutToAliDebug(2,cout << "result:"; srcAndDest.Print("tracks"););
92aeef15 772 return kTRUE;
773}
774
775//_____________________________________________________________________________
776void
777AliMUONDigitizerV3::MergeWithSDigits(AliMUONData& outputData,
05314992 778 const AliMUONData& inputData, Int_t mask)
92aeef15 779{
9265505b 780 /// Merge the sdigits in inputData with the digits already present in outputData
781
ad26d4f6 782 AliDebug(2,"");
92aeef15 783
784 for ( Int_t ich = 0; ich < AliMUONConstants::NCh(); ++ich )
785 {
786 TClonesArray* iDigits = inputData.SDigits(ich);
787 TClonesArray* oDigits = outputData.Digits(ich);
788 if (!iDigits)
789 {
790 AliError(Form("Could not get sdigits for ich=%d",ich));
791 return;
792 }
793 Int_t nSDigits = iDigits->GetEntriesFast();
794 for ( Int_t k = 0; k < nSDigits; ++k )
795 {
796 AliMUONDigit* sdigit = static_cast<AliMUONDigit*>(iDigits->UncheckedAt(k));
92aeef15 797 if (!sdigit)
798 {
799 AliError(Form("Could not get sdigit for ich=%d and k=%d",ich,k));
800 }
801 else
802 {
05314992 803 // Update the track references using the mask.
804 // FIXME: this is dirty, for backward compatibility only.
805 // Should re-design all this way of keeping track of MC information...
806 if ( mask ) sdigit->PatchTracks(mask);
807 // Then add or update the digit to the output.
92aeef15 808 AddOrUpdateDigit(*oDigits,*sdigit);
809 }
9265505b 810 }
92aeef15 811 }
812}