source: trunk/Mars/mfbase/MFDataPhrase.cc@ 10166

Last change on this file since 10166 was 8709, checked in by tbretz, 17 years ago
*** empty log message ***
File size: 9.7 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 01/2002 <mailto:tbretz@astro.uni-wuerzburg.de>
19!
20! Copyright: MAGIC Software Development, 2000-2007
21!
22!
23\* ======================================================================== */
24
25/////////////////////////////////////////////////////////////////////////////
26//
27// MF
28//
29// With this filter you can filter in all variables from Mars parameter
30// containers.
31//
32// In the constructor you can give the filter rule, like
33// "MHillas.fLength < 15"
34// Where MHillas is the name of the parameter container in the parameter
35// list and fLength is the name of the data member which should be used
36// for the filter rule. If the name of the container is use specified
37// (MyHillas) the name to give would be:
38// "MyHillas.fLength < 15"
39//
40// Also more difficult rules are allowed, like:
41// "MHillas.fWidth<0.5 && MHillas.fLength<0.6"
42//
43// You can also use parantheses:
44// "MHillas.fSize>200 || (MHillas.fWidth<0.5 && MHillas.fLength<0.6)"
45//
46// For more details on available functions and expressions see MDataChain!
47//
48// The allowed logigal conditionals are:
49// &&: logical and
50// ||: logical or
51// ^: exclusive or
52//
53// As conditional signs, for now, only:
54// <, >
55// are allowed.
56//
57//
58// Warning: There is no priority rule build in. So better use parantheses
59// to get correct results. The rule is parsed/evaluated from the left
60// to the right, which means:
61//
62// "MHillas.fSize>200 || MHillas.fWidth<0.5 && MHillas.fLength<0.6"
63//
64// is parses as
65//
66// "(MHillas.fSize>200 || MHillas.fWidth<0.5) && MHillas.fLength<0.6"
67//
68//
69// FIXME: The possibility to use also complete filters is missing.
70// Maybe we can use gInterpreter->Calc("") for this.
71// gROOT->ProcessLineFast("line");
72//
73//
74// Class Version 2:
75// ----------------
76// + Bool_t fDefault
77//
78/////////////////////////////////////////////////////////////////////////////
79#include "MFDataPhrase.h"
80
81#include <fstream> // ofstream, ...
82
83#include <TMethodCall.h>
84
85#include "MParList.h"
86
87#include "MDataPhrase.h"
88
89#include "MLog.h"
90#include "MLogManip.h"
91
92ClassImp(MFDataPhrase);
93
94using namespace std;
95
96const TString MFDataPhrase::gsDefName = "MFDataPhrase";
97const TString MFDataPhrase::gsDefTitle = "Filter setup by a text-rule";
98
99// --------------------------------------------------------------------------
100//
101// Default Constructor. Don't use.
102//
103MFDataPhrase::MFDataPhrase()
104 : fData(NULL), fAllowEmpty(kFALSE), fDefault(kTRUE)
105{
106 fName = gsDefName.Data();
107 fTitle = gsDefTitle.Data();
108}
109
110// --------------------------------------------------------------------------
111//
112// Constructor. For the text describing the filter rule please see
113// the class description above.
114//
115MFDataPhrase::MFDataPhrase(const char *text, const char *name, const char *title)
116 : fData(NULL), fAllowEmpty(kFALSE), fDefault(kTRUE)
117{
118 fName = name ? name : gsDefName.Data();
119 fTitle = title ? title : gsDefTitle.Data();
120
121 if (!text)
122 return;
123
124 *fLog << inf << "Parsing filter rule... " << flush;
125 fData=new MDataPhrase(text);
126 *fLog << inf << "found: ";
127 fData->Print();
128 *fLog << endl;
129}
130
131// --------------------------------------------------------------------------
132//
133// Destructor. Delete filters.
134//
135MFDataPhrase::~MFDataPhrase()
136{
137 if (fData)
138 delete fData;
139}
140
141// --------------------------------------------------------------------------
142//
143// PreProcess all filters.
144//
145Int_t MFDataPhrase::PreProcess(MParList *plist)
146{
147 if (!fData)
148 {
149 if (IsAllowEmpty())
150 return kTRUE;
151
152 *fLog << err << dbginf << "No filter rule available." << endl;
153 return kFALSE;
154 }
155
156// fData->SetAccelerator(GetAccelerator());
157
158 if (!fData->PreProcess(plist))
159 {
160 *fLog << err << dbginf << "PreProcessing filters in ";
161 *fLog << fName << " failed." << endl;
162 return kFALSE;
163 }
164
165 return kTRUE;
166}
167
168// --------------------------------------------------------------------------
169//
170// Process all filters.
171//
172Int_t MFDataPhrase::Process()
173{
174 fResult = fData ? fData->GetValue()>0.5 : fDefault;
175
176 return kTRUE;
177}
178
179// --------------------------------------------------------------------------
180//
181// Postprocess all filters.
182//
183Int_t MFDataPhrase::PostProcess()
184{
185 return kTRUE;
186}
187
188TString MFDataPhrase::GetRule() const
189{
190 return fData ? fData->GetRule() : MFilter::GetRule();
191}
192
193void MFDataPhrase::SetVariables(const TArrayD &arr)
194{
195 if (fData)
196 fData->SetVariables(arr);
197}
198
199// --------------------------------------------------------------------------
200//
201// Return the result of the filter rule. If no filter available the
202// condition is always true
203//
204Bool_t MFDataPhrase::IsExpressionTrue() const
205{
206 return fResult;
207}
208
209// --------------------------------------------------------------------------
210//
211// Return a comma seperated list of all data members used in the chain.
212// This is mainly used in MTask::AddToBranchList
213//
214TString MFDataPhrase::GetDataMember() const
215{
216 return fData ? fData->GetDataMember() : (TString)"";
217}
218
219void MFDataPhrase::StreamPrimitive(ostream &out) const
220{
221 out << " MF " << GetUniqueName();
222
223 if (!fData)
224 {
225 out << ";" << endl;
226 return;
227 }
228
229 out << "(\"" << fData->GetRule() << "\"";
230 if (fName!=gsDefName || fTitle!=gsDefTitle)
231 {
232 out << "(\"" << fName << "\"";
233 if (fTitle!=gsDefTitle)
234 out << ", \"" << fTitle << "\"";
235 }
236 out << ");" << endl;
237
238}
239
240// --------------------------------------------------------------------------
241//
242// Print the rule.
243// if now filter is set up '<n/a>' is printed.
244//
245void MFDataPhrase::Print(Option_t *opt) const
246{
247 *fLog << all << underline << GetDescriptor() << endl;
248 if (fData)
249 fData->Print();
250 else
251 *fLog << "<n/a>" << endl;
252 *fLog << endl;
253}
254
255// --------------------------------------------------------------------------
256//
257// Check for corresponding entries in resource file and setup filters.
258//
259// Assuming your MF-filter is called (Set/GetName): MyFilter
260//
261// First you can setup whether the filter is inverted or not:
262// MyFilter.Inverted: yes, no <default=no>
263//
264// Now setup the condition, eg:
265// MyFilter.Condition: MHillas.fSize<1000
266// or
267// MyFilter.Condition: MHillas.fSize>500 && MHillas.fSize<10000
268//
269// If you want to use more difficult filters you can split the
270// condition into subcondistions. Subcondistions are identified
271// by {}-brackets. Avoid trailing 0's! For example:
272//
273// MyFilter.Condition: MHillas.fSize>500 && {0} && {1}
274// MyFilter.0: MHillas.fSize>1000
275// MyFilter.1: MHillas.fSize<10000
276//
277// The numbering must be continous and start with 0. You can use
278// a subcondition more than once. All {}-brackets are simply replaced
279// by the correspodning conditions. The rules how conditions can
280// be written can be found in the class description MDataPhrase.
281//
282Int_t MFDataPhrase::ReadEnv(const TEnv &env, TString prefix, Bool_t print)
283{
284 Int_t rc1 = MFilter::ReadEnv(env, prefix, print);
285 if (rc1==kERROR)
286 return kERROR;
287
288 if (IsEnvDefined(env, prefix, "Condition", print))
289 {
290 TString rule = GetEnvValue(env, prefix, "Condition", "");
291 rule.ReplaceAll(" ", "");
292
293 Int_t idx=0;
294 while (1)
295 {
296 TString cond;
297 if (IsEnvDefined(env, prefix, Form("%d", idx), print))
298 {
299 cond += "(";
300 cond += GetEnvValue(env, prefix, Form("%d", idx), "");
301 cond += ")";
302 }
303
304 if (cond.IsNull())
305 break;
306
307 rule.ReplaceAll(Form("{%d}", idx), cond);
308 idx++;
309 }
310
311 if (fData)
312 {
313 delete fData;
314 fData = 0;
315 }
316
317 if (rule.IsNull())
318 {
319 *fLog << warn << GetDescriptor() << " ::ReadEnv - WARNING: Empty condition found." << endl;
320 SetAllowEmpty();
321 return kTRUE;
322 }
323
324 SetAllowEmpty(kFALSE);
325
326 fData = new MDataPhrase(rule);
327 /*
328 if (!(fF=ParseString(rule, 1)))
329 {
330 *fLog << err << "MFDataPhrase::ReadEnv - ERROR: Parsing '" << rule << "' failed." << endl;
331 return kERROR;
332 }
333 */
334 if (print)
335 {
336 *fLog << inf << "found: ";
337 fData->Print();
338 *fLog << endl;
339 }
340
341 rc1 = kTRUE;
342 }
343 else
344 {
345 if (!fData)
346 {
347 *fLog << warn << GetDescriptor() << " ::ReadEnv - WARNING: No condition found." << endl;
348 SetAllowEmpty();
349 return kFALSE;
350 }
351 }
352
353 const Int_t rc2 = fData->ReadEnv(env, prefix, print);
354 if (rc2==kERROR)
355 return kERROR;
356
357 // This is a workaround, because MFilter::ReadEnv and fF->ReadEnv
358 // might check for "Inverted" in this case both gets inverted
359 // and double-inversion is no inversion
360 /*
361 if (IsEnvDefined(env, prefix, "Inverted", print))
362 if (GetEnvValue(env, prefix, "Inverted", kFALSE)==kTRUE)
363 SetInverted(kFALSE);*/
364
365 return rc1 || rc2;
366}
Note: See TracBrowser for help on using the repository browser.