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