Jpp 19.3.0-rc.3
the software that should make you happy
Loading...
Searching...
No Matches
JFit.cc File Reference

General purpose fit program for 1D ROOT objects. More...

#include <string>
#include <iostream>
#include <iomanip>
#include <vector>
#include <algorithm>
#include <chrono>
#include "TROOT.h"
#include "TFile.h"
#include "TKey.h"
#include "TH1.h"
#include "TGraph.h"
#include "TProfile.h"
#include "TF1.h"
#include "TFitResult.h"
#include "TString.h"
#include "TRegexp.h"
#include "JROOT/JMinimizer.hh"
#include "JLang/JType.hh"
#include "JLang/JTypeList.hh"
#include "JLang/JToken.hh"
#include "JTools/JRange.hh"
#include "JGizmo/JRootObjectID.hh"
#include "JGizmo/JGizmoToolkit.hh"
#include "Jeep/JPrint.hh"
#include "Jeep/JParser.hh"
#include "Jeep/JMessage.hh"

Go to the source code of this file.

Functions

int main (int argc, char **argv)
 

Detailed Description

General purpose fit program for 1D ROOT objects.


The option -f corresponds to <file name>:<object name>.

The expressions for the fit function, start and fixed values should comply with ROOT class TFormula.

In the expressions of the start and fixed values, names of member methods of corresponding class of the fit object may appear, such as TH1::GetMaximum, TH1::GetRMS, etc., e.g:

     -F "[0]*exp(x/[1])+[2]"
     -@ "p0 = GetMaximum; p1 = 2*GetRMS"
     -= "p2 = 0"

The result of the formulas for the start and fixed values will be evaluated for each histogram separately.

Author
mdejong

Definition in file JFit.cc.

Function Documentation

◆ main()

int main ( int argc,
char ** argv )

Definition at line 100 of file JFit.cc.

