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