source: trunk/MagicSoft/Mars/msimcamera/MSimTrigger.cc@ 9518

Last change on this file since 9518 was 9518, checked in by tbretz, 15 years ago
*** empty log message ***
File size: 22.5 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// MSimTrigger
28//
29// This task takes the pure analog channels and simulates a trigger
30// electronics.
31//
32// In a first step several channels can be summed together by a look-up table
33// fRouteAC.
34//
35// In a second step from these analog channels the output of a discriminator
36// is calculated using a threshold and optional a fixed digital signal length.
37//
38// The signal length of the digital signal emitted by the discriminator
39// can either be bound to the time the signal is above the threshold
40// defined by fDiscriminatorThreshold if fDigitalSignalLength<0 or set to a
41// fixed length (fDigitalSignalLength>0).
42//
43// With a second look-up table fCoincidenceMap the analog channels are
44// checked for coincidences. The coincidence must at least be of the length
45// defined by fCoincidenceTime. The earliest coincide is then stored as
46// trigger position.
47//
48// If a minimum multiplicity m is given, m signals above threshold
49// in the coincidence patterns are enough to emit a trigger signal.
50//
51//
52// For MAGIC1:
53// - fDigitalSignalLength between 6ns and 12ns
54// - fCoincidenceTime between 0.25ns to 1ns
55//
56//
57// Input Containers:
58// IntendedPulsePos [MParameterD]
59// MAnalogChannels
60// MRawRunHeader
61//
62// Output Containers:
63// TriggerPos [MParameterD]
64// MRawEvtHeader
65//
66//////////////////////////////////////////////////////////////////////////////
67#include "MSimTrigger.h"
68
69#include "MLog.h"
70#include "MLogManip.h"
71
72#include "MParList.h"
73#include "MParameters.h"
74
75#include "MLut.h"
76#include "MArrayI.h"
77
78#include "MRawEvtHeader.h"
79#include "MRawRunHeader.h"
80
81#include "MAnalogSignal.h"
82#include "MAnalogChannels.h"
83#include "MDigitalSignal.h"
84
85#include "MTriggerPattern.h"
86
87#include "MPedestalCam.h"
88#include "MPedestalPix.h"
89
90ClassImp(MSimTrigger);
91
92using namespace std;
93
94// --------------------------------------------------------------------------
95//
96// Default Constructor.
97//
98MSimTrigger::MSimTrigger(const char *name, const char *title)
99 : fCamera(0), fPulsePos(0), fTrigger(0), fRunHeader(0),
100 fEvtHeader(0), fElectronicNoise(0), fGain(0),
101 fDiscriminatorThreshold(-1), fDigitalSignalLength(8), fCoincidenceTime(0.5),
102 fShiftBaseline(kTRUE), fUngainSignal(kTRUE), fSimulateElectronics(kTRUE),
103 fMinMultiplicity(-1)
104{
105 fName = name ? name : "MSimTrigger";
106 fTitle = title ? title : "Task to simulate trigger electronics";
107}
108
109// --------------------------------------------------------------------------
110//
111// Take two TObjArrays with a collection of digital signals.
112// Every signal from one array is compared with any from the other array.
113// For all signals which overlap and which have an overlap time >gate
114// a new digital signal is created storing start time and length of overlap.
115// They are collected in a newly allocated TObjArray. A pointer to this array
116// is returned.
117//
118// The user gains owenership of the object, i.e., the user is responsible of
119// deleting the memory.
120//
121TObjArray *MSimTrigger::CalcCoincidence(const TObjArray &arr1, const TObjArray &arr2/*, Float_t gate*/) const
122{
123 TObjArray *res = new TObjArray;
124
125 if (arr1.GetEntriesFast()==0 || arr2.GetEntriesFast()==0)
126 return res;
127
128 TIter Next1(&arr1);
129 MDigitalSignal *ttl1 = 0;
130 while ((ttl1=static_cast<MDigitalSignal*>(Next1())))
131 {
132 TIter Next2(&arr2);
133 MDigitalSignal *ttl2 = 0;
134 while ((ttl2=static_cast<MDigitalSignal*>(Next2())))
135 {
136 MDigitalSignal *ttl = new MDigitalSignal(*ttl1, *ttl2);
137 /*
138 if (ttl->GetLength()<=gate)
139 {
140 delete ttl;
141 continue;
142 }
143 */
144 res->Add(ttl);
145 }
146 }
147
148 res->SetOwner();
149
150 return res;
151}
152
153class Edge : public TObject
154{
155private:
156 Double_t fEdge;
157 Int_t fRising;
158
159public:
160 Edge(Double_t t, Int_t rising) : fEdge(t), fRising(rising) { }
161 Bool_t IsSortable() const { return kTRUE; }
162 Int_t Compare(const TObject *o) const { const Edge *e = static_cast<const Edge*>(o); if (e->fEdge<fEdge) return 1; if (e->fEdge>fEdge) return -1; return 0; }
163
164 Int_t IsRising() const { return fRising; }
165 Double_t GetEdge() const { return fEdge; }
166};
167
168// --------------------------------------------------------------------------
169//
170// Calculate a multiplicity trigger on the given array(s). The idx-array
171// conatins all channels which should be checked for coincidences
172// and the ttls array conatins the arrays with the digital signals.
173//
174// For the windows in which more or euqal than threshold channels have
175// a high signal a new MDigitalSignal is created. newly allocated
176// array with a collection of these trigger signals is returned.
177//
178TObjArray *MSimTrigger::CalcMinMultiplicity(const MArrayI &idx, const TObjArray &ttls, Int_t threshold) const
179{
180 // Create a new array for the rising and falling edges of the signals
181 TObjArray times;
182 times.SetOwner();
183
184 // Fill the array with edges from all digital signals of all our channels
185 for (UInt_t k=0; k<idx.GetSize(); k++)
186 {
187 TObjArray *arr = static_cast<TObjArray*>(ttls[idx[k]]);
188
189 TIter Next(arr);
190 MDigitalSignal *ttl = 0;
191 while ((ttl=static_cast<MDigitalSignal*>(Next())))
192 {
193 times.Add(new Edge(ttl->GetStart(), 1));
194 times.Add(new Edge(ttl->GetEnd(), -1));
195 }
196 }
197
198 // Sort them in time
199 times.Sort();
200
201 // Start with no channel active
202 Int_t lvl = 0;
203
204 TObjArray *res = new TObjArray;
205 res->SetOwner();
206
207 // First remove all edges which do not change the status
208 // "below threshold" or "above threshold"
209 for (int i=0; i<times.GetEntriesFast(); i++)
210 {
211 // Get i-th edge
212 const Edge &e = *static_cast<Edge*>(times.UncheckedAt(i));
213
214 // Claculate what the number of active channels after the edge is
215 const Int_t lvl1 = lvl + e.IsRising();
216
217 // Remove edge if number of active channels before and after the
218 // edge lower is lower than the threshold or higher than
219 // the threshold
220 if (lvl+1<threshold || lvl-1>=threshold)
221 delete times.RemoveAt(i);
222
223 // keep the (now) "previous" level
224 lvl = lvl1<0 ? 0 : lvl1;
225 }
226
227 // Remove the empty slots from the array
228 times.Compress();
229
230 //
231 for (int i=0; i<times.GetEntriesFast()-1; i++)
232 {
233 // get the current edge
234 const Edge &e0 = *static_cast<Edge*>(times.UncheckedAt(i));
235
236 // go ahead if this is a falling edge
237 if (e0.IsRising()!=1)
238 continue;
239
240 // get the following edge (must be a falling edge now)
241 const Edge &e1 = *static_cast<Edge*>(times.UncheckedAt(i+1));
242
243 // calculate the length of the digital signal
244 const Double_t len = e1.GetEdge()-e0.GetEdge();
245
246 // Create a digital trigger signal
247 MDigitalSignal *ds = new MDigitalSignal(e0.GetEdge(), len);
248 //ds->SetIndex(lvl);
249 res->Add(ds);
250 }
251
252 return res;
253}
254
255// --------------------------------------------------------------------------
256//
257// Check for the necessary parameter containers. Read the luts.
258//
259Int_t MSimTrigger::PreProcess(MParList *pList)
260{
261 fTrigger = (MParameterD*)pList->FindCreateObj("MParameterD", "TriggerPos");
262 if (!fTrigger)
263 return kFALSE;
264
265 fPulsePos = (MParameterD*)pList->FindObject("IntendedPulsePos", "MParameterD");
266 if (!fPulsePos)
267 {
268 *fLog << err << "IntendedPulsePos [MParameterD] not found... aborting." << endl;
269 return kFALSE;
270 }
271
272 fCamera = (MAnalogChannels*)pList->FindObject("MAnalogChannels");
273 if (!fCamera)
274 {
275 *fLog << err << "MAnalogChannels not found... aborting." << endl;
276 return kFALSE;
277 }
278
279 fRunHeader = (MRawRunHeader*)pList->FindObject("MRawRunHeader");
280 if (!fRunHeader)
281 {
282 *fLog << err << "MRawRunHeader not found... aborting." << endl;
283 return kFALSE;
284 }
285
286 fEvtHeader = (MRawEvtHeader*)pList->FindCreateObj("MRawEvtHeader");
287 if (!fEvtHeader)
288 return kFALSE;
289
290 if (!fSimulateElectronics)
291 {
292 *fLog << inf << "Simulation of electronics switched off... first photon will trigger." << endl;
293 return kTRUE;
294 }
295
296 fElectronicNoise = 0;
297 if (fShiftBaseline)
298 {
299 fElectronicNoise = (MPedestalCam*)pList->FindObject("ElectronicNoise", "MPedestalCam");
300 if (!fElectronicNoise)
301 {
302 *fLog << err << "ElectronicNoise [MPedestalCam] not found... aborting." << endl;
303 return kFALSE;
304 }
305 *fLog << inf << "Baseline will be shifted back to 0 for discriminator." << endl;
306 }
307
308 fGain = 0;
309 if (fUngainSignal)
310 {
311 fGain = (MPedestalCam*)pList->FindObject("Gain", "MPedestalCam");
312 if (!fGain)
313 {
314 *fLog << err << "Gain [MPedestalCam] not found... aborting." << endl;
315 return kFALSE;
316 }
317 *fLog << inf << "Discriminator will be multiplied by applied gain." << endl;
318 }
319
320 fRouteAC.Delete();
321 if (!fNameRouteAC.IsNull() && fRouteAC.ReadFile(fNameRouteAC)<0)
322 return kFALSE;
323
324 fCoincidenceMap.Delete();
325 if (!fNameCoincidenceMap.IsNull() && fCoincidenceMap.ReadFile(fNameCoincidenceMap)<0)
326 return kFALSE;
327
328 // ---------------- Consistency checks ----------------------
329
330 if (!fRouteAC.IsEmpty() && !fCoincidenceMap.IsEmpty() &&
331 fCoincidenceMap.GetMaxIndex()>fRouteAC.GetNumRows()-1)
332 {
333 *fLog << err;
334 *fLog << "ERROR - AC routing produces " << fRouteAC.GetNumRows() << " analog channels," << endl;
335 *fLog << " but the coincidence map expects at least " << fCoincidenceMap.GetMaxIndex()+1 << " channels." << endl;
336 return kERROR;
337 }
338
339 if (fDiscriminatorThreshold<=0)
340 {
341 *fLog << err << "ERROR - Discriminator threshold " << fDiscriminatorThreshold << " invalid." << endl;
342 return kFALSE;
343 }
344
345 if (fElectronicNoise && !fRouteAC.IsEmpty() && !fRouteAC.IsDefaultCol())
346 {
347 // FIXME: Apply to analog channels when summing
348 *fLog << warn << "WARNING - A baseline shift doesn't make sense for sum-channels... reset." << endl;
349 fElectronicNoise = 0;
350 }
351
352 if (fGain && !fRouteAC.IsEmpty() && !fRouteAC.IsDefaultCol())
353 {
354 // FIXME: Apply to analog channels when summing
355 *fLog << warn << "WARNING - Ungain doesn't make sense for sum-channels... reset." << endl;
356 fGain = 0;
357 }
358
359
360 // ---------------- Information output ----------------------
361
362 *fLog << inf;
363
364 if (fRouteAC.IsEmpty())
365 *fLog << "Re-routing/summing of analog channels before discriminator switched off." << endl;
366 else
367 *fLog << "Using " << fNameRouteAC << " for re-routing/summing of analog channels before discriminator." << endl;
368
369 if (fCoincidenceMap.IsEmpty() && fMinMultiplicity<=0)
370 *fLog << "No coincidences of digital channels will be checked. Signal-above-threshold trigger applied." << endl;
371 else
372 {
373 *fLog << "Using ";
374 if (fCoincidenceMap.IsEmpty())
375 *fLog << "the whole camera";
376 else
377 *fLog << "patterns from " << fNameCoincidenceMap;
378 *fLog << " to check for ";
379 if (fMinMultiplicity>0)
380 *fLog << fMinMultiplicity << " multiplicity." << endl;
381 else
382 *fLog << "coincidences of the digital channels." << endl;
383 }
384
385 *fLog << "Using discriminator threshold of " << fDiscriminatorThreshold << endl;
386
387 return kTRUE;
388}
389
390/*
391class MDigitalChannel : public TObjArray
392{
393private:
394 TObjArray fArray;
395
396public:
397 MDigitalSignal *GetSignal(UInt_t i) { return static_cast<MDigitalSignal*>(fArray[i]); }
398
399};
400*/
401
402#include "MCamEvent.h"
403class MTriggerSignal : public MParContainer, public MCamEvent
404{
405private:
406 TObjArray fSignals;
407
408public:
409 MTriggerSignal() { fSignals.SetOwner(); }
410
411 void Add(MDigitalSignal *signal) { fSignals.Add(signal); }
412
413 MDigitalSignal *GetSignal(UInt_t i) { return static_cast<MDigitalSignal*>(fSignals[i]); }
414
415 void Sort() { fSignals.Sort(); }
416
417 Int_t GetNumSignals() const { return fSignals.GetEntriesFast(); }
418
419 Float_t GetFirstTrigger() const
420 {
421 MDigitalSignal *sig = static_cast<MDigitalSignal*>(fSignals[0]);
422 return sig ? sig->GetStart() : -1;
423 }
424 Bool_t GetPixelContent(Double_t&, Int_t, const MGeomCam&, Int_t) const
425 {
426 switch (1)
427 {
428 case 1: // yes/no
429 case 2: // first time
430 case 3: // length
431 case 4: // n
432 break;
433 }
434
435 return kTRUE;
436 }
437 void DrawPixelContent(Int_t) const
438 {
439 }
440};
441
442
443void MSimTrigger::SetTrigger(Double_t pos)
444{
445 // FIXME: Jitter! (Own class?)
446 fTrigger->SetVal(pos);
447 fTrigger->SetReadyToSave();
448
449 // Trigger pattern to be set
450 // FIXME: Make flexible
451 const UInt_t pat = (UInt_t)~(MTriggerPattern::kTriggerLvl1 | (MTriggerPattern::kTriggerLvl1<<8));
452
453 // Flag this event as triggered by the lvl1 trigger (FIXME?)
454 fEvtHeader->SetTriggerPattern(pos<0 ? 0 : pat);
455 fEvtHeader->SetReadyToSave();
456}
457
458// --------------------------------------------------------------------------
459//
460Int_t MSimTrigger::Process()
461{
462 // Invalidate trigger
463 //fTrigger->SetVal(-1);
464 // Calculate the minimum and maximum time for a valid trigger
465 const Double_t freq = fRunHeader->GetFreqSampling()/1000.;
466 const Float_t nsamp = fRunHeader->GetNumSamplesHiGain();
467 const Float_t pulspos = fPulsePos->GetVal()/freq;
468
469 // Valid range in units of bins
470 const Float_t min = fCamera->GetValidRangeMin()+pulspos;
471 const Float_t max = fCamera->GetValidRangeMax()-(nsamp-pulspos);
472
473 if (!fSimulateElectronics)
474 {
475 SetTrigger(min);
476 return kTRUE;
477 }
478
479 // ================== Simulate channel bundling ====================
480
481 // FIXME: Before we can bundle the channels we have to make a copy
482 // and simulate clipping
483
484 // Check if routing should be done
485 const Bool_t empty = fRouteAC.IsEmpty();
486
487 // If no channels are summed the number of patches stays the same
488 const UInt_t npatch = empty ? fCamera->GetNumChannels() : fRouteAC.GetEntriesFast();
489
490 // Use the given analog channels as default out. If channels are
491 // summed overwrite with a newly allocated set of analog channels
492 MAnalogChannels *patches = fCamera;
493 if (!empty)
494 {
495 // FIXME: Can we add gain and offset here into a new container?
496
497 patches = new MAnalogChannels(npatch, fCamera->GetNumSamples());
498 for (UInt_t i=0; i<npatch; i++)
499 {
500 const MArrayI &row = fRouteAC.GetRow(i);
501 for (UInt_t j=0; j<row.GetSize(); j++)
502 {
503 const UInt_t idx = row[j];
504
505 // FIXME: Shrinking the mapping table earlier (e.g.
506 // ReInit) would avoid a lot of if's
507 if (idx<fCamera->GetNumChannels())
508 (*patches)[i].AddSignal((*fCamera)[idx]);
509 }
510 }
511 }
512
513 // FIXME: Write patches
514
515 // ================== Simulate discriminators ====================
516
517 TObjArray ttls(npatch);
518 ttls.SetOwner();
519
520 for (UInt_t i=0; i<npatch; i++)
521 {
522 // FIXME: What if the gain was also allpied to the baseline?
523 const Double_t offset = fElectronicNoise ? (*fElectronicNoise)[i].GetPedestal() : 0;
524 const Double_t gain = fGain ? (*fGain)[i].GetPedestal() : 1;
525 ttls.AddAt((*patches)[i].Discriminate(fDiscriminatorThreshold*gain+offset, fDigitalSignalLength), i);
526 }
527
528 // FIXME: Write TTLs!
529
530 // If analog channels had been newly allocated free memmory
531 if (patches!=fCamera)
532 delete patches;
533
534 // =================== Simulate coincidences ======================
535
536 // If the map is empty we create a one-pixel-coincidence map
537 // FIMXE: This could maybe be accelerated if the Clone can be
538 // omitted in the loop
539 if (fCoincidenceMap.IsEmpty())
540 {
541 if (fMinMultiplicity>0)
542 fCoincidenceMap.SetDefaultRow(npatch);
543 else
544 fCoincidenceMap.SetDefaultCol(npatch);
545 }
546
547 // Create an array for the individual triggers
548 MTriggerSignal triggers;
549
550 Int_t cnt = 0;
551 Int_t rmlo = 0;
552 Int_t rmhi = 0;
553
554 for (int j=0; j<fCoincidenceMap.GetEntries(); j++)
555 {
556 const MArrayI &idx = fCoincidenceMap.GetRow(j);
557
558 TObjArray *arr = 0;
559
560 if (fMinMultiplicity>0)
561 {
562 arr = CalcMinMultiplicity(idx, ttls, fMinMultiplicity);
563 }
564 else
565 {
566 arr = CalcMinMultiplicity(idx, ttls, idx.GetSize());
567 /*
568 // Start with a copy of the first coincidence channel
569 arr = static_cast<TObjArray*>(ttls[idx[0]]->Clone());
570 arr->SetOwner();
571
572 // compare to all other channels in this coincidence patch, one by one
573 for (UInt_t k=1; k<idx.GetSize() && arr->GetEntriesFast()>0; k++)
574 {
575 TObjArray *res = CalcCoincidence(*arr, *static_cast<TObjArray*>(ttls[idx[k]]));//, fCoincidenceTime);
576
577 // Delete the original array and keep the new one
578 delete arr;
579 arr = res;
580 }*/
581 }
582
583 // Count the number of totally emitted coincidence signals
584 cnt += arr->GetEntriesFast();
585
586 // Remove all signals which are not in the valid digitization range
587 // (This is not the digitization window, but the region in which
588 // the analog channels contain usefull data)
589 // and which are shorter than the defined coincidence gate.
590 TIter Next(arr);
591 MDigitalSignal *ttl = 0;
592 while ((ttl=static_cast<MDigitalSignal*>(Next())))
593 {
594 if (ttl->GetLength()<fCoincidenceTime)
595 {
596 delete arr->Remove(ttl);
597 continue;
598 }
599
600 if (ttl->GetStart()<min)
601 {
602 delete arr->Remove(ttl);
603 rmlo++;
604 continue;
605 }
606 if (ttl->GetStart()>max)
607 {
608 delete arr->Remove(ttl);
609 rmhi++;
610 continue;
611 }
612
613 // Set trigger channel index
614 ttl->SetIndex(j);
615 }
616
617 // Remove the empty slots
618 arr->Compress();
619
620 // If we have at least one trigger keep the earliest one.
621 // FIXME: The triggers might be ordered in time automatically:
622 // To be checked!
623 // FIXME: Simulate trigger dead-time!
624 if (arr->GetEntriesFast()>0)
625 triggers.Add(static_cast<MDigitalSignal*>(arr->RemoveAt(0)));
626
627 // delete the allocated space
628 delete arr;
629 }
630
631 // There are usually not enough entries that it is worth to search
632 // for the earliest instead of just sorting and taking the first one
633 // FIXME: This could be improved if checking for IsSortable
634 // is omitted
635 triggers.Sort();
636 // FIXME: Store triggers! (+ Reversed pixels?)
637
638 SetTrigger(triggers.GetFirstTrigger());
639
640 // No trigger issued. Go on.
641 if (triggers.GetNumSignals()==0)
642 {
643 if (rmlo>0 || rmhi>0)
644 *fLog << inf2 << GetNumExecutions() << ": " << rmlo << "/" << rmhi << " trigger out of valid range. No trigger raised." << endl;
645 return kTRUE;
646 }
647
648 // Number of patches which have triggered out of the total number of
649 // Coincidence signals emitted. (If the total number is higher than
650 // the number of triggers either some triggers had to be removed or
651 // or a patch has emitted more than one trigger signal)
652 // FIXME: inf2?
653 *fLog << inf << GetNumExecutions() << ": ";
654 *fLog << setw(3) << triggers.GetNumSignals() << " triggers left out of ";
655 *fLog << setw(3) << cnt << " (" << rmlo << "/" << rmhi << " trigger out of valid range), T=" << fTrigger->GetVal();
656 *fLog << endl;
657
658 //# Trigger characteristics: gate length (ns), min. overlapping time (ns),
659 //# amplitude and FWHM of (gaussian) single phe response for trigger:
660 //trigger_prop 3.0 0.25 1.0 2.0
661
662 return kTRUE;
663}
664
665// --------------------------------------------------------------------------
666//
667// FileNameRouteac: routeac.txt
668// FileNameCoincidenceMap: coincidence.txt
669// DiscriminatorTheshold: 3.5
670// DigitalSignalLength: 8
671// CoincidenceTime: 0.5
672// SimulateElectronics: Yes
673//
674Int_t MSimTrigger::ReadEnv(const TEnv &env, TString prefix, Bool_t print)
675{
676 Bool_t rc = kFALSE;
677 if (IsEnvDefined(env, prefix, "FileNameRouteAC", print))
678 {
679 rc = kTRUE;
680 fNameRouteAC = GetEnvValue(env, prefix, "FileNameRouteAC", fNameRouteAC);
681 }
682
683 if (IsEnvDefined(env, prefix, "FileNameCoincidenceMap", print))
684 {
685 rc = kTRUE;
686 fNameCoincidenceMap = GetEnvValue(env, prefix, "FileNameCoincidenceMap", fNameCoincidenceMap);
687 }
688
689 if (IsEnvDefined(env, prefix, "DiscriminatorThreshold", print))
690 {
691 rc = kTRUE;
692 fDiscriminatorThreshold = GetEnvValue(env, prefix, "DiscriminatorThreshold", fDiscriminatorThreshold);
693 }
694
695 if (IsEnvDefined(env, prefix, "DigitalSignalLength", print))
696 {
697 rc = kTRUE;
698 fDigitalSignalLength = GetEnvValue(env, prefix, "DigitalSignalLength", fDigitalSignalLength);
699 }
700
701 if (IsEnvDefined(env, prefix, "CoincidenceTime", print))
702 {
703 rc = kTRUE;
704 fCoincidenceTime = GetEnvValue(env, prefix, "CoincidenceTime", fCoincidenceTime);
705 }
706
707 if (IsEnvDefined(env, prefix, "SimulateElectronics", print))
708 {
709 rc = kTRUE;
710 fSimulateElectronics = GetEnvValue(env, prefix, "SimulateElectronics", fSimulateElectronics);
711 }
712
713 if (IsEnvDefined(env, prefix, "MinMultiplicity", print))
714 {
715 rc = kTRUE;
716 fMinMultiplicity = GetEnvValue(env, prefix, "MinMultiplicity", fMinMultiplicity);
717 }
718
719 return rc;
720}
Note: See TracBrowser for help on using the repository browser.