13 #include "TGraph2DErrors.h"
15 #include "TFitResult.h"
38 const char*
const _F2 =
".f2";
53 const std::string& option) :
66 void operator()(
const JType<T>& type)
69 result =
dynamic_cast<T&
>(object).
Fit(fcn, option.c_str(),
"same");
71 catch(
const std::exception&) {}
102 int main(
int argc,
char **argv)
125 JParser<> zap(
"General purpose fit program for 2D ROOT objects.");
127 zap[
'f'] =
make_field(inputFile,
"<input file>:<object name>");
129 zap[
'F'] =
make_field(formula,
"fit formula, e.g: \"[0]+[1]*x\"");
130 zap[
'@'] =
make_field(startValues,
"start values, e.g: \"p0 = GetMaximum;\"");
136 zap[
'O'] =
make_field(option,
"Fit option") =
"";
137 zap[
'w'] =
make_field(writeFits,
"write fit function(s) to ROOT file " <<
"(\"<name>" << _F2 <<
"\")");
143 catch(
const exception &error) {
144 FATAL(error.what() << endl);
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"; }
152 if (
debug == 0 && option.find(
'Q') == string::npos) { option +=
"Q"; }
158 TF2* fcn =
new TF2(
"user", formula.c_str());
163 if (fcn->IsZombie()) {
164 FATAL(
"Function: " << formula <<
" is zombie." << endl);
169 DEBUG(
"Input: " << *input << endl);
174 ERROR(
"File: " << input->getFullFilename() <<
" not opened." << endl);
178 const TRegexp regexp(input->getObjectName());
180 TIter iter(dir->GetListOfKeys());
182 for (TKey* key; (key = (TKey*) iter.Next()) != NULL; ) {
184 const TString tag(key->GetName());
186 DEBUG(
"Key: " << tag <<
" match = " << tag.Contains(regexp) << endl);
190 if (tag.Contains(regexp) &&
isTObject(key)) {
192 TObject*
object = key->ReadObj();
203 for (Int_t i = 0; i != fcn->GetNpar(); ++i) {
204 fcn->SetParError(i, 0.0);
220 FATAL(error << endl);
223 DEBUG(
"Start values " << object->GetName() << endl);
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);
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();
236 TH2* h2 =
dynamic_cast<TH2*
>(object);
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());
251 TGraph2D* g2 =
dynamic_cast<TGraph2D*
>(object);
254 for (Int_t i = 0; i != g2->GetN(); ++i) {
257 ymin = min(ymin, g2->GetY()[i]);
258 ymax = max(ymax, g2->GetY()[i]);
273 fcn->SetRange(
xmin, ymin,
xmax, ymax);
278 const chrono::steady_clock::time_point t0 = chrono::steady_clock::now();
280 JFit fit(*
object, fcn, option);
284 const chrono::steady_clock::time_point t1 = chrono::steady_clock::now();
286 if (fit.result != -1) {
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);
296 for (
int j = 0;
j != fcn->GetNpar(); ++
j) {
297 NOTICE(left << setw(12) << fcn->GetParName (
j) <<
' ' <<
298 SCIENTIFIC(12,5) << fcn->GetParameter(
j) <<
" +/- " <<
304 WARNING(
"Object: not compatible with ROOT Fit." << endl);
317 TH2* h2 =
dynamic_cast<TH2*
>(p);
320 for (Int_t ix = 1; ix <= h2->GetXaxis()->GetNbins(); ++ix) {
321 for (Int_t iy = 1; iy <= h2->GetYaxis()->GetNbins(); ++iy) {
323 const Double_t
x = h2->GetXaxis()->GetBinCenter(ix);
324 const Double_t
y = h2->GetYaxis()->GetBinCenter(iy);
326 h2->SetBinContent(ix, iy, fcn->Eval(
x,
y));
327 h2->SetBinError (ix, iy, 0.0);
334 TGraph2D* g2 =
dynamic_cast<TGraph2D*
>(p);
337 for (Int_t i = 0; i != g2->GetN(); ++i) {
339 const Double_t
x = g2->GetX()[i];
340 const Double_t
y = g2->GetY()[i];
342 g2->GetZ()[i] = fcn->Eval(
x,
y);
348 TGraph2DErrors* g2 =
dynamic_cast<TGraph2DErrors*
>(p);
351 for (Int_t i = 0; i != g2->GetN(); ++i) {
352 g2->SetPointError(i, 0.0, 0.0, 0.0);
int main(int argc, char **argv)
General purpose messaging.
#define DEBUG(A)
Message macros.
static JMinimizer minimizer
ROOT minimizer.
Utility class to parse command line options.
#define make_field(A,...)
macro to convert parameter to JParserTemplateElement object
I/O formatting auxiliaries.
#define MAKE_CSTRING(A)
Make C-string.
Auxiliary class to define a range between two values.
Exception for parsing value.
Wrapper class around string.
Utility class to parse command line options.
double getValue(const JScale_t scale)
Get numerical value corresponding to scale.
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.
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.
Auxiliary data structure for floating point format specification.
Type definition of range.
JFit()
Default constructor.
Auxiliary class for a type holder.
Auxiliary data structure to define ROOT minimizer.
Empty structure for specification of parser element that is initialised (i.e. does not require input)...
Auxiliary data structure for floating point format specification.