source: branches/Mars_MC/msimcamera/MSimCamera.cc@ 17050

Last change on this file since 17050 was 17044, checked in by ftemme, 11 years ago
uncomment the exception throwing if the sampling frequency is not equal to 1 GHz
File size: 11.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
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)
78
79{
80 fName = name ? name : "MSimCamera";
81 fTitle = title ? title : "Task to simulate the electronic noise and to convert photons into pulses";
82}
83
84// --------------------------------------------------------------------------
85//
86// Search for the necessayr parameter containers.
87// Setup spline for pulse shape.
88//
89Int_t MSimCamera::PreProcess(MParList *pList)
90{
91 fMcEvt = (MMcEvt*)pList->FindCreateObj("MMcEvt");
92 if (!fMcEvt)
93 return kFALSE;
94
95 fCamera = (MAnalogChannels*)pList->FindCreateObj("MAnalogChannels");
96 if (!fCamera)
97 return kFALSE;
98
99 fEvt = (MPhotonEvent*)pList->FindObject("MPhotonEvent");
100 if (!fEvt)
101 {
102 *fLog << err << "MPhotonEvent not found... aborting." << endl;
103 return kFALSE;
104 }
105
106 fStat = (MPhotonStatistics*)pList->FindObject("MPhotonStatistics");
107 if (!fStat)
108 {
109 *fLog << err << "MPhotonStatistics not found... aborting." << endl;
110 return kFALSE;
111 }
112
113 fRunHeader = (MRawRunHeader *)pList->FindObject("MRawRunHeader");
114 if (!fRunHeader)
115 {
116 *fLog << err << "MRawRunHeader not found... aborting." << endl;
117 return kFALSE;
118 }
119/*
120 fPulsePos = (MParameterD*)pList->FindObject("IntendedPulsePos", "MParameterD");
121 if (!fPulsePos)
122 {
123 *fLog << err << "IntendedPulsePos [MParameterD] not found... aborting." << endl;
124 return kFALSE;
125 }
126 */
127
128 // Create it here to make sure that MGeomApply will set the correct size
129 fElectronicNoise = (MPedestalCam*)pList->FindCreateObj("MPedestalCam", "ElectronicNoise");
130 if (!fElectronicNoise)
131 return kFALSE;
132
133 fGain = (MPedestalCam*)pList->FindCreateObj("MPedestalCam", "Gain");
134 if (!fGain)
135 return kFALSE;
136
137 fAccidentalPhotons = (MPedestalCam*)pList->FindObject("AccidentalPhotonRates","MPedestalCam");
138 if(!fAccidentalPhotons)
139 {
140 *fLog << err << "AccidentalPhotonRates [MPedestalCam] not found... aborting." << endl;
141 return kFALSE;
142 }
143
144 MParSpline *pulse = (MParSpline*)pList->FindObject("PulseShape", "MParSpline");
145 if (!pulse)
146 {
147 *fLog << err << "PulseShape [MParSpline] not found... aborting." << endl;
148 return kFALSE;
149 }
150
151// if (fRunHeader->GetFreqSampling()!=1000)
152// {
153// *fLog << err << "ERROR - Sampling frequencies others than 1GHz are not yet supported." << endl;
154// *fLog << warn << "FIXME - SCALE MPulsShape WITH THE SAMPLING FREQUENCY." << endl;
155// return kFALSE;
156// }
157
158 fSpline = pulse->GetSpline();
159 if (!fSpline)
160 {
161 *fLog << err << "No spline initialized." << endl;
162 return kFALSE;
163 }
164
165 // ---------------- Information output ----------------------
166
167 if (fBaselineGain)
168 *fLog << inf << "Gain is also applied to the electronic noise." << endl;
169
170 return kTRUE;
171}
172
173// --------------------------------------------------------------------------
174//
175// FIXME: For now this is a workaround to set a baseline and the
176// electronic (guassian noise)
177//
178Bool_t MSimCamera::ReInit(MParList *plist)
179{
180 for (int i=0; i<fElectronicNoise->GetSize(); i++)
181 {
182 MPedestalPix &ped = (*fElectronicNoise)[i];
183 if (fDefaultOffset>0)
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 = 0; // [MHz]
254 Float_t crossTalkProb = 0; // [1]
255 Double_t areaOfOnePulse = 0; // [ADC-Counts * s]
256 Double_t samplingRate = 0; // [slices * MHz]
257
258 // The accidental photon rate is stored in GHz, so we have to multiply
259 // with 1E3 to get MHz:
260 MPedestalPix &accPhoPix = (*fAccidentalPhotons)[i];
261 accidentalPhotonRate = accPhoPix.GetPedestal() * 1E3;
262
263 // I don't know how to get the variable fCrosstalkProb from
264 // the class APD (see MAvalanchePhotoDiode.h), because there is no
265 // getter for the APD array(fAPDs) in MSimAPD.
266 // So I set the crossTalkProb hardcoded to the value 0.15, which is
267 // equal to the value of the apd of type 4
268 crossTalkProb = 0.15;
269
270 // To get the area of one Pulse, I only need to calculate the Integral
271 // of the Pulse Shape, which is stored in fSpline. Because the spline is
272 // normalized to a maximal amplitude of 1.0, I had to multiply it with
273 // the Default gain:
274 areaOfOnePulse = fSpline->Integral() * fDefaultGain;
275
276 // The sampling rate I get from the RunHeader:
277 samplingRate = fRunHeader->GetFreqSampling();
278
279 Double_t accouplingPerSlice = accidentalPhotonRate * (1 + crossTalkProb)
280 * areaOfOnePulse / samplingRate;
281
282 // The accoupling is substracted from the timeline by decreasing the
283 // mean of the gaussian noise which is added
284
285 if (!fBaselineGain)
286 {
287 (*fCamera)[i].AddGaussianNoise(rms, val - accouplingPerSlice);
288 continue;
289 }
290 // Sorry, the name "pedestal" is misleading here
291 // FIXME: Simulate gain fluctuations
292 const Double_t gain = (*fGain)[i].GetPedestal();
293
294 // FIXME: We might add the base line here already.
295 // FIXME: How stable is the offset?
296 // FIXME: Should we write a container AppliedGain for MSImTrigger?
297
298 (*fCamera)[i].AddGaussianNoise(rms*gain, (val - accouplingPerSlice)*gain);
299 }
300
301 // FIXME: Simulate correlations with neighboring pixels
302
303 const Int_t num = fEvt->GetNumPhotons();
304
305 // A random shift, uniformely distributed within one slice, to make sure that
306 // the first photon is not always aligned identically with a sample edge.
307 // FIXME: Make it switchable
308 const Float_t rndm = gRandom->Uniform();
309
310 // FIXME: Shell we add a random shift of [0,1] samples per channel?
311 // Or maybe per channel and run?
312
313 Double_t tot = 0;
314
315 // Simulate pulses
316 for (Int_t i=0; i<num; i++)
317 {
318 const MPhotonData &ph = (*fEvt)[i];
319
320 const UInt_t idx = ph.GetTag();
321 const Double_t t = (ph.GetTime()-fStat->GetTimeFirst())*freq+rndm;// - fSpline->GetXmin();
322
323 // FIXME: Time jitter?
324 // FIXME: Add additional routing here?
325 // FIMXE: How stable is the gain?
326
327 if (ph.GetPrimary()!=MMcEvt::kNightSky && ph.GetPrimary()!=MMcEvt::kArtificial)
328 tot += ph.GetWeight();
329
330 // Sorry, the name "pedestal" is misleading here
331 // FIXME: Simulate gain fluctuations
332 const Double_t gain = (*fGain)[idx].GetPedestal();
333
334 // === FIXME === FIXME === FIXME === Frequency!!!!
335 (*fCamera)[idx].AddPulse(*fSpline, t, ph.GetWeight()*gain);
336 }
337
338 fMcEvt->SetPhotElfromShower(TMath::Nint(tot));
339
340 return kTRUE;
341}
342
343// --------------------------------------------------------------------------
344//
345// BaselineGain: Off
346//
347Int_t MSimCamera::ReadEnv(const TEnv &env, TString prefix, Bool_t print)
348{
349 Bool_t rc = kFALSE;
350 if (IsEnvDefined(env, prefix, "BaselineGain", print))
351 {
352 rc = kTRUE;
353 fBaselineGain = GetEnvValue(env, prefix, "BaselineGain", fBaselineGain);
354 }
355
356 if (IsEnvDefined(env, prefix, "DefaultOffset", print))
357 {
358 rc = kTRUE;
359 fDefaultOffset = GetEnvValue(env, prefix, "DefaultOffset", fDefaultOffset);
360 }
361 if (IsEnvDefined(env, prefix, "DefaultNoise", print))
362 {
363 rc = kTRUE;
364 fDefaultNoise = GetEnvValue(env, prefix, "DefaultNoise", fDefaultNoise);
365 }
366 if (IsEnvDefined(env, prefix, "DefaultGain", print))
367 {
368 rc = kTRUE;
369 fDefaultGain = GetEnvValue(env, prefix, "DefaultGain", fDefaultGain);
370 }
371
372 return rc;
373}
Note: See TracBrowser for help on using the repository browser.