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

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