added the option to write the content of the MINUIT2.OUTPUT ascii file as yaml. This extends the previous commit from Ryan M.L. McFadden.
This commit is contained in:
@ -265,8 +265,8 @@ UInt_t PSectorChisq::GetNDF(UInt_t idx)
|
||||
* \param runListCollection pointer of the run list collection (pre-processed historgrams)
|
||||
* \param chisq_only flag: true=calculate chisq only (no fitting)
|
||||
*/
|
||||
PFitter::PFitter(PMsrHandler *runInfo, PRunListCollection *runListCollection, Bool_t chisq_only) :
|
||||
fChisqOnly(chisq_only), fRunInfo(runInfo), fRunListCollection(runListCollection)
|
||||
PFitter::PFitter(PMsrHandler *runInfo, PRunListCollection *runListCollection, Bool_t chisq_only, Bool_t yaml_out) :
|
||||
fChisqOnly(chisq_only), fYamlOut(yaml_out), fRunInfo(runInfo), fRunListCollection(runListCollection)
|
||||
{
|
||||
// initialize variables
|
||||
fIsScanOnly = true;
|
||||
@ -2475,120 +2475,121 @@ Bool_t PFitter::ExecuteSave(Bool_t firstSave)
|
||||
hcorr->Write("hcorr", TObject::kOverwrite, sizeof(hcorr));
|
||||
ff.Close();
|
||||
|
||||
// write the fit results to an easy-to-read/parse yaml file
|
||||
// note: the block names follow those used by Python library iminuit
|
||||
// https://github.com/scikit-hep/iminuit
|
||||
if (fYamlOut) {
|
||||
// write the fit results to an easy-to-read/parse yaml file
|
||||
// note: the block names follow those used by Python library iminuit
|
||||
// https://github.com/scikit-hep/iminuit
|
||||
|
||||
// dynamically name the yaml output file
|
||||
// https://stackoverflow.com/a/25389052
|
||||
std::string yaml_filename(fRunInfo->GetFileName().Data());
|
||||
const std::string msr_ext(".msr");
|
||||
yaml_filename.replace(yaml_filename.find(msr_ext), msr_ext.length(),
|
||||
".yaml");
|
||||
// dynamically name the yaml output file
|
||||
// https://stackoverflow.com/a/25389052
|
||||
std::string yaml_filename(fRunInfo->GetFileName().Data());
|
||||
const std::string msr_ext(".msr");
|
||||
yaml_filename.replace(yaml_filename.find(msr_ext), msr_ext.length(),
|
||||
".yaml");
|
||||
|
||||
// define yaml's 2-space indentation
|
||||
const std::string yaml_indent(" ");
|
||||
// define yaml's 2-space indentation
|
||||
const std::string yaml_indent(" ");
|
||||
|
||||
// open the yaml file for writing
|
||||
std::ofstream yaml_file(yaml_filename);
|
||||
// open the yaml file for writing
|
||||
std::ofstream yaml_file(yaml_filename);
|
||||
|
||||
// number formatting of the output
|
||||
yaml_file << std::scientific << std::setprecision(16);
|
||||
// number formatting of the output
|
||||
yaml_file << std::scientific << std::setprecision(16);
|
||||
|
||||
// write the parameter values
|
||||
yaml_file << "values:\n";
|
||||
for (unsigned int i = 0; i < fParams.size(); ++i) {
|
||||
yaml_file << yaml_indent << fParams[i].fName.Data() << ": "
|
||||
<< fParams[i].fValue << "\n";
|
||||
}
|
||||
|
||||
// write the parabolic errors
|
||||
yaml_file << "errors:\n";
|
||||
for (unsigned int i = 0; i < fParams.size(); ++i) {
|
||||
yaml_file << yaml_indent << fParams[i].fName.Data() << ": "
|
||||
<< fMnUserParams.Error(i) << "\n";
|
||||
}
|
||||
|
||||
// write the minos errors
|
||||
yaml_file << "mnerrors:\n";
|
||||
for (unsigned int i = 0; i < fParams.size(); ++i) {
|
||||
// use boost's implementation of a variant, which can be streamed by
|
||||
// default - see: https://stackoverflow.com/q/47168477
|
||||
boost::variant<double, std::string> positive_error, negative_error;
|
||||
if (fParams[i].fPosErrorPresent) {
|
||||
positive_error = fParams[i].fPosError;
|
||||
negative_error = fParams[i].fStep;
|
||||
} else {
|
||||
positive_error = "null";
|
||||
negative_error = "null";
|
||||
// write the parameter values
|
||||
yaml_file << "values:\n";
|
||||
for (unsigned int i = 0; i < fParams.size(); ++i) {
|
||||
yaml_file << yaml_indent << fParams[i].fName.Data() << ": "
|
||||
<< fParams[i].fValue << "\n";
|
||||
}
|
||||
|
||||
yaml_file << yaml_indent << fParams[i].fName.Data() << ":\n";
|
||||
yaml_file << yaml_indent << yaml_indent
|
||||
<< "positive: " << positive_error << "\n";
|
||||
yaml_file << yaml_indent << yaml_indent
|
||||
<< "negative: " << negative_error << "\n";
|
||||
}
|
||||
|
||||
// write the parameter limits
|
||||
yaml_file << "limits:\n";
|
||||
for (unsigned int i = 0; i < fParams.size(); ++i) {
|
||||
// use boost's implementation of a variant, which can be streamed by
|
||||
// default - see: https://stackoverflow.com/q/47168477
|
||||
boost::variant<double, std::string> upper_limit, lower_limit;
|
||||
if (fParams[i].fLowerBoundaryPresent) {
|
||||
lower_limit = fParams[i].fLowerBoundary;
|
||||
} else {
|
||||
lower_limit = "null";
|
||||
}
|
||||
if (fParams[i].fUpperBoundaryPresent) {
|
||||
upper_limit = fParams[i].fUpperBoundary;
|
||||
} else {
|
||||
upper_limit = "null";
|
||||
// write the parabolic errors
|
||||
yaml_file << "errors:\n";
|
||||
for (unsigned int i = 0; i < fParams.size(); ++i) {
|
||||
yaml_file << yaml_indent << fParams[i].fName.Data() << ": "
|
||||
<< fMnUserParams.Error(i) << "\n";
|
||||
}
|
||||
|
||||
yaml_file << yaml_indent << fParams[i].fName.Data() << ":\n";
|
||||
yaml_file << yaml_indent << yaml_indent << "lower: " << lower_limit
|
||||
<< "\n";
|
||||
yaml_file << yaml_indent << yaml_indent << "upper: " << upper_limit
|
||||
<< "\n";
|
||||
}
|
||||
// write the minos errors
|
||||
yaml_file << "mnerrors:\n";
|
||||
for (unsigned int i = 0; i < fParams.size(); ++i) {
|
||||
// use boost's implementation of a variant, which can be streamed by
|
||||
// default - see: https://stackoverflow.com/q/47168477
|
||||
boost::variant<double, std::string> positive_error, negative_error;
|
||||
if (fParams[i].fPosErrorPresent) {
|
||||
positive_error = fParams[i].fPosError;
|
||||
negative_error = fParams[i].fStep;
|
||||
} else {
|
||||
positive_error = "null";
|
||||
negative_error = "null";
|
||||
}
|
||||
|
||||
// write if the parameter is fixed
|
||||
yaml_file << "fixed:\n";
|
||||
for (unsigned int i = 0; i < fParams.size(); ++i) {
|
||||
std::string is_fixed = fParams[i].fStep == 0.0 ? "true" : "false";
|
||||
yaml_file << yaml_indent << fParams[i].fName.Data() << ": " << is_fixed
|
||||
<< "\n";
|
||||
}
|
||||
|
||||
// write the covariance matrix (omitting fixed parameters)
|
||||
yaml_file << "covariance:\n";
|
||||
for (unsigned int i = 0; i < cov.Nrow(); ++i) {
|
||||
yaml_file << yaml_indent << mnState.Name(parNo[i]) << ":\n";
|
||||
for (unsigned int j = 0; j < cov.Nrow(); ++j) {
|
||||
yaml_file << yaml_indent << yaml_indent << mnState.Name(parNo[j])
|
||||
<< ": " << cov(i, j) << "\n";
|
||||
yaml_file << yaml_indent << fParams[i].fName.Data() << ":\n";
|
||||
yaml_file << yaml_indent << yaml_indent
|
||||
<< "positive: " << positive_error << "\n";
|
||||
yaml_file << yaml_indent << yaml_indent
|
||||
<< "negative: " << negative_error << "\n";
|
||||
}
|
||||
}
|
||||
|
||||
// write the correlation matrix (omitting fixed parameters)
|
||||
yaml_file << "correlation:\n";
|
||||
for (unsigned int i = 0; i < cov.Nrow(); ++i) {
|
||||
yaml_file << yaml_indent << mnState.Name(parNo[i]) << ":\n";
|
||||
for (unsigned int j = 0; j < cov.Nrow(); ++j) {
|
||||
double correlation =
|
||||
i == j ? 1.0
|
||||
: cov(i, j) / (fMnUserParams.Error(parNo[i]) *
|
||||
fMnUserParams.Error(parNo[j]));
|
||||
yaml_file << yaml_indent << yaml_indent << mnState.Name(parNo[j])
|
||||
<< ": " << correlation << "\n";
|
||||
// write the parameter limits
|
||||
yaml_file << "limits:\n";
|
||||
for (unsigned int i = 0; i < fParams.size(); ++i) {
|
||||
// use boost's implementation of a variant, which can be streamed by
|
||||
// default - see: https://stackoverflow.com/q/47168477
|
||||
boost::variant<double, std::string> upper_limit, lower_limit;
|
||||
if (fParams[i].fLowerBoundaryPresent) {
|
||||
lower_limit = fParams[i].fLowerBoundary;
|
||||
} else {
|
||||
lower_limit = "null";
|
||||
}
|
||||
if (fParams[i].fUpperBoundaryPresent) {
|
||||
upper_limit = fParams[i].fUpperBoundary;
|
||||
} else {
|
||||
upper_limit = "null";
|
||||
}
|
||||
|
||||
yaml_file << yaml_indent << fParams[i].fName.Data() << ":\n";
|
||||
yaml_file << yaml_indent << yaml_indent << "lower: " << lower_limit
|
||||
<< "\n";
|
||||
yaml_file << yaml_indent << yaml_indent << "upper: " << upper_limit
|
||||
<< "\n";
|
||||
}
|
||||
|
||||
// write if the parameter is fixed
|
||||
yaml_file << "fixed:\n";
|
||||
for (unsigned int i = 0; i < fParams.size(); ++i) {
|
||||
std::string is_fixed = fParams[i].fStep == 0.0 ? "true" : "false";
|
||||
yaml_file << yaml_indent << fParams[i].fName.Data() << ": " << is_fixed
|
||||
<< "\n";
|
||||
}
|
||||
|
||||
// write the covariance matrix (omitting fixed parameters)
|
||||
yaml_file << "covariance:\n";
|
||||
for (unsigned int i = 0; i < cov.Nrow(); ++i) {
|
||||
yaml_file << yaml_indent << mnState.Name(parNo[i]) << ":\n";
|
||||
for (unsigned int j = 0; j < cov.Nrow(); ++j) {
|
||||
yaml_file << yaml_indent << yaml_indent << mnState.Name(parNo[j])
|
||||
<< ": " << cov(i, j) << "\n";
|
||||
}
|
||||
}
|
||||
|
||||
// write the correlation matrix (omitting fixed parameters)
|
||||
yaml_file << "correlation:\n";
|
||||
for (unsigned int i = 0; i < cov.Nrow(); ++i) {
|
||||
yaml_file << yaml_indent << mnState.Name(parNo[i]) << ":\n";
|
||||
for (unsigned int j = 0; j < cov.Nrow(); ++j) {
|
||||
double correlation =
|
||||
i == j ? 1.0
|
||||
: cov(i, j) / (fMnUserParams.Error(parNo[i]) *
|
||||
fMnUserParams.Error(parNo[j]));
|
||||
yaml_file << yaml_indent << yaml_indent << mnState.Name(parNo[j])
|
||||
<< ": " << correlation << "\n";
|
||||
}
|
||||
}
|
||||
|
||||
// close the yaml file
|
||||
yaml_file.close();
|
||||
}
|
||||
|
||||
// close the yaml file
|
||||
yaml_file.close();
|
||||
|
||||
}
|
||||
parNo.clear(); // clean up
|
||||
} else {
|
||||
|
Reference in New Issue
Block a user