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

Last change on this file since 9308 was 9308, checked in by tbretz, 16 years ago
*** empty log message ***
File size: 11.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 coincidense must at least be of the length
45// defined by fCoincidenceTime. The earliest coincide is then stored as
46// trigger position.
47//
48//
49// For MAGIC1:
50// - fDigitalSignalLength between 6ns and 12ns
51// - fCoincidenceTime between 0.25ns to 1ns
52//
53//
54// Input Containers:
55// IntendedPulsePos [MParameterD]
56// MAnalogChannels
57// MRawRunHeader
58//
59// Output Containers:
60// TriggerPos [MParameterD]
61// MRawEvtHeader
62//
63//////////////////////////////////////////////////////////////////////////////
64#include "MSimTrigger.h"
65
66#include "MLog.h"
67#include "MLogManip.h"
68
69#include "MParList.h"
70#include "MParameters.h"
71
72#include "MLut.h"
73#include "MArrayI.h"
74
75#include "MRawEvtHeader.h"
76#include "MRawRunHeader.h"
77
78#include "MAnalogSignal.h"
79#include "MAnalogChannels.h"
80#include "MDigitalSignal.h"
81
82#include "MTriggerPattern.h"
83
84ClassImp(MSimTrigger);
85
86using namespace std;
87
88// --------------------------------------------------------------------------
89//
90// Default Constructor.
91//
92MSimTrigger::MSimTrigger(const char *name, const char *title)
93 : fCamera(0), fPulsePos(0), fTrigger(0), fRunHeader(0), fEvtHeader(0),
94 fDiscriminatorThreshold(-1), fDigitalSignalLength(8), fCoincidenceTime(0.5)
95{
96 fName = name ? name : "MSimTrigger";
97 fTitle = title ? title : "Task to simulate trigger electronics";
98}
99
100// --------------------------------------------------------------------------
101//
102// Take two TObjArrays with a collection of digital signals.
103// Every signal from one array is compared with any from the other array.
104// For all signals whihc overlaps and which have an overlap time >gate
105// a new digital signal is created storing start time and length of overlap.
106// They are collected in a newly allocated TObjArray. A pointer to this array
107// is returned.
108//
109// Th euser gains owenership of the object, ie.e., the user is responsible of
110// deleting the memory.
111//
112TObjArray *MSimTrigger::CalcCoincidence(const TObjArray &arr1, const TObjArray &arr2, Float_t gate) const
113{
114 TObjArray *res = new TObjArray;
115
116 if (arr1.GetEntriesFast()==0 || arr2.GetEntriesFast()==0)
117 return res;
118
119 TIter Next1(&arr1);
120 MDigitalSignal *ttl1 = 0;
121 while ((ttl1=static_cast<MDigitalSignal*>(Next1())))
122 {
123 TIter Next2(&arr2);
124 MDigitalSignal *ttl2 = 0;
125 while ((ttl2=static_cast<MDigitalSignal*>(Next2())))
126 {
127 MDigitalSignal *ttl = new MDigitalSignal(*ttl1, *ttl2);
128
129 if (ttl->GetLength()<=gate)
130 {
131 delete ttl;
132 continue;
133 }
134
135 res->Add(ttl);
136 }
137 }
138
139 res->SetOwner();
140
141 return res;
142}
143
144// --------------------------------------------------------------------------
145//
146// Check for the necessary parameter containers. Read the luts.
147//
148Int_t MSimTrigger::PreProcess(MParList *pList)
149{
150 fTrigger = (MParameterD*)pList->FindCreateObj("MParameterD", "TriggerPos");
151 if (!fTrigger)
152 return kFALSE;
153
154 fPulsePos = (MParameterD*)pList->FindObject("IntendedPulsePos", "MParameterD");
155 if (!fPulsePos)
156 {
157 *fLog << err << "IntendedPulsePos [MParameterD] not found... aborting." << endl;
158 return kFALSE;
159 }
160
161 fCamera = (MAnalogChannels*)pList->FindObject("MAnalogChannels");
162 if (!fCamera)
163 {
164 *fLog << err << "MAnalogChannels not found... aborting." << endl;
165 return kFALSE;
166 }
167
168 fRunHeader = (MRawRunHeader*)pList->FindObject("MRawRunHeader");
169 if (!fRunHeader)
170 {
171 *fLog << err << "MRawRunHeader not found... aborting." << endl;
172 return kFALSE;
173 }
174
175 fEvtHeader = (MRawEvtHeader*)pList->FindCreateObj("MRawEvtHeader");
176 if (!fEvtHeader)
177 return kFALSE;
178
179
180 if (fRouteAC.ReadFile(fNameRouteAC)<0)
181 return kFALSE;
182
183 if (fCoincidenceMap.ReadFile(fNameCoincidenceMap)<0)
184 return kFALSE;
185
186 if (fDiscriminatorThreshold<=0)
187 {
188 *fLog << err << "ERROR - Discriminator threshold " << fDiscriminatorThreshold << " invalid." << endl;
189 return kFALSE;
190 }
191
192 *fLog << inf << "Using discriminator threshold of " << fDiscriminatorThreshold << endl;
193
194 return kTRUE;
195}
196
197// --------------------------------------------------------------------------
198//
199Int_t MSimTrigger::Process()
200{
201 // Invalidate trigger
202 fTrigger->SetVal(-1);
203
204 // ================== Simulate channel bundling ====================
205
206 const UInt_t npatch = fRouteAC.GetEntriesFast();
207
208 MAnalogChannels patches(npatch, fCamera->GetNumSamples());
209
210 for (UInt_t i=0; i<npatch; i++)
211 {
212 const MArrayI &row = fRouteAC.GetRow(i);
213 for (UInt_t j=0; j<row.GetSize(); j++)
214 {
215 // FIXME: Simulate clipping
216 const UInt_t idx = row[j];
217 patches[i].AddSignal((*fCamera)[idx]);
218 }
219 }
220
221 // FIXME: Write patches
222
223 // ================== Simulate discriminators ====================
224
225 TObjArray ttls(npatch);
226 ttls.SetOwner();
227
228 for (UInt_t i=0; i<npatch; i++)
229 ttls.AddAt(patches[i].Discriminate(fDiscriminatorThreshold, fDigitalSignalLength), i);
230
231 // FIXME: Write TTLs!
232
233 // =================== Simulate coincidences ======================
234
235 // Calculate the minimum and maximum time for a valid trigger
236 const Double_t freq = fRunHeader->GetFreqSampling()/1000.;
237 const Float_t nsamp = fRunHeader->GetNumSamplesHiGain();
238 const Float_t pulspos = fPulsePos->GetVal()/freq;
239
240 // Valid range in units of bins
241 const Float_t min = fCamera->GetValidRangeMin()+pulspos;
242 const Float_t max = fCamera->GetValidRangeMax()-(nsamp-pulspos);
243
244 // Create an array for the individual triggers
245 TObjArray triggers;
246 triggers.SetOwner();
247
248 Int_t cnt = 0;
249 Int_t rmlo = 0;
250 Int_t rmhi = 0;
251
252 for (int j=0; j<fCoincidenceMap.GetEntries(); j++)
253 {
254 const MArrayI &idx = fCoincidenceMap.GetRow(j);
255
256 // Start with a copy of the first coincidence channel
257 TObjArray *arr = static_cast<TObjArray*>(ttls[idx[0]]->Clone());
258 arr->SetOwner();
259
260 // compare to all other channels in this coincidence patch, one by one
261 for (UInt_t k=1; k<idx.GetSize() && arr->GetEntriesFast()>0; k++)
262 {
263 TObjArray *res = CalcCoincidence(*arr, *static_cast<TObjArray*>(ttls[idx[k]]),
264 fCoincidenceTime);
265
266 // Delete the original array and keep the new one
267 delete arr;
268 arr = res;
269 }
270
271 // Remove all signals which are not in the valid digitization range
272 // (This is not the digitization window, but the region in which
273 // the analog channels contain usefull data)
274 TIter Next(arr);
275 MDigitalSignal *ttl = 0;
276 while ((ttl=static_cast<MDigitalSignal*>(Next())))
277 {
278 if (ttl->GetStart()<min)
279 {
280 delete arr->Remove(ttl);
281 rmlo++;
282 }
283 if (ttl->GetStart()>max)
284 {
285 delete arr->Remove(ttl);
286 rmhi++;
287 }
288 }
289
290 // Remove the empty slots
291 arr->Compress();
292
293 cnt += arr->GetEntriesFast();
294
295 // If we have at least one trigger keep the earliest one.
296 // FIXME: The triggers should be ordered in time automatically: To be checked!
297 // FIXME: Simulate trigger dead-time!
298 if (arr->GetEntriesFast()>0)
299 triggers.Add(arr->RemoveAt(0));
300
301 // delete the allocated space
302 delete arr;
303 }
304
305 // No trigger issued. Go on.
306 if (triggers.GetEntriesFast()==0)
307 {
308 if (rmlo>0 || rmhi>0)
309 *fLog << inf2 << rmlo << "/" << rmhi << " trigger out of valid range. No trigger raised." << endl;
310 return kTRUE;
311 }
312
313 // There are usually not enough entries that it is worth to search
314 // for the earliest instead of just sorting and taking the first one
315 // FIXME: This could be improved if checking for IsSortable
316 // is omitted
317 triggers.Sort();
318
319 // FIXME: Jitter! (Own class?)
320 fTrigger->SetVal(static_cast<MDigitalSignal*>(triggers[0])->GetStart());
321 fTrigger->SetReadyToSave();
322
323 // Flag this event as triggered by the lvl1 trigger (FIXME?)
324 fEvtHeader->SetTriggerPattern((UInt_t)~(MTriggerPattern::kTriggerLvl1 | (MTriggerPattern::kTriggerLvl1<<8)));
325 fEvtHeader->SetReadyToSave();
326
327 // inf2?
328 *fLog << inf;
329 *fLog << cnt << " triggers left in " << triggers.GetEntriesFast() << " patches (" << rmlo << "/" << rmhi << " trigger out of valid range), T=" << fTrigger->GetVal();
330 *fLog << endl;
331
332 return kTRUE;
333}
334
335// --------------------------------------------------------------------------
336//
337// FileNameRouteac: routeac.txt
338// FileNameCoincidenceMap: coincidence.txt
339// DiscriminatorTheshold: 3.5
340// DigitalSignalLength: 8
341// CoincidenceTime: 0.5
342//
343Int_t MSimTrigger::ReadEnv(const TEnv &env, TString prefix, Bool_t print)
344{
345 Bool_t rc = kFALSE;
346 if (IsEnvDefined(env, prefix, "FileNameRouteAC", print))
347 {
348 rc = kTRUE;
349 fNameRouteAC = GetEnvValue(env, prefix, "FileNameRouteAC", fNameRouteAC);
350 }
351
352 if (IsEnvDefined(env, prefix, "FileNameCoincidenceMap", print))
353 {
354 rc = kTRUE;
355 fNameCoincidenceMap = GetEnvValue(env, prefix, "FileNameCoincidenceMap", fNameCoincidenceMap);
356 }
357
358 if (IsEnvDefined(env, prefix, "DiscriminatorThreshold", print))
359 {
360 rc = kTRUE;
361 fDiscriminatorThreshold = GetEnvValue(env, prefix, "DiscriminatorThreshold", fDiscriminatorThreshold);
362 }
363
364 if (IsEnvDefined(env, prefix, "DigitalSignalLength", print))
365 {
366 rc = kTRUE;
367 fDigitalSignalLength = GetEnvValue(env, prefix, "DigitalSignalLength", fDigitalSignalLength);
368 }
369
370 if (IsEnvDefined(env, prefix, "CoincidenceTime", print))
371 {
372 rc = kTRUE;
373 fCoincidenceTime = GetEnvValue(env, prefix, "CoincidenceTime", fCoincidenceTime);
374 }
375
376 return rc;
377}
Note: See TracBrowser for help on using the repository browser.