Skip to content

Commit 71dfea7

Browse files
committed
[RF] Rewrite variable printing with std::stringstream
This ensures that RooFit printouts will be independent of the locale setting. Here is my little script to test this: ```Python import locale def check_numeric_locale(): locale.setlocale(locale.LC_ALL, "") # Get the active numeric locale current = locale.setlocale(locale.LC_NUMERIC) print(f"Active LC_NUMERIC: {current}") # Format a floating point number according to this locale number = 12345.67 formatted = locale.format_string("%.2f", number, grouping=True) print(f"Formatted number: {formatted}") # Show what decimal point is being used conv = locale.localeconv() print(f"Decimal point: {conv['decimal_point']}") print(f"Thousands separator: {conv['thousands_sep']}") if __name__ == "__main__": check_numeric_locale() import ROOT print(ROOT.std.stod("3.33")) x = ROOT.RooRealVar("x", "x", 3.12, -10., 10.) x.setError(1.23) print(x.format(4, "")) ROOT.RooRealVar.printScientific(True) x.writeToStream(ROOT.std.cout, False) x.writeToStream(ROOT.std.cout, True) ```
1 parent dc33411 commit 71dfea7

File tree

3 files changed

+84
-117
lines changed

3 files changed

+84
-117
lines changed

roofit/histfactory/src/HistoToWorkspaceFactoryFast.cxx

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,8 @@
6868
#include "RooStats/HistFactory/HistFactoryException.h"
6969

7070
#include <algorithm>
71+
#include <fstream>
72+
#include <iomanip>
7173
#include <memory>
7274
#include <utility>
7375

