source: trunk/Mars/msimcamera/MSimCamera.cc@ 17559

Last change on this file since 17559 was 17384, checked in by tbretz, 11 years ago
Cleanup of the includes; my suspicion is that the math.h is for the sqrt (which is not needed, and should be in trinagular brackets as in all other files). To get a common namespace, I replaced it by TMath::Sqrt.
File size: 12.7 KB
Line 
1/* ======================================================================== *\
2!
3! *
4! * This file is part of CheObs, the Modular Analysis and Reconstruction
5! * Software. It is distributed to you in the hope that it can be a useful
6! * and timesaving tool in analysing Data of imaging Cerenkov telescopes.
7! * It is distributed WITHOUT ANY WARRANTY.
8! *
9! * Permission to use, copy, modify and distribute this software and its
10! * documentation for any purpose is hereby granted without fee,
11! * provided that the above copyright notice appears in all copies and
12! * that both that copyright notice and this permission notice appear
13! * in supporting documentation. It is provided "as is" without express
14! * or implied warranty.
15! *
16!
17!
18! Author(s): Thomas Bretz, 1/2009 <mailto:tbretz@phys.ethz.ch>
19!
20! Copyright: CheObs Software Development, 2000-2013
21!
22!
23\* ======================================================================== */
24
25//////////////////////////////////////////////////////////////////////////////
26//
27// MSimCamera
28//
29// This task initializes the analog channels with analog noise and simulated
30// the analog pulses from the photon signal.
31//
32// Input Containers:
33// MPhotonEvent
34// MPhotonStatistics
35// MRawRunHeader
36//
37// Output Containers:
38// MAnalogChannels
39//
40//////////////////////////////////////////////////////////////////////////////
41#include "MSimCamera.h"
42
43#include <TF1.h>
44#include <TRandom.h> // Needed for TRandom
45
46#include "MLog.h"
47#include "MLogManip.h"
48
49#include "MSpline3.h"
50#include "MParSpline.h"
51
52#include "MParList.h"
53
54#include "MPhotonEvent.h"
55#include "MPhotonData.h"
56
57#include "MPedestalCam.h"
58#include "MPedestalPix.h"
59
60#include "MAnalogSignal.h"
61#include "MAnalogChannels.h"
62
63#include "MMcEvt.hxx" // To be replaced by a CheObs class
64#include "MRawRunHeader.h"
65
66ClassImp(MSimCamera);
67
68using namespace std;
69
70// --------------------------------------------------------------------------
71//
72// Default Constructor.
73//
74MSimCamera::MSimCamera(const char* name, const char *title)
75 : fEvt(0), fStat(0), fRunHeader(0), fElectronicNoise(0), fGain(0),
76 fCamera(0), fMcEvt(0), fSpline(0), fBaselineGain(kFALSE),
77 fDefaultOffset(-1), fDefaultNoise(-1), fDefaultGain(-1), fACFudgeFactor(0),
78 fACTimeConstant(0)
79
80{
81 fName = name ? name : "MSimCamera";
82 fTitle = title ? title : "Task to simulate the electronic noise and to convert photons into pulses";
83}
84
85// --------------------------------------------------------------------------
86//
87// Search for the necessayr parameter containers.
88// Setup spline for pulse shape.
89//
90Int_t MSimCamera::PreProcess(MParList *pList)
91{
92 fMcEvt = (MMcEvt*)pList->FindCreateObj("MMcEvt");
93 if (!fMcEvt)
94 return kFALSE;
95
96 fCamera = (MAnalogChannels*)pList->FindCreateObj("MAnalogChannels");
97 if (!fCamera)
98 return kFALSE;
99
100 fEvt = (MPhotonEvent*)pList->FindObject("MPhotonEvent");
101 if (!fEvt)
102 {
103 *fLog << err << "MPhotonEvent not found... aborting." << endl;
104 return kFALSE;
105 }
106
107 fStat = (MPhotonStatistics*)pList->FindObject("MPhotonStatistics");
108 if (!fStat)
109 {
110 *fLog << err << "MPhotonStatistics not found... aborting." << endl;
111 return kFALSE;
112 }
113
114 fRunHeader = (MRawRunHeader *)pList->FindObject("MRawRunHeader");
115 if (!fRunHeader)
116 {
117 *fLog << err << "MRawRunHeader not found... aborting." << endl;
118 return kFALSE;
119 }
120/*
121 fPulsePos = (MParameterD*)pList->FindObject("IntendedPulsePos", "MParameterD");
122 if (!fPulsePos)
123 {
124 *fLog << err << "IntendedPulsePos [MParameterD] not found... aborting." << endl;
125 return kFALSE;
126 }
127 */
128
129 // Create it here to make sure that MGeomApply will set the correct size
130 fElectronicNoise = (MPedestalCam*)pList->FindCreateObj("MPedestalCam", "ElectronicNoise");
131 if (!fElectronicNoise)
132 return kFALSE;
133
134 fGain = (MPedestalCam*)pList->FindCreateObj("MPedestalCam", "Gain");
135 if (!fGain)
136 return kFALSE;
137
138 fAccidentalPhotons = (MPedestalCam*)pList->FindObject("AccidentalPhotonRates","MPedestalCam");
139 if(!fAccidentalPhotons)
140 {
141 *fLog << err << "AccidentalPhotonRates [MPedestalCam] not found... aborting." << endl;
142 return kFALSE;
143 }
144
145 MParSpline *pulse = (MParSpline*)pList->FindObject("PulseShape", "MParSpline");
146 if (!pulse)
147 {
148 *fLog << err << "PulseShape [MParSpline] not found... aborting." << endl;
149 return kFALSE;
150 }
151
152// if (fRunHeader->GetFreqSampling()!=1000)
153// {
154// *fLog << err << "ERROR - Sampling frequencies others than 1GHz are not yet supported." << endl;
155// *fLog << warn << "FIXME - SCALE MPulsShape WITH THE SAMPLING FREQUENCY." << endl;
156// return kFALSE;
157// }
158
159 fSpline = pulse->GetSpline();
160 if (!fSpline)
161 {
162 *fLog << err << "No spline initialized." << endl;
163 return kFALSE;
164 }
165
166 // ---------------- Information output ----------------------
167
168 if (fBaselineGain)
169 *fLog << inf << "Gain is also applied to the electronic noise." << endl;
170
171 return kTRUE;
172}
173
174// --------------------------------------------------------------------------
175//
176// FIXME: For now this is a workaround to set a baseline and the
177// electronic (guassian noise)
178//
179Bool_t MSimCamera::ReInit(MParList *plist)
180{
181 for (int i=0; i<fElectronicNoise->GetSize(); i++)
182 {
183 MPedestalPix &ped = (*fElectronicNoise)[i];
184 ped.SetPedestal(fDefaultOffset);
185 if (fDefaultNoise>0)
186 ped.SetPedestalRms(fDefaultNoise);
187
188 ped.SetPedestalABoffset(0);
189 ped.SetNumEvents(0);
190
191
192 MPedestalPix &gain = (*fGain)[i];
193 if (fDefaultGain>0)
194 gain.SetPedestal(fDefaultGain);
195
196 gain.SetPedestalRms(0);
197 gain.SetPedestalABoffset(0);
198 gain.SetNumEvents(0);
199 }
200
201 return kTRUE;
202}
203
204// --------------------------------------------------------------------------
205//
206// fStat->GetMaxIndex must return the maximum index possible
207// (equiv. number of pixels) not just the maximum index stored!
208//
209Int_t MSimCamera::Process()
210{
211 // Calculate start time, end time and corresponding number of samples
212 const Double_t freq = fRunHeader->GetFreqSampling()/1000.;
213
214 // FIXME: Should we use a higher sampling here?
215
216 const Double_t start = fStat->GetTimeFirst()*freq;
217 const Double_t end = fStat->GetTimeLast() *freq;
218
219 const UInt_t nlen = TMath::CeilNint(end-start);
220
221 // Get number of pixels/channels
222 const UInt_t npix = fStat->GetMaxIndex()+1;
223
224 if (npix>(UInt_t)fElectronicNoise->GetSize())
225 {
226 *fLog << err << "ERROR - More indices (" << npix << ") ";
227 *fLog << "assigned than existing in camera (";
228 *fLog << fElectronicNoise->GetSize() << ")!" << endl;
229 return kERROR;
230 }
231
232 const Double_t pl = fSpline->GetXmin()*freq;
233 const Double_t pr = fSpline->GetXmax()*freq;
234
235 // Init the arrays and set the range which will contain valid data
236 fCamera->Init(npix, nlen);
237 fCamera->SetValidRange(TMath::FloorNint(pr), TMath::CeilNint(nlen+pl));
238
239 // Add electronic noise to empty channels
240 for (UInt_t i=0; i<npix; i++)
241 {
242 const MPedestalPix &pix = (*fElectronicNoise)[i];
243
244 const Double_t val = pix.GetPedestal();
245 const Double_t rms = pix.GetPedestalRms();
246
247 // FTemme: Implementation of AC-coupling:
248 // to calculate the value of the accoupling per slice I use the
249 // following equation:
250 // accouplingPerSlice = accidentalPhotonRate * (1 + crossTalkProb)
251 // * areaOfOnePulse / samplingRate;
252 // Therefore I need the following variables
253 // Double_t accidentalPhotonRate; // [MHz]
254 // Float_t crossTalkProb; // [1]
255 // Double_t areaOfOnePulse; // [ADC-Counts * s]
256 // Double_t samplingRate; // [slices * MHz]
257
258 // The accidental photon rate is stored in GHz, so we have to multiply
259 // with 1E3 to get MHz:
260 const MPedestalPix &accPhoPix = (*fAccidentalPhotons)[i];
261
262 const Double_t accidentalPhotonRate = accPhoPix.GetPedestal() * 1e3; //[MHz]
263
264 Double_t currentAccidentalPhotonRate = accidentalPhotonRate;
265 if (fACTimeConstant!=0)
266 {
267 const Double_t accidentalPhotons = fACTimeConstant * accidentalPhotonRate;
268 const Double_t sigmaAccidentalPhotons = TMath::Sqrt(accidentalPhotons);
269
270 const Double_t gaus = gRandom->Gaus(accidentalPhotons,sigmaAccidentalPhotons);
271
272 currentAccidentalPhotonRate = gaus / fACTimeConstant;
273 }
274
275 // FIXME: I don't know how to get the variable fCrosstalkProb from
276 // the class APD (see MAvalanchePhotoDiode.h), because there is no
277 // getter for the APD array(fAPDs) in MSimAPD.
278 // So I set the crossTalkProb hardcoded to the value 0.15, which is
279 // equal to the value of the apd of type 4
280 const Double_t crossTalkProb = 0.15;
281
282 // To get the area of one Pulse, I only need to calculate the Integral
283 // of the Pulse Shape, which is stored in fSpline. Because the spline is
284 // normalized to a maximal amplitude of 1.0, I had to multiply it with
285 // the Default gain [ADC-Counts * s]
286 const Double_t areaOfOnePulse = fSpline->Integral() * fDefaultGain;
287
288 // The sampling rate I get from the RunHeader:
289 const Double_t samplingRate = fRunHeader->GetFreqSampling(); // [slices * MHz]
290
291 const Double_t accouplingPerSlice = currentAccidentalPhotonRate
292 * (1 + crossTalkProb + fACFudgeFactor)
293 * areaOfOnePulse / samplingRate;
294
295 // The accoupling is substracted from the timeline by decreasing the
296 // mean of the gaussian noise which is added
297
298 if (!fBaselineGain)
299 {
300 (*fCamera)[i].AddGaussianNoise(rms, val - accouplingPerSlice);
301 continue;
302 }
303 // Sorry, the name "pedestal" is misleading here
304 // FIXME: Simulate gain fluctuations
305 const Double_t gain = (*fGain)[i].GetPedestal();
306
307 // FIXME: We might add the base line here already.
308 // FIXME: How stable is the offset?
309 // FIXME: Should we write a container AppliedGain for MSImTrigger?
310
311 (*fCamera)[i].AddGaussianNoise(rms*gain, (val - accouplingPerSlice)*gain);
312 }
313
314 // FIXME: Simulate correlations with neighboring pixels
315
316 const Int_t num = fEvt->GetNumPhotons();
317
318 // A random shift, uniformely distributed within one slice, to make sure that
319 // the first photon is not always aligned identically with a sample edge.
320 // FIXME: Make it switchable
321 const Float_t rndm = gRandom->Uniform();
322
323 // FIXME: Shell we add a random shift of [0,1] samples per channel?
324 // Or maybe per channel and run?
325
326 Double_t tot = 0;
327
328 // Simulate pulses
329 for (Int_t i=0; i<num; i++)
330 {
331 const MPhotonData &ph = (*fEvt)[i];
332
333 const UInt_t idx = ph.GetTag();
334 const Double_t t = (ph.GetTime()-fStat->GetTimeFirst())*freq+rndm;// - fSpline->GetXmin();
335
336 // FIXME: Time jitter?
337 // FIXME: Add additional routing here?
338 // FIMXE: How stable is the gain?
339
340 if (ph.GetPrimary()!=MMcEvt::kNightSky && ph.GetPrimary()!=MMcEvt::kArtificial)
341 tot += ph.GetWeight();
342
343 // Sorry, the name "pedestal" is misleading here
344 // FIXME: Simulate gain fluctuations
345 const Double_t gain = (*fGain)[idx].GetPedestal();
346
347 // === FIXME === FIXME === FIXME === Frequency!!!!
348 (*fCamera)[idx].AddPulse(*fSpline, t, ph.GetWeight()*gain);
349 }
350
351 fMcEvt->SetPhotElfromShower(TMath::Nint(tot));
352
353 return kTRUE;
354}
355
356// --------------------------------------------------------------------------
357//
358// BaselineGain: Off
359//
360Int_t MSimCamera::ReadEnv(const TEnv &env, TString prefix, Bool_t print)
361{
362 Bool_t rc = kFALSE;
363 if (IsEnvDefined(env, prefix, "BaselineGain", print))
364 {
365 rc = kTRUE;
366 fBaselineGain = GetEnvValue(env, prefix, "BaselineGain", fBaselineGain);
367 }
368
369 if (IsEnvDefined(env, prefix, "DefaultOffset", print))
370 {
371 rc = kTRUE;
372 fDefaultOffset = GetEnvValue(env, prefix, "DefaultOffset", fDefaultOffset);
373 }
374 if (IsEnvDefined(env, prefix, "DefaultNoise", print))
375 {
376 rc = kTRUE;
377 fDefaultNoise = GetEnvValue(env, prefix, "DefaultNoise", fDefaultNoise);
378 }
379 if (IsEnvDefined(env, prefix, "DefaultGain", print))
380 {
381 rc = kTRUE;
382 fDefaultGain = GetEnvValue(env, prefix, "DefaultGain", fDefaultGain);
383 }
384 if (IsEnvDefined(env, prefix, "fACFudgeFactor", print))
385 {
386 rc = kTRUE;
387 fACFudgeFactor = GetEnvValue(env, prefix, "fACFudgeFactor", fACFudgeFactor);
388 }
389 if (IsEnvDefined(env, prefix, "fACTimeConstant", print))
390 {
391 rc = kTRUE;
392 fACTimeConstant = GetEnvValue(env, prefix, "fACTimeConstant", fACTimeConstant);
393 }
394
395 return rc;
396}
Note: See TracBrowser for help on using the repository browser.