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

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