source: trunk/Mars/mfbase/MFilterList.cc

Last change on this file was 7810, checked in by tbretz, 18 years ago
*** empty log message ***
File size: 12.5 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): Thomas Bretz, 07/2001 <mailto:tbretz@astro.uni-wuerzburg.de>
19!
20! Copyright: MAGIC Software Development, 2000-2003
21!
22!
23\* ======================================================================== */
24
25/////////////////////////////////////////////////////////////////////////////
26//
27// MFilterList
28//
29// A filter list can be used to concatenate filter (derived from MFilter)
30// by a logical or bitwise operator. For more details see the constructor.
31//
32// The list is setup by adding filters to the list calling AddToList().
33// For example in the case of the default constructor ("&&") all results
34// are logically and'd together and the result of this and is returned.
35//
36// Because the meaning of all filters can be inverted calling SetInverted()
37// which is defined in the base class MFilter you can use this list to
38// invert the meaning of a filter, by eg:
39//
40// MF anyfilter("MHillas.fAlpha");
41//
42// MFilterList alist;
43// alist.AddToList(&anyfilter);
44//
45// alist.SetInverted();
46//
47// or do
48//
49// MFilterList alist(&anyfilter);
50//
51//
52// Adding the filterlist to the eventloop will process all contained filters.
53// Doing this as early as possible is a simple way of processing all filters.
54//
55// If you want to make the list delete all contained filters you may make
56// the list owner of the filters by calling SetOwner()
57//
58/////////////////////////////////////////////////////////////////////////////
59#include "MFilterList.h"
60
61#include <fstream>
62
63#include <TString.h>
64
65#include "MLog.h"
66#include "MLogManip.h"
67
68#include "MIter.h"
69
70ClassImp(MFilterList);
71
72using namespace std;
73
74static const TString gsDefName = "MFilterList";
75static const TString gsDefTitle = "List combining filters logically.";
76
77// --------------------------------------------------------------------------
78//
79// Wrapper to simplify constructors.
80//
81void MFilterList::Init(const char *name, const char *title)
82{
83 fName = name ? name : gsDefName.Data();
84 fTitle = title ? title : gsDefTitle.Data();
85
86 gROOT->GetListOfCleanups()->Add(&fFilters);
87 fFilters.SetBit(kMustCleanup);
88
89 fFilterType = kEAnd;
90}
91
92// --------------------------------------------------------------------------
93//
94// Default Constructor.
95//
96// Specify the boolean operation which is used to evaluate the
97// result of this list. If no operation is specified "land" is
98// used.
99//
100// Options:
101// and, & : is a bitwise and
102// or, | : is a bitwise or
103// xor, ^ : is a bitwise exclusive or
104// land, && : is a logical and
105// lor, || : is a logical or
106//
107// The bitwise operators are implemented for convinience. They may not
108// make much sense. Maybe IsExpressionTrue should change its return
109// type from Bool_t to Int_t.
110//
111MFilterList::MFilterList(const char *type, const char *name, const char *title)
112{
113 Init(name, title);
114
115 TString str(type);
116
117 if (!str.CompareTo("OR", TString::kIgnoreCase) || !str.CompareTo("|"))
118 fFilterType = kEOr;
119 if (!str.CompareTo("XOR", TString::kIgnoreCase) || !str.CompareTo("^"))
120 fFilterType = kEXor;
121 if (!str.CompareTo("LAND", TString::kIgnoreCase) || !str.CompareTo("&&"))
122 fFilterType = kELAnd;
123 if (!str.CompareTo("LOR", TString::kIgnoreCase) || !str.CompareTo("||"))
124 fFilterType = kELOr;
125}
126
127// --------------------------------------------------------------------------
128//
129// Constructor.
130//
131// Setup an '&&' filter list, adds the filter to the list and
132// call MFilterList::SetInverted()
133//
134// To be used as a logical NOT.
135//
136MFilterList::MFilterList(MFilter *f, const char *name, const char *title)
137{
138 Init(name, title);
139
140 SetInverted();
141 AddToList(f);
142}
143
144// --------------------------------------------------------------------------
145//
146// CopyConstructor
147//
148MFilterList::MFilterList(MFilterList &ts)
149{
150 fFilters.AddAll(&ts.fFilters);
151 fFilterType = ts.fFilterType;
152}
153
154// --------------------------------------------------------------------------
155//
156// Evaluates and returns the result of the filter list.
157// The expression is evaluated step by step, eg:
158// ((filter[0] # filter[1]) # filter[3]) # filter[4])
159// The '#' stands for the boolean operation which is specified in
160// the constructor.
161//
162Bool_t MFilterList::IsExpressionTrue() const
163{
164 TIter Next(&fFilters);
165
166 MFilter *filter=(MFilter*)Next();
167
168 if (!filter)
169 return kTRUE;
170
171 Bool_t rc = filter->IsConditionTrue();
172
173 //
174 // loop over all filters
175 //
176 switch (fFilterType)
177 {
178 case kEAnd:
179 while ((filter=(MFilter*)Next()))
180 rc &= filter->IsConditionTrue();
181 break;
182
183 case kEOr:
184 while ((filter=(MFilter*)Next()))
185 rc |= filter->IsConditionTrue();
186 break;
187
188 case kEXor:
189 while ((filter=(MFilter*)Next()))
190 rc ^= filter->IsConditionTrue();
191 break;
192
193 case kELAnd:
194 while ((filter=(MFilter*)Next()))
195 rc = (rc && filter->IsConditionTrue());
196 break;
197
198 case kELOr:
199 while ((filter=(MFilter*)Next()))
200 rc = (rc || filter->IsConditionTrue());
201 break;
202 }
203 return rc;
204}
205
206// --------------------------------------------------------------------------
207//
208// If you want to add a new filter to the list call this function with the
209// pointer to the filter to be added.
210//
211Bool_t MFilterList::AddToList(MFilter *filter)
212{
213 if (!filter)
214 return kTRUE;
215
216 const char *name = filter->GetName();
217
218 if (fFilters.FindObject(filter))
219 {
220 *fLog << warn << dbginf << "Filter " << filter << " already existing... skipped." << endl;
221 return kTRUE;
222 }
223
224 if (fFilters.FindObject(name))
225 *fLog << inf << "MFilterList::AddToList - '" << name << "' exists in List already..." << endl;
226
227 *fLog << inf << "Adding " << name << " to " << GetName() << "... " << flush;
228
229 filter->SetBit(kMustCleanup);
230 fFilters.Add(filter);
231
232 *fLog << "Done." << endl;
233
234 AddToBranchList(filter->GetDataMember());
235
236 return kTRUE;
237}
238
239// --------------------------------------------------------------------------
240//
241// If you want to add a new filters from a TCollection to the list call
242// this function.
243//
244Bool_t MFilterList::AddToList(const TCollection &col)
245{
246 TIter Next(&col);
247 MFilter *f=0;
248 Int_t idx=0;
249 while ((f=(MFilter*)Next()))
250 {
251 if (!f->InheritsFrom(MFilter::Class()))
252 {
253 *fLog << warn << "WARNING - An object in TCollection doesn't inherit from MFilter... ignored." << endl;
254 continue;
255 }
256
257 f->SetName(Form("F%d", idx++));
258 if (!AddToList(f))
259 return kFALSE;
260 }
261 return kTRUE;
262}
263
264void MFilterList::SetAccelerator(Byte_t acc)
265{
266 fFilters.R__FOR_EACH(MTask, SetAccelerator)(acc);
267 MFilter::SetAccelerator(acc);
268}
269
270// --------------------------------------------------------------------------
271//
272// PreProcesses all filters in the list
273//
274Int_t MFilterList::PreProcess(MParList *pList)
275{
276 TIter Next(&fFilters);
277
278 MFilter *filter=NULL;
279
280 //
281 // loop over all filters
282 //
283 while ((filter=(MFilter*)Next()))
284 {
285 filter->SetAccelerator(GetAccelerator());
286 if (!filter->CallPreProcess(pList))
287 {
288 *fLog << err << "Error - Preprocessing Filter ";
289 *fLog << filter->GetName() << " in " << fName << endl;
290 return kFALSE;
291 }
292 }
293
294 return kTRUE;
295}
296
297// --------------------------------------------------------------------------
298//
299// ReInit all filters in the list
300//
301Bool_t MFilterList::ReInit(MParList *pList)
302{
303 TIter Next(&fFilters);
304
305 MFilter *filter=NULL;
306
307 //
308 // loop over all filters
309 //
310 while ((filter=(MFilter*)Next()))
311 {
312 if (!filter->ReInit(pList))
313 {
314 *fLog << err << "Error - ReInit Filter ";
315 *fLog << filter->GetName() << " in " << fName << endl;
316 return kFALSE;
317 }
318 }
319
320 return kTRUE;
321}
322
323// --------------------------------------------------------------------------
324//
325// Processes (updates) all filters in the list.
326//
327Int_t MFilterList::Process()
328{
329 TIter Next(&fFilters);
330
331 MFilter *filter=NULL;
332
333 //
334 // loop over all filters
335 //
336 while ((filter=(MFilter*)Next()))
337 if (!filter->CallProcess())
338 return kFALSE;
339
340 return kTRUE;
341}
342
343// --------------------------------------------------------------------------
344//
345// PostProcesses all filters in the list.
346//
347Int_t MFilterList::PostProcess()
348{
349 TIter Next(&fFilters);
350
351 MFilter *filter=NULL;
352
353 //
354 // loop over all filters
355 //
356 while ((filter=(MFilter*)Next()))
357 if (!filter->CallPostProcess())
358 return kFALSE;
359
360 return kTRUE;
361}
362
363// --------------------------------------------------------------------------
364//
365// If you want to use a verbose output ("and") instead of a symbolic ("&")
366// one the option string must conatin a "v"
367//
368void MFilterList::Print(Option_t *opt) const
369{
370 *fLog << all << GetRule(opt) << flush;
371}
372
373// --------------------------------------------------------------------------
374//
375// Implementation of SavePrimitive. Used to write the call to a constructor
376// to a macro. In the original root implementation it is used to write
377// gui elements to a macro-file.
378//
379void MFilterList::StreamPrimitive(ostream &out) const
380{
381 out << " MFilterList " << ToLower(fName) << "(\"";
382
383 switch (fFilterType)
384 {
385 case kEAnd:
386 out << "&";
387 break;
388
389 case kEOr:
390 out << "|";
391 break;
392
393 case kEXor:
394 out << "^";
395 break;
396
397 case kELAnd:
398 out << "&&";
399 break;
400
401 case kELOr:
402 out << "||";
403 break;
404 }
405
406 out << "\"";
407
408 if (fName!=gsDefName || fTitle!=gsDefTitle)
409 {
410 out << ", \"" << fName << "\"";
411 if (fTitle!=gsDefTitle)
412 out << ", \"" << fTitle << "\"";
413 }
414 out << ");" << endl << endl;
415
416 MIter Next(&fFilters);
417
418 MParContainer *cont = NULL;
419 while ((cont=Next()))
420 {
421 cont->SavePrimitive(out, "");
422
423 out << " " << ToLower(fName) << ".AddToList(&";
424 out << cont->GetUniqueName() << ");" << endl << endl;
425 }
426}
427
428TString MFilterList::GetRule(Option_t *opt) const
429{
430 TString str(opt);
431 const Bool_t verbose = str.Contains("V", TString::kIgnoreCase);
432
433 TString ret = "(";
434
435 TIter Next(&fFilters);
436
437 MFilter *filter=(MFilter*)Next();
438
439 //
440 // loop over all filters
441 //
442 if (!filter)
443 return "<empty>";
444
445 ret += filter->GetRule();
446
447 while ((filter=(MFilter*)Next()))
448 {
449 switch (fFilterType)
450 {
451 case kEAnd:
452 ret += (verbose?" and ":" & ");
453 break;
454
455 case kEOr:
456 ret += (verbose?" or ":" | ");
457 break;
458
459 case kEXor:
460 ret += (verbose?" xor ":" ^ ");
461 break;
462
463 case kELAnd:
464 ret += (verbose?" land ":" && ");
465 break;
466
467 case kELOr:
468 ret += (verbose?" lor ":" || ");
469 break;
470 }
471
472 ret += filter->GetRule();
473 }
474
475 return ret+")";
476}
477
478// --------------------------------------------------------------------------
479//
480// Return the data members existing in this array in a comma-seperated list
481// (This is mainly used for MTask::AddToBranchList)
482//
483TString MFilterList::GetDataMember() const
484{
485 TString str;
486
487 TIter Next(&fFilters);
488 MFilter *filter = NULL;
489 while ((filter=(MFilter*)Next()))
490 {
491 if (filter->GetDataMember().IsNull())
492 continue;
493
494 str += ",";
495 str += filter->GetDataMember();
496 }
497 return str;
498}
499
500// --------------------------------------------------------------------------
501//
502// Loop over all set filters and distribute arr to their SetVariables.
503// Make sure, that the values are unique (not two filters using the
504// same index in the array with different meanings)
505//
506void MFilterList::SetVariables(const TArrayD &arr)
507{
508 fFilters.R__FOR_EACH(MFilter, SetVariables)(arr);
509}
Note: See TracBrowser for help on using the repository browser.