diff --git a/Core/Export/PyFmt.cpp b/Core/Export/PyFmt.cpp index c19b4e5f7b73acbfe9058b5ced20d978950173f8..273849e4681f5b35be66d99de166012259dd9340 100644 --- a/Core/Export/PyFmt.cpp +++ b/Core/Export/PyFmt.cpp @@ -43,17 +43,35 @@ std::string printDouble(double input) { return inter.str(); } +//! prints double as an integer, if possible within standard accuracy +std::string printLightDouble(double input) { + std::ostringstream inter; + int ival = std::lround(input); + if (std::abs(input-ival)<1e-11) + inter << ival; + else { + inter << std::setprecision(12); + if (std::abs(input) < std::numeric_limits<double>::epsilon()) + return "0.0"; + inter << input; + if (inter.str().find('e') == std::string::npos && + inter.str().find('.') == std::string::npos) + inter << ".0"; + } + return inter.str(); +} + std::string printNm(double input) { std::ostringstream inter; inter << std::setprecision(12); - inter << printDouble(input) << "*nm"; + inter << printLightDouble(input) << "*nm"; return inter.str(); } std::string printNm2(double input) { std::ostringstream inter; inter << std::setprecision(12); - inter << printDouble(input) << "*nm2"; + inter << printLightDouble(input) << "*nm2"; return inter.str(); } @@ -79,10 +97,7 @@ std::string printScientificDouble(double input) { std::string printDegrees(double input) { std::ostringstream inter; - inter << std::setprecision(11) << Units::rad2deg(input); - if (inter.str().find('e') == std::string::npos && inter.str().find('.') == std::string::npos) - inter << ".0"; - inter << "*deg"; + inter << printLightDouble(Units::rad2deg(input)) << "*deg"; return inter.str(); } diff --git a/Core/Export/PyFmt.h b/Core/Export/PyFmt.h index 5bcd068d5a1293c7ac55a761cf2b964bd572724a..d123014c5aaf557bdf3f75609fa4a470184f8f04 100644 --- a/Core/Export/PyFmt.h +++ b/Core/Export/PyFmt.h @@ -23,8 +23,6 @@ #include "Base/Vector/Vectors3D.h" #include <string> -class RealLimits; - //! Utility functions for writing Python code snippets. namespace pyfmt { @@ -34,6 +32,7 @@ std::string scriptPreamble(); std::string printInt(int value); std::string printBool(double value); std::string printDouble(double input); +std::string printLightDouble(double input); std::string printNm(double input); std::string printNm2(double input); std::string printScientificDouble(double input); diff --git a/Core/Export/PyFmt2.cpp b/Core/Export/PyFmt2.cpp index 9beef009a77ebb61df04debf295232b0de8ca6ca..90514074f3f9bd2b76d0599e191f7a62f0365fed 100644 --- a/Core/Export/PyFmt2.cpp +++ b/Core/Export/PyFmt2.cpp @@ -96,9 +96,7 @@ std::string representShape2D(const std::string& indent, const IShape2D* ishape, //! Returns parameter value, followed by its unit multiplicator (like "* nm"). std::string valueTimesUnit(const RealParameter* par) { - if (par->unit() == "rad") - return pyfmt::printDegrees(par->value()); - return pyfmt::printDouble(par->value()) + (par->unit() == "" ? "" : ("*" + par->unit())); + return pyfmt::printValue(par->value(), par->unit()); } //! Returns comma-separated list of parameter values, including unit multiplicator (like "* nm"). diff --git a/Tests/UnitTests/Core/Core/PythonFormattingTest.cpp b/Tests/UnitTests/Core/Core/PythonFormattingTest.cpp index 233ce35ed27010da39c6dd4367cac6c80c301d27..f2a9e7b75dfee11a8719d7e387d2b985efda1f43 100644 --- a/Tests/UnitTests/Core/Core/PythonFormattingTest.cpp +++ b/Tests/UnitTests/Core/Core/PythonFormattingTest.cpp @@ -9,37 +9,37 @@ class PythonFormattingTest : public ::testing::Test {}; TEST_F(PythonFormattingTest, ValueTimesUnits) { - EXPECT_EQ("2.0*nm", pyfmt::printValue(2.0, "nm")); - EXPECT_EQ("2.0*deg", pyfmt::printValue(2.0 * Units::deg, "rad")); + EXPECT_EQ("2*nm", pyfmt::printValue(2.0, "nm")); + EXPECT_EQ("2*deg", pyfmt::printValue(2.0 * Units::deg, "rad")); EXPECT_EQ("2.0", pyfmt::printValue(2.0, "")); } TEST_F(PythonFormattingTest, RealLimits) { EXPECT_EQ("RealLimits.lowerLimited(1.0)", pyfmt::printRealLimits(RealLimits::lowerLimited(1.0))); - EXPECT_EQ("RealLimits.lowerLimited(1.0*nm)", + EXPECT_EQ("RealLimits.lowerLimited(1*nm)", pyfmt::printRealLimits(RealLimits::lowerLimited(1.0), "nm")); - EXPECT_EQ("RealLimits.lowerLimited(1.0*deg)", + EXPECT_EQ("RealLimits.lowerLimited(1*deg)", pyfmt::printRealLimits(RealLimits::lowerLimited(1.0 * Units::deg), "rad")); EXPECT_EQ("RealLimits.upperLimited(1.0)", pyfmt::printRealLimits(RealLimits::upperLimited(1.0))); - EXPECT_EQ("RealLimits.upperLimited(1.0*nm)", + EXPECT_EQ("RealLimits.upperLimited(1*nm)", pyfmt::printRealLimits(RealLimits::upperLimited(1.0), "nm")); - EXPECT_EQ("RealLimits.upperLimited(1.0*deg)", + EXPECT_EQ("RealLimits.upperLimited(1*deg)", pyfmt::printRealLimits(RealLimits::upperLimited(1.0 * Units::deg), "rad")); EXPECT_EQ("RealLimits.limited(1.0, 2.0)", pyfmt::printRealLimits(RealLimits::limited(1.0, 2.0))); - EXPECT_EQ("RealLimits.limited(1.0*nm, 2.0*nm)", + EXPECT_EQ("RealLimits.limited(1*nm, 2*nm)", pyfmt::printRealLimits(RealLimits::limited(1.0, 2.0), "nm")); EXPECT_EQ( - "RealLimits.limited(1.0*deg, 2.0*deg)", + "RealLimits.limited(1*deg, 2*deg)", pyfmt::printRealLimits(RealLimits::limited(1.0 * Units::deg, 2.0 * Units::deg), "rad")); // testing printing of real limits in the context of ParameterDistribution and similar EXPECT_EQ( - ", ba.RealLimits.limited(1.0*deg, 2.0*deg)", + ", ba.RealLimits.limited(1*deg, 2*deg)", pyfmt::printRealLimitsArg(RealLimits::limited(1.0 * Units::deg, 2.0 * Units::deg), "rad")); EXPECT_EQ("", pyfmt::printRealLimitsArg(RealLimits::limitless())); @@ -50,14 +50,14 @@ TEST_F(PythonFormattingTest, printDistribution) { "ba.DistributionGate(1.0, 2.0)"); EXPECT_EQ(pyfmt2::printDistribution(DistributionGate(1.0, 2.0), "nm"), - "ba.DistributionGate(1.0*nm, 2.0*nm)"); + "ba.DistributionGate(1*nm, 2*nm)"); EXPECT_EQ( pyfmt2::printDistribution(DistributionGate(1.0 * Units::deg, 2.0 * Units::deg), "rad"), - "ba.DistributionGate(1.0*deg, 2.0*deg)"); + "ba.DistributionGate(1*deg, 2*deg)"); EXPECT_EQ(pyfmt2::printDistribution(DistributionLogNormal(1.0 * Units::deg, 0.01), "rad"), - "ba.DistributionLogNormal(1.0*deg, 0.01)"); + "ba.DistributionLogNormal(1*deg, 0.01)"); } TEST_F(PythonFormattingTest, printParameterDistribution) { @@ -79,12 +79,12 @@ TEST_F(PythonFormattingTest, printParameterDistribution) { ParameterDistribution dist3("ParName", gate, 5, 2.0, RealLimits::limited(1.0, 2.0)); EXPECT_EQ(pyfmt2::printParameterDistribution(dist3, "distr_1", "nm"), "ba.ParameterDistribution(\"ParName\", distr_1, " - "5, 2.0, ba.RealLimits.limited(1.0*nm, 2.0*nm))"); + "5, 2.0, ba.RealLimits.limited(1*nm, 2*nm))"); // RealLimits defined, checking that method guess radians units correctly ParameterDistribution dist4("/Particle/ZRotation/Angle", gate, 5, 2.0, RealLimits::limited(1.0 * Units::deg, 2.0 * Units::deg)); EXPECT_EQ(pyfmt2::printParameterDistribution(dist4, "distr_1", "rad"), "ba.ParameterDistribution(\"/Particle/ZRotation/Angle\", " - "distr_1, 5, 2.0, ba.RealLimits.limited(1.0*deg, 2.0*deg))"); + "distr_1, 5, 2.0, ba.RealLimits.limited(1*deg, 2*deg))"); } diff --git a/auto/Wrap/doxygenCore.i b/auto/Wrap/doxygenCore.i index e3146e9007ac9bc782a3ce5a28992d4fd24d770e..f36d5b93012e96a20de8d593cd1771e0ab21c9b9 100644 --- a/auto/Wrap/doxygenCore.i +++ b/auto/Wrap/doxygenCore.i @@ -2401,6 +2401,11 @@ Returns default metric name. %feature("docstring") pyfmt::printDouble "std::string pyfmt::printDouble(double input) "; +%feature("docstring") pyfmt::printLightDouble "std::string pyfmt::printLightDouble(double input) + +prints double as an integer, if possible within standard accuracy +"; + %feature("docstring") pyfmt::printNm "std::string pyfmt::printNm(double input) ";