@@ -694,26 +696,28 @@ RooArgList HistoToWorkspaceFactoryFast::createObservables(const TH1 *hist, RooWo
694696

695697
void HistoToWorkspaceFactoryFast::PrintCovarianceMatrix(RooFitResult* result, RooArgSet* params, string filename){
696698

697-
FILE* covFile = fopen ((filename).c_str(),"w");
698-
fprintf(covFile," ") ;
699+
std::ofstream covFile(filename);
700+
701+
covFile << " ";
699702
for (auto const *myargi : static_range_cast<RooRealVar *>(*params)) {
700703
if(myargi->isConstant()) continue;
701-
fprintf(covFile," & %s", myargi->GetName());
704+
covFile << " & " << myargi->GetName();
702705
}
703-
fprintf(covFile,"\\\\ \\hline \n" );
706+
covFile << "\\\\ \\hline \n";
704707
for (auto const *myargi : static_range_cast<RooRealVar *>(*params)) {
705708
if(myargi->isConstant()) continue;
706-
fprintf(covFile,"%s", myargi->GetName());
709+
covFile << myargi->GetName();
707710
for (auto const *myargj : static_range_cast<RooRealVar *>(*params)) {
708711
if(myargj->isConstant()) continue;
709712
std::cout << myargi->GetName() << "," << myargj->GetName();
710-
fprintf(covFile, " & %.2f", result->correlation(*myargi, *myargj));
713+
double corr = result->correlation(*myargi, *myargj);
714+
covFile << " & " << std::fixed << std::setprecision(2) << corr;
711715
}
712716
std::cout << std::endl;
713-
fprintf(covFile, " \\\\\n");
717+
covFile << " \\\\\n";
714718
}
715-
fclose(covFile);
716719

720+
covFile.close();
717721
}
718722

719723

roofit/roofitcore/inc/RooRealVar.h

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -147,8 +147,6 @@ class RooRealVar : public RooAbsRealLValue {
147147
void attachToVStore(RooVectorDataStore& vstore) override ;
148148
void fillTreeBranch(TTree& t) override ;
149149

150-
double chopAt(double what, Int_t where) const ;
151-
152150
double _error; ///< Symmetric error associated with current value
153151
double _asymErrLo ; ///< Low side of asymmetric error associated with current value
154152
double _asymErrHi ; ///< High side of asymmetric error associated with current value

roofit/roofitcore/src/RooRealVar.cxx

Lines changed: 72 additions & 107 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,8 @@ or integrals to sub ranges. The range without any name is used as default range.
4444
#include "TTree.h"
4545
#include "TBuffer.h"
4646
#include "TBranch.h"
47-
#include "snprintf.h"
47+
48+
#include <iomanip>
4849

4950
using std::endl, std::ostream, std::istream;
5051

@@ -753,63 +754,63 @@ bool RooRealVar::readFromStream(istream& is, bool compact, bool verbose)
753754
////////////////////////////////////////////////////////////////////////////////
754755
/// Write object contents to given stream
755756

756-
void RooRealVar::writeToStream(ostream& os, bool compact) const
757+
void RooRealVar::writeToStream(ostream &os, bool compact) const
757758
{
758-
if (compact) {
759-
// Write value only
760-
os << getVal() ;
761-
} else {
759+
if (compact) {
760+
// Write value only
761+
os << getVal();
762+
return;
763+
}
764+
765+
// Write value with error (if not zero)
766+
if (_printScientific) {
767+
std::stringstream text;
762768

763-
// Write value with error (if not zero)
764-
if (_printScientific) {
765-
char fmtVal[16];
766-
char fmtErr[16];
767-
snprintf(fmtVal,16,"%%.%de",_printSigDigits) ;
768-
snprintf(fmtErr,16,"%%.%de",(_printSigDigits+1)/2) ;
769-
if (_value>=0) os << " " ;
770-
os << Form(fmtVal,_value) ;
769+
int nDigitsVal = _printSigDigits;
770+
int nDigitsErr = (_printSigDigits + 1) / 2;
771771

772+
text << std::scientific;
773+
774+
if (_value >= 0)
775+
text << " ";
776+
text << std::setprecision(nDigitsVal) << _value;
777+
778+
text << std::setprecision(nDigitsErr) << " +/- ";
772779
if (hasAsymError()) {
773-
os << " +/- (" << Form(fmtErr,getAsymErrorLo())
774-
<< ", " << Form(fmtErr,getAsymErrorHi()) << ")" ;
775-
} else if (hasError()) {
776-
os << " +/- " << Form(fmtErr,getError()) ;
780+
text << "(" << getAsymErrorLo() << ", " << getAsymErrorHi() << ")";
781+
} else if (hasError()) {
782+
text << getError();
777783
}
778784

779-
os << " " ;
780-
} else {
781-
os << format(_printSigDigits,"EFA") << " " ;
782-
}
785+
os << text.str() << " ";
786+
} else {
787+
os << format(_printSigDigits, "EFA") << " ";
788+
}
783789

784-
// Append limits if not constants
785-
if (isConstant()) {
786-
os << "C " ;
787-
}
790+
// Append limits if not constants
791+
if (isConstant()) {
792+
os << "C ";
793+
}
788794

789-
// Append fit limits
790-
os << "L(" ;
791-
if(hasMin()) {
792-
os << getMin();
793-
}
794-
else {
795-
os << "-INF";
796-
}
797-
if(hasMax()) {
798-
os << " - " << getMax() ;
799-
}
800-
else {
801-
os << " - +INF";
802-
}
803-
os << ") " ;
795+
// Append fit limits
796+
if (hasMin()) {
797+
os << "L(" << getMin();
798+
} else {
799+
os << "L(-INF";
800+
}
801+
if (hasMax()) {
802+
os << " - " << getMax() << ") ";
803+
} else {
804+
os << " - +INF) ";
805+
}
804806

805-
if (getBins()!=100) {
806-
os << "B(" << getBins() << ") " ;
807-
}
807+
if (getBins() != 100) {
808+
os << "B(" << getBins() << ") ";
809+
}
808810

809-
// Add comment with unit, if unit exists
810-
if (!_unit.IsNull())
811-
os << "// [" << getUnit() << "]" ;
812-
}
811+
// Add comment with unit, if unit exists
812+
if (!_unit.IsNull())
813+
os << "// [" << getUnit() << "]";
813814
}
814815

815816

@@ -1010,107 +1011,71 @@ std::string RooRealVar::format(Int_t sigDigits, const char *options) const
10101011
Int_t leadingDigitErr= (Int_t)floor(log10(std::abs(_error+1e-10)));
10111012
Int_t whereVal= leadingDigitVal - sigDigits + 1;
10121013
Int_t whereErr= leadingDigitErr - sigDigits + 1;
1013-
char fmtVal[16];
1014-
char fmtErr[16];
10151014

10161015
if (_value<0) whereVal -= 1 ;
1017-
snprintf(fmtVal,16,"%%.%df", whereVal < 0 ? -whereVal : 0);
1018-
snprintf(fmtErr,16,"%%.%df", whereErr < 0 ? -whereErr : 0);
1019-
std::string text;
1020-
if(latexMode) text += "$";
1016+
int nDigitsVal = whereVal < 0 ? -whereVal : 0;
1017+
int nDigitsErr = whereErr < 0 ? -whereErr : 0;
1018+
1019+
std::stringstream text;
1020+
1021+
if(latexMode) text << "$";
10211022
// begin the string with "<name> = " if requested
10221023
if(showName || showTitle) {
10231024
if (latexTableMode && latexVerbatimName) {
1024-
text += "\\verb+";
1025+
text << "\\verb+";
10251026
}
1026-
text += label;
1027-
if (latexVerbatimName) text += "+";
1027+
text << label;
1028+
if (latexVerbatimName) text << "+";
10281029

10291030
if (!latexTableMode) {
1030-
text += " = ";
1031+
text << " = ";
10311032
} else {
1032-
text += " $ & $ ";
1033+
text << " $ & $ ";
10331034
}
10341035
}
10351036

10361037
// Add leading space if value is positive
1037-
if (_value>=0) text += " ";
1038+
if (_value>=0) text << " ";
10381039

10391040
// append our value if requested
1040-
char buffer[256];
1041+
text << std::fixed;
10411042
if(!hideValue) {
1042-
chopAt(_value, whereVal);
1043-
snprintf(buffer, 256,fmtVal, _value);
1044-
text += buffer;
1043+
text << std::setprecision(nDigitsVal) << _value;
10451044
}
1045+
text << std::setprecision(nDigitsErr); // we only print errors from now on
10461046

10471047
// append our error if requested and this variable is not constant
10481048
if(hasError(false) && showError && !(asymError && hasAsymError(false))) {
10491049
if(tlatexMode) {
1050-
text += " #pm ";
1050+
text << " #pm " << getError();
10511051
}
10521052
else {
1053-
text += latexMode ? "\\pm " : " +/- ";
1053+
text << (latexMode ? "\\pm " : " +/- ") << getError();
10541054
}
1055-
snprintf(buffer, 256,fmtErr, getError());
1056-
text += buffer;
10571055
}
10581056

10591057
if (asymError && hasAsymError() && showError) {
10601058
if(tlatexMode) {
1061-
text += " #pm _{";
1062-
snprintf(buffer, 256,fmtErr, getAsymErrorLo());
1063-
text += buffer;
1064-
text += "}^{+";
1065-
snprintf(buffer, 256,fmtErr, getAsymErrorHi());
1066-
text += buffer;
1067-
text += "}";
1059+
text << " #pm _{" << getAsymErrorLo() << "}^{+" << getAsymErrorHi() << "}";
10681060
}
10691061
else if(latexMode) {
1070-
text += "\\pm _{";
1071-
snprintf(buffer, 256,fmtErr, getAsymErrorLo());
1072-
text += buffer;
1073-
text += "}^{+";
1074-
snprintf(buffer, 256,fmtErr, getAsymErrorHi());
1075-
text += buffer;
1076-
text += "}";
1062+
text << "\\pm _{" << getAsymErrorLo() << "}^{+" << getAsymErrorHi() << "}";
10771063
}
10781064
else {
1079-
text += " +/- (";
1080-
snprintf(buffer, 256, fmtErr, getAsymErrorLo());
1081-
text += buffer;
1082-
text += ", ";
1083-
snprintf(buffer, 256, fmtErr, getAsymErrorHi());
1084-
text += buffer;
1085-
text += ")";
1065+
text << " +/- (" << getAsymErrorLo() << ", " << getAsymErrorHi() << ")";
10861066
}
10871067

10881068
}
10891069

10901070
// append our units if requested
10911071
if(!_unit.IsNull() && showUnit) {
1092-
text += ' ';
1093-
text += _unit;
1072+
text << ' ' << _unit;
10941073
}
1095-
if(latexMode) text += "$";
1096-
return text;
1074+
if(latexMode) text << "$";
1075+
return text.str();
10971076
}
10981077

10991078

1100-
1101-
////////////////////////////////////////////////////////////////////////////////
1102-
/// Utility to calculate number of decimals to show
1103-
/// based on magnitude of error
1104-
1105-
double RooRealVar::chopAt(double what, Int_t where) const
1106-
{
1107-
double scale= pow(10.0,where);
1108-
Int_t trunc= (Int_t)floor(what/scale + 0.5);
1109-
return (double)trunc*scale;
1110-
}
1111-
1112-
1113-
11141079
////////////////////////////////////////////////////////////////////////////////
11151080
/// Overload RooAbsReal::attachToTree to also attach
11161081
/// branches for errors and/or asymmetric errors

0 commit comments

Comments
 (0)