source: trunk/MagicSoft/Mars/mdata/MDataFormula.cc@ 9278

Last change on this file since 9278 was 7804, checked in by tbretz, 18 years ago
*** empty log message ***
File size: 7.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, 04/2004 <mailto:tbretz@astro.uni-wuerzburg.de>
19!
20! Copyright: MAGIC Software Development, 2000-2004
21!
22!
23\* ======================================================================== */
24
25/////////////////////////////////////////////////////////////////////////////
26//
27// MDataFormula
28//
29// A MDataFormula is a wrapper for TFormula. It should have access to all
30// multi-argument functions, to formulas and to single-argument functions
31// unknown by MDataChain intrinsically.
32//
33// eg.
34// MDataFormula("myfunc(MParams.fValue)");
35// MDataFormula("TMath::Hypot(MParams.fX, MParams.fY)");
36// MDataFormula("TMath::Pow(MParams.fX, 7.5)");
37// MDataFormula("TMath::Pow(MParams.fX, [6])");
38//
39// Using this should be rather slow. If you can create a 'plain' Data-Chain
40// this should be much faster.
41//
42// To do:
43// - implement SetVariables to be used in functions like "gaus(0)" or
44// "pol0(1)"
45//
46/////////////////////////////////////////////////////////////////////////////
47#include "MDataFormula.h"
48
49#include <TArrayD.h>
50#include <TFormula.h>
51
52#include "MLog.h"
53#include "MLogManip.h"
54
55#include "MDataChain.h"
56
57ClassImp(MDataFormula);
58
59using namespace std;
60
61TString MDataFormula::Parse(const char *rule)
62{
63 TString txt(rule);
64
65 Int_t pos1 = txt.First('(');
66 if (pos1<0)
67 {
68 *fLog << err << dbginf << "Syntax Error: '(' not found in " << txt << endl;
69 return "";
70 }
71
72 Int_t pos2 = txt.Last(')');
73 if (pos2<0)
74 {
75 *fLog << err << dbginf << "Syntax Error: ')' not found in " << txt << endl;
76 return "";
77 }
78
79 if (pos2<pos1+1)
80 {
81 *fLog << err << dbginf << "Syntax Error: '(' not behind ')' in " << txt << endl;
82 return "";
83 }
84
85 //TObject *func = gROOT->GetListOfFunctions()->FindObject(txt(0, pos1));
86
87 TString args = txt(pos1+1, pos2-pos1);
88 Int_t num = 0;
89
90 while (args.Length()>0 && num<5)
91 {
92 const Int_t last = args.First(',');
93 const Int_t len = last<0 ? args.Last(')') : last;
94 if (len<0)
95 {
96 *fLog << err << dbginf << "Syntax Error: ',' found after ')'" << endl;
97 return "";
98 }
99
100 const TString arg = args(0, len);
101
102 MDataChain *chain = new MDataChain(arg);
103 if (!chain->IsValid())
104 {
105 delete chain;
106 return "";
107 }
108 fMembers.AddLast(chain);
109
110 args.Remove(0, len+1);
111 pos1 += len;
112
113 txt.Replace(txt.Index(arg), len, Form("[%d]", num++));
114 }
115
116 return txt;
117}
118
119// --------------------------------------------------------------------------
120//
121// Default Constructor. Not for usage!
122//
123MDataFormula::MDataFormula(const char *rule, const char *name, const char *title) : fFormula(0)
124{
125 fName = name ? name : "MDataFormula";
126 fTitle = title ? title : rule;
127
128 fMembers.SetOwner();
129
130 if (!rule)
131 return;
132
133 const TString txt=Parse(rule);
134 if (txt.IsNull())
135 {
136 fMembers.Delete();
137 return;
138 }
139
140 fFormula = new TFormula;
141 // Must have a name otherwise all axis labels disappear like a miracle
142 fFormula->SetName(fName.IsNull()?"TFormula":fName.Data());
143
144 if (fFormula->Compile(txt))
145 {
146 *fLog << err << dbginf << "Syntax Error: TFormula::Compile failed for " << txt << endl;
147 delete fFormula;
148 fFormula = 0;
149 return;
150 }
151
152 gROOT->GetListOfFunctions()->Remove(fFormula);
153}
154
155// --------------------------------------------------------------------------
156//
157// Destructor
158//
159MDataFormula::~MDataFormula()
160{
161 if (fFormula)
162 delete fFormula;
163}
164
165// --------------------------------------------------------------------------
166//
167// CopyConstructor
168//
169MDataFormula::MDataFormula(MDataFormula &ts)
170{
171 TFormula *f = ts.fFormula;
172
173 fName = "MDataFormula";
174 fTitle = f ? f->GetExpFormula() : (TString)"";
175
176 fFormula = f ? (TFormula*)f->Clone() : 0;
177 gROOT->GetListOfFunctions()->Remove(fFormula);
178
179 fMembers.SetOwner();
180
181 TObject *o = NULL;
182 TIter Next(&ts.fMembers);
183 while ((o=Next()))
184 fMembers.AddLast(o->Clone());
185}
186
187// --------------------------------------------------------------------------
188//
189// Evaluates and returns the result of the member list.
190// The expression is evaluated step by step, eg:
191// ((member[0] # member[1]) # member[3]) # member[4])
192// The '#' stands for the boolean operation which is specified in
193// the constructor.
194//
195Double_t MDataFormula::GetValue() const
196{
197 TArrayD val(fMembers.GetSize());
198
199 MData *member = NULL;
200
201 Int_t i=0;
202 TIter Next(&fMembers);
203 while ((member=(MData*)Next()))
204 val[i++] = member->GetValue();
205
206 return fFormula->EvalPar(0, val.GetArray());
207}
208
209Bool_t MDataFormula::IsValid() const
210{
211 TIter Next(&fMembers);
212
213 MData *data = NULL;
214 while ((data=(MData*)Next()))
215 if (!data->IsValid())
216 return kFALSE;
217
218 return fFormula ? kTRUE : kFALSE;
219}
220
221// --------------------------------------------------------------------------
222//
223// Checks whether at least one member has the ready-to-save flag.
224//
225Bool_t MDataFormula::IsReadyToSave() const
226{
227 TIter Next(&fMembers);
228
229 MData *data = NULL;
230
231 while ((data=(MData*)Next()))
232 if (data->IsReadyToSave())
233 return kTRUE;
234
235 return kFALSE;
236}
237
238// --------------------------------------------------------------------------
239//
240// PreProcesses all members in the list
241//
242Bool_t MDataFormula::PreProcess(const MParList *plist)
243{
244 TIter Next(&fMembers);
245
246 MData *member=NULL;
247
248 //
249 // loop over all members
250 //
251 while ((member=(MData*)Next()))
252 if (!member->PreProcess(plist))
253 {
254 *fLog << err << "Error - Preprocessing Data Member ";
255 *fLog << member->GetName() << " in " << fName << endl;
256 return kFALSE;
257 }
258
259 return kTRUE;
260}
261
262// --------------------------------------------------------------------------
263//
264// Builds a rule from all the list members. This is a rule which could
265// be used to rebuild the list using the constructor of a MDataChain
266//
267TString MDataFormula::GetRule() const
268{
269 if (!fFormula)
270 return "<empty>";
271
272 TString rule = fFormula->GetTitle(); //fFormula->GetExpFormula();
273
274 MData *member = NULL;
275
276 Int_t i=0;
277 TIter Next(&fMembers);
278 while ((member=(MData*)Next()))
279 {
280 TString r = member->GetRule();
281 r.ReplaceAll("]", "\\]");
282 rule.ReplaceAll(Form("[%d]", i++), r);
283 }
284 rule.ReplaceAll("\\]", "]");
285
286 return rule;
287}
288/*
289// --------------------------------------------------------------------------
290//
291// Return a comma seperated list of all data members used in the chain.
292// This is mainly used in MTask::AddToBranchList
293//
294TString MDataFormula::GetDataMember() const
295{
296 TString str;
297
298 TIter Next(&fMembers);
299
300 MData *member=(MData*)Next();
301
302 if (!member->GetDataMember().IsNull())
303 str += member->GetDataMember();
304
305 while ((member=(MData*)Next()))
306 {
307 if (!member->GetDataMember().IsNull())
308 {
309 str += ",";
310 str += member->GetDataMember();
311 }
312 }
313
314 return str;
315}
316*/
317void MDataFormula::SetVariables(const TArrayD &arr)
318{
319 fMembers.R__FOR_EACH(MData, SetVariables)(arr);
320}
321
Note: See TracBrowser for help on using the repository browser.