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

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