source: trunk/MagicSoft/Mars/mfbase/MFDataPhrase.cc@ 8604

Last change on this file since 8604 was 8310, checked in by tbretz, 18 years ago
*** empty log message ***
File size: 9.6 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#include "MFDataPhrase.h"
75
76#include <fstream> // ofstream, ...
77
78#include <TMethodCall.h>
79
80#include "MParList.h"
81
82#include "MDataPhrase.h"
83
84#include "MLog.h"
85#include "MLogManip.h"
86
87ClassImp(MFDataPhrase);
88
89using namespace std;
90
91const TString MFDataPhrase::gsDefName = "MFDataPhrase";
92const TString MFDataPhrase::gsDefTitle = "Filter setup by a text-rule";
93
94// --------------------------------------------------------------------------
95//
96// Default Constructor. Don't use.
97//
98MFDataPhrase::MFDataPhrase() : fData(NULL), fAllowEmpty(kFALSE)
99{
100 fName = gsDefName.Data();
101 fTitle = gsDefTitle.Data();
102}
103
104// --------------------------------------------------------------------------
105//
106// Constructor. For the text describing the filter rule please see
107// the class description above.
108//
109MFDataPhrase::MFDataPhrase(const char *text, const char *name, const char *title) : fAllowEmpty(kFALSE)
110{
111 fName = name ? name : gsDefName.Data();
112 fTitle = title ? title : gsDefTitle.Data();
113
114 *fLog << inf << "Parsing filter rule... " << flush;
115 fData=new MDataPhrase(text);
116 *fLog << inf << "found: ";
117 fData->Print();
118 *fLog << endl;
119}
120
121// --------------------------------------------------------------------------
122//
123// Destructor. Delete filters.
124//
125MFDataPhrase::~MFDataPhrase()
126{
127 if (fData)
128 delete fData;
129}
130
131// --------------------------------------------------------------------------
132//
133// PreProcess all filters.
134//
135Int_t MFDataPhrase::PreProcess(MParList *plist)
136{
137 if (!fData)
138 {
139 if (IsAllowEmpty())
140 return kTRUE;
141
142 *fLog << err << dbginf << "No filter rule available." << endl;
143 return kFALSE;
144 }
145
146// fData->SetAccelerator(GetAccelerator());
147
148 if (!fData->PreProcess(plist))
149 {
150 *fLog << err << dbginf << "PreProcessing filters in ";
151 *fLog << fName << " failed." << endl;
152 return kFALSE;
153 }
154
155 return kTRUE;
156}
157
158// --------------------------------------------------------------------------
159//
160// Process all filters.
161//
162Int_t MFDataPhrase::Process()
163{
164 if (fData)
165 fResult = fData->GetValue()>0.5;
166
167 return kTRUE;
168}
169
170// --------------------------------------------------------------------------
171//
172// Postprocess all filters.
173//
174Int_t MFDataPhrase::PostProcess()
175{
176 return kTRUE;
177}
178
179TString MFDataPhrase::GetRule() const
180{
181 return fData ? fData->GetRule() : MFilter::GetRule();
182}
183
184void MFDataPhrase::SetVariables(const TArrayD &arr)
185{
186 if (fData)
187 fData->SetVariables(arr);
188}
189
190// --------------------------------------------------------------------------
191//
192// Return the result of the filter rule. If no filter available the
193// condition is always true
194//
195Bool_t MFDataPhrase::IsExpressionTrue() const
196{
197 return fResult;
198}
199
200// --------------------------------------------------------------------------
201//
202// Return a comma seperated list of all data members used in the chain.
203// This is mainly used in MTask::AddToBranchList
204//
205TString MFDataPhrase::GetDataMember() const
206{
207 return fData ? fData->GetDataMember() : (TString)"";
208}
209
210void MFDataPhrase::StreamPrimitive(ostream &out) const
211{
212 out << " MF " << GetUniqueName();
213
214 if (!fData)
215 {
216 out << ";" << endl;
217 return;
218 }
219
220 out << "(\"" << fData->GetRule() << "\"";
221 if (fName!=gsDefName || fTitle!=gsDefTitle)
222 {
223 out << "(\"" << fName << "\"";
224 if (fTitle!=gsDefTitle)
225 out << ", \"" << fTitle << "\"";
226 }
227 out << ");" << endl;
228
229}
230
231// --------------------------------------------------------------------------
232//
233// Print the rule.
234// if now filter is set up '<n/a>' is printed.
235//
236void MFDataPhrase::Print(Option_t *opt) const
237{
238 *fLog << all << underline << GetDescriptor() << endl;
239 if (fData)
240 fData->Print();
241 else
242 *fLog << "<n/a>" << endl;
243 *fLog << endl;
244}
245
246// --------------------------------------------------------------------------
247//
248// Check for corresponding entries in resource file and setup filters.
249//
250// Assuming your MF-filter is called (Set/GetName): MyFilter
251//
252// First you can setup whether the filter is inverted or not:
253// MyFilter.Inverted: yes, no <default=no>
254//
255// Now setup the condition, eg:
256// MyFilter.Condition: MHillas.fSize<1000
257// or
258// MyFilter.Condition: MHillas.fSize>500 && MHillas.fSize<10000
259//
260// If you want to use more difficult filters you can split the
261// condition into subcondistions. Subcondistions are identified
262// by {}-brackets. Avoid trailing 0's! For example:
263//
264// MyFilter.Condition: MHillas.fSize>500 && {0} && {1}
265// MyFilter.0: MHillas.fSize>1000
266// MyFilter.1: MHillas.fSize<10000
267//
268// The numbering must be continous and start with 0. You can use
269// a subcondition more than once. All {}-brackets are simply replaced
270// by the correspodning conditions. The rules how conditions can
271// be written can be found in the class description MDataPhrase.
272//
273Int_t MFDataPhrase::ReadEnv(const TEnv &env, TString prefix, Bool_t print)
274{
275 Int_t rc1 = MFilter::ReadEnv(env, prefix, print);
276 if (rc1==kERROR)
277 return kERROR;
278
279 if (IsEnvDefined(env, prefix, "Condition", print))
280 {
281 TString rule = GetEnvValue(env, prefix, "Condition", "");
282 rule.ReplaceAll(" ", "");
283
284 Int_t idx=0;
285 while (1)
286 {
287 TString cond;
288 if (IsEnvDefined(env, prefix, Form("%d", idx), print))
289 {
290 cond += "(";
291 cond += GetEnvValue(env, prefix, Form("%d", idx), "");
292 cond += ")";
293 }
294
295 if (cond.IsNull())
296 break;
297
298 rule.ReplaceAll(Form("{%d}", idx), cond);
299 idx++;
300 }
301
302 if (fData)
303 {
304 delete fData;
305 fData = 0;
306 }
307
308 if (rule.IsNull())
309 {
310 *fLog << warn << GetDescriptor() << " ::ReadEnv - WARNING: Empty condition found." << endl;
311 SetAllowEmpty();
312 return kTRUE;
313 }
314
315 SetAllowEmpty(kFALSE);
316
317 fData = new MDataPhrase(rule);
318 /*
319 if (!(fF=ParseString(rule, 1)))
320 {
321 *fLog << err << "MFDataPhrase::ReadEnv - ERROR: Parsing '" << rule << "' failed." << endl;
322 return kERROR;
323 }
324 */
325 if (print)
326 {
327 *fLog << inf << "found: ";
328 fData->Print();
329 *fLog << endl;
330 }
331
332 rc1 = kTRUE;
333 }
334 else
335 {
336 if (!fData)
337 {
338 *fLog << warn << GetDescriptor() << " ::ReadEnv - WARNING: No condition found." << endl;
339 SetAllowEmpty();
340 return kFALSE;
341 }
342 }
343
344 const Int_t rc2 = fData->ReadEnv(env, prefix, print);
345 if (rc2==kERROR)
346 return kERROR;
347
348 // This is a workaround, because MFilter::ReadEnv and fF->ReadEnv
349 // might check for "Inverted" in this case both gets inverted
350 // and double-inversion is no inversion
351 /*
352 if (IsEnvDefined(env, prefix, "Inverted", print))
353 if (GetEnvValue(env, prefix, "Inverted", kFALSE)==kTRUE)
354 SetInverted(kFALSE);*/
355
356 return rc1 || rc2;
357}
Note: See TracBrowser for help on using the repository browser.