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

Last change on this file since 7601 was 7601, checked in by tbretz, 15 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.