103{
  106 
  107  typedef JToken<
';'>      JToken_t;
 
  109 
  112  string                   formula;
  119  string                   option;
  120  bool                     writeFits;
  122 
  123  try {
  124 
  125    JParser<> zap(
"General purpose fit program for 2D ROOT objects.");
 
  126 
  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 << 
"\")");
 
  140 
  141    zap(argc, argv);
  142  }
  143  catch(const exception &error) {
  144    FATAL(error.what() << endl);
 
  145  }
  146 
  147 
  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"; }
  151  
  152  if (
debug ==  0 && option.find(
'Q') == string::npos) { option += 
"Q"; }
 
  153 
  154 
  156 
  157 
  158  TF2* fcn = new TF2("user", formula.c_str());
  159 
  160  fcn->SetNpx(1000);
  161  fcn->SetNpy(1000);
  162 
  163  if (fcn->IsZombie()) {
  164    FATAL(
"Function: " << formula << 
" is zombie." << endl);
 
  165  }
  166 
  167  for (vector<JRootObjectID>::const_iterator input = inputFile.begin(); input != inputFile.end(); ++input) {
  168 
  169    DEBUG(
"Input: " << *input << endl);
 
  170 
  172 
  173    if (dir == NULL) {
  174      ERROR(
"File: " << input->getFullFilename() << 
" not opened." << endl);
 
  175      continue;
  176    }
  177 
  178    const TRegexp regexp(input->getObjectName());
  179 
  180    TIter iter(dir->GetListOfKeys());
  181 
  182    for (TKey* key; (
key = (TKey*) iter.Next()) != NULL; ) {
 
  183       
  184      const TString tag(
key->GetName());
 
  185 
  186      DEBUG(
"Key: " << tag << 
" match = " << tag.Contains(regexp) << endl);
 
  187 
  188      
  189      
  190      if (tag.Contains(regexp) && 
isTObject(key)) {
 
  191        
  193      
  194 
  195        
  196 
  197        try {
  198 
  199          for (vector<JToken_t>::const_iterator i = startValues.begin(); i != startValues.end(); ++i) {
  201          }
  202 
  203          for (Int_t i = 0; i != fcn->GetNpar(); ++i) {
  204            fcn->SetParError(i, 0.0);
  205          }
  206 
  207          for (vector<JToken_t>::const_iterator i = startErrors.begin(); i != startErrors.end(); ++i) {
  209          }
  210          
  211          for (vector<JToken_t>::const_iterator i = fixedValues.begin(); i != fixedValues.end(); ++i) {
  213          }
  214 
  215          for (vector<JToken_t>::const_iterator i = limitValues.begin(); i != limitValues.end(); ++i) {
  217          }
  218        }
  220          FATAL(error << endl);
 
  221        }
  222 
  223        DEBUG(
"Start values " << object->GetName() << endl);
 
  224 
  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);
 
  228        }
  229 
  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();
  234 
  235        {
  236          TH2* h2 = dynamic_cast<TH2*>(object);
  237 
  238          if (h2 != NULL) {
  239 
  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());
  244 
  247          }
  248        }
  249        
  250        {
  251          TGraph2D* g2 = dynamic_cast<TGraph2D*>(object);
  252 
  253          if (g2 != NULL) {
  254            for (Int_t i = 0; i != g2->GetN(); ++i) {
  255              xmin = min(xmin, g2->GetX()[i]);
 
  256              xmax = max(xmax, g2->GetX()[i]);
 
  257              ymin = min(ymin, g2->GetY()[i]);
  258              ymax = max(ymax, g2->GetY()[i]);
  259            }
  260          }
  261        }
  262 
  266        }
  267 
  271        }
  272 
  273        fcn->SetRange(xmin, ymin, xmax, ymax);
  274 
  275          
  276        
  277 
  278        const chrono::steady_clock::time_point t0 = chrono::steady_clock::now();
  279 
  280        JFit fit(*
object, fcn, option);
 
  281 
  283  
  284        const chrono::steady_clock::time_point t1 = chrono::steady_clock::now();
  285 
  286        if (fit.result != -1) {
  287 
  288          
  289            
  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);
 
  295 
  296          for (
int j = 0; 
j != fcn->GetNpar(); ++
j) {
 
  297            NOTICE(left << setw(12) << fcn->GetParName  (
j) << 
' '     << 
 
  298                   SCIENTIFIC(12,5) << fcn->GetParameter(
j) << 
" +/- " << 
 
  300          }
  301 
  302        } else {
  303 
  304          WARNING(
"Object: not compatible with ROOT Fit." << endl);
 
  305        }
  306 
  307        out.cd();
  308 
  309        object->Write();
  310        fcn   ->Write();
  311 
  312        if (writeFits) {
  313 
  315 
  316          {
  317            TH2* h2 = dynamic_cast<TH2*>(p);
  318 
  319            if (h2 != NULL) {
  320              for (Int_t ix = 1; ix <= h2->GetXaxis()->GetNbins(); ++ix) {
  321                for (Int_t iy = 1; iy <= h2->GetYaxis()->GetNbins(); ++iy) {
  322 
  323                  const Double_t 
x = h2->GetXaxis()->GetBinCenter(ix);
 
  324                  const Double_t 
y = h2->GetYaxis()->GetBinCenter(iy);
 
  325 
  326                  h2->SetBinContent(ix, iy, fcn->Eval(x,y));
  327                  h2->SetBinError  (ix, iy, 0.0);
  328                }
  329              }
  330            }
  331          }
  332 
  333          {
  334            TGraph2D* g2 = dynamic_cast<TGraph2D*>(p);
  335 
  336            if (g2 != NULL) {
  337              for (Int_t i = 0; i != g2->GetN(); ++i) {
  338 
  339                const Double_t 
x = g2->GetX()[i];
 
  340                const Double_t 
y = g2->GetY()[i];
 
  341 
  342                g2->GetZ()[i] = fcn->Eval(x,y);
  343              }
  344            }
  345          }
  346 
  347          {
  348            TGraph2DErrors* g2 = dynamic_cast<TGraph2DErrors*>(p);
  349 
  350            if (g2 != NULL) {
  351              for (Int_t i = 0; i != g2->GetN(); ++i) {
  352                g2->SetPointError(i, 0.0, 0.0, 0.0);
  353              }
  354            }
  355          }
  356        }
  357      }
  358    }
  359 
  360    dir->Close();
  361  }
  362 
  363  out.Write();
  364  out.Close();
  365}
#define DEBUG(A)
Message macros.
 
static JMinimizer minimizer
ROOT minimizer.
 
#define make_field(A,...)
macro to convert parameter to JParserTemplateElement object
 
#define MAKE_CSTRING(A)
Make C-string.
 
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.