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

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