source: trunk/MagicSoft/Mars/mfilter/MFSoftwareTrigger.cc@ 9620

Last change on this file since 9620 was 9518, checked in by tbretz, 15 years ago
*** empty log message ***
File size: 13.7 KB
Line 
1/* ======================================================================== *\
2!
3! *
4! * This file is part of MARS, the MAGIC 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 appear 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): Wolfgang Wittek, 04/2003 <mailto:wittek@mppmu.mpg.de>
19! Author(s): Thomas Bretz, 04/2003 <mailto:tbretz@astro.uni-wuerzburg.de>
20!
21! Copyright: MAGIC Software Development, 2000-2005
22!
23!
24\* ======================================================================== */
25
26/////////////////////////////////////////////////////////////////////////////
27//
28// MFSoftwareTrigger
29//
30// This is a class to evaluate a software trigger
31//
32// The number of required pixels is setup by:
33// SetNumNeighbors(4) // default
34//
35// The Threshold is setup by:
36// SetThreshold(5) // default
37//
38// Time window for coincidence:
39// SetTimeWindow(3.3)
40// To switch off time-coincidence use
41// SetTimeWindow(-1)
42// or
43// SetTimeWindow()
44//
45// kSinglePixelsNeighbors <default>
46// ----------------------
47// Checks whether there is at least one pixel above threshold which
48// has fNumNeighbors direct neighbors which are also above threshold.
49// The outermost ring of pixels is ignord. Only 'used' pixels are
50// taken into account.
51//
52// kAnyPattern
53// -----------
54// Checks whether it find a cluster of pixels above fThreshold which
55// has a size bigger/equal than fNumNeighbors. The layout (pattern) of
56// the cluster is ignored. Unmapped pixels are ignored.
57//
58// WARNING: Using trigger type kAllPattern resets the BIT(21) bit
59// of all pixels in MSignalCam
60//
61//
62// Input:
63// MSignalCam
64// MGeomCam
65//
66/////////////////////////////////////////////////////////////////////////////
67#include "MFSoftwareTrigger.h"
68
69#include "MLog.h"
70#include "MLogManip.h"
71
72#include "MParList.h"
73
74#include "MGeom.h"
75#include "MGeomCam.h"
76
77#include "MSignalCam.h"
78//#include "MArrivalTime.h"
79
80ClassImp(MFSoftwareTrigger);
81
82using namespace std;
83
84// --------------------------------------------------------------------------
85//
86// Default constructor.
87//
88MFSoftwareTrigger::MFSoftwareTrigger(const char *name, const char *title)
89 : fCam(NULL), fEvt(NULL), fThreshold(5),
90 fTimeWindow(1.7), fNumNeighbors(4), fType(kSinglePixelNeighbors)
91{
92 fName = name ? name : "MFSoftwareTrigger";
93 fTitle = title ? title : "Filter for software trigger";
94}
95
96// --------------------------------------------------------------------------
97//
98// This function recursively finds all pixels of one island and sets
99// BIT(14) for the pixel.
100//
101// 1) Check whether a pixel with the index idx exists, is unused
102// and has not yet BIT(14) set
103// 2) Set BIT(14) to the pixel
104// 3) Loop over all its neighbors taken from the geometry geom. For all
105// neighbors recursively call this function (CountPixels)
106// 4) Sum the number of valid neighbors newly found
107//
108// Returns the size of the cluster
109//
110Int_t MFSoftwareTrigger::CountPixels(Int_t idx, Float_t tm0) const
111{
112 // get the pixel information of a pixel with this index
113 MSignalPix &pix = (*fEvt)[idx];
114
115 // If pixel already assigned to a cluster
116 if (pix.TestBit(kWasChecked))
117 return 0;
118
119 if (pix.IsPixelUnmapped())
120 return 0;
121
122 // Assign the new island number num to this used pixel
123 pix.SetBit(kWasChecked);
124
125 // Get the size of this pixel and check threshold
126 const Double_t size = pix.GetNumPhotons()*fCam->GetPixRatio(idx);
127 if (size<fThreshold)
128 return 0;
129
130 const Float_t tm1 = pix.GetArrivalTime();
131 if (TMath::Abs(tm1-tm0)>fTimeWindow)
132 return 0;
133
134 //pix.SetBit(kAboveThreshold);
135
136 Int_t num = 1;
137
138 // Get the geometry information (neighbors) of this pixel
139 const MGeom &gpix = (*fCam)[idx];
140
141 // Now do the same with all its neighbors and sum the
142 // sizes which they correspond to
143 const Int_t n = gpix.GetNumNeighbors();
144 for (int i=0; i<n; i++)
145 num += CountPixels(gpix.GetNeighbor(i), tm1);
146
147 // return size of this (sub)cluster
148 return num;
149}
150/*
151Int_t MFSoftwareTrigger::CountCoincidencePixels(Int_t idx) const
152{
153 // Try to get the pixel information of a pixel with this index
154 MSignalPix *pix = fEvt->GetPixById(idx);
155
156 // If a pixel with this index is not existing... do nothing.
157 if (!pix)
158 return 0;
159
160 // If pixel already assigned to a cluster
161 if (pix->TestBit(kWasChecked))
162 return 0;
163
164 if (pix->IsPixelUnmapped())
165 return 0;
166
167 // Assign the new island number num to this used pixel
168 pix->SetBit(kWasChecked);
169
170 // Get the size of this pixel and check threshold
171 const Double_t size = pix->GetNumPhotons();
172 if (size<fThreshold)
173 return 0;
174
175 Int_t num = 1;
176
177 // Get the geometry information (neighbors) of this pixel
178 const MGeomPix &gpix = (*fCam)[idx];
179
180 // Now do the same with all its neighbors and sum the
181 // sizes which they correspond to
182 const Int_t n = gpix.GetNumNeighbors();
183 for (int i=0; i<n; i++)
184 num += CountPixels(gpix.GetNeighbor(i));
185
186 // return size of this (sub)cluster
187 return num;
188}
189*/
190void MFSoftwareTrigger::ResetBits(Int_t bits) const
191{
192 TObject *obj=0;
193
194 TIter Next(*fEvt);
195 while ((obj=Next()))
196 obj->ResetBit(bits);
197}
198
199// --------------------------------------------------------------------------
200//
201// Check if there is at least one pixel which fullfills the condition
202//
203Bool_t MFSoftwareTrigger::ClusterTrigger() const
204{
205 ResetBits(kWasChecked);
206
207 const UInt_t npixevt = fEvt->GetNumPixels();
208 for (UInt_t idx=0; idx<npixevt; idx++)
209 {
210 const MSignalPix &pix = (*fEvt)[idx];
211 if (!pix.IsPixelUsed())
212 continue;
213
214 // Check if trigger condition is fullfilled for this pixel
215 if (CountPixels(idx, pix.GetArrivalTime()) >= fNumNeighbors)
216 return kTRUE;
217 }
218
219/*
220 // Reset bit
221 MSignalPix *pix=0;
222
223 // We could loop over all indices which looks more straight
224 // forward but should be a lot slower (assuming zero supression)
225 TIter Next(*fEvt);
226 while ((pix=static_cast<MSignalPix*>(Next())))
227 {
228 // Check if trigger condition is fullfilled for this pixel
229 const Int_t idx = pix->GetPixId();
230 if (CountPixels(idx, (*fTme)[idx]) >= fNumNeighbors)
231 return kTRUE;
232 }
233 */
234 return kFALSE;
235}
236/*
237Int_t MFSoftwareTrigger::CheckCoincidence(Int_t idx, Float_t tm0) const
238{
239 // Try to get the pixel information of a pixel with this index
240 MSignalPix *pix = fEvt->GetPixById(idx);
241
242 // If a pixel with this index is not existing... do nothing.
243 if (!pix)
244 return 0;
245
246 // If pixel already assigned to a cluster
247 if (pix->TestBit(kWasChecked))
248 return 0;
249
250 if (pix->IsPixelUnmapped())
251 return 0;
252
253 // Assign the new island number num to this used pixel
254 pix->SetBit(kWasChecked);
255
256 const Double_t size = pix->GetNumPhotons();
257 if (size<fThreshold)
258 return 0;
259
260 const Float_t tm1 = (*fTme)[idx];
261 if (TMath::Abs(tm1-tm0)>fTimeWindow)
262 return 0;
263
264 pix->SetBit(kIsCoincident);
265
266
267 Int_t num = 1;
268
269 // Get the geometry information (neighbors) of this pixel
270 const MGeomPix &gpix = (*fCam)[idx];
271
272 Int_t cnt = 0;
273
274 // Now do the same with all its neighbors and sum the
275 // sizes which they correspond to
276 const Int_t n = gpix.GetNumNeighbors();
277 for (int i=0; i<n; i++)
278 {
279 const Int_t rc = CheckCoincidence(gpix.GetNeighbor(i), tm0);
280 if (fEvt->GetPixById(gpix.GetNeighbor(i))->TestBit(kIsCoincident))
281 cnt++;
282 num += rc;
283 }
284
285 // return size of this (sub)cluster
286 return cnt<2 ? 0 : num;
287
288}
289
290Bool_t MFSoftwareTrigger::MagicLvl1Trigger() const
291{
292 // Reset bit
293 MSignalPix *pix=0;
294
295 // We could loop over all indices which looks more straight
296 // forward but should be a lot slower (assuming zero supression)
297 TIter Next(*fEvt);
298 while ((pix=static_cast<MSignalPix*>(Next())))
299 {
300 ResetBits(kWasChecked|kIsCoincident);
301
302 const Int_t idx = pix->GetPixId();
303 if (CheckCoincidence(idx, (*fTme)[idx])<fNumNeighbors)
304 continue;
305
306 return kTRUE;
307 }
308 return kFALSE;
309}
310*/
311
312const MSignalPix *MFSoftwareTrigger::CheckPixel(Int_t i) const
313{
314 const MSignalPix &pix = (*fEvt)[i];
315
316 if (!pix.IsPixelUsed())
317 return NULL;
318
319 if (pix.GetNumPhotons()*fCam->GetPixRatio(i)<fThreshold)
320 return NULL;
321
322 if ((*fCam)[i].IsInOutermostRing())
323 return NULL;
324
325 return &pix;
326}
327
328// --------------------------------------------------------------------------
329//
330// Software single pixel coincidence trigger
331//
332Bool_t MFSoftwareTrigger::SwTrigger() const
333{
334 const Int_t entries = fEvt->GetNumPixels();
335
336 for (Int_t i=0; i<entries; i++)
337 {
338 const MSignalPix *pix0 = CheckPixel(i);
339 if (!pix0)
340 continue;
341
342 Int_t num = 1;
343
344 const MGeom &gpix = (*fCam)[i];
345
346 const Int_t nneighbors = gpix.GetNumNeighbors();
347 for (Int_t n=0; n<nneighbors; n++)
348 {
349 const Int_t idx1 = gpix.GetNeighbor(n);
350
351 const MSignalPix *pix1 = CheckPixel(idx1);
352 if (!pix1)
353 continue;
354
355 const Float_t t0 = pix0->GetArrivalTime();
356 const Float_t t1 = pix1->GetArrivalTime();
357
358 if (TMath::Abs(t0-t1)>fTimeWindow)
359 continue;
360
361 if (++num==fNumNeighbors)
362 return kTRUE;
363 }
364 }
365 return kFALSE;
366}
367
368// --------------------------------------------------------------------------
369//
370// Request pointer to MSignalCam and MGeomCam from paremeter list
371//
372Int_t MFSoftwareTrigger::PreProcess(MParList *pList)
373{
374 fEvt = (MSignalCam*)pList->FindObject("MSignalCam");
375 if (!fEvt)
376 {
377 *fLog << err << "MSignalCam not found... aborting." << endl;
378 return kFALSE;
379 }
380
381 fCam = (MGeomCam*)pList->FindObject("MGeomCam");
382 if (!fCam)
383 {
384 *fLog << err << "MGeomCam not found... aborting." << endl;
385 return kFALSE;
386 }
387
388 memset(fCut, 0, sizeof(fCut));
389
390 switch (fType)
391 {
392 case kSinglePixelNeighbors:
393 if (fNumNeighbors<2)
394 *fLog << inf << "Software trigger switched off (fNumNeighbors<2)." << endl;
395 else
396 *fLog << inf << fNumNeighbors << " required above " << fThreshold << " within " << fTimeWindow << "ns." << endl;
397 break;
398 case kAnyPattern:
399 *fLog << inf << "Cluster trigger switched on." << endl;
400 break;
401 }
402
403 return kTRUE;
404}
405
406// --------------------------------------------------------------------------
407//
408// Evaluate software trigger
409//
410Int_t MFSoftwareTrigger::Process()
411{
412 switch (fType)
413 {
414 case kSinglePixelNeighbors:
415 fResult = fNumNeighbors>1 ? SwTrigger() : kTRUE;
416 break;
417 case kAnyPattern:
418 fResult = ClusterTrigger();
419 break;
420 }
421
422 fCut[fResult ? 0 : 1]++;
423 return kTRUE;
424}
425
426// --------------------------------------------------------------------------
427//
428// Prints some statistics about the Basic selections.
429//
430Int_t MFSoftwareTrigger::PostProcess()
431{
432 if (GetNumExecutions()==0)
433 return kTRUE;
434
435 TString type;
436 switch (fType)
437 {
438 case kSinglePixelNeighbors:
439 type = " single pixel trigger";
440 break;
441 case kAnyPattern:
442 type = " any pattern trigger";
443 break;
444 }
445
446 *fLog << inf << endl;
447 *fLog << GetDescriptor() << " execution statistics:" << endl;
448 *fLog << " Threshold=" << fThreshold << ", Number=" << (int)fNumNeighbors;
449 if (fTimeWindow>0)
450 *fLog << ", Time Window=" << fTimeWindow << "ns";
451 *fLog << endl;
452 *fLog << dec << setfill(' ');
453
454 *fLog << " " << setw(7) << fCut[0] << " (" << setw(3) ;
455 *fLog << (int)(fCut[0]*100/GetNumExecutions());
456 *fLog << "%) Evts fullfilled" << type << endl;
457 *fLog << " " << setw(7) << fCut[1] << " (" << setw(3) ;
458 *fLog << (int)(fCut[1]*100/GetNumExecutions());
459 *fLog << "%) Evts didn't fullfill" << type << "." << endl;
460
461 return kTRUE;
462}
463
464// --------------------------------------------------------------------------
465//
466// Read the setup from a TEnv, eg:
467// MFSoftwareTrigger.Threshold: 5
468// MFSoftwareTrigger.NumNeighbors: 4
469// MFSoftwareTrigger.TimeWindow: 3.3
470// MFSoftwareTrigger.TriggerType: SinglePixel, AnyPattern
471//
472// To switch off time-coincidence use
473// MFSoftwareTrigger.TimeWindow: -1
474//
475Int_t MFSoftwareTrigger::ReadEnv(const TEnv &env, TString prefix, Bool_t print)
476{
477 Bool_t rc = kFALSE;
478 if (IsEnvDefined(env, prefix, "Threshold", print))
479 {
480 rc = kTRUE;
481 SetThreshold(GetEnvValue(env, prefix, "Threshold", fThreshold));
482 }
483 if (IsEnvDefined(env, prefix, "NumNeighbors", print))
484 {
485 rc = kTRUE;
486 SetNumNeighbors(GetEnvValue(env, prefix, "NumNeighbors", fNumNeighbors));
487 }
488 if (IsEnvDefined(env, prefix, "TimeWindow", print))
489 {
490 rc = kTRUE;
491 SetTimeWindow(GetEnvValue(env, prefix, "TimeWindow", fTimeWindow));
492 }
493
494 if (IsEnvDefined(env, prefix, "TriggerType", print))
495 {
496 TString dat = GetEnvValue(env, prefix, "TriggerType", "");
497 dat = dat.Strip(TString::kBoth);
498 dat.ToLower();
499
500 if (dat == (TString)"singlepixel")
501 SetTriggerType(kSinglePixelNeighbors);
502 if (dat == (TString)"anypattern")
503 SetTriggerType(kAnyPattern);
504
505 rc = kTRUE;
506 }
507
508 return rc;
509}
Note: See TracBrowser for help on using the repository browser.