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

Last change on this file since 7418 was 7418, checked in by tbretz, 19 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
142 //Must have a name otherwise all axis label disappear like a miracle
143 fFormula->SetName(fName);
144
145 if (fFormula->Compile(txt))
146 {
147 *fLog << err << dbginf << "Syntax Error: TFormula::Compile failed for " << txt << endl;
148 delete fFormula;
149 fFormula = 0;
150 return;
151 }
152
153 gROOT->GetListOfFunctions()->Remove(fFormula);
154}
155
156// --------------------------------------------------------------------------
157//
158// Destructor
159//
160MDataFormula::~MDataFormula()
161{
162 if (fFormula)
163 delete fFormula;
164}
165
166// --------------------------------------------------------------------------
167//
168// CopyConstructor
169//
170MDataFormula::MDataFormula(MDataFormula &ts)
171{
172 TFormula *f = ts.fFormula;
173
174 fName = "MDataFormula";
175 fTitle = f ? f->GetExpFormula() : (TString)"";
176
177 fFormula = f ? (TFormula*)f->Clone() : 0;
178 gROOT->GetListOfFunctions()->Remove(fFormula);
179
180 fMembers.SetOwner();
181
182 TObject *o = NULL;
183 TIter Next(&ts.fMembers);
184 while ((o=Next()))
185 fMembers.AddLast(o->Clone());
186}
187
188// --------------------------------------------------------------------------
189//
190// Evaluates and returns the result of the member list.
191// The expression is evaluated step by step, eg:
192// ((member[0] # member[1]) # member[3]) # member[4])
193// The '#' stands for the boolean operation which is specified in
194// the constructor.
195//
196Double_t MDataFormula::GetValue() const
197{
198 TArrayD val(fMembers.GetSize());
199
200 MData *member = NULL;
201
202 Int_t i=0;
203 TIter Next(&fMembers);
204 while ((member=(MData*)Next()))
205 val[i++] = member->GetValue();
206
207 return fFormula->EvalPar(0, val.GetArray());
208}
209
210Bool_t MDataFormula::IsValid() const
211{
212 TIter Next(&fMembers);
213
214 MData *data = NULL;
215 while ((data=(MData*)Next()))
216 if (!data->IsValid())
217 return kFALSE;
218
219 return fFormula ? kTRUE : kFALSE;
220}
221
222// --------------------------------------------------------------------------
223//
224// Checks whether at least one member has the ready-to-save flag.
225//
226Bool_t MDataFormula::IsReadyToSave() const
227{
228 TIter Next(&fMembers);
229
230 MData *data = NULL;
231
232 while ((data=(MData*)Next()))
233 if (data->IsReadyToSave())
234 return kTRUE;
235
236 return kFALSE;
237}
238
239// --------------------------------------------------------------------------
240//
241// PreProcesses all members in the list
242//
243Bool_t MDataFormula::PreProcess(const MParList *plist)
244{
245 TIter Next(&fMembers);
246
247 MData *member=NULL;
248
249 //
250 // loop over all members
251 //
252 while ((member=(MData*)Next()))
253 if (!member->PreProcess(plist))
254 {
255 *fLog << err << "Error - Preprocessing Data Member ";
256 *fLog << member->GetName() << " in " << fName << endl;
257 return kFALSE;
258 }
259
260 return kTRUE;
261}
262
263// --------------------------------------------------------------------------
264//
265// Builds a rule from all the list members. This is a rule which could
266// be used to rebuild the list using the constructor of a MDataChain
267//
268TString MDataFormula::GetRule() const
269{
270 if (!fFormula)
271 return "<empty>";
272
273 TString rule = fFormula->GetTitle(); //fFormula->GetExpFormula();
274
275 MData *member = NULL;
276
277 Int_t i=0;
278 TIter Next(&fMembers);
279 while ((member=(MData*)Next()))
280 {
281 TString r = member->GetRule();
282 r.ReplaceAll("]", "\\]");
283 rule.ReplaceAll(Form("[%d]", i++), r);
284 }
285 rule.ReplaceAll("\\]", "]");
286
287 return rule;
288}
289/*
290// --------------------------------------------------------------------------
291//
292// Return a comma seperated list of all data members used in the chain.
293// This is mainly used in MTask::AddToBranchList
294//
295TString MDataFormula::GetDataMember() const
296{
297 TString str;
298
299 TIter Next(&fMembers);
300
301 MData *member=(MData*)Next();
302
303 if (!member->GetDataMember().IsNull())
304 str += member->GetDataMember();
305
306 while ((member=(MData*)Next()))
307 {
308 if (!member->GetDataMember().IsNull())
309 {
310 str += ",";
311 str += member->GetDataMember();
312 }
313 }
314
315 return str;
316}
317*/
318void MDataFormula::SetVariables(const TArrayD &arr)
319{
320 fMembers.ForEach(MData, SetVariables)(arr);
321}
322
Note: See TracBrowser for help on using the repository browser.