BornAgain  1.19.79
Open-source research software to simulate and fit neutron and x-ray reflectometry and grazing-incidence small-angle scattering
PyFmt2.cpp
Go to the documentation of this file.
1 // ************************************************************************************************
2 //
3 // BornAgain: simulate and fit reflection and scattering
4 //
5 //! @file Sim/Export/PyFmt2.cpp
6 //! @brief Implements functions from namespace pyfmt2.
7 //!
8 //! @homepage http://www.bornagainproject.org
9 //! @license GNU General Public License v3 or higher (see COPYING)
10 //! @copyright Forschungszentrum Jülich GmbH 2018
11 //! @authors Scientific Computing Group at MLZ (see CITATION, AUTHORS)
12 //
13 // ************************************************************************************************
14 
15 #include "Sim/Export/PyFmt2.h"
16 #include "Base/Axis/FixedBinAxis.h"
18 #include "Base/Const/Units.h"
19 #include "Base/Math/Constants.h"
20 #include "Base/Py/PyFmt.h"
21 #include "Base/Util/Algorithms.h"
22 #include "Base/Util/StringUtils.h"
23 #include "Device/Mask/Ellipse.h"
25 #include "Device/Mask/Line.h"
26 #include "Device/Mask/Polygon.h"
27 #include "Device/Mask/Rectangle.h"
31 #include "Sim/Export/PyFmtLimits.h"
32 #include <iomanip>
33 
34 namespace Py::Fmt2 {
35 
36 //! Returns fixed Python code snippet that defines the function "simulate".
37 
38 std::string representShape2D(const std::string& indent, const IShape2D* ishape, bool mask_value,
39  std::function<std::string(double)> printValueFunc)
40 {
41  std::ostringstream result;
42  result << std::setprecision(12);
43 
44  if (const auto* shape = dynamic_cast<const Polygon*>(ishape)) {
45  std::vector<double> xpos, ypos;
46  shape->getPoints(xpos, ypos);
47  result << indent << "points = [";
48  for (size_t i = 0; i < xpos.size(); ++i) {
49  result << "[" << printValueFunc(xpos[i]) << ", " << printValueFunc(ypos[i]) << "]";
50  if (i != xpos.size() - 1)
51  result << ", ";
52  }
53  result << "]\n";
54  result << indent << "simulation.addMask("
55  << "ba.Polygon(points), " << Py::Fmt::printBool(mask_value) << ")\n";
56  } else if (dynamic_cast<const InfinitePlane*>(ishape))
57  result << indent << "simulation.maskAll()\n";
58  else if (const auto* shape = dynamic_cast<const Ellipse*>(ishape)) {
59  result << indent << "simulation.addMask(";
60  result << "ba.Ellipse(" << printValueFunc(shape->getCenterX()) << ", "
61  << printValueFunc(shape->getCenterY()) << ", " << printValueFunc(shape->radiusX())
62  << ", " << printValueFunc(shape->radiusY());
63  if (shape->getTheta() != 0.0)
64  result << ", " << Py::Fmt::printDegrees(shape->getTheta());
65  result << "), " << Py::Fmt::printBool(mask_value) << ")\n";
66  }
67 
68  else if (const auto* shape = dynamic_cast<const Rectangle*>(ishape)) {
69  result << indent << "simulation.addMask(";
70  result << "ba.Rectangle(" << printValueFunc(shape->getXlow()) << ", "
71  << printValueFunc(shape->getYlow()) << ", " << printValueFunc(shape->getXup())
72  << ", " << printValueFunc(shape->getYup()) << "), " << Py::Fmt::printBool(mask_value)
73  << ")\n";
74  }
75 
76  else if (const auto* shape = dynamic_cast<const VerticalLine*>(ishape)) {
77  result << indent << "simulation.addMask(";
78  result << "ba.VerticalLine(" << printValueFunc(shape->getXpos()) << "), "
79  << Py::Fmt::printBool(mask_value) << ")\n";
80  }
81 
82  else if (const auto* shape = dynamic_cast<const HorizontalLine*>(ishape)) {
83  result << indent << "simulation.addMask(";
84  result << "ba.HorizontalLine(" << printValueFunc(shape->getYpos()) << "), "
85  << Py::Fmt::printBool(mask_value) << ")\n";
86  } else
87  throw std::runtime_error("representShape2D(const IShape2D*) -> Error. Unknown shape");
88 
89  return result.str();
90 }
91 
92 //! Prints an axis.
93 std::string printAxis(const IAxis* axis, const std::string& unit)
94 {
95  std::ostringstream result;
96  if (const auto* a = dynamic_cast<const FixedBinAxis*>(axis); a)
97  result << "ba.FixedBinAxis(" << Py::Fmt::printString(a->axisName()) << ", " << a->size()
98  << ", " << Py::Fmt::printValue(a->min(), unit) << ", "
99  << Py::Fmt::printValue(a->max(), unit) << ")";
100  else if (const auto* a = dynamic_cast<const PointwiseAxis*>(axis); a) {
101  result << "numpy.asarray([";
102  const std::vector<double>& points = a->binCenters();
103  for (auto iter = points.begin(); iter != points.end() - 1; ++iter)
104  result << Py::Fmt::printValue(*iter, unit) << ",";
105  result << Py::Fmt::printValue(points.back(), unit) << "])\n";
106  } else
107  throw std::runtime_error("printAxis not implemented for current axis type");
108  return result.str();
109 }
110 
112  const std::string& distVarName, const std::string& units)
113 {
114  std::ostringstream result;
115 
116  result << "ba.ParameterDistribution(ba." << par_distr.whichParameterAsPyEnum() << ", "
117  << distVarName << ", " << par_distr.nDraws() << ", "
118  << Py::Fmt::printDouble(par_distr.sigmaFactor())
119  << Py::Fmt::printRealLimitsArg(par_distr.getLimits(), units) << ")";
120 
121  return result.str();
122 }
123 
125 {
126  std::ostringstream result;
127  result << Py::Fmt::indent() << "distribution = ba.";
128  result << distr.name();
129  result << "(" << distr.nSamples() << ", " << Py::Fmt::printDouble(distr.sigmaFactor());
130  if (!distr.limits().isLimitless())
131  result << Py::Fmt::printRealLimitsArg(distr.limits());
132  result << ")";
133  return result.str();
134 }
135 
136 } // namespace Py::Fmt2
Defines and implements namespace BaseUtils::algo with some algorithms.
Defines a few helper functions.
Defines M_PI and some more mathematical constants.
Defines classes representing one-dimensional distributions.
Defines class Rectangle.
Defines class FixedBinAxis.
Defines class InfinitePlane.
Defines class Line.
Defines class ParameterDistribution.
Defines class PointwiseAxis.
Defines class Polygon.
Defines namespace pyfmt2.
Defines namespace pyfmt.
Defines namespace pyfmt.
Defines classes representing ranged one-dimensional distributions.
Defines class Rectangle.
Defines some unit conversion factors and other constants in namespace Units.
An ellipse, for use in detector masks.
Definition: Ellipse.h:23
Axis with fixed bin size.
Definition: FixedBinAxis.h:23
An infinite horizontal line.
Definition: Line.h:55
Abstract base class for one-dimensional axes.
Definition: IAxis.h:27
Interface for one-dimensional ranged distributions. All derived distributions allow for generating sa...
double sigmaFactor() const
Returns sigma factor to use during sampling.
virtual std::string name() const =0
Returns distribution name for python-formatted text.
RealLimits limits() const
Returns current limits of the distribution.
size_t nSamples() const
Returns number of samples to generate.
Basic class for all shapes in 2D.
Definition: IShape2D.h:26
The infinite plane is used for masking the entire detector.
Definition: InfinitePlane.h:28
A parametric distribution function, for use with any model parameter.
std::string whichParameterAsPyEnum() const
double sigmaFactor() const
get the sigma factor
size_t nDraws() const
get number of samples for this distribution
RealLimits getLimits() const
Axis containing arbitrary (non-equidistant) coordinate values. Lower boundary of the first bin and up...
Definition: PointwiseAxis.h:33
A polygon, for use in detector masks.
Definition: Polygon.h:30
bool isLimitless() const
Definition: RealLimits.cpp:192
A rectangle, for use in detector masks.
Definition: Rectangle.h:25
An infinite vertical line.
Definition: Line.h:38
Utility functions for writing Python code snippets.
Definition: PyFmt2.cpp:34
std::string representShape2D(const std::string &indent, const IShape2D *ishape, bool mask_value, std::function< std::string(double)> printValueFunc)
Returns fixed Python code snippet that defines the function "simulate".
Definition: PyFmt2.cpp:38
std::string printRangedDistribution(const IRangedDistribution &distr)
Definition: PyFmt2.cpp:124
std::string printParameterDistribution(const ParameterDistribution &par_distr, const std::string &distVarName, const std::string &units)
Definition: PyFmt2.cpp:111
std::string printAxis(const IAxis *axis, const std::string &unit)
Prints an axis.
Definition: PyFmt2.cpp:93
std::string printDegrees(double input)
Definition: PyFmt.cpp:116
std::string printDouble(double input)
Definition: PyFmt.cpp:46
std::string printString(const std::string &value)
Definition: PyFmt.cpp:144
std::string printRealLimitsArg(const RealLimits &limits, const std::string &units)
Prints RealLimits in the form of argument (in the context of ParameterDistribution and similar)....
Definition: PyFmtLimits.cpp:59
std::string printBool(double value)
Definition: PyFmt.cpp:41
std::string indent(size_t width)
Returns a string of blanks with given width. By default the width equals standard offset in python fi...
Definition: PyFmt.cpp:203
std::string printValue(double value, const std::string &units)
Definition: PyFmt.cpp:123