101{
104
105 typedef JToken<
';'> JToken_t;
107
110 string formula;
118 string option;
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>");
127 zap[
'F'] =
make_field(formula,
"fit formula, e.g: \"[0]+[1]*x\"");
128 zap[
'@'] =
make_field(startValues,
"start values, e.g: \"p0 = GetMaximum;\"");
134 zap[
'P'] =
make_field(project,
"projection") =
'\0',
'x',
'X',
'y',
'Y';
135 zap[
'O'] =
make_field(option,
"Fit option") =
"";
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
150 if (
debug == 0 && option.find(
'Q') == string::npos) { option +=
"Q"; }
151
154
155 if (py) {
156 swap(Y, X);
157 }
158
159
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
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
193
194 if (tag.Contains(regexp) &&
isTObject(key)) {
195
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",
215
216 } else if (py) {
217
218 object = h2.ProjectionY("_py",
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
233
234 try {
235
236 for (vector<JToken_t>::const_iterator i = startValues.begin(); i != startValues.end(); ++i) {
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) {
246 }
247
248 for (vector<JToken_t>::const_iterator i = fixedValues.begin(); i != fixedValues.end(); ++i) {
250 }
251
252 for (vector<JToken_t>::const_iterator i = limitValues.begin(); i != limitValues.end(); ++i) {
254 }
255 }
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) <<
' ' <<
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
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
293 }
294
295 fcn->SetRange(xmin, xmax);
296
297
298
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
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) <<
" +/- " <<
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}
#define DEBUG(A)
Message macros.
static JMinimizer minimizer
ROOT minimizer.
#define make_field(A,...)
macro to convert parameter to JParserTemplateElement object
Double_t g1(const Double_t x)
Function.
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.
void 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).
Auxiliary data structure for floating point format specification.
Type definition of range.
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.