Jpp  master_rocky-40-g5f0272dcd
the software that should make you happy
Functions
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 ERROR(A)
Definition: JMessage.hh:66
#define NOTICE(A)
Definition: JMessage.hh:64
#define FATAL(A)
Definition: JMessage.hh:67
int debug
debug level
Definition: JSirene.cc:69
#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.
Definition: JException.hh:198
Wrapper class around string.
Definition: JToken.hh:26
Utility class to parse command line options.
Definition: JParser.hh:1698
T getLowerLimit() const
Get lower limit.
Definition: JRange.hh:202
T getUpperLimit() const
Get upper limit.
Definition: JRange.hh:213
const double xmax
Definition: JQuadrature.cc:24
const double xmin
Definition: JQuadrature.cc:23
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.
JObject_t & for_each(JObject_t &object, JType< JTypeList< JHead_t, JTail_t > > typelist)
For each data type method.
Definition: JTypeList.hh:415
This name space includes all other name spaces (except KM3NETDAQ, KM3NET and ANTARES).
int j
Definition: JPolint.hh:792
Definition: JSTDTypes.hh:14
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
Definition: JRoot.hh:19