101{
102 using namespace std;
103 using namespace JPP;
104
105 typedef JToken<';'> JToken_t;
106 typedef JRange<double> JRange_t;
107
108 vector<JRootObjectID> inputFile;
109 string outputFile;
110 string formula;
111 vector<JToken_t> startValues;
112 vector<JToken_t> startErrors;
113 vector<JToken_t> fixedValues;
114 vector<JToken_t> limitValues;
115 JRange_t X;
116 JRange_t Y;
117 char project;
118 string option;
119 int debug;
120
121 try {
122
123 JParser<> zap("General purpose fit program for 1D ROOT objects.");
124
125 zap['f'] = make_field(inputFile, "<input file>:<object name>");
126 zap['o'] = make_field(outputFile, "ROOT file with fit results") = "fit.root";
127 zap['F'] = make_field(formula, "fit formula, e.g: \"[0]+[1]*x\"");
128 zap['@'] = make_field(startValues, "start values, e.g: \"p0 = GetMaximum;\"");
129 zap['E'] = make_field(startErrors, "start errors, e.g: \"p0 = 0.01 * GetMaximum;\"") = JPARSER::initialised();
130 zap['='] = make_field(fixedValues, "fixed values, e.g: \"p0 = GetMaximum;\"") = JPARSER::initialised();
131 zap['R'] = make_field(limitValues, "limit values, e.g: \"p0 = <lower limit> <upper limit>;\"") = JPARSER::initialised();
132 zap['x'] = make_field(X, "abscissa range") = JRange_t();
133 zap['y'] = make_field(Y, "ordinate range") = JRange_t();
134 zap['P'] = make_field(project, "projection") = '\0', 'x', 'X', 'y', 'Y';
135 zap['O'] = make_field(option, "Fit option") = "";
136 zap['M'] = make_field(minimizer, "ROOT minimizer type and algorithm [debug]") = JMinimizer();
137 zap['d'] = make_field(debug) = 1;
138
139 zap(argc, argv);
140 }
141 catch(const exception &error) {
142 FATAL(error.what() << endl);
143 }
144
145
146 if (option.find('O') == string::npos) { option += "O"; }
147 if (option.find("R") == string::npos) { option += "R"; }
148 if (option.find("S") == string::npos) { option += "S"; }
149 //if (option.find('N') == string::npos) { option += "N"; }
150 if (debug == 0 && option.find('Q') == string::npos) { option += "Q"; }
151
152 bool px = (project == 'x' || project == 'X'); // projection on x-axis
153 bool py = (project == 'y' || project == 'Y'); // projection on y-axis
154
155 if (py) {
156 swap(Y, X); // Y becomes x-axis range and X becomes y-axis range
157 }
158
159
160 TFile out(outputFile.c_str(), "recreate");
161
162
163 TF1* fcn = new TF1("user", formula.c_str());
164
165 fcn->SetNpx(1000);
166
167 if (fcn->IsZombie()) {
168 FATAL("Function: " << formula << " is zombie." << endl);
169 }
170
171 for (vector<JRootObjectID>::const_iterator input = inputFile.begin(); input != inputFile.end(); ++input) {
172
173 DEBUG("Input: " << *input << endl);
174
175 TDirectory* dir = getDirectory(*input);
176
177 if (dir == NULL) {
178 ERROR("File: " << input->getFullFilename() << " not opened." << endl);
179 continue;
180 }
181
182 const TRegexp regexp(input->getObjectName());
183
184 TIter iter(dir->GetListOfKeys());
185
186 for (TKey* key; (key = (TKey*) iter.Next()) != NULL; ) {
187
188 const TString tag(key->GetName());
189
190 DEBUG("Key: " << tag << " match = " << tag.Contains(regexp) << endl);
191
192 // option match
193
194 if (tag.Contains(regexp) && isTObject(key)) {
195
196 TObject* object = key->ReadObj();
197
198 try {
199
200 TProfile& h1 = dynamic_cast<TProfile&>(*object);
201
202 object = h1.ProjectionX();
203 }
204 catch(exception&) {}
205
206 try {
207
208 TH2& h2 = dynamic_cast<TH2&>(*object);
209
210 if (px) {
211
212 object = h2.ProjectionX("_px",
213 h2.GetYaxis()->FindBin(Y.getLowerLimit()),
214 h2.GetYaxis()->FindBin(Y.getUpperLimit()));
215
216 } else if (py) {
217
218 object = h2.ProjectionY("_py",
219 h2.GetXaxis()->FindBin(Y.getLowerLimit()),
220 h2.GetXaxis()->FindBin(Y.getUpperLimit()));
221
222 } else {
223
224 ERROR("For 2D histograms, use option option -P for projections." << endl);
225
226 continue;
227 }
228 }
229 catch(exception&) {}
230
231
232 // set fit parameters
233
234 try {
235
236 for (vector<JToken_t>::const_iterator i = startValues.begin(); i != startValues.end(); ++i) {
237 fcn->SetParameter(getParameter(*i), getValue(*i,object));
238 }
239
240 for (Int_t i = 0; i != fcn->GetNpar(); ++i) {
241 fcn->SetParError (i, 0.0);
242 }
243
244 for (vector<JToken_t>::const_iterator i = startErrors.begin(); i != startErrors.end(); ++i) {
245 fcn->SetParError (getParameter(*i), getValue(*i,object));
246 }
247
248 for (vector<JToken_t>::const_iterator i = fixedValues.begin(); i != fixedValues.end(); ++i) {
249 fcn->FixParameter(getParameter(*i), getValue(*i,object));
250 }
251
252 for (vector<JToken_t>::const_iterator i = limitValues.begin(); i != limitValues.end(); ++i) {
253 fcn->SetParLimits(getParameter(*i), getValue(*i,0), getValue(*i,1));
254 }
255 }
256 catch(JLANG::JParseError& error) {
257 FATAL(error << endl);
258 }
259
260 DEBUG("Start values " << object->GetName() << endl);
261
262 for (int j = 0; j != fcn->GetNpar(); ++j) {
263 DEBUG(left << setw(12) << fcn->GetParName (j) << ' ' <<
264 SCIENTIFIC(12,5) << fcn->GetParameter(j) << endl);
265 }
266
267 Double_t xmin = numeric_limits<Double_t>::max();
268 Double_t xmax = numeric_limits<Double_t>::lowest();
269
270 {
271 TH1* h1 = dynamic_cast<TH1*>(object);
272
273 if (h1 != NULL) {
274 xmin = min(xmin, h1->GetXaxis()->GetXmin());
275 xmax = max(xmax, h1->GetXaxis()->GetXmax());
276 }
277 }
278
279 {
280 TGraph* g1 = dynamic_cast<TGraph*>(object);
281
282 if (g1 != NULL) {
283 for (Int_t i = 0; i != g1->GetN(); ++i) {
284 xmin = min(xmin, g1->GetX()[i]);
285 xmax = max(xmax, g1->GetX()[i]);
286 }
287 }
288 }
289
290 if (X != JRange_t()) {
291 xmin = X.getLowerLimit();
292 xmax = X.getUpperLimit();
293 }
294
295 fcn->SetRange(xmin, xmax);
296
297
298 // execute fit
299
300 const chrono::steady_clock::time_point t0 = chrono::steady_clock::now();
301
302 JFit fit(*object, fcn, option);
303
305
306 const chrono::steady_clock::time_point t1 = chrono::steady_clock::now();
307
308 if (fit.result != -1) {
309
310 // output fit results
311
312 NOTICE("Fit values " << object->GetName() << endl);
313 NOTICE("Fit formula " << formula << endl);
314 NOTICE("chi2/NDF " << FIXED(7,3) << fit.result->Chi2() << '/' << fit.result->Ndf() << ' ' << (fit.result->IsValid() ? "" : "failed") << endl);
315 NOTICE("Number of calls " << fit.result->NCalls() << endl);
316 NOTICE("Elapsed time [us] " << setw(8) << chrono::duration_cast<chrono::microseconds>(t1 - t0).count() << endl);
317
318 for (int j = 0; j != fcn->GetNpar(); ++j) {
319 NOTICE(left << setw(12) << fcn->GetParName (j) << ' ' <<
320 SCIENTIFIC(12,5) << fcn->GetParameter(j) << " +/- " <<
321 SCIENTIFIC(12,5) << fcn->GetParError (j) << endl);
322 }
323
324 } else {
325
326 WARNING("Object: not compatible with ROOT Fit." << endl);
327 }
328
329 out.cd();
330
331 object->Write();
332 }
333 }
334
335 dir->Close();
336 }
337
338 out.Write();
339 out.Close();
340}
string outputFile
#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
#define make_field(A,...)
macro to convert parameter to JParserTemplateElement object
Definition JParser.hh:2142
Double_t g1(const Double_t x)
Function.
Definition JQuantiles.cc:25
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
const double xmax
const double xmin
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).
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