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.