source: trunk/MagicSoft/Mars/mfbase/MFilterList.cc@ 7601

Last change on this file since 7601 was 7601, checked in by tbretz, 19 years ago
*** empty log message ***
File size: 11.9 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 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.ForEach(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// Processes (updates) all filters in the list.
300//
301Int_t MFilterList::Process()
302{
303 TIter Next(&fFilters);
304
305 MFilter *filter=NULL;
306
307 //
308 // loop over all filters
309 //
310 while ((filter=(MFilter*)Next()))
311 if (!filter->CallProcess())
312 return kFALSE;
313
314 return kTRUE;
315}
316
317// --------------------------------------------------------------------------
318//
319// PostProcesses all filters in the list.
320//
321Int_t MFilterList::PostProcess()
322{
323 TIter Next(&fFilters);
324
325 MFilter *filter=NULL;
326
327 //
328 // loop over all filters
329 //
330 while ((filter=(MFilter*)Next()))
331 if (!filter->CallPostProcess())
332 return kFALSE;
333
334 return kTRUE;
335}
336
337// --------------------------------------------------------------------------
338//
339// If you want to use a verbose output ("and") instead of a symbolic ("&")
340// one the option string must conatin a "v"
341//
342void MFilterList::Print(Option_t *opt) const
343{
344 *fLog << all << GetRule(opt) << flush;
345}
346
347// --------------------------------------------------------------------------
348//
349// Implementation of SavePrimitive. Used to write the call to a constructor
350// to a macro. In the original root implementation it is used to write
351// gui elements to a macro-file.
352//
353void MFilterList::StreamPrimitive(ofstream &out) const
354{
355 out << " MFilterList " << ToLower(fName) << "(\"";
356
357 switch (fFilterType)
358 {
359 case kEAnd:
360 out << "&";
361 break;
362
363 case kEOr:
364 out << "|";
365 break;
366
367 case kEXor:
368 out << "^";
369 break;
370
371 case kELAnd:
372 out << "&&";
373 break;
374
375 case kELOr:
376 out << "||";
377 break;
378 }
379
380 out << "\"";
381
382 if (fName!=gsDefName || fTitle!=gsDefTitle)
383 {
384 out << ", \"" << fName << "\"";
385 if (fTitle!=gsDefTitle)
386 out << ", \"" << fTitle << "\"";
387 }
388 out << ");" << endl << endl;
389
390 MIter Next(&fFilters);
391
392 MParContainer *cont = NULL;
393 while ((cont=Next()))
394 {
395 cont->SavePrimitive(out, "");
396
397 out << " " << ToLower(fName) << ".AddToList(&";
398 out << cont->GetUniqueName() << ");" << endl << endl;
399 }
400}
401
402TString MFilterList::GetRule(Option_t *opt) const
403{
404 TString str(opt);
405 const Bool_t verbose = str.Contains("V", TString::kIgnoreCase);
406
407 TString ret = "(";
408
409 TIter Next(&fFilters);
410
411 MFilter *filter=(MFilter*)Next();
412
413 //
414 // loop over all filters
415 //
416 if (!filter)
417 return "<empty>";
418
419 ret += filter->GetRule();
420
421 while ((filter=(MFilter*)Next()))
422 {
423 switch (fFilterType)
424 {
425 case kEAnd:
426 ret += (verbose?" and ":" & ");
427 break;
428
429 case kEOr:
430 ret += (verbose?" or ":" | ");
431 break;
432
433 case kEXor:
434 ret += (verbose?" xor ":" ^ ");
435 break;
436
437 case kELAnd:
438 ret += (verbose?" land ":" && ");
439 break;
440
441 case kELOr:
442 ret += (verbose?" lor ":" || ");
443 break;
444 }
445
446 ret += filter->GetRule();
447 }
448
449 return ret+")";
450}
451
452// --------------------------------------------------------------------------
453//
454// Return the data members existing in this array in a comma-seperated list
455// (This is mainly used for MTask::AddToBranchList)
456//
457TString MFilterList::GetDataMember() const
458{
459 TString str;
460
461 TIter Next(&fFilters);
462 MFilter *filter = NULL;
463 while ((filter=(MFilter*)Next()))
464 {
465 if (filter->GetDataMember().IsNull())
466 continue;
467
468 str += ",";
469 str += filter->GetDataMember();
470 }
471 return str;
472}
473
474// --------------------------------------------------------------------------
475//
476// Loop over all set filters and distribute arr to their SetVariables.
477// Make sure, that the values are unique (not two filters using the
478// same index in the array with different meanings)
479//
480void MFilterList::SetVariables(const TArrayD &arr)
481{
482 fFilters.ForEach(MFilter, SetVariables)(arr);
483}
Note: See TracBrowser for help on using the repository browser.