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

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