Jpp  15.0.0
the software that should make you happy
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
JFit.cc
Go to the documentation of this file.
1 #include <string>
2 #include <iostream>
3 #include <iomanip>
4 #include <vector>
5 #include <algorithm>
6 
7 #include "TROOT.h"
8 #include "TFile.h"
9 #include "TKey.h"
10 #include "TH1.h"
11 #include "TGraph.h"
12 #include "TProfile.h"
13 #include "TF1.h"
14 #include "TString.h"
15 #include "TRegexp.h"
16 
17 #include "JLang/JType.hh"
18 #include "JLang/JTypeList.hh"
19 #include "JLang/JToken.hh"
20 #include "JTools/JRange.hh"
21 
22 #include "JGizmo/JRootObjectID.hh"
23 #include "JGizmo/JGizmoToolkit.hh"
24 
25 #include "Jeep/JPrint.hh"
26 #include "Jeep/JParser.hh"
27 #include "Jeep/JMessage.hh"
28 
29 
30 namespace {
31 
32  using namespace JPP;
33 
34  /**
35  * Auxiliary class for ROOT fit.
36  */
37  struct JFit {
38  /**
39  * Constructor.
40  *
41  * \param object object
42  * \param fcn fcn
43  * \param option option
44  */
45  JFit(TObject& object,
46  TF1* fcn,
47  const std::string& option) :
48  object(object),
49  fcn (fcn),
50  option(option)
51  {}
52 
53 
54  /**
55  * Attempt fit for given data type.
56  *
57  * \param type data type
58  */
59  template<class T>
60  void operator()(const JType<T>& type)
61  {
62  try {
63  result = dynamic_cast<T&>(object).Fit(fcn, option.c_str(), "same");
64  }
65  catch(const std::exception&) {}
66  }
67 
68  TObject& object;
69  TF1* fcn;
70  std::string option;
71  TFitResultPtr result;
72  };
73 }
74 
75 
76 /**
77  * \file
78  * General purpose fit program using ROOT.
79  * The option <tt>-f</tt> corresponds to <tt><file name>:<object name></tt>.
80  *
81  * The expressions for the fit function, start and fixed values should comply
82  * with ROOT class TFormula.
83  *
84  * In the expressions of the start and fixed values, names of member methods
85  * of corresponding class of the fit object may appear,
86  * such as TH1::GetMaximum, TH1::GetRMS, etc., e.g:
87  * <pre>
88  * -F "[0]*exp(x/[1])+[2]"
89  * -@ "p0 = GetMaximum; p1 = 2*GetRMS"
90  * -= "p2 = 0"
91  * </pre>
92  * The result of the formulas for the start and fixed values will be evaluated
93  * for each histogram separately.
94  * \author mdejong
95  */
96 int main(int argc, char **argv)
97 {
98  using namespace std;
99  using namespace JPP;
100 
101  typedef JToken<';'> JToken_t;
102  typedef JRange<double> JRange_t;
103 
104  vector<JRootObjectID> inputFile;
105  string outputFile;
106  string formula;
107  vector<JToken_t> startValues;
108  vector<JToken_t> fixedValues;
109  JRange_t X;
110  JRange_t Y;
111  char project;
112  string option;
113  int debug;
114 
115  try {
116 
117  JParser<> zap("General purpose fit program using ROOT.");
118 
119  zap['f'] = make_field(inputFile, "<input file>:<object name>");
120  zap['o'] = make_field(outputFile, "ROOT file with fit results") = "fit.root";
121  zap['F'] = make_field(formula, "fit formula, e.g: \"[0]+[1]*x\"");
122  zap['@'] = make_field(startValues, "start values, e.g: \"p0 = GetMaximum;\"");
123  zap['='] = make_field(fixedValues, "fixed values, e.g: \"p0 = GetMaximum;\"") = JPARSER::initialised();
124  zap['x'] = make_field(X, "abscissa range") = JRange_t();
125  zap['y'] = make_field(Y, "ordinate range") = JRange_t();
126  zap['P'] = make_field(project, "projection") = '\0', 'x', 'X', 'y', 'Y';
127  zap['O'] = make_field(option, "Fit option") = "";
128  zap['d'] = make_field(debug) = 1;
129 
130  zap(argc, argv);
131  }
132  catch(const exception &error) {
133  FATAL(error.what() << endl);
134  }
135 
136 
137  if (option.find('O') == string::npos) { option += "O"; }
138  //if (option.find('N') == string::npos) { option += "N"; }
139  if (debug == 0 && option.find('Q') == string::npos) { option += "Q"; }
140 
141  bool px = (project == 'x' || project == 'X'); // projection on x-axis
142  bool py = (project == 'y' || project == 'Y'); // projection on y-axis
143 
144  if (py) {
145  swap(Y, X); // Y becomes x-axis range and X becomes y-axis range
146  }
147 
148 
149  TFile out(outputFile.c_str(), "recreate");
150 
151 
152  TF1* fcn = new TF1("user", formula.c_str());
153 
154  fcn->SetNpx(1000);
155 
156  if (fcn->IsZombie()) {
157  FATAL("Function: " << formula << " is zombie." << endl);
158  }
159 
160  for (vector<JRootObjectID>::const_iterator input = inputFile.begin(); input != inputFile.end(); ++input) {
161 
162  DEBUG("Input: " << *input << endl);
163 
164  TDirectory* dir = getDirectory(*input);
165 
166  if (dir == NULL) {
167  ERROR("File: " << input->getFullFilename() << " not opened." << endl);
168  continue;
169  }
170 
171  const TRegexp regexp(input->getObjectName());
172 
173  TIter iter(dir->GetListOfKeys());
174 
175  for (TKey* key; (key = (TKey*) iter.Next()) != NULL; ) {
176 
177  const TString tag(key->GetName());
178 
179  DEBUG("Key: " << tag << " match = " << tag.Contains(regexp) << endl);
180 
181  // option match
182 
183  if (tag.Contains(regexp)) {
184 
185  TObject* object = key->ReadObj();
186 
187  try {
188 
189  TProfile& h1 = dynamic_cast<TProfile&>(*object);
190 
191  object = h1.ProjectionX();
192  }
193  catch(exception&) {}
194 
195  try {
196 
197  TH2& h2 = dynamic_cast<TH2&>(*object);
198 
199  if (px) {
200 
201  object = h2.ProjectionX("_px",
202  h2.GetYaxis()->FindBin(Y.getLowerLimit()),
203  h2.GetYaxis()->FindBin(Y.getUpperLimit()));
204 
205  } else if (py) {
206 
207  object = h2.ProjectionY("_py",
208  h2.GetXaxis()->FindBin(Y.getLowerLimit()),
209  h2.GetXaxis()->FindBin(Y.getUpperLimit()));
210 
211  } else {
212 
213  ERROR("For 2D histograms, use option option -P for projections." << endl);
214 
215  continue;
216  }
217  }
218  catch(exception&) {}
219 
220 
221  // set fit parameters
222 
223  try {
224 
225  for (vector<JToken_t>::const_iterator j = startValues.begin(); j != startValues.end(); ++j) {
226  fcn->SetParameter(getParameter(*j), getValue(*j,object));
227  }
228 
229  for (vector<JToken_t>::const_iterator j = fixedValues.begin(); j != fixedValues.end(); ++j) {
230  fcn->FixParameter(getParameter(*j), getValue(*j,object));
231  }
232  }
233  catch(JLANG::JParseError& error) {
234  FATAL(error << endl);
235  }
236 
237  DEBUG("Start values " << object->GetName() << endl);
238 
239  for (int j = 0; j != fcn->GetNpar(); ++j) {
240  DEBUG(left << setw(12) << fcn->GetParName (j) << ' ' <<
241  SCIENTIFIC(12,5) << fcn->GetParameter(j) << endl);
242  }
243 
244  Double_t xmin = numeric_limits<Double_t>::max();
245  Double_t xmax = numeric_limits<Double_t>::lowest();
246 
247  {
248  TH1* h1 = dynamic_cast<TH1*>(object);
249 
250  if (h1 != NULL) {
251  xmin = min(xmin, h1->GetXaxis()->GetXmin());
252  xmax = max(xmax, h1->GetXaxis()->GetXmax());
253  }
254  }
255 
256  {
257  TGraph* g1 = dynamic_cast<TGraph*>(object);
258 
259  if (g1 != NULL) {
260  for (Int_t i = 0; i != g1->GetN(); ++i) {
261  xmin = min(xmin, g1->GetX()[i]);
262  xmax = max(xmax, g1->GetX()[i]);
263  }
264  }
265  }
266 
267  if (X != JRange_t()) {
268  xmin = X.getLowerLimit();
269  xmax = X.getUpperLimit();
270  }
271 
272  fcn->SetRange(xmin, xmax);
273 
274  if (option.find("R") == string::npos) {
275  option += "R";
276  }
277 
278 
279  // execute fit
280 
281  JFit fit(*object, fcn, option);
282 
284 
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 
293  for (int j = 0; j != fcn->GetNpar(); ++j) {
294  NOTICE(left << setw(12) << fcn->GetParName (j) << ' ' <<
295  SCIENTIFIC(12,5) << fcn->GetParameter(j) << " +/- " <<
296  SCIENTIFIC(12,5) << fcn->GetParError (j) << endl);
297  }
298 
299  } else {
300 
301  WARNING("Object: not compatible with ROOT Fit." << endl);
302  }
303 
304  out.cd();
305 
306  object->Write();
307  }
308  }
309 
310  dir->Close();
311  }
312 
313  out.Write();
314  out.Close();
315 }
Utility class to parse command line options.
Definition: JParser.hh:1500
#define WARNING(A)
Definition: JMessage.hh:65
double getValue(const JScale_t scale)
Get numerical value corresponding to scale.
Definition: JScale.hh:47
int main(int argc, char *argv[])
Definition: Main.cc:15
int getParameter(const std::string &text)
Get parameter number from text string.
TFitResultPtr Fit(TH1D *h)
Definition: JNanobeacon.hh:14
Definition: JRoot.hh:19
then for HISTOGRAM in h0 h1
Definition: JMatrixNZ.sh:71
Empty structure for specification of parser element that is initialised (i.e. does not require input)...
Definition: JParser.hh:66
Auxiliary class for a type holder.
Definition: JType.hh:19
then fatal Wrong number of arguments fi set_variable STRING $argv[1] set_variable DETECTORXY_TXT $WORKDIR $DETECTORXY_TXT tail read X Y CHI2 RMS printf optimum n $X $Y $CHI2 $RMS awk v Y
string outputFile
Acoustic single fit.
Type list.
Definition: JTypeList.hh:22
I/O formatting auxiliaries.
#define make_field(A,...)
macro to convert parameter to JParserTemplateElement object
Definition: JParser.hh:1961
return result
Definition: JPolint.hh:727
do set_variable OUTPUT_DIRECTORY $WORKDIR T
#define NOTICE(A)
Definition: JMessage.hh:64
#define ERROR(A)
Definition: JMessage.hh:66
then break fi done getCenter read X Y Z let X
int debug
debug level
Definition: JSirene.cc:63
General purpose messaging.
JObject_t & for_each(JObject_t &object, JType< JTypeList< JHead_t, JTail_t > > typelist)
For each data type method.
Definition: JTypeList.hh:415
#define FATAL(A)
Definition: JMessage.hh:67
Auxiliary class to define a range between two values.
Utility class to parse command line options.
Wrapper class around string.
Definition: JToken.hh:23
then usage $script< input_file >< detector_file > fi set_variable OUTPUT_DIR set_variable SELECTOR JDAQTimesliceL1 set_variable DEBUG case set_variable DEBUG
Exception for parsing value.
Definition: JException.hh:180
TDirectory * getDirectory(const JRootObjectID &id)
Get TDirectory pointer.
int j
Definition: JPolint.hh:666
Auxiliary data structure for floating point format specification.
Definition: JManip.hh:484
JFit()
Default constructor.
Double_t g1(const Double_t x)
Function.
Definition: JQuantiles.cc:25