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

Last change on this file since 9256 was 9256, checked in by tbretz, 16 years ago
*** empty log message ***
File size: 8.9 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{
82 fName = name ? name : "MSimTrigger";
83 fTitle = title ? title : "Task to simulate trigger electronics";
84}
85
86// --------------------------------------------------------------------------
87//
88// Take two TObjArrays with a collection of digital signals.
89// Every signal from one array is compared with any from the other array.
90// For all signals whihc overlaps and which have an overlap time >gate
91// a new digital signal is created storing start time and length of overlap.
92// They are collected in a newly allocated TObjArray. A pointer to this array
93// is returned.
94//
95// Th euser gains owenership of the object, ie.e., the user is responsible of
96// deleting the memory.
97//
98TObjArray *MSimTrigger::CalcCoincidence(const TObjArray &arr1, const TObjArray &arr2, Float_t gate) const
99{
100 TObjArray *res = new TObjArray;
101
102 if (arr1.GetEntriesFast()==0 || arr2.GetEntriesFast()==0)
103 return res;
104
105 TIter Next1(&arr1);
106 MDigitalSignal *ttl1 = 0;
107 while ((ttl1=static_cast<MDigitalSignal*>(Next1())))
108 {
109 TIter Next2(&arr2);
110 MDigitalSignal *ttl2 = 0;
111 while ((ttl2=static_cast<MDigitalSignal*>(Next2())))
112 {
113 MDigitalSignal *ttl = new MDigitalSignal(*ttl1, *ttl2);
114
115 if (ttl->GetLength()<=gate)
116 {
117 delete ttl;
118 continue;
119 }
120
121 res->Add(ttl);
122 }
123 }
124
125 res->SetOwner();
126
127 return res;
128}
129
130// --------------------------------------------------------------------------
131//
132// Check for the necessary parameter containers. Read the luts.
133//
134Int_t MSimTrigger::PreProcess(MParList *pList)
135{
136 fTrigger = (MParameterD*)pList->FindCreateObj("MParameterD", "TriggerPos");
137 if (!fTrigger)
138 return kFALSE;
139
140 fPulsePos = (MParameterD*)pList->FindObject("IntendedPulsePos", "MParameterD");
141 if (!fPulsePos)
142 {
143 *fLog << err << "IntendedPulsePos [MParameterD] not found... aborting." << endl;
144 return kFALSE;
145 }
146
147 fCamera = (MAnalogChannels*)pList->FindObject("MAnalogChannels");
148 if (!fCamera)
149 {
150 *fLog << err << "MAnalogChannels not found... aborting." << endl;
151 return kFALSE;
152 }
153
154 fRunHeader = (MRawRunHeader*)pList->FindObject("MRawRunHeader");
155 if (!fRunHeader)
156 {
157 *fLog << err << "MRawRunHeader not found... aborting." << endl;
158 return kFALSE;
159 }
160
161 fEvtHeader = (MRawEvtHeader*)pList->FindCreateObj("MRawEvtHeader");
162 if (!fEvtHeader)
163 return kFALSE;
164
165
166 if (fRouteAC.ReadFile(fNameRouteAC)<0)
167 return kFALSE;
168
169 if (fCoincidenceMap.ReadFile(fNameCoincidenceMap)<0)
170 return kFALSE;
171
172 return kTRUE;
173}
174
175// --------------------------------------------------------------------------
176//
177Int_t MSimTrigger::Process()
178{
179 // Invalidate trigger
180 fTrigger->SetVal(-1);
181
182 // FIXME: Set from somewhere else? (see also MSimCalibrationSignal)
183 fEvtHeader->SetDAQEvtNumber(GetNumExecutions());
184 fEvtHeader->SetReadyToSave();
185
186 // ================== Simulate channel bundling ====================
187
188 const UInt_t npatch = fRouteAC.GetEntriesFast();
189
190 MAnalogChannels patches(npatch, fCamera->GetNumSamples());
191
192 for (UInt_t i=0; i<npatch; i++)
193 {
194 const MArrayI &row = fRouteAC.GetRow(i);
195 for (UInt_t j=0; j<row.GetSize(); j++)
196 {
197 const UInt_t idx = row[j];
198 patches[i].AddSignal((*fCamera)[idx]);
199 }
200 }
201
202 // FIXME: Write patches
203
204 // ================== Simulate discriminators ====================
205
206 TObjArray ttls(npatch);
207 ttls.SetOwner();
208
209 // MAGIC: Constant length of signals between 6ns and 12ns
210 const Double_t siglen = 8; // Signal length (-1: As long as Signal-above-Threshold)
211
212 for (UInt_t i=0; i<npatch; i++)
213 ttls.AddAt(patches[i].Discriminate(fDiscriminatorThreshold, siglen), i);
214
215 // FIXME: Write TTLs!
216
217 // =================== Simulate coincidences ======================
218
219 // Calculate the minimum and maximum time for a valid trigger
220 const Double_t freq = fRunHeader->GetFreqSampling()/1000.;
221 const Float_t nsamp = fRunHeader->GetNumSamplesHiGain();
222 const Float_t pulspos = fPulsePos->GetVal()/freq;
223
224 const Float_t min = fCamera->GetValidRangeMin()+pulspos;
225 const Float_t max = fCamera->GetValidRangeMax()+pulspos-nsamp;
226
227 // Define gate time (minimum coincidence time)
228 const Double_t gate = 1; // MAGIC: minimum coincidence time 0.25ns to 1ns,
229
230 // Create an array for the individual triggers
231 TObjArray triggers;
232 triggers.SetOwner();
233
234 for (int j=0; j<fCoincidenceMap.GetEntries(); j++)
235 {
236 const MArrayI &idx = fCoincidenceMap.GetRow(j);
237
238 // Start with a copy of the first coincidence channel
239 TObjArray *arr = static_cast<TObjArray*>(ttls[idx[0]]->Clone());
240 arr->SetOwner();
241
242 // compare to all other channels in this coincidence patch, one by one
243 for (UInt_t k=1; k<idx.GetSize() && arr->GetEntriesFast()>0; k++)
244 {
245 TObjArray *res = CalcCoincidence(*arr, *static_cast<TObjArray*>(ttls[idx[k]]),
246 gate);
247
248 // Delete the original array and keep the new one
249 delete arr;
250 arr = res;
251 }
252
253 // Remove all signals which are not in the valid digitization range
254 // (This is not the digitization window, but the region in which
255 // the analog channels contain usefull data)
256 TIter Next(arr);
257 MDigitalSignal *ttl = 0;
258 while ((ttl=static_cast<MDigitalSignal*>(Next())))
259 if (ttl->GetStart()<min || ttl->GetStart()>max)
260 delete arr->Remove(ttl);
261
262 // If we have at least one trigger keep the earliest one.
263 // FIXME: The triggers should be ordered in time automatically: To be checked!
264 // FIXME: Simulate trigger dead-time!
265 if (arr->GetEntriesFast()>0)
266 triggers.Add(arr->RemoveAt(0));
267
268 // delete the allocated space
269 delete arr;
270 }
271
272 // No trigger issued. Go on.
273 if (triggers.GetEntriesFast()==0)
274 return kTRUE;
275
276 // There are usually not enough entries that it is worth to search
277 // for the earliest instead of just sorting and taking the first one
278 // FIXME: This could be improved if checking for IsSortable
279 // is omitted
280 triggers.Sort();
281
282 // FIXME: Jitter! (Own class?)
283 fTrigger->SetVal(static_cast<MDigitalSignal*>(triggers[0])->GetStart());
284
285
286 // inf2?
287 *fLog << all << triggers.GetEntriesFast() << " triggers in " << triggers.GetEntriesFast() << " patches." << endl;
288
289 return kTRUE;
290}
Note: See TracBrowser for help on using the repository browser.