Jpp test-rotations-new
the software that should make you happy
Loading...
Searching...
No Matches
JFit2D.cc
Go to the documentation of this file.
1#include <string>
2#include <iostream>
3#include <iomanip>
4#include <vector>
5#include <algorithm>
6#include <chrono>
7
8#include "TROOT.h"
9#include "TFile.h"
10#include "TKey.h"
11#include "TH2.h"
12#include "TGraph2D.h"
13#include "TGraph2DErrors.h"
14#include "TF2.h"
15#include "TFitResult.h"
16#include "TString.h"
17#include "TRegexp.h"
18
19#include "JROOT/JMinimizer.hh"
20
21#include "JLang/JType.hh"
22#include "JLang/JTypeList.hh"
23#include "JLang/JToken.hh"
24#include "JTools/JRange.hh"
25
28
29#include "Jeep/JPrint.hh"
30#include "Jeep/JParser.hh"
31#include "Jeep/JMessage.hh"
32
33
34namespace {
35
36 using namespace JPP;
37
38 const char* const _F2 = ".f2"; //!< extension of name for fit function
39
40 /**
41 * Auxiliary class for ROOT fit.
42 */
43 struct JFit {
44 /**
45 * Constructor.
46 *
47 * \param object object
48 * \param fcn fcn
49 * \param option option
50 */
51 JFit(TObject& object,
52 TF2* fcn,
53 const std::string& option) :
54 object(object),
55 fcn (fcn),
56 option(option)
57 {}
58
59
60 /**
61 * Attempt fit for given data type.
62 *
63 * \param type data type
64 */
65 template<class T>
66 void operator()(const JType<T>& type)
67 {
68 try {
69 result = dynamic_cast<T&>(object).Fit(fcn, option.c_str(), "same");
70 }
71 catch(const std::exception&) {}
72 }
73
74 TObject& object;
75 TF2* fcn;
76 std::string option;
77 TFitResultPtr result;
78 };
79}
80
81
82/**
83 * \file
84 * General purpose fit program for 2D ROOT objects.\n
85 * The option <tt>-f</tt> corresponds to <tt><file name>:<object name></tt>.
86 *
87 * The expressions for the fit function, start and fixed values should comply
88 * with ROOT class TFormula.
89 *
90 * In the expressions of the start and fixed values, names of member methods
91 * of corresponding class of the fit object may appear,
92 * such as TH1::GetMaximum, TH1::GetRMS, etc., e.g:
93 * <pre>
94 * -F "[0]*exp(-0.5*x*x/([1]*[1])*exp(-0.5*y*y/([2]*[2])"
95 * -@ "p0 = GetMaximum; p1 = 2*GetRMS(1); .."
96 * -= "p2 = 1"
97 * </pre>
98 * The result of the formulas for the start and fixed values will be evaluated
99 * for each histogram separately.
100 * \author mdejong
101 */
102int main(int argc, char **argv)
103{
104 using namespace std;
105 using namespace JPP;
106
107 typedef JToken<';'> JToken_t;
108 typedef JRange<double> JRange_t;
109
110 vector<JRootObjectID> inputFile;
111 string outputFile;
112 string formula;
113 vector<JToken_t> startValues;
114 vector<JToken_t> startErrors;
115 vector<JToken_t> fixedValues;
116 vector<JToken_t> limitValues;
117 JRange_t X;
118 JRange_t Y;
119 string option;
120 bool writeFits;
121 int debug;
122
123 try {
124
125 JParser<> zap("General purpose fit program for 2D ROOT objects.");
126
127 zap['f'] = make_field(inputFile, "<input file>:<object name>");
128 zap['o'] = make_field(outputFile, "ROOT file with fit results") = "fit.root";
129 zap['F'] = make_field(formula, "fit formula, e.g: \"[0]+[1]*x\"");
130 zap['@'] = make_field(startValues, "start values, e.g: \"p0 = GetMaximum;\"");
131 zap['E'] = make_field(startErrors, "start errors, e.g: \"p0 = 0.01 * GetMaximum;\"") = JPARSER::initialised();
132 zap['='] = make_field(fixedValues, "fixed values, e.g: \"p0 = GetMaximum;\"") = JPARSER::initialised();
133 zap['R'] = make_field(limitValues, "limit values, e.g: \"p0 = <lower limit> <upper limit>;\"") = JPARSER::initialised();
134 zap['x'] = make_field(X, "abscissa range") = JRange_t();
135 zap['y'] = make_field(Y, "abscissa range") = JRange_t();
136 zap['O'] = make_field(option, "Fit option") = "";
137 zap['w'] = make_field(writeFits, "write fit function(s) to ROOT file " << "(\"<name>" << _F2 << "\")");
138 zap['M'] = make_field(minimizer, "ROOT minimizer type and algorithm [debug]") = JMinimizer();
139 zap['d'] = make_field(debug) = 1;
140
141 zap(argc, argv);
142 }
143 catch(const exception &error) {
144 FATAL(error.what() << endl);
145 }
146
147
148 if (option.find('O') == string::npos) { option += "O"; }
149 if (option.find("R") == string::npos) { option += "R"; }
150 if (option.find("S") == string::npos) { option += "S"; }
151 //if (option.find('N') == string::npos) { option += "N"; }
152 if (debug == 0 && option.find('Q') == string::npos) { option += "Q"; }
153
154
155 TFile out(outputFile.c_str(), "recreate");
156
157
158 TF2* fcn = new TF2("user", formula.c_str());
159
160 fcn->SetNpx(1000);
161 fcn->SetNpy(1000);
162
163 if (fcn->IsZombie()) {
164 FATAL("Function: " << formula << " is zombie." << endl);
165 }
166
167 for (vector<JRootObjectID>::const_iterator input = inputFile.begin(); input != inputFile.end(); ++input) {
168
169 DEBUG("Input: " << *input << endl);
170
171 TDirectory* dir = getDirectory(*input);
172
173 if (dir == NULL) {
174 ERROR("File: " << input->getFullFilename() << " not opened." << endl);
175 continue;
176 }
177
178 const TRegexp regexp(input->getObjectName());
179
180 TIter iter(dir->GetListOfKeys());
181
182 for (TKey* key; (key = (TKey*) iter.Next()) != NULL; ) {
183
184 const TString tag(key->GetName());
185
186 DEBUG("Key: " << tag << " match = " << tag.Contains(regexp) << endl);
187
188 // option match
189
190 if (tag.Contains(regexp) && isTObject(key)) {
191
192 TObject* object = key->ReadObj();
193
194
195 // set fit parameters
196
197 try {
198
199 for (vector<JToken_t>::const_iterator i = startValues.begin(); i != startValues.end(); ++i) {
200 fcn->SetParameter(getParameter(*i), getValue(*i,object));
201 }
202
203 for (Int_t i = 0; i != fcn->GetNpar(); ++i) {
204 fcn->SetParError(i, 0.0);
205 }
206
207 for (vector<JToken_t>::const_iterator i = startErrors.begin(); i != startErrors.end(); ++i) {
208 fcn->SetParError (getParameter(*i), getValue(*i,object));
209 }
210
211 for (vector<JToken_t>::const_iterator i = fixedValues.begin(); i != fixedValues.end(); ++i) {
212 fcn->FixParameter(getParameter(*i), getValue(*i,object));
213 }
214
215 for (vector<JToken_t>::const_iterator i = limitValues.begin(); i != limitValues.end(); ++i) {
216 fcn->SetParLimits(getParameter(*i), getValue(*i,0), getValue(*i,1));
217 }
218 }
219 catch(JLANG::JParseError& error) {
220 FATAL(error << endl);
221 }
222
223 DEBUG("Start values " << object->GetName() << endl);
224
225 for (int i = 0; i != fcn->GetNpar(); ++i) {
226 DEBUG(left << setw(12) << fcn->GetParName (i) << ' ' <<
227 SCIENTIFIC(12,5) << fcn->GetParameter(i) << endl);
228 }
229
230 Double_t xmin = numeric_limits<Double_t>::max();
231 Double_t xmax = numeric_limits<Double_t>::lowest();
232 Double_t ymin = numeric_limits<Double_t>::max();
233 Double_t ymax = numeric_limits<Double_t>::lowest();
234
235 {
236 TH2* h2 = dynamic_cast<TH2*>(object);
237
238 if (h2 != NULL) {
239
240 xmin = min(xmin, h2->GetXaxis()->GetXmin());
241 xmax = max(xmax, h2->GetXaxis()->GetXmax());
242 ymin = min(ymin, h2->GetYaxis()->GetXmin());
243 ymax = max(ymax, h2->GetYaxis()->GetXmax());
244
245 if (X != JRange_t()) { h2->GetXaxis()->SetRangeUser(X.getLowerLimit(), X.getUpperLimit()); }
246 if (Y != JRange_t()) { h2->GetYaxis()->SetRangeUser(Y.getLowerLimit(), Y.getUpperLimit()); }
247 }
248 }
249
250 {
251 TGraph2D* g2 = dynamic_cast<TGraph2D*>(object);
252
253 if (g2 != NULL) {
254 for (Int_t i = 0; i != g2->GetN(); ++i) {
255 xmin = min(xmin, g2->GetX()[i]);
256 xmax = max(xmax, g2->GetX()[i]);
257 ymin = min(ymin, g2->GetY()[i]);
258 ymax = max(ymax, g2->GetY()[i]);
259 }
260 }
261 }
262
263 if (X != JRange_t()) {
264 xmin = X.getLowerLimit();
265 xmax = X.getUpperLimit();
266 }
267
268 if (Y != JRange_t()) {
269 ymin = Y.getLowerLimit();
270 ymax = Y.getUpperLimit();
271 }
272
273 fcn->SetRange(xmin, ymin, xmax, ymax);
274
275
276 // execute fit
277
278 const chrono::steady_clock::time_point t0 = chrono::steady_clock::now();
279
280 JFit fit(*object, fcn, option);
281
283
284 const chrono::steady_clock::time_point t1 = chrono::steady_clock::now();
285
286 if (fit.result != -1) {
287
288 // output fit results
289
290 NOTICE("Fit values " << object->GetName() << endl);
291 NOTICE("Fit formula " << formula << endl);
292 NOTICE("chi2/NDF " << FIXED(7,3) << fit.result->Chi2() << '/' << fit.result->Ndf() << ' ' << (fit.result->IsValid() ? "" : "failed") << endl);
293 NOTICE("Number of calls " << fit.result->NCalls() << endl);
294 NOTICE("Elapsed time [us] " << setw(8) << chrono::duration_cast<chrono::microseconds>(t1 - t0).count() << endl);
295
296 for (int j = 0; j != fcn->GetNpar(); ++j) {
297 NOTICE(left << setw(12) << fcn->GetParName (j) << ' ' <<
298 SCIENTIFIC(12,5) << fcn->GetParameter(j) << " +/- " <<
299 SCIENTIFIC(12,5) << fcn->GetParError (j) << endl);
300 }
301
302 } else {
303
304 WARNING("Object: not compatible with ROOT Fit." << endl);
305 }
306
307 out.cd();
308
309 object->Write();
310 fcn ->Write();
311
312 if (writeFits) {
313
314 TObject* p = object->Clone(MAKE_CSTRING(object->GetName() << _F2));
315
316 {
317 TH2* h2 = dynamic_cast<TH2*>(p);
318
319 if (h2 != NULL) {
320 for (Int_t ix = 1; ix <= h2->GetXaxis()->GetNbins(); ++ix) {
321 for (Int_t iy = 1; iy <= h2->GetYaxis()->GetNbins(); ++iy) {
322
323 const Double_t x = h2->GetXaxis()->GetBinCenter(ix);
324 const Double_t y = h2->GetYaxis()->GetBinCenter(iy);
325
326 h2->SetBinContent(ix, iy, fcn->Eval(x,y));
327 h2->SetBinError (ix, iy, 0.0);
328 }
329 }
330 }
331 }
332
333 {
334 TGraph2D* g2 = dynamic_cast<TGraph2D*>(p);
335
336 if (g2 != NULL) {
337 for (Int_t i = 0; i != g2->GetN(); ++i) {
338
339 const Double_t x = g2->GetX()[i];
340 const Double_t y = g2->GetY()[i];
341
342 g2->GetZ()[i] = fcn->Eval(x,y);
343 }
344 }
345 }
346
347 {
348 TGraph2DErrors* g2 = dynamic_cast<TGraph2DErrors*>(p);
349
350 if (g2 != NULL) {
351 for (Int_t i = 0; i != g2->GetN(); ++i) {
352 g2->SetPointError(i, 0.0, 0.0, 0.0);
353 }
354 }
355 }
356 }
357 }
358 }
359
360 dir->Close();
361 }
362
363 out.Write();
364 out.Close();
365}
string outputFile
int main(int argc, char **argv)
Definition JFit2D.cc:102
General purpose messaging.
#define DEBUG(A)
Message macros.
Definition JMessage.hh:62
#define NOTICE(A)
Definition JMessage.hh:64
#define FATAL(A)
Definition JMessage.hh:67
int debug
debug level
Definition JSirene.cc:72
#define WARNING(A)
Definition JMessage.hh:65
static JMinimizer minimizer
ROOT minimizer.
Definition JMinimizer.hh:80
Utility class to parse command line options.
#define make_field(A,...)
macro to convert parameter to JParserTemplateElement object
Definition JParser.hh:2142
I/O formatting auxiliaries.
#define MAKE_CSTRING(A)
Make C-string.
Definition JPrint.hh:72
Auxiliary class to define a range between two values.
Exception for parsing value.
Wrapper class around string.
Definition JToken.hh:26
Utility class to parse command line options.
Definition JParser.hh:1698
Range of values.
Definition JRange.hh:42
T getLowerLimit() const
Get lower limit.
Definition JRange.hh:202
T getUpperLimit() const
Get upper limit.
Definition JRange.hh:213
double getValue(const JScale_t scale)
Get numerical value corresponding to scale.
Definition JScale.hh:47
int getParameter(const std::string &text)
Get parameter number from text string.
TDirectory * getDirectory(const JRootObjectID &id)
Get TDirectory pointer.
bool isTObject(const TKey *key)
Check if given key corresponds to a TObject.
void for_each(JObject_t &object, JType< JTypeList< JHead_t, JTail_t > > typelist)
For each data type method.
Definition JTypeList.hh:414
This name space includes all other name spaces (except KM3NETDAQ, KM3NET and ANTARES).
JRootfit_t< JF1_t > Fit(const TH1 &h1, const JF1_t &f1, const index_list &ls=index_list(), const range_type &X=range_type())
Global fit fuction.
Definition JRootfit.hh:1247
return result
Definition JPolint.hh:862
int j
Definition JPolint.hh:801
Auxiliary data structure for floating point format specification.
Definition JManip.hh:448
Type definition of range.
Definition JHead.hh:43
Acoustic single fit.
Type list.
Definition JTypeList.hh:23
Auxiliary class for a type holder.
Definition JType.hh:19
Auxiliary data structure to define ROOT minimizer.
Definition JMinimizer.hh:14
Empty structure for specification of parser element that is initialised (i.e. does not require input)...
Definition JParser.hh:68
Auxiliary data structure for floating point format specification.
Definition JManip.hh:488