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

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