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

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