102{
  105 
  106  typedef JToken<
';'>      JToken_t;
 
  108 
  111  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;\"");
 
  137    zap[
'O'] = 
make_field(option,      
"Fit option")                         = 
"";
 
  138    zap[
'w'] = 
make_field(writeFits,   
"write fit function(s) to ROOT file " << 
"(\"<name>" << _F3 << 
"\")");
 
  141 
  142    zap(argc, argv);
  143  }
  144  catch(const exception &error) {
  145    FATAL(error.what() << endl);
 
  146  }
  147 
  148 
  149  if (option.find('O') == string::npos) { option += "O"; }
  150  if (option.find("R") == string::npos) { option += "R"; }
  151  if (option.find("S") == string::npos) { option += "S"; }
  152  
  153  if (
debug ==  0 && option.find(
'Q') == string::npos) { option += 
"Q"; }
 
  154 
  155 
  157 
  158 
  159  TF3* fcn = new TF3("user", formula.c_str());
  160 
  161  fcn->SetNpx(300);
  162  fcn->SetNpy(300);
  163  fcn->SetNpz(300);
  164 
  165  if (fcn->IsZombie()) {
  166    FATAL(
"Function: " << formula << 
" is zombie." << endl);
 
  167  }
  168 
  169  for (vector<JRootObjectID>::const_iterator input = inputFile.begin(); input != inputFile.end(); ++input) {
  170 
  171    DEBUG(
"Input: " << *input << endl);
 
  172 
  174 
  175    if (dir == NULL) {
  176      ERROR(
"File: " << input->getFullFilename() << 
" not opened." << endl);
 
  177      continue;
  178    }
  179 
  180    const TRegexp regexp(input->getObjectName());
  181 
  182    TIter iter(dir->GetListOfKeys());
  183 
  184    for (TKey* key; (
key = (TKey*) iter.Next()) != NULL; ) {
 
  185       
  186      const TString tag(
key->GetName());
 
  187 
  188      DEBUG(
"Key: " << tag << 
" match = " << tag.Contains(regexp) << endl);
 
  189 
  190      
  191      
  192      if (tag.Contains(regexp) && 
isTObject(key)) {
 
  193        
  195      
  196 
  197        
  198 
  199        try {
  200 
  201          for (vector<JToken_t>::const_iterator i = startValues.begin(); i != startValues.end(); ++i) {
  203          }
  204 
  205          for (Int_t i = 0; i != fcn->GetNpar(); ++i) {
  206            fcn->SetParError (i, 0.0);
  207          }
  208 
  209          for (vector<JToken_t>::const_iterator i = startErrors.begin(); i != startErrors.end(); ++i) {
  211          }
  212          
  213          for (vector<JToken_t>::const_iterator i = fixedValues.begin(); i != fixedValues.end(); ++i) {
  215          }
  216 
  217          for (vector<JToken_t>::const_iterator i = limitValues.begin(); i != limitValues.end(); ++i) {
  219          }
  220 
  221        }
  223          FATAL(error << endl);
 
  224        }
  225 
  226        DEBUG(
"Start values " << object->GetName() << endl);
 
  227 
  228        for (int i = 0; i != fcn->GetNpar(); ++i) {
  229          DEBUG(left << setw(12) << fcn->GetParName  (i) << 
' ' << 
 
  230                SCIENTIFIC(12,5) << fcn->GetParameter(i) << endl);
 
  231        }
  232 
  233        Double_t 
xmin = numeric_limits<Double_t>::max();
 
  234        Double_t 
xmax = numeric_limits<Double_t>::lowest();
 
  235        Double_t ymin = numeric_limits<Double_t>::max();
  236        Double_t ymax = numeric_limits<Double_t>::lowest();
  237        Double_t zmin = numeric_limits<Double_t>::max();
  238        Double_t zmax = numeric_limits<Double_t>::lowest();
  239 
  240        {
  241          TH3* h3 = dynamic_cast<TH3*>(object);
  242 
  243          if (h3 != NULL) {
  244            xmin = min(xmin, h3->GetXaxis()->GetXmin());
 
  245            xmax = max(xmax, h3->GetXaxis()->GetXmax());
 
  246            ymin = min(ymin, h3->GetYaxis()->GetXmin());
  247            ymax = max(ymax, h3->GetYaxis()->GetXmax());
  248            zmin = min(zmin, h3->GetZaxis()->GetXmin());
  249            zmax = max(zmax, h3->GetZaxis()->GetXmax());
  250          }
  251        }
  252 
  256        }
  257 
  261        }
  262 
  266        }
  267 
  268        fcn->SetRange(xmin, ymin, zmin, xmax, ymax, zmax);
  269 
  270          
  271        
  272 
  273        const chrono::steady_clock::time_point t0 = chrono::steady_clock::now();
  274 
  275        JFit fit(*
object, fcn, option);
 
  276 
  278  
  279        const chrono::steady_clock::time_point t1 = chrono::steady_clock::now();
  280 
  281        if (fit.result != -1) {
  282 
  283          
  284            
  285          NOTICE(
"Fit values  " << object->GetName() << endl);
 
  286          NOTICE(
"Fit formula " << formula           << endl);
 
  287          NOTICE(
"chi2/NDF "    << 
FIXED(7,3) << fit.result->Chi2() << 
'/' << fit.result->Ndf() << 
' ' << (fit.result->IsValid() ? 
"" : 
"failed") << endl);
 
  288          NOTICE(
"Number of calls " << fit.result->NCalls() << endl);
 
  289          NOTICE(
"Elapsed time [us] " << setw(8) << chrono::duration_cast<chrono::microseconds>(t1 - t0).count() << endl);
 
  290 
  291          for (
int j = 0; 
j != fcn->GetNpar(); ++
j) {
 
  292            NOTICE(left << setw(12) << fcn->GetParName  (
j) << 
' '     << 
 
  293                   SCIENTIFIC(12,5) << fcn->GetParameter(
j) << 
" +/- " << 
 
  295          }
  296 
  297        } else {
  298 
  299          WARNING(
"Object: not compatible with ROOT Fit." << endl);
 
  300        }
  301 
  302        out.cd();
  303        
  304        object->Write();
  305        fcn   ->Write();
  306 
  307        if (writeFits) {
  308 
  310 
  311          {
  312            TH2* h2 = dynamic_cast<TH2*>(p);
  313 
  314            if (h2 != NULL) {
  315              for (Int_t ix = 1; ix <= h2->GetXaxis()->GetNbins(); ++ix) {
  316                for (Int_t iy = 1; iy <= h2->GetYaxis()->GetNbins(); ++iy) {
  317                  for (Int_t iz = 1; iz <= h2->GetZaxis()->GetNbins(); ++iz) {
  318 
  319                    const Double_t 
x = h2->GetXaxis()->GetBinCenter(ix);
 
  320                    const Double_t 
y = h2->GetYaxis()->GetBinCenter(iy);
 
  321                    const Double_t z = h2->GetZaxis()->GetBinCenter(iz);
  322 
  323                    h2->SetBinContent(ix, iy, fcn->Eval(x,y,z));
  324                    h2->SetBinError  (ix, iy, 0.0);
  325                  }
  326                }
  327              }
  328            }
  329          }
  330        }
  331      }
  332    }
  333 
  334    dir->Close();
  335  }
  336 
  337  out.Write();
  338  out.Close();
  339}
#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.