Moved kMAXTRACKS from AliMUONDigit.h to here.
[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"
21#include "AliMUONCalibrationData.h"
22#include "AliMUONChamber.h"
23#include "AliMUONConstants.h"
24#include "AliMUONData.h"
25#include "AliMUONDigit.h"
26#include "AliMUONTriggerDecisionV1.h"
4f8a3d8b 27#include "AliMUONTriggerElectronics.h"
92aeef15 28#include "AliMUONCalibParam.h"
29#include "AliMpDEManager.h"
30#include "AliMpStationType.h"
31#include "AliRun.h"
32#include "AliRunDigitizer.h"
33#include "AliRunLoader.h"
34#include "Riostream.h"
35#include "TRandom.h"
36#include "TString.h"
37
38ClassImp(AliMUONDigitizerV3)
39
40//_____________________________________________________________________________
41AliMUONDigitizerV3::AliMUONDigitizerV3(AliRunDigitizer* manager,
42 ETriggerCodeVersion triggerCodeVersion)
43: AliDigitizer(manager),
44fZeroSuppression(6),
45fSaturation(3000),
46fIsInitialized(kFALSE),
47fOutputData(0x0),
48fCalibrationData(0x0),
49fTriggerProcessor(0x0),
50fTriggerCodeVersion(triggerCodeVersion)
51{
52 AliDebug(1,Form("AliRunDigitizer=%p",fManager));
53}
54
55//_____________________________________________________________________________
56AliMUONDigitizerV3::~AliMUONDigitizerV3()
57{
58 AliDebug(1,"dtor");
59 delete fOutputData;
60 delete fCalibrationData;
61 delete fTriggerProcessor;
62}
63
64//_____________________________________________________________________________
65void
66AliMUONDigitizerV3::ApplyResponseToDigit(AliMUONDigit& digit)
67{
68 // For trigger digits, simply sets the digit's charge to 0 or 1.
69 //
70 // For tracking digits, starting from an ideal digit's charge, we :
71 //
72 // - add some noise (thus leading to a realistic charge)
73 // - divide by a gain (thus decalibrating the digit)
74 // - add a pedestal (thus decalibrating the digit)
75 // - sets the signal to zero if below ZeroSuppression() level (thus simulating
76 // zero suppression).
77 //
78
79 Int_t detElemId = digit.DetElemId();
80 AliMpStationType stationType = AliMpDEManager::GetStationType(detElemId);
81 if ( stationType == kStationTrigger )
82 {
83 if ( digit.Signal() > 0 )
84 {
85 digit.SetSignal(1);
86 }
87 else
88 {
89 digit.SetSignal(0);
90 }
91 return;
92 }
93
94 // The following is for tracking digits only.
95
96 Int_t manuId = digit.ManuId();
97 Int_t manuChannel = digit.ManuChannel();
98
99 AliMUONCalibParam* pedestal = fCalibrationData->Pedestal(detElemId,manuId,manuChannel);
100 if (!pedestal)
101 {
102 AliFatal(Form("Could not get pedestal for DE=%d manuId=%d manuChannel=%d",
103 detElemId,manuId,manuChannel));
104 }
105 Float_t adc_noise = gRandom->Gaus(0.0,pedestal->Sigma());
106
107 AliMUONCalibParam* gain = fCalibrationData->Gain(detElemId,manuId,manuChannel);
108 if (!gain)
109 {
110 AliFatal(Form("Could not get gain for DE=%d manuId=%d manuChannel=%d",
111 detElemId,manuId,manuChannel));
112 }
113
114 Float_t signal_noise = adc_noise*gain->Mean();
115
116 Float_t signal = digit.Signal() + signal_noise;
117 Int_t adc;
118
119 if ( signal > fSaturation )
120 {
121 adc = fSaturation;
122 digit.Saturated(kTRUE);
123 }
124 else
125 {
126 if ( gain->Mean() < 1E-6 )
127 {
128 AliFatal(Form("Got a too small gain %e for DE=%d manuId=%d manuChannel=%d",
129 gain->Mean(),detElemId,manuId,manuChannel));
130 }
131 adc = TMath::Nint( signal / gain->Mean() + pedestal->Mean() );
132
133 if ( adc <= pedestal->Mean() + 3.0*pedestal->Sigma() )
134 {
135 adc = 0;
136 }
137 }
138 digit.SetPhysicsSignal(TMath::Nint(signal));
139 digit.SetSignal(adc);
140 digit.SetADC(adc);
141}
142
143//_____________________________________________________________________________
144void
145AliMUONDigitizerV3::ApplyResponse()
146{
147 for ( Int_t ich = 0; ich < AliMUONConstants::NCh(); ++ich )
148 {
149 TClonesArray* digits = fOutputData->Digits(ich);
150 Int_t n = digits->GetEntriesFast();
151 for ( Int_t i = 0; i < n; ++i )
152 {
153 AliMUONDigit* d = static_cast<AliMUONDigit*>(digits->UncheckedAt(i));
154 ApplyResponseToDigit(*d);
155 if ( d->Signal() <= 0 )
156 {
157 digits->RemoveAt(i);
158 }
159 }
160 }
161
162 for ( Int_t ich = 0; ich < AliMUONConstants::NCh(); ++ich )
163 {
164 fOutputData->Digits(ich)->Compress();
165 }
166}
167
168//_____________________________________________________________________________
169void
170AliMUONDigitizerV3::AddOrUpdateDigit(TClonesArray& array,
171 const AliMUONDigit& digit)
172{
173 Int_t ix = FindDigitIndex(array,digit);
174
175 if (ix>=0)
176 {
177 AliMUONDigit* d = static_cast<AliMUONDigit*>(array.UncheckedAt(ix));
178 Bool_t ok = MergeDigits(digit,*d);
179 if (!ok)
180 {
181 AliError("Digits are not mergeable !");
182 }
183 else
184 {
185 new(array[ix]) AliMUONDigit(*d);
186 }
187 }
188 else
189 {
190 ix = array.GetLast() + 1;
191 new(array[ix]) AliMUONDigit(digit);
192 }
193
194}
195
196//_____________________________________________________________________________
197void
198AliMUONDigitizerV3::Exec(Option_t*)
199{
200 AliDebug(1, "Running digitizer.");
201
202 if ( fManager->GetNinputs() == 0 )
203 {
204 AliWarning("No input set. Nothing to do.");
205 return;
206 }
207
208 if ( !fIsInitialized )
209 {
210 AliError("Not initialized. Cannot perform the work. Sorry");
211 return;
212 }
213
214 Int_t nInputFiles = fManager->GetNinputs();
215
216 if ( fOutputData->TreeD() == 0x0 )
217 {
218 AliDebug(1,"Calling MakeDigitsContainer");
219 fOutputData->GetLoader()->MakeDigitsContainer();
220 }
221 fOutputData->MakeBranch("D,GLT");
222 fOutputData->SetTreeAddress("D,GLT");
223
224 // Loop over all the input files, and merge the sdigits found in those
225 // files.
226 for ( Int_t iFile = 0; iFile < nInputFiles; ++iFile )
227 {
228 AliMUONData* inputData = GetDataAccess(fManager->GetInputFolderName(iFile));
229 if (!inputData)
230 {
231 AliFatal(Form("Could not get access to input file #%d",iFile));
232 }
233 AliDebug(1,Form("inputData=%p",inputData));
234 //FIXME: what about the fMask ???
235 inputData->GetLoader()->LoadSDigits("READ");
236 TTree* treeS = inputData->GetLoader()->TreeS();
237 AliDebug(1,Form("TreeS=%p",treeS));
238 inputData->SetTreeAddress("S");
239 inputData->GetSDigits();
240 MergeWithSDigits(*fOutputData,*inputData);
241 inputData->ResetSDigits();
242 inputData->GetLoader()->UnloadSDigits();
243 delete inputData;
244 }
245
246 // At this point, we do have digit arrays (one per chamber) which contains
247 // the merging of all the sdigits of the input file(s).
248 // We now massage them to apply the detector response, i.e. this
249 // is here that we do the "digitization" work.
250
251 ApplyResponse();
252
253 //
254
255 // We generate the global and local trigger decisions.
256 fTriggerProcessor->ExecuteTask();
257
258 // Fill the output treeD
259 fOutputData->Fill("D,GLT");
260
261 // Write to the output tree(D).
262 // Please note that as GlobalTrigger, LocalTrigger and Digits are in the same
263 // tree (=TreeD) in different branches, this WriteDigits in fact writes all of
264 // the 3 branches.
265 fOutputData->GetLoader()->WriteDigits("OVERWRITE");
266
267 // Finally, we clean up after ourselves.
268 fOutputData->ResetDigits();
269 fOutputData->ResetTrigger();
270 fOutputData->GetLoader()->UnloadDigits();
271}
272
273//_____________________________________________________________________________
274Int_t
275AliMUONDigitizerV3::FindDigitIndex(TClonesArray& array, const AliMUONDigit& digit)
276{
277 // FIXME: this is of course not the best implementation you can think of.
278 // Reconsider the use of hit/digit map...
279 Int_t n = array.GetEntriesFast();
280 for ( Int_t i = 0; i < n; ++i )
281 {
282 AliMUONDigit* d = static_cast<AliMUONDigit*>(array.UncheckedAt(i));
283 if ( d->DetElemId() == digit.DetElemId() &&
284 d->PadX() == digit.PadX() &&
285 d->PadY() == digit.PadY() &&
286 d->Cathode() == digit.Cathode() )
287 {
288 return i;
289 }
290 }
291 return -1;
292}
293
294//_____________________________________________________________________________
295AliMUONData*
296AliMUONDigitizerV3::GetDataAccess(const TString& folderName)
297{
298 AliDebug(1,Form("Getting access to folder %s",folderName.Data()));
299 AliRunLoader* runLoader = AliRunLoader::GetRunLoader(folderName);
300 if (!runLoader)
301 {
302 AliError(Form("Could not get RunLoader from folder %s",folderName.Data()));
303 return 0x0;
304 }
305 AliLoader* loader = static_cast<AliLoader*>(runLoader->GetLoader("MUONLoader"));
306 if (!loader)
307 {
308 AliError(Form("Could not get MuonLoader from folder %s",folderName.Data()));
309 return 0x0;
310 }
311 AliMUONData* data = new AliMUONData(loader,"MUON","MUONDataForDigitOutput");
312 AliDebug(1,Form("AliMUONData=%p loader=%p",data,loader));
313 return data;
314}
315
316//_____________________________________________________________________________
317Bool_t
318AliMUONDigitizerV3::Init()
319{
320 AliDebug(1,"");
321
322 if ( fIsInitialized )
323 {
324 AliError("Object already initialized.");
325 return kFALSE;
326 }
327
328 if (!fManager)
329 {
330 AliError("fManager is null !");
331 return kFALSE;
332 }
333
334 fOutputData = GetDataAccess(fManager->GetOutputFolderName());
335 if (!fOutputData)
336 {
337 AliError("Can not perform digitization. I'm sorry");
338 return kFALSE;
339 }
340 AliDebug(1,Form("fOutputData=%p",fOutputData));
341
342 AliRunLoader* runLoader = fOutputData->GetLoader()->GetRunLoader();
343 AliRun* galice = runLoader->GetAliRun();
344 Int_t runnumber = galice->GetRunNumber();
345
346 fCalibrationData = new AliMUONCalibrationData(runnumber);
347
348 switch (fTriggerCodeVersion)
349 {
350 case kTriggerDecision:
351 fTriggerProcessor = new AliMUONTriggerDecisionV1(fOutputData);
352 break;
353 case kTriggerElectronics:
4f8a3d8b 354 fTriggerProcessor = new AliMUONTriggerElectronics(fOutputData);
92aeef15 355 break;
356 default:
357 AliFatal("Unknown trigger processor type");
358 break;
359 }
4f8a3d8b 360 AliDebug(1,Form("Using the following trigger code %s - %s",
361 fTriggerProcessor->GetName(),fTriggerProcessor->GetTitle()));
92aeef15 362 fIsInitialized = kTRUE;
363 return kTRUE;
364}
365
366//_____________________________________________________________________________
367Bool_t
368AliMUONDigitizerV3::MergeDigits(const AliMUONDigit& src, AliMUONDigit& srcAndDest)
369{
370 AliDebug(1,"Merging the following digits:");
371 StdoutToAliDebug(1,src.Print(););
372 StdoutToAliDebug(1,srcAndDest.Print(););
373
374 Bool_t check = ( src.DetElemId() == srcAndDest.DetElemId() &&
375 src.PadX() == srcAndDest.PadX() &&
376 src.PadY() == srcAndDest.PadY() &&
377 src.Cathode() == srcAndDest.Cathode() );
378 if (!check)
379 {
380 return kFALSE;
381 }
382
383
384 srcAndDest.AddSignal(src.Signal());
385 srcAndDest.AddPhysicsSignal(src.Physics());
386 StdoutToAliDebug(1,cout << "result:"; srcAndDest.Print(););
387 return kTRUE;
388}
389
390//_____________________________________________________________________________
391void
392AliMUONDigitizerV3::MergeWithSDigits(AliMUONData& outputData,
393 const AliMUONData& inputData)
394{
395 AliDebug(1,"");
396
397 for ( Int_t ich = 0; ich < AliMUONConstants::NCh(); ++ich )
398 {
399 TClonesArray* iDigits = inputData.SDigits(ich);
400 TClonesArray* oDigits = outputData.Digits(ich);
401 if (!iDigits)
402 {
403 AliError(Form("Could not get sdigits for ich=%d",ich));
404 return;
405 }
406 Int_t nSDigits = iDigits->GetEntriesFast();
407 for ( Int_t k = 0; k < nSDigits; ++k )
408 {
409 AliMUONDigit* sdigit = static_cast<AliMUONDigit*>(iDigits->UncheckedAt(k));
410 // FIXME: Merging logic should go here.
411 // For testing, only put the digit in the output.
412 if (!sdigit)
413 {
414 AliError(Form("Could not get sdigit for ich=%d and k=%d",ich,k));
415 }
416 else
417 {
418 AddOrUpdateDigit(*oDigits,*sdigit);
419 }
420 }
421 }
422}
423
424//------------------------------------------------------------------------
425//void AliMUONDigitizerv2::FillTriggerOutput()
426//{
427// // Derived to fill TreeD and resets the trigger array in fMUONData.
428//
429// AliDebug(3,"Filling trees with trigger.");
430// fMUONData->Fill("GLT");
431// fMUONData->ResetTrigger();
432//}
433//
434//------------------------------------------------------------------------
435//void AliMUONDigitizerv2::CreateTrigger()
436//{
437// fMUONData->MakeBranch("GLT");
438// fMUONData->SetTreeAddress("GLT");
439// fTrigDec->Digits2Trigger();
440// FillTriggerOutput();
441//
442//}
443