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

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