]>
Commit | Line | Data |
---|---|---|
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" |
92aeef15 | 23 | #include "AliMUONConstants.h" |
92aeef15 | 24 | #include "AliMUONDigit.h" |
ad26d4f6 | 25 | #include "AliMUONLogger.h" |
4f8a3d8b | 26 | #include "AliMUONTriggerElectronics.h" |
40e382ae | 27 | #include "AliMUONTriggerStoreV1.h" |
05314992 | 28 | #include "AliMUONVCalibParam.h" |
40e382ae | 29 | #include "AliMUONVDigitStore.h" |
331a617a | 30 | #include "AliMUONGeometryTransformer.h" //ADDED for trigger noise |
31 | ||
88544f7e | 32 | #include "AliMpCDB.h" |
331a617a | 33 | #include "AliMpSegmentation.h" |
40e382ae | 34 | #include "AliMpCathodType.h" |
35 | #include "AliMpConstants.h" | |
4ce497c4 | 36 | #include "AliMpDEIterator.h" |
92aeef15 | 37 | #include "AliMpDEManager.h" |
4ce497c4 | 38 | #include "AliMpIntPair.h" |
39 | #include "AliMpPad.h" | |
40e382ae | 40 | #include "AliMpStationType.h" |
4ce497c4 | 41 | #include "AliMpVSegmentation.h" |
331a617a | 42 | |
43 | #include "AliCDBManager.h" | |
44 | #include "AliCodeTimer.h" | |
45 | #include "AliLog.h" | |
92aeef15 | 46 | #include "AliRun.h" |
47 | #include "AliRunDigitizer.h" | |
48 | #include "AliRunLoader.h" | |
331a617a | 49 | |
866c3232 | 50 | #include <Riostream.h> |
51 | #include <TF1.h> | |
40e382ae | 52 | #include <TFile.h> |
866c3232 | 53 | #include <TMath.h> |
54 | #include <TRandom.h> | |
55 | #include <TString.h> | |
40e382ae | 56 | #include <TSystem.h> |
57 | ||
3d1463c8 | 58 | //----------------------------------------------------------------------------- |
9265505b | 59 | /// \class AliMUONDigitizerV3 |
4ce497c4 | 60 | /// The digitizer is performing the transformation to go from SDigits (digits |
61 | /// w/o any electronic noise) to Digits (w/ electronic noise, and decalibration) | |
62 | /// | |
63 | /// The decalibration is performed by doing the reverse operation of the | |
64 | /// calibration, that is we do (Signal+pedestal)/gain -> ADC | |
65 | /// | |
66 | /// Note also that the digitizer takes care of merging sdigits that belongs | |
67 | /// to the same pad, either because we're merging several input sdigit files | |
68 | /// or with a single file because the sdigitizer does not merge sdigits itself | |
69 | /// (for performance reason mainly, and because anyway we know we have to do it | |
70 | /// here, at the digitization level). | |
71 | /// | |
c4ee792d | 72 | /// \author Laurent Aphecetche |
3d1463c8 | 73 | //----------------------------------------------------------------------------- |
4ce497c4 | 74 | |
75 | namespace | |
76 | { | |
77 | AliMUON* muon() | |
78 | { | |
79 | return static_cast<AliMUON*>(gAlice->GetModule("MUON")); | |
80 | } | |
8c0b5e70 | 81 | |
82 | //ADDED for trigger noise | |
83 | const AliMUONGeometryTransformer* GetTransformer() | |
84 | { | |
85 | return muon()->GetGeometryTransformer(); | |
86 | } | |
4ce497c4 | 87 | } |
88 | ||
89 | const Double_t AliMUONDigitizerV3::fgkNSigmas=3; | |
90 | ||
9265505b | 91 | /// \cond CLASSIMP |
92aeef15 | 92 | ClassImp(AliMUONDigitizerV3) |
9265505b | 93 | /// \endcond |
92aeef15 | 94 | |
95 | //_____________________________________________________________________________ | |
96 | AliMUONDigitizerV3::AliMUONDigitizerV3(AliRunDigitizer* manager, | |
8c0b5e70 | 97 | Int_t generateNoisyDigits) |
92aeef15 | 98 | : AliDigitizer(manager), |
92aeef15 | 99 | fIsInitialized(kFALSE), |
92aeef15 | 100 | fCalibrationData(0x0), |
101 | fTriggerProcessor(0x0), | |
8c0b5e70 | 102 | fNoiseFunctionTrig(0x0), |
ec9acc85 | 103 | fGenerateNoisyDigits(generateNoisyDigits), |
104 | fLogger(new AliMUONLogger(1000)), | |
40e382ae | 105 | fTriggerStore(new AliMUONTriggerStoreV1), |
106 | fDigitStore(0x0), | |
9ec6a948 | 107 | fOutputDigitStore(0x0), |
108 | fInputDigitStore(0x0) | |
92aeef15 | 109 | { |
9265505b | 110 | /// Ctor. |
111 | ||
92aeef15 | 112 | AliDebug(1,Form("AliRunDigitizer=%p",fManager)); |
ec9acc85 | 113 | |
92aeef15 | 114 | } |
115 | ||
116 | //_____________________________________________________________________________ | |
117 | AliMUONDigitizerV3::~AliMUONDigitizerV3() | |
118 | { | |
9265505b | 119 | /// Dtor. Note we're the owner of some pointers. |
120 | ||
92aeef15 | 121 | AliDebug(1,"dtor"); |
4ce497c4 | 122 | |
92c23b09 | 123 | // delete fCalibrationData; |
92aeef15 | 124 | delete fTriggerProcessor; |
8c0b5e70 | 125 | delete fNoiseFunctionTrig; |
40e382ae | 126 | delete fTriggerStore; |
127 | delete fDigitStore; | |
128 | delete fOutputDigitStore; | |
9ec6a948 | 129 | delete fInputDigitStore; |
130 | ||
ad26d4f6 | 131 | AliInfo("Summary of messages"); |
132 | fLogger->Print(); | |
4ce497c4 | 133 | |
ad26d4f6 | 134 | delete fLogger; |
92aeef15 | 135 | } |
136 | ||
137 | //_____________________________________________________________________________ | |
138 | void | |
40e382ae | 139 | AliMUONDigitizerV3::ApplyResponseToTrackerDigit(AliMUONVDigit& digit, Bool_t addNoise) |
92aeef15 | 140 | { |
9265505b | 141 | /// For tracking digits, starting from an ideal digit's charge, we : |
142 | /// | |
cf27231a | 143 | /// - "divide" by a gain (thus decalibrating the digit) |
9265505b | 144 | /// - add a pedestal (thus decalibrating the digit) |
b74ca120 | 145 | /// - add some electronics noise (thus leading to a realistic adc), if requested to do so |
9265505b | 146 | /// - sets the signal to zero if below 3*sigma of the noise |
59b91539 | 147 | |
cf27231a | 148 | Float_t charge = digit.Charge(); |
149 | ||
150 | // We set the charge to 0, as the only relevant piece of information | |
151 | // after Digitization is the ADC value. | |
152 | digit.SetCharge(0); | |
b74ca120 | 153 | |
4ce497c4 | 154 | Int_t detElemId = digit.DetElemId(); |
92aeef15 | 155 | Int_t manuId = digit.ManuId(); |
92aeef15 | 156 | |
4ce497c4 | 157 | AliMUONVCalibParam* pedestal = fCalibrationData->Pedestals(detElemId,manuId); |
92aeef15 | 158 | if (!pedestal) |
ad26d4f6 | 159 | { |
160 | fLogger->Log(Form("%s:%d:Could not get pedestal for DE=%4d manuId=%4d. Disabling.", | |
161 | __FILE__,__LINE__, | |
162 | detElemId,manuId)); | |
ad26d4f6 | 163 | digit.SetADC(0); |
164 | return; | |
165 | } | |
59b91539 | 166 | |
4ce497c4 | 167 | AliMUONVCalibParam* gain = fCalibrationData->Gains(detElemId,manuId); |
92aeef15 | 168 | if (!gain) |
ad26d4f6 | 169 | { |
170 | fLogger->Log(Form("%s:%d:Could not get gain for DE=%4d manuId=%4d. Disabling.", | |
171 | __FILE__,__LINE__, | |
172 | detElemId,manuId)); | |
ad26d4f6 | 173 | digit.SetADC(0); |
174 | return; | |
175 | } | |
cf27231a | 176 | |
b74ca120 | 177 | Int_t manuChannel = digit.ManuChannel(); |
ad26d4f6 | 178 | |
ec9acc85 | 179 | Int_t adc = DecalibrateTrackerDigit(*pedestal,*gain,manuChannel,charge,addNoise, |
180 | digit.IsNoiseOnly()); | |
59b91539 | 181 | |
92aeef15 | 182 | digit.SetADC(adc); |
183 | } | |
184 | ||
185 | //_____________________________________________________________________________ | |
186 | void | |
40e382ae | 187 | AliMUONDigitizerV3::ApplyResponse(const AliMUONVDigitStore& store, |
188 | AliMUONVDigitStore& filteredStore) | |
92aeef15 | 189 | { |
9265505b | 190 | /// Loop over all chamber digits, and apply the response to them |
191 | /// Note that this method may remove digits. | |
192 | ||
40e382ae | 193 | filteredStore.Clear(); |
194 | ||
4ce497c4 | 195 | const Bool_t kAddNoise = kTRUE; |
196 | ||
40e382ae | 197 | TIter next(store.CreateIterator()); |
198 | AliMUONVDigit* digit; | |
199 | ||
200 | while ( ( digit = static_cast<AliMUONVDigit*>(next()) ) ) | |
4ce497c4 | 201 | { |
40e382ae | 202 | AliMp::StationType stationType = AliMpDEManager::GetStationType(digit->DetElemId()); |
203 | ||
204 | if ( stationType != AliMp::kStationTrigger ) | |
92aeef15 | 205 | { |
40e382ae | 206 | ApplyResponseToTrackerDigit(*digit,kAddNoise); |
92aeef15 | 207 | } |
7d7d22a6 | 208 | |
cf27231a | 209 | if ( digit->ADC() > 0 || digit->Charge() > 0 ) |
40e382ae | 210 | { |
211 | filteredStore.Add(*digit,AliMUONVDigitStore::kIgnore); | |
92aeef15 | 212 | } |
92aeef15 | 213 | } |
40e382ae | 214 | } |
92aeef15 | 215 | |
b74ca120 | 216 | //_____________________________________________________________________________ |
217 | Int_t | |
218 | AliMUONDigitizerV3::DecalibrateTrackerDigit(const AliMUONVCalibParam& pedestals, | |
219 | const AliMUONVCalibParam& gains, | |
220 | Int_t channel, | |
221 | Float_t charge, | |
ec9acc85 | 222 | Bool_t addNoise, |
223 | Bool_t noiseOnly) | |
b74ca120 | 224 | { |
225 | /// Decalibrate (i.e. go from charge to adc) a tracker digit, given its | |
226 | /// pedestal and gain parameters. | |
227 | /// Must insure before calling that channel is valid (i.e. between 0 and | |
228 | /// pedestals or gains->GetSize()-1, but also corresponding to a valid channel | |
229 | /// otherwise results are not predictible...) | |
230 | ||
231 | static const Int_t kMaxADC = (1<<12)-1; // We code the charge on a 12 bits ADC. | |
232 | ||
233 | Float_t pedestalMean = pedestals.ValueAsFloat(channel,0); | |
234 | Float_t pedestalSigma = pedestals.ValueAsFloat(channel,1); | |
235 | ||
ec9acc85 | 236 | AliDebugClass(1,Form("DE %04d MANU %04d CH %02d PEDMEAN %7.2f PEDSIGMA %7.2f", |
237 | pedestals.ID0(),pedestals.ID1(),channel,pedestalMean,pedestalSigma)); | |
238 | ||
b74ca120 | 239 | Float_t a0 = gains.ValueAsFloat(channel,0); |
240 | Float_t a1 = gains.ValueAsFloat(channel,1); | |
241 | Int_t thres = gains.ValueAsInt(channel,2); | |
242 | Int_t qual = gains.ValueAsInt(channel,3); | |
243 | if ( qual <= 0 ) return 0; | |
244 | ||
245 | Float_t chargeThres = a0*thres; | |
246 | ||
247 | Float_t padc(0); // (adc - ped) value | |
248 | ||
249 | if ( charge <= chargeThres || TMath::Abs(a1) < 1E-12 ) | |
250 | { | |
251 | // linear part only | |
252 | ||
253 | if ( TMath::Abs(a0) > 1E-12 ) | |
254 | { | |
255 | padc = charge/a0; | |
256 | } | |
257 | } | |
258 | else | |
259 | { | |
260 | // linear + parabolic part | |
261 | Double_t qt = chargeThres - charge; | |
262 | Double_t delta = a0*a0-4*a1*qt; | |
263 | if ( delta < 0 ) | |
264 | { | |
265 | AliErrorClass(Form("delta=%e DE %d Manu %d Channel %d " | |
266 | " charge %e a0 %e a1 %e thres %d ped %e pedsig %e", | |
267 | delta,pedestals.ID0(),pedestals.ID1(), | |
268 | channel, charge, a0, a1, thres, pedestalMean, | |
269 | pedestalSigma)); | |
270 | } | |
271 | else | |
272 | { | |
273 | delta = TMath::Sqrt(delta); | |
274 | ||
275 | padc = ( ( -a0 + delta ) > 0 ? ( -a0 + delta ) : ( -a0 - delta ) ); | |
276 | ||
277 | padc /= 2*a1; | |
278 | ||
279 | if ( padc < 0 ) | |
280 | { | |
281 | if ( TMath::Abs(padc) > 1E-3) | |
282 | { | |
283 | // this is more than a precision problem : let's signal it ! | |
284 | AliErrorClass(Form("padc=%e DE %d Manu %d Channel %d " | |
285 | " charge %e a0 %e a1 %e thres %d ped %e pedsig %e delta %e", | |
286 | padc,pedestals.ID0(),pedestals.ID1(), | |
287 | channel, charge, a0, a1, thres, pedestalMean, | |
288 | pedestalSigma,delta)); | |
289 | } | |
290 | ||
291 | // ok. consider we're just at thres, let it be zero. | |
292 | padc = 0; | |
293 | } | |
294 | ||
295 | padc += thres; | |
296 | ||
297 | } | |
298 | } | |
299 | ||
300 | Int_t adc(0); | |
301 | ||
ec9acc85 | 302 | Float_t adcNoise = 0.0; |
b74ca120 | 303 | |
ec9acc85 | 304 | if ( addNoise ) |
305 | { | |
306 | if ( noiseOnly ) | |
307 | { | |
308 | adcNoise = NoiseFunction()->GetRandom()*pedestalSigma; | |
309 | } | |
310 | else | |
311 | { | |
312 | adcNoise = gRandom->Gaus(0.0,pedestalSigma); | |
313 | } | |
314 | } | |
b74ca120 | 315 | |
ec9acc85 | 316 | adc = TMath::Nint(padc + pedestalMean + adcNoise + 0.5); |
317 | ||
318 | if ( adc < TMath::Nint(pedestalMean + fgkNSigmas*pedestalSigma + 0.5) ) | |
319 | { | |
320 | adc = 0; | |
b74ca120 | 321 | } |
322 | ||
323 | // be sure we stick to 12 bits. | |
324 | if ( adc > kMaxADC ) | |
325 | { | |
326 | adc = kMaxADC; | |
327 | } | |
328 | ||
329 | return adc; | |
330 | } | |
331 | ||
9ec6a948 | 332 | //_____________________________________________________________________________ |
333 | void | |
334 | AliMUONDigitizerV3::CreateInputDigitStore() | |
335 | { | |
336 | /// Create an input digit store, and check that all input files | |
337 | /// actually contains the same type of AliMUONVDigitStore | |
338 | ||
339 | fInputDigitStore = 0x0; | |
340 | ||
341 | for ( Int_t iFile = 0; iFile < fManager->GetNinputs(); ++iFile ) | |
342 | { | |
343 | AliLoader* inputLoader = GetLoader(fManager->GetInputFolderName(iFile)); | |
344 | ||
345 | inputLoader->LoadSDigits("READ"); | |
346 | ||
347 | TTree* iTreeS = inputLoader->TreeS(); | |
348 | if (!iTreeS) | |
349 | { | |
350 | AliFatal(Form("Could not get access to input file #%d",iFile)); | |
351 | } | |
352 | ||
353 | AliMUONVDigitStore* inputStore = AliMUONVDigitStore::Create(*iTreeS); | |
354 | ||
355 | if (!fInputDigitStore) | |
356 | { | |
357 | fInputDigitStore = inputStore; | |
358 | } | |
359 | else | |
360 | { | |
361 | if ( inputStore->IsA() != fInputDigitStore->IsA() ) | |
362 | { | |
363 | AliFatal("Got different types of AliMUONVDigitStore here. Please implement me."); | |
364 | } | |
365 | } | |
366 | } | |
367 | } | |
368 | ||
92aeef15 | 369 | //_____________________________________________________________________________ |
370 | void | |
371 | AliMUONDigitizerV3::Exec(Option_t*) | |
372 | { | |
9265505b | 373 | /// Main method. |
374 | /// We first loop over input files, and merge the sdigits we found there. | |
375 | /// Second, we digitize all the resulting sdigits | |
376 | /// Then we generate noise-only digits (for tracker only) | |
377 | /// And we finally generate the trigger outputs. | |
4ce497c4 | 378 | |
b74ca120 | 379 | AliCodeTimerAuto("") |
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 | ||
395 | Int_t nInputFiles = fManager->GetNinputs(); | |
396 | ||
40e382ae | 397 | AliLoader* outputLoader = GetLoader(fManager->GetOutputFolderName()); |
398 | ||
399 | outputLoader->MakeDigitsContainer(); | |
400 | ||
401 | TTree* oTreeD = outputLoader->TreeD(); | |
402 | ||
403 | if (!oTreeD) | |
92aeef15 | 404 | { |
40e382ae | 405 | AliFatal("Cannot create output TreeD"); |
92aeef15 | 406 | } |
40e382ae | 407 | |
92aeef15 | 408 | // Loop over all the input files, and merge the sdigits found in those |
409 | // files. | |
40e382ae | 410 | |
92aeef15 | 411 | for ( Int_t iFile = 0; iFile < nInputFiles; ++iFile ) |
412 | { | |
40e382ae | 413 | AliLoader* inputLoader = GetLoader(fManager->GetInputFolderName(iFile)); |
414 | ||
415 | inputLoader->LoadSDigits("READ"); | |
416 | ||
417 | TTree* iTreeS = inputLoader->TreeS(); | |
418 | if (!iTreeS) | |
92aeef15 | 419 | { |
420 | AliFatal(Form("Could not get access to input file #%d",iFile)); | |
421 | } | |
9ec6a948 | 422 | |
423 | if (!fInputDigitStore) | |
424 | { | |
425 | CreateInputDigitStore(); | |
426 | } | |
427 | fInputDigitStore->Connect(*iTreeS); | |
40e382ae | 428 | |
429 | iTreeS->GetEvent(0); | |
430 | ||
9ec6a948 | 431 | MergeWithSDigits(fDigitStore,*fInputDigitStore,fManager->GetMask(iFile)); |
05314992 | 432 | |
40e382ae | 433 | inputLoader->UnloadSDigits(); |
05314992 | 434 | |
9ec6a948 | 435 | fInputDigitStore->Clear(); |
92aeef15 | 436 | } |
437 | ||
438 | // At this point, we do have digit arrays (one per chamber) which contains | |
439 | // the merging of all the sdigits of the input file(s). | |
440 | // We now massage them to apply the detector response, i.e. this | |
441 | // is here that we do the "digitization" work. | |
442 | ||
40e382ae | 443 | if (!fOutputDigitStore) |
444 | { | |
445 | fOutputDigitStore = fDigitStore->Create(); | |
446 | } | |
447 | ||
8c0b5e70 | 448 | if ( fGenerateNoisyDigits>=2 ) |
449 | { | |
450 | // Generate noise-only digits for trigger. | |
451 | GenerateNoisyDigitsForTrigger(*fDigitStore); | |
452 | } | |
453 | ||
40e382ae | 454 | ApplyResponse(*fDigitStore,*fOutputDigitStore); |
4ce497c4 | 455 | |
456 | if ( fGenerateNoisyDigits ) | |
457 | { | |
458 | // Generate noise-only digits for tracker. | |
40e382ae | 459 | GenerateNoisyDigits(*fOutputDigitStore); |
4ce497c4 | 460 | } |
461 | ||
92aeef15 | 462 | // We generate the global and local trigger decisions. |
40e382ae | 463 | fTriggerProcessor->Digits2Trigger(*fOutputDigitStore,*fTriggerStore); |
464 | ||
465 | // Prepare output tree | |
466 | Bool_t okD = fOutputDigitStore->Connect(*oTreeD,kFALSE); | |
467 | Bool_t okT = fTriggerStore->Connect(*oTreeD,kFALSE); | |
468 | if (!okD || !okT) | |
469 | { | |
470 | AliError(Form("Could not make branch : Digit %d Trigger %d",okD,okT)); | |
471 | return; | |
472 | } | |
92aeef15 | 473 | |
474 | // Fill the output treeD | |
40e382ae | 475 | oTreeD->Fill(); |
92aeef15 | 476 | |
477 | // Write to the output tree(D). | |
478 | // Please note that as GlobalTrigger, LocalTrigger and Digits are in the same | |
479 | // tree (=TreeD) in different branches, this WriteDigits in fact writes all of | |
480 | // the 3 branches. | |
40e382ae | 481 | outputLoader->WriteDigits("OVERWRITE"); |
92aeef15 | 482 | |
40e382ae | 483 | outputLoader->UnloadDigits(); |
4ce497c4 | 484 | |
40e382ae | 485 | // Finally, we clean up after ourselves. |
486 | fTriggerStore->Clear(); | |
487 | fDigitStore->Clear(); | |
488 | fOutputDigitStore->Clear(); | |
92aeef15 | 489 | } |
490 | ||
4ce497c4 | 491 | |
4ce497c4 | 492 | //_____________________________________________________________________________ |
493 | void | |
40e382ae | 494 | AliMUONDigitizerV3::GenerateNoisyDigits(AliMUONVDigitStore& digitStore) |
4ce497c4 | 495 | { |
9265505b | 496 | /// According to a given probability, generate digits that |
497 | /// have a signal above the noise cut (ped+n*sigma_ped), i.e. digits | |
498 | /// that are "only noise". | |
4ce497c4 | 499 | |
b74ca120 | 500 | AliCodeTimerAuto("") |
501 | ||
4ce497c4 | 502 | for ( Int_t i = 0; i < AliMUONConstants::NTrackingCh(); ++i ) |
503 | { | |
504 | AliMpDEIterator it; | |
505 | ||
506 | it.First(i); | |
507 | ||
508 | while ( !it.IsDone() ) | |
509 | { | |
510 | for ( Int_t cathode = 0; cathode < 2; ++cathode ) | |
511 | { | |
40e382ae | 512 | GenerateNoisyDigitsForOneCathode(digitStore,it.CurrentDEId(),cathode); |
4ce497c4 | 513 | } |
514 | it.Next(); | |
515 | } | |
516 | } | |
4ce497c4 | 517 | } |
518 | ||
519 | //_____________________________________________________________________________ | |
520 | void | |
40e382ae | 521 | AliMUONDigitizerV3::GenerateNoisyDigitsForOneCathode(AliMUONVDigitStore& digitStore, |
522 | Int_t detElemId, Int_t cathode) | |
4ce497c4 | 523 | { |
9265505b | 524 | /// Generate noise-only digits for one cathode of one detection element. |
525 | /// Called by GenerateNoisyDigits() | |
4ce497c4 | 526 | |
9265505b | 527 | const AliMpVSegmentation* seg |
866c3232 | 528 | = AliMpSegmentation::Instance()->GetMpSegmentation(detElemId,AliMp::GetCathodType(cathode)); |
4ce497c4 | 529 | Int_t nofPads = seg->NofPads(); |
530 | ||
531 | Int_t maxIx = seg->MaxPadIndexX(); | |
532 | Int_t maxIy = seg->MaxPadIndexY(); | |
533 | ||
cdea095e | 534 | static const Double_t kProbToBeOutsideNsigmas = TMath::Erfc(fgkNSigmas/TMath::Sqrt(2.0)) / 2. ; |
4ce497c4 | 535 | |
84aac932 | 536 | Int_t nofNoisyPads = TMath::Nint(kProbToBeOutsideNsigmas*nofPads); |
4ce497c4 | 537 | if ( !nofNoisyPads ) return; |
538 | ||
539 | nofNoisyPads = | |
540 | TMath::Nint(gRandom->Gaus(nofNoisyPads, | |
541 | nofNoisyPads/TMath::Sqrt(nofNoisyPads))); | |
542 | ||
543 | AliDebug(3,Form("DE %d cath %d nofNoisyPads %d",detElemId,cathode,nofNoisyPads)); | |
544 | ||
40e382ae | 545 | for ( Int_t i = 0; i < nofNoisyPads; ++i ) |
4ce497c4 | 546 | { |
547 | Int_t ix(-1); | |
548 | Int_t iy(-1); | |
40e382ae | 549 | AliMpPad pad; |
550 | ||
4ce497c4 | 551 | do { |
552 | ix = gRandom->Integer(maxIx+1); | |
553 | iy = gRandom->Integer(maxIy+1); | |
40e382ae | 554 | pad = seg->PadByIndices(AliMpIntPair(ix,iy),kFALSE); |
555 | } while ( !pad.IsValid() ); | |
556 | ||
4ce497c4 | 557 | Int_t manuId = pad.GetLocation().GetFirst(); |
40e382ae | 558 | Int_t manuChannel = pad.GetLocation().GetSecond(); |
559 | ||
4ce497c4 | 560 | AliMUONVCalibParam* pedestals = fCalibrationData->Pedestals(detElemId,manuId); |
561 | ||
ad26d4f6 | 562 | if (!pedestals) |
563 | { | |
564 | // no pedestal available for this channel, simply give up | |
40e382ae | 565 | continue; |
ad26d4f6 | 566 | } |
567 | ||
40e382ae | 568 | AliMUONVDigit* d = digitStore.CreateDigit(detElemId,manuId,manuChannel,cathode); |
569 | ||
570 | d->SetPadXY(ix,iy); | |
571 | ||
ec9acc85 | 572 | d->SetCharge(0.0); // charge is zero, the ApplyResponseToTrackerDigit will add the noise |
40e382ae | 573 | d->NoiseOnly(kTRUE); |
ec9acc85 | 574 | ApplyResponseToTrackerDigit(*d,kTRUE); |
cf27231a | 575 | if ( d->ADC() > 0 ) |
4ce497c4 | 576 | { |
40e382ae | 577 | Bool_t ok = digitStore.Add(*d,AliMUONVDigitStore::kDeny); |
578 | // this can happen (that we randomly chose a digit that is | |
579 | // already there). We simply ignore this, but log the occurence | |
580 | // to cross-check that it's not too frequent. | |
581 | if (!ok) | |
582 | { | |
583 | fLogger->Log("Collision while adding noiseOnly digit"); | |
584 | } | |
585 | else | |
586 | { | |
587 | fLogger->Log("Added noiseOnly digit"); | |
588 | } | |
4ce497c4 | 589 | } |
590 | else | |
591 | { | |
592 | AliError("Pure noise below threshold. This should not happen. Not adding " | |
593 | "this digit."); | |
594 | } | |
40e382ae | 595 | delete d; |
4ce497c4 | 596 | } |
597 | } | |
598 | ||
8c0b5e70 | 599 | |
600 | //_____________________________________________________________________________ | |
601 | void | |
602 | AliMUONDigitizerV3::GenerateNoisyDigitsForTrigger(AliMUONVDigitStore& digitStore) | |
603 | { | |
604 | /// Generate noise-only digits for one cathode of one detection element. | |
605 | /// Called by GenerateNoisyDigits() | |
606 | ||
607 | if ( !fNoiseFunctionTrig ) | |
608 | { | |
609 | fNoiseFunctionTrig = new TF1("AliMUONDigitizerV3::fNoiseFunctionTrig","landau", | |
610 | 50.,270.); | |
611 | ||
612 | fNoiseFunctionTrig->SetParameters(3.91070e+02, 9.85026, 9.35881e-02); | |
613 | } | |
614 | ||
615 | AliMpPad pad[2]; | |
616 | AliMUONVDigit *d[2]={0x0}; | |
617 | ||
618 | for ( Int_t chamberId = AliMUONConstants::NTrackingCh(); chamberId < AliMUONConstants::NCh(); ++chamberId ) | |
619 | { | |
620 | ||
621 | Int_t nofNoisyPads = 50; | |
622 | ||
623 | Float_t r=-1, fi = 0., gx, gy, x, y, z, xg01, yg01, zg, xg02, yg02; | |
624 | AliMpDEIterator it; | |
625 | ||
626 | AliDebug(3,Form("Chamber %d nofNoisyPads %d",chamberId,nofNoisyPads)); | |
627 | ||
628 | for ( Int_t i = 0; i < nofNoisyPads; ++i ) | |
629 | { | |
630 | //printf("Generating noise %i\n",i); | |
631 | Int_t ix(-1); | |
632 | Int_t iy(-1); | |
633 | Bool_t isOk = kFALSE; | |
634 | Int_t detElemId = -1; | |
635 | do { | |
636 | //r = gRandom->Landau(9.85026, 9.35881e-02); | |
637 | r = fNoiseFunctionTrig->GetRandom(); | |
638 | fi = 2. * TMath::Pi() * gRandom->Rndm(); | |
639 | //printf("r = %f\tfi = %f\n", r, fi); | |
640 | gx = r * TMath::Cos(fi); | |
641 | gy = r * TMath::Sin(fi); | |
642 | ||
643 | for ( it.First(chamberId); ! it.IsDone(); it.Next() ){ | |
644 | Int_t currDetElemId = it.CurrentDEId(); | |
645 | const AliMpVSegmentation* seg | |
646 | = AliMpSegmentation::Instance()->GetMpSegmentation(currDetElemId,AliMp::GetCathodType(0)); | |
647 | if (!seg) continue; | |
648 | Float_t deltax = seg->Dimensions().X(); | |
649 | Float_t deltay = seg->Dimensions().Y(); | |
650 | GetTransformer()->Local2Global(currDetElemId, -deltax, -deltay, 0, xg01, yg01, zg); | |
651 | GetTransformer()->Local2Global(currDetElemId, deltax, deltay, 0, xg02, yg02, zg); | |
652 | Float_t xg1 = xg01, xg2 = xg02, yg1 = yg01, yg2 = yg02; | |
653 | if(xg01>xg02){ | |
654 | xg1 = xg02; | |
655 | xg2 = xg01; | |
656 | } | |
657 | if(yg01>yg02){ | |
658 | yg1 = yg02; | |
659 | yg2 = yg01; | |
660 | } | |
661 | if(gx>=xg1 && gx<=xg2 && gy>=yg1 && gy<=yg2){ | |
662 | detElemId = currDetElemId; | |
663 | GetTransformer()->Global2Local(detElemId, gx, gy, 0, x, y, z); | |
664 | pad[0] = seg->PadByPosition(TVector2(x,y),kFALSE); | |
665 | if(!pad[0].IsValid()) continue; | |
666 | isOk = kTRUE; | |
667 | break; | |
668 | } | |
669 | } // loop on slats | |
670 | } while ( !isOk ); | |
671 | ||
672 | const AliMpVSegmentation* seg1 | |
673 | = AliMpSegmentation::Instance()->GetMpSegmentation(detElemId,AliMp::GetCathodType(1)); | |
674 | pad[1] = seg1->PadByPosition(TVector2(x,y),kFALSE); | |
675 | ||
676 | for ( Int_t cathode = 0; cathode < 2; ++cathode ){ | |
677 | Int_t manuId = pad[cathode].GetLocation(0).GetFirst(); | |
678 | Int_t manuChannel = pad[cathode].GetLocation(0).GetSecond(); | |
679 | d[cathode] = digitStore.CreateDigit(detElemId,manuId,manuChannel,cathode); | |
680 | ix = pad[cathode].GetIndices().GetFirst(); | |
681 | iy = pad[cathode].GetIndices().GetSecond(); | |
682 | d[cathode]->SetPadXY(ix,iy); | |
683 | //d[cathode].SetSignal(1); | |
684 | //d[cathode].SetPhysicsSignal(0); | |
685 | d[cathode]->SetCharge(1); | |
686 | d[cathode]->NoiseOnly(kTRUE); | |
687 | AliDebug(3,Form("Adding a pure noise digit :")); | |
688 | ||
689 | Bool_t ok = digitStore.Add(*d[cathode],AliMUONVDigitStore::kDeny); | |
690 | if (!ok) | |
691 | { | |
692 | fLogger->Log("Collision while adding TriggerNoise digit"); | |
693 | } | |
694 | else | |
695 | { | |
696 | fLogger->Log("Added triggerNoise digit"); | |
697 | } | |
698 | } //loop on cathodes | |
699 | } // loop on noisy pads | |
700 | } // loop on chambers | |
701 | } | |
702 | ||
703 | ||
92aeef15 | 704 | //_____________________________________________________________________________ |
40e382ae | 705 | AliLoader* |
706 | AliMUONDigitizerV3::GetLoader(const TString& folderName) | |
92aeef15 | 707 | { |
40e382ae | 708 | /// Get a MUON loader |
9265505b | 709 | |
ad26d4f6 | 710 | AliDebug(2,Form("Getting access to folder %s",folderName.Data())); |
40e382ae | 711 | AliLoader* loader = AliRunLoader::GetDetectorLoader("MUON",folderName.Data()); |
92aeef15 | 712 | if (!loader) |
713 | { | |
714 | AliError(Form("Could not get MuonLoader from folder %s",folderName.Data())); | |
715 | return 0x0; | |
716 | } | |
40e382ae | 717 | return loader; |
92aeef15 | 718 | } |
719 | ||
720 | //_____________________________________________________________________________ | |
721 | Bool_t | |
722 | AliMUONDigitizerV3::Init() | |
723 | { | |
9265505b | 724 | /// Initialization of the TTask : |
40e382ae | 725 | /// a) create the calibrationData, according to run number |
726 | /// b) create the trigger processing task | |
9265505b | 727 | |
ad26d4f6 | 728 | AliDebug(2,""); |
92aeef15 | 729 | |
730 | if ( fIsInitialized ) | |
731 | { | |
732 | AliError("Object already initialized."); | |
733 | return kFALSE; | |
734 | } | |
735 | ||
736 | if (!fManager) | |
737 | { | |
738 | AliError("fManager is null !"); | |
739 | return kFALSE; | |
740 | } | |
741 | ||
331a617a | 742 | // Load mapping |
743 | if ( ! AliMpCDB::LoadDDLStore() ) { | |
88544f7e | 744 | AliFatal("Could not access mapping from OCDB !"); |
745 | } | |
746 | ||
92c23b09 | 747 | if (!fCalibrationData) |
748 | AliFatal("Calibration data object not defined"); | |
749 | ||
ad26d4f6 | 750 | if ( !fCalibrationData->Pedestals() ) |
751 | { | |
752 | AliFatal("Could not access pedestals from OCDB !"); | |
753 | } | |
754 | if ( !fCalibrationData->Gains() ) | |
755 | { | |
756 | AliFatal("Could not access gains from OCDB !"); | |
757 | } | |
92c23b09 | 758 | |
759 | ||
760 | AliInfo("Using trigger configuration from CDB"); | |
761 | ||
40e382ae | 762 | fTriggerProcessor = new AliMUONTriggerElectronics(fCalibrationData); |
4ce497c4 | 763 | |
ad26d4f6 | 764 | AliDebug(1, Form("Will %s generate noise-only digits for tracker", |
765 | (fGenerateNoisyDigits ? "":"NOT"))); | |
766 | ||
92aeef15 | 767 | fIsInitialized = kTRUE; |
768 | return kTRUE; | |
769 | } | |
770 | ||
92aeef15 | 771 | //_____________________________________________________________________________ |
772 | void | |
40e382ae | 773 | AliMUONDigitizerV3::MergeWithSDigits(AliMUONVDigitStore*& outputStore, |
774 | const AliMUONVDigitStore& input, | |
775 | Int_t mask) | |
92aeef15 | 776 | { |
9265505b | 777 | /// Merge the sdigits in inputData with the digits already present in outputData |
92aeef15 | 778 | |
40e382ae | 779 | if ( !outputStore ) outputStore = input.Create(); |
780 | ||
781 | TIter next(input.CreateIterator()); | |
782 | AliMUONVDigit* sdigit; | |
783 | ||
784 | while ( ( sdigit = static_cast<AliMUONVDigit*>(next()) ) ) | |
785 | { | |
786 | // Update the track references using the mask. | |
787 | // FIXME: this is dirty, for backward compatibility only. | |
788 | // Should re-design all this way of keeping track of MC information... | |
789 | if ( mask ) sdigit->PatchTracks(mask); | |
790 | // Then add or update the digit to the output. | |
791 | AliMUONVDigit* added = outputStore->Add(*sdigit,AliMUONVDigitStore::kMerge); | |
792 | if (!added) | |
92aeef15 | 793 | { |
40e382ae | 794 | AliError("Could not add digit in merge mode"); |
92aeef15 | 795 | } |
92aeef15 | 796 | } |
797 | } | |
ec9acc85 | 798 | |
799 | //_____________________________________________________________________________ | |
800 | TF1* | |
801 | AliMUONDigitizerV3::NoiseFunction() | |
802 | { | |
803 | /// Return noise function | |
804 | static TF1* f = 0x0; | |
805 | if (!f) | |
806 | { | |
807 | f = new TF1("AliMUONDigitizerV3::NoiseFunction","gaus",fgkNSigmas,fgkNSigmas*10); | |
808 | f->SetParameters(1,0,1); | |
809 | } | |
810 | return f; | |
811 | } | |
812 |