BornAgain  1.19.79
Open-source research software to simulate and fit neutron and x-ray reflectometry and grazing-incidence small-angle scattering
SimulationToPython.cpp
Go to the documentation of this file.
1 // ************************************************************************************************
2 //
3 // BornAgain: simulate and fit reflection and scattering
4 //
5 //! @file Sim/Export/SimulationToPython.cpp
6 //! @brief Implements class SimulationToPython.
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 
16 #include "Base/Axis/IAxis.h"
17 #include "Base/Py/PyFmt.h"
18 #include "Base/Util/Algorithms.h"
19 #include "Base/Util/Assert.h"
20 #include "Device/Beam/Beam.h"
30 #include "Param/Node/NodeUtils.h"
34 #include "Sim/Export/PyFmt2.h"
35 #include "Sim/Export/PyFmtLimits.h"
37 #include "Sim/Scan/AlphaScan.h"
38 #include "Sim/Scan/QzScan.h"
41 #include <iomanip>
42 
43 using Py::Fmt::indent;
44 
45 namespace {
46 
47 //! Returns a function that converts a coordinate to a Python code snippet with appropriate unit
48 std::function<std::string(double)> printFunc(const IDetector& detector)
49 {
50  if (detector.defaultCoords() == Coords::MM)
51  return Py::Fmt::printDouble;
52  if (detector.defaultCoords() == Coords::RADIANS)
53  return Py::Fmt::printDegrees;
54  throw std::runtime_error("SimulationToPython::defineMasks() -> Error. Unknown detector units.");
55 }
56 
57 bool isQuadraticDetector(const IDetector& det)
58 {
59  ASSERT(det.rank() == 2);
60  if (det.axis(0).size() != det.axis(1).size())
61  return false;
62  if (std::abs(det.axis(0).span() - det.axis(1).span())
63  > 1e-12 * (det.axis(0).span() + det.axis(1).span()))
64  return false;
65  return true;
66 }
67 
68 //! Returns true if it is (0, -1, 0) vector
69 bool isDefaultDirection(const R3 direction)
70 {
71  return BaseUtils::algo::almostEqual(direction.x(), 0.0)
72  && BaseUtils::algo::almostEqual(direction.y(), -1.0)
73  && BaseUtils::algo::almostEqual(direction.z(), 0.0);
74 }
75 
76 std::string defineFootprintFactor(const IFootprintFactor& foot)
77 {
78  std::ostringstream result;
79  result << indent() << "footprint = ba." << foot.name();
80  result << "(" << Py::Fmt::printDouble(foot.widthRatio()) << ")\n";
81  return result.str();
82 }
83 
84 std::string defineScanResolution(const ScanResolution& scan)
85 {
86  std::ostringstream result;
87  result << Py::Fmt2::printRangedDistribution(*scan.distribution()) << "\n"
88  << indent() << "resolution = "
89  << "ba." << scan.name() << "(distribution, " << Py::Fmt::printDouble(scan.delta())
90  << ")\n";
91  return result.str();
92 }
93 
94 std::string defineAlphaScan(const AlphaScan& scan)
95 {
96  std::ostringstream result;
97  result << "\n"
98  << indent() << "# Define specular scan:\n"
99  << indent() << "axis = " << Py::Fmt2::printAxis(scan.coordinateAxis(), "rad") << "\n"
100  << indent() << "scan = "
101  << "ba.AlphaScan(" << Py::Fmt::printDouble(scan.wavelength()) << ", axis)\n";
102 
103  if (scan.footprintFactor()) {
104  result << defineFootprintFactor(*scan.footprintFactor());
105  result << indent() << "scan.setFootprintFactor(footprint)\n";
106  }
107  if (const auto* r = scan.angleResolution(); r && r->distribution()) {
108  result << defineScanResolution(*r) << "\n";
109  result << indent() << "scan.setAngleResolution(resolution)\n";
110  }
111  if (const auto* r = scan.wavelengthResolution(); r && r->distribution()) {
112  result << defineScanResolution(*r) << "\n";
113  result << indent() << "scan.setWavelengthResolution(resolution)\n";
114  }
115  return result.str();
116 }
117 
118 std::string defineQzScan(const QzScan& scan)
119 {
120  std::ostringstream result;
121  const std::string axis_def = indent() + "axis = ";
122  result << axis_def << Py::Fmt2::printAxis(scan.coordinateAxis(), "") << "\n";
123  // TODO correct unit would be 1/nm
124 
125  result << indent() << "scan = ba.QzScan(axis)";
126  if (scan.resolution()) {
127  result << "\n";
128  result << defineScanResolution(*scan.resolution()) << "\n";
129  result << indent() << "scan.setQResolution(resolution)";
130  }
131  return result.str();
132 }
133 
134 std::string definePolarizationAnalyzer(const PolFilter& analyzer, const std::string parent)
135 {
136  std::ostringstream result;
137  R3 analyzer_direction = analyzer.analyzerDirection();
138  double analyzer_efficiency = analyzer.analyzerEfficiency();
139  double analyzer_total_transmission = analyzer.totalTransmission();
140 
141  if (analyzer_direction.mag() > 0.0) {
142  std::string direction_name = "analyzer_direction";
143  result << indent() << direction_name << " = R3("
144  << Py::Fmt::printDouble(analyzer_direction.x()) << ", "
145  << Py::Fmt::printDouble(analyzer_direction.y()) << ", "
146  << Py::Fmt::printDouble(analyzer_direction.z()) << ")\n";
147  result << indent() << parent << ".setAnalyzer(" << direction_name << ", "
148  << Py::Fmt::printDouble(analyzer_efficiency) << ", "
149  << Py::Fmt::printDouble(analyzer_total_transmission) << ")\n";
150  }
151  return result.str();
152 }
153 
154 std::string defineScan(const ISpecularScan* scan)
155 {
156  if (const auto* s = dynamic_cast<const AlphaScan*>(scan); s)
157  return defineAlphaScan(*s);
158  if (const auto* s = dynamic_cast<const QzScan*>(scan); s)
159  return defineQzScan(*s);
160  ASSERT(0);
161 }
162 
163 std::string defineDetector(const ISimulation2D* simulation)
164 {
165  const IDetector& detector = simulation->detector();
166  if (detector.rank() != 2)
167  throw std::runtime_error("defineDetector: "
168  "detector must be two-dimensional for GISAS");
169  std::ostringstream result;
170  result << std::setprecision(12);
171 
172  if (const auto* const det = dynamic_cast<const SphericalDetector*>(&detector)) {
173  ASSERT(det->rank() == 2);
174  result << indent() << "detector = ba.SphericalDetector(";
175  if (isQuadraticDetector(*det)) {
176  result << det->axis(0).size() << ", " << Py::Fmt::printDegrees(det->axis(0).span())
177  << ", " << Py::Fmt::printDegrees(det->axis(0).center()) << ", "
178  << Py::Fmt::printDegrees(det->axis(1).center());
179  } else {
180  result << det->axis(0).size() << ", " << Py::Fmt::printDegrees(det->axis(0).min())
181  << ", " << Py::Fmt::printDegrees(det->axis(0).max()) << ", "
182  << det->axis(1).size() << ", " << Py::Fmt::printDegrees(det->axis(1).min())
183  << ", " << Py::Fmt::printDegrees(det->axis(1).max());
184  }
185  result << ")\n";
186  } else if (const auto* const det = dynamic_cast<const RectangularDetector*>(&detector)) {
187  result << "\n";
188  result << indent() << "detector = ba.RectangularDetector(" << det->xSize() << ", "
189  << Py::Fmt::printDouble(det->width()) << ", " << det->ySize() << ", "
190  << Py::Fmt::printDouble(det->height()) << ")\n";
191  if (det->getDetectorArrangment() == RectangularDetector::GENERIC) {
192  result << indent() << "detector.setDetectorPosition("
193  << Py::Fmt::printKvector(det->getNormalVector()) << ", "
194  << Py::Fmt::printDouble(det->getU0()) << ", "
195  << Py::Fmt::printDouble(det->getV0());
196  if (!isDefaultDirection(det->getDirectionVector()))
197  result << ", " << Py::Fmt::printKvector(det->getDirectionVector());
198  result << ")\n";
199  } else if (det->getDetectorArrangment() == RectangularDetector::PERPENDICULAR_TO_SAMPLE) {
200  result << indent() << "detector.setPerpendicularToSampleX("
201  << Py::Fmt::printDouble(det->getDistance()) << ", "
202  << Py::Fmt::printDouble(det->getU0()) << ", "
203  << Py::Fmt::printDouble(det->getV0()) << ")\n";
204  } else if (det->getDetectorArrangment()
206  result << indent() << "detector.setPerpendicularToDirectBeam("
207  << Py::Fmt::printDouble(det->getDistance()) << ", "
208  << Py::Fmt::printDouble(det->getU0()) << ", "
209  << Py::Fmt::printDouble(det->getV0()) << ")\n";
210  } else if (det->getDetectorArrangment()
212  result << indent() << "detector.setPerpendicularToReflectedBeam("
213  << Py::Fmt::printDouble(det->getDistance()) << ", "
214  << Py::Fmt::printDouble(det->getU0()) << ", "
215  << Py::Fmt::printDouble(det->getV0()) << ")\n";
216  } else if (det->getDetectorArrangment()
218  result << indent() << "detector.setPerpendicularToReflectedBeam("
219  << Py::Fmt::printDouble(det->getDistance()) << ")\n";
220  result << indent() << "detector.setDirectBeamPosition("
221  << Py::Fmt::printDouble(det->getDirectBeamU0()) << ", "
222  << Py::Fmt::printDouble(det->getDirectBeamV0()) << ")\n";
223  } else
224  throw std::runtime_error("defineDetector() -> Error. Unknown alignment.");
225  } else
226  throw std::runtime_error("defineDetector() -> Error. Unknown detector");
227  if (detector.hasExplicitRegionOfInterest()) {
228  const auto xBounds = detector.regionOfInterestBounds(0);
229  const auto yBounds = detector.regionOfInterestBounds(1);
230  result << indent() << "detector.setRegionOfInterest(" << printFunc(detector)(xBounds.first)
231  << ", " << printFunc(detector)(yBounds.first) << ", "
232  << printFunc(detector)(xBounds.second) << ", " << printFunc(detector)(yBounds.second)
233  << ")\n";
234  }
235  result << definePolarizationAnalyzer(detector.analyzer(), "detector");
236  return result.str();
237 }
238 
239 std::string defineDetectorResolutionFunction(const IDetector& detector)
240 {
241  std::ostringstream result;
242 
243  if (const IDetectorResolution* resfunc = detector.detectorResolution()) {
244  if (const auto* convfunc = dynamic_cast<const ConvolutionDetectorResolution*>(resfunc)) {
245  if (const auto* resfunc = dynamic_cast<const ResolutionFunction2DGaussian*>(
246  convfunc->getResolutionFunction2D())) {
247  result << indent() << "simulation.detector().setResolutionFunction(";
248  result << "ba.ResolutionFunction2DGaussian(";
249  result << printFunc(detector)(resfunc->sigmaX()) << ", ";
250  result << printFunc(detector)(resfunc->sigmaY()) << "))\n";
251  } else
252  throw std::runtime_error("defineDetectorResolutionFunction() -> Error. "
253  "Unknown detector resolution function");
254  } else
255  throw std::runtime_error("defineDetectorResolutionFunction() -> Error. "
256  "Not a ConvolutionDetectorResolution function");
257  }
258  return result.str();
259 }
260 
261 std::string defineBeamPolarization(const Beam& beam)
262 {
263  std::ostringstream result;
264  auto bloch_vector = beam.polVector();
265  if (bloch_vector.mag() > 0.0) {
266  std::string beam_polMatrices = "beam_polMatrices";
267  result << indent() << beam_polMatrices << " = R3(" << Py::Fmt::printDouble(bloch_vector.x())
268  << ", " << Py::Fmt::printDouble(bloch_vector.y()) << ", "
269  << Py::Fmt::printDouble(bloch_vector.z()) << ")\n";
270  result << indent() << "beam.setPolarization(" << beam_polMatrices << ")\n";
271  }
272  return result.str();
273 }
274 
275 std::string defineBeamIntensity(const Beam& beam)
276 {
277  std::ostringstream result;
278  double beam_intensity = beam.intensity();
279  if (beam_intensity > 0.0)
280  result << indent() << "simulation.beam().setIntensity("
281  << Py::Fmt::printScientificDouble(beam_intensity) << ")\n";
282  return result.str();
283 }
284 
285 std::string defineGISASBeam(const ScatteringSimulation& simulation)
286 {
287  std::ostringstream result;
288  const Beam& beam = simulation.beam();
289 
290  result << indent() << "beam = ba.Beam(" << Py::Fmt::printDouble(beam.intensity()) << ", "
291  << Py::Fmt::printNm(beam.wavelength()) << ", ba.Direction("
292  << Py::Fmt::printDegrees(beam.direction().alpha()) << ", "
293  << Py::Fmt::printDegrees(beam.direction().phi()) << "))\n";
294 
295  result << defineBeamPolarization(beam);
296 
297  return result.str();
298 }
299 
300 std::string defineOffspecBeam(const OffspecSimulation& simulation)
301 {
302  std::ostringstream result;
303  const Beam& beam = simulation.beam();
304 
305  const std::string axidef = indent() + "alpha_i_axis = ";
306  result << axidef << Py::Fmt2::printAxis(simulation.beamAxis(), "rad") << "\n";
307 
308  result << indent() << "simulation.setBeamParameters(" << Py::Fmt::printNm(beam.wavelength())
309  << ", "
310  << "alpha_i_axis, " << Py::Fmt::printDegrees(beam.direction().phi()) << ")\n";
311 
312  result << defineBeamPolarization(beam);
313  result << defineBeamIntensity(beam);
314  return result.str();
315 }
316 
317 std::string defineSpecularScan(const SpecularSimulation& simulation)
318 {
319  std::ostringstream result;
320  const ISpecularScan* scan = simulation.scan();
321  if (!scan)
322  throw std::runtime_error("Error defineSpecularScan: passed simulation "
323  "does not contain any scan");
324  result << defineScan(scan) << "\n";
325  const PolFilter* analyzer = scan->analyzer();
326  if (analyzer)
327  result << definePolarizationAnalyzer(*analyzer, "scan");
328  return result.str();
329 }
330 
331 std::string defineParameterDistributions(const ISimulation* simulation)
332 {
333  std::ostringstream result;
334  const std::vector<ParameterDistribution>& distributions = simulation->getDistributions();
335  if (distributions.empty())
336  return "";
337  for (size_t i = 0; i < distributions.size(); ++i) {
338  const std::string mainParUnits =
339  simulation->unitOfParameter(distributions[i].whichParameter());
340 
341  const std::string distr = "distr_" + std::to_string(i + 1);
342  result << indent() << distr << " = "
343  << "ba." << distributions[i].getDistribution()->pythonConstructor(mainParUnits)
344  << "\n";
345 
346  result << indent() << "simulation.addParameterDistribution(ba."
347  << distributions[i].whichParameterAsPyEnum() << ", " << distr << ", "
348  << distributions[i].nDraws() << ", "
349  << Py::Fmt::printDouble(distributions[i].sigmaFactor())
350  << Py::Fmt::printRealLimitsArg(distributions[i].getLimits(), mainParUnits) << ")\n";
351  }
352  return result.str();
353 }
354 
355 std::string defineMasks(const IDetector& detector)
356 {
357  std::ostringstream result;
358  result << std::setprecision(12);
359 
360  const DetectorMask* detectorMask = detector.detectorMask();
361  if (detectorMask && detectorMask->hasMasks()) {
362  result << "\n";
363  for (size_t i_mask = 0; i_mask < detectorMask->numberOfMasks(); ++i_mask) {
364  const MaskPattern* pat = detectorMask->patternAt(i_mask);
365  IShape2D* shape = pat->shape;
366  bool mask_value = pat->doMask;
367  result << Py::Fmt2::representShape2D(indent(), shape, mask_value, printFunc(detector));
368  }
369  result << "\n";
370  }
371  return result.str();
372 }
373 
374 std::string defineSimulationOptions(const ISimulation* simulation)
375 {
376  std::ostringstream result;
377  result << std::setprecision(12);
378 
379  const SimulationOptions& options = simulation->options();
380  if (options.getHardwareConcurrency() != options.getNumberOfThreads())
381  result << indent() << "simulation.options().setNumberOfThreads("
382  << options.getNumberOfThreads() << ")\n";
383  if (options.isIntegrate())
384  result << indent() << "simulation.options().setMonteCarloIntegration(True, "
385  << options.getMcPoints() << ")\n";
386  if (options.useAvgMaterials())
387  result << indent() << "simulation.options().setUseAvgMaterials(True)\n";
388  if (options.includeSpecular())
389  result << indent() << "simulation.options().setIncludeSpecular(True)\n";
390  return result.str();
391 }
392 
393 std::string defineBackground(const ISimulation* simulation)
394 {
395  std::ostringstream result;
396 
397  const auto* bg = simulation->background();
398  if (const auto* constant_bg = dynamic_cast<const ConstantBackground*>(bg)) {
399  if (constant_bg->backgroundValue() > 0.0) {
400  result << indent() << "background = ba.ConstantBackground("
401  << Py::Fmt::printScientificDouble(constant_bg->backgroundValue()) << ")\n";
402  result << indent() << "simulation.setBackground(background)\n";
403  }
404  } else if (dynamic_cast<const PoissonBackground*>(bg)) {
405  result << indent() << "background = ba.PoissonBackground()\n";
406  result << indent() << "simulation.setBackground(background)\n";
407  }
408  return result.str();
409 }
410 
411 std::string defineScatteringSimulation(const ScatteringSimulation* simulation)
412 {
413  std::ostringstream result;
414  result << defineGISASBeam(*simulation);
415  result << defineDetector(simulation);
416  result << indent() << "simulation = ba.ScatteringSimulation(beam, sample, detector)\n";
417  result << defineDetectorResolutionFunction(simulation->detector());
418  result << defineParameterDistributions(simulation);
419  result << defineMasks(simulation->detector());
420  result << defineSimulationOptions(simulation);
421  result << defineBackground(simulation);
422  return result.str();
423 }
424 
425 std::string defineOffspecSimulation(const OffspecSimulation* simulation)
426 {
427  std::ostringstream result;
428  result << indent() << "simulation = ba.OffspecSimulation()\n";
429  result << defineDetector(simulation);
430  result << defineDetectorResolutionFunction(simulation->detector());
431  result << defineOffspecBeam(*simulation);
432  result << defineParameterDistributions(simulation);
433  result << defineMasks(simulation->detector());
434  result << defineSimulationOptions(simulation);
435  result << defineBackground(simulation);
436  return result.str();
437 }
438 
439 std::string defineSpecularSimulation(const SpecularSimulation* simulation)
440 {
441  std::ostringstream result;
442  result << defineSpecularScan(*simulation);
443  result << indent() << "simulation = ba.SpecularSimulation(scan, sample)\n";
444  result << defineParameterDistributions(simulation);
445  result << defineSimulationOptions(simulation);
446  result << defineBackground(simulation);
447  // result << defineBeamIntensity(simulation->beam());
448  result << "\n";
449  return result.str();
450 }
451 
452 std::string defineSimulate(const ISimulation* simulation)
453 {
454  std::ostringstream result;
455  result << "def get_simulation(sample):\n";
456  if (const auto* gisas = dynamic_cast<const ScatteringSimulation*>(simulation))
457  result << defineScatteringSimulation(gisas);
458  else if (const auto* offspec = dynamic_cast<const OffspecSimulation*>(simulation))
459  result << defineOffspecSimulation(offspec);
460  else if (const auto* spec = dynamic_cast<const SpecularSimulation*>(simulation))
461  result << defineSpecularSimulation(spec);
462  else
463  ASSERT(0);
464  result << " return simulation\n\n\n";
465 
466  return result.str();
467 }
468 
469 std::string simulationCode(const ISimulation& simulation)
470 {
471  if (simulation.sample() == nullptr)
472  throw std::runtime_error("Cannot export: Simulation has no sample");
473  std::string code =
474  SampleToPython().sampleCode(*simulation.sample()) + defineSimulate(&simulation);
475  return "import bornagain as ba\n" + Py::Fmt::printImportedSymbols(code) + "\n\n" + code;
476 }
477 
478 } // namespace
479 
480 // ************************************************************************************************
481 // class SimulationToPython
482 // ************************************************************************************************
483 
485 {
486  return simulationCode(simulation)
487  + "if __name__ == '__main__':\n"
488  " from bornagain import ba_plot as bp\n"
489  " bp.parse_args()\n"
490  " sample = get_sample()\n"
491  " simulation = get_simulation(sample)\n"
492  " result = simulation.simulate()\n"
493  " bp.plot_simulation_result(result)\n";
494 }
495 
497  const std::string& fname)
498 {
499  return simulationCode(simulation)
500  + "if __name__ == '__main__':\n"
501  " sample = get_sample()\n"
502  " simulation = get_simulation(sample)\n"
503  " result = simulation.simulate()\n"
504  " ba.IOFactory.writeSimulationResult(result, \""
505  + fname + "\")\n";
506 }
Defines and implements namespace BaseUtils::algo with some algorithms.
Declares AlphaScan class.
Defines the macro ASSERT.
#define ASSERT(condition)
Definition: Assert.h:45
Defines class Beam.
Defines class ConstantBackground.
Defines class ConvolutionDetectorResolution.
Defines class DetectorMask.
Defines classes representing one-dimensional distributions.
Defines class FootprintGauss.
Defines class FootprintSquare.
Defines interface IAxis.
Defines collection of utility functions for INode.
Defines class PoissonBackground.
Defines namespace pyfmt2.
Defines namespace pyfmt.
Defines namespace pyfmt.
Declares QzScan class.
Defines classes representing ranged one-dimensional distributions.
Defines class RectangularDetector.
Defines class ResolutionFunction2DGaussian.
Defines class SampleToPython.
Defines scan resolution class.
Defines class SimulationOptions.
Defines class SimulationToPython.
Defines class SphericalDetector.
Scan type with inclination angles as coordinate values and a unique wavelength. Features footprint co...
Definition: AlphaScan.h:27
const IAxis * coordinateAxis() const override
Returns coordinate axis assigned to the data holder.
Definition: AlphaScan.h:45
const IFootprintFactor * footprintFactor() const override
Returns IFootprintFactor object pointer.
Definition: AlphaScan.h:48
const ScanResolution * angleResolution() const
Definition: AlphaScan.h:64
double wavelength() const override
Definition: AlphaScan.h:67
const ScanResolution * wavelengthResolution() const
Definition: AlphaScan.h:63
An incident neutron or x-ray beam.
Definition: Beam.h:28
Direction direction() const
Definition: Beam.h:46
double intensity() const
Returns the beam intensity in neutrons/sec.
Definition: Beam.h:43
double wavelength() const
Definition: Beam.h:44
R3 polVector() const
Returns polarization density as Bloch vector.
Definition: Beam.cpp:150
Constant background, to be added to simulated scattering.
Convolutes the intensity in 1 or 2 dimensions with a resolution function.
Collection of detector masks.
Definition: DetectorMask.h:42
const MaskPattern * patternAt(size_t iMask) const
bool hasMasks() const
Returns true if has masks.
size_t numberOfMasks() const
double phi() const
Definition: Direction.h:37
double alpha() const
Definition: Direction.h:36
double span() const
Returns distance from first to last point.
Definition: IAxis.cpp:55
virtual double max() const =0
Returns value of last point of axis.
virtual double min() const =0
Returns value of first point of axis.
virtual size_t size() const =0
Returns the number of bins.
double center() const
Returns midpoint of axis.
Definition: IAxis.cpp:60
Interface for detector resolution algorithms.
Abstract detector interface.
Definition: IDetector.h:57
virtual Coords defaultCoords() const =0
Return default axes units.
const PolFilter & analyzer() const
Returns detection properties.
Definition: IDetector.h:204
std::pair< double, double > regionOfInterestBounds(size_t iAxis) const
The lower and upper bound of the region of interest. If no region of interest is explicitly defined,...
Definition: IDetector.cpp:227
const IAxis & axis(size_t index) const
One axis of the complete detector. Any region of interest is not taken into account.
Definition: IDetector.cpp:74
bool hasExplicitRegionOfInterest() const
True if a region of interest is explicitly set.
Definition: IDetector.cpp:131
const IDetectorResolution * detectorResolution() const
Returns a pointer to detector resolution object.
Definition: IDetector.cpp:186
size_t rank() const
Returns number of defined axes.
Definition: IDetector.cpp:64
const DetectorMask * detectorMask() const
Definition: IDetector.cpp:372
Abstract base for classes that calculate the beam footprint factor.
double widthRatio() const
virtual std::string name() const =0
Basic class for all shapes in 2D.
Definition: IShape2D.h:26
Abstract base class of simulations that generate 2D patterns.
Definition: ISimulation2D.h:34
IDetector & detector()
Definition: ISimulation2D.h:58
Beam & beam()
Definition: ISimulation2D.h:57
Abstract base class, holds the infrastructure to run a simulation.
Definition: ISimulation.h:42
const IBackground * background() const
Definition: ISimulation.h:76
const MultiLayer * sample() const
const SimulationOptions & options() const
const std::vector< ParameterDistribution > & getDistributions() const
std::string unitOfParameter(ParameterDistribution::WhichParameter which) const
Abstract base class for all types of specular scans.
Definition: ISpecularScan.h:34
const PolFilter * analyzer() const
Definition: ISpecularScan.h:45
IShape2D * shape
Definition: DetectorMask.h:35
Off-specular scattering simulation.
const IAxis * beamAxis() const
Returns axis of the beam.
Poisson distributed noise, to be added to simulated scattering.
Detector properties (efficiency, transmission).
Definition: PolFilter.h:27
double totalTransmission() const
Definition: PolFilter.cpp:58
double analyzerEfficiency() const
will always return positive value
Definition: PolFilter.cpp:53
R3 analyzerDirection() const
Retrieve the analyzer characteristics.
Definition: PolFilter.cpp:48
Scan type with z-components of scattering vector as coordinate values. Wavelength and incident angles...
Definition: QzScan.h:28
const IAxis * coordinateAxis() const override
Returns coordinate axis assigned to the data holder.
Definition: QzScan.h:51
const ScanResolution * resolution() const
Definition: QzScan.h:42
A flat rectangular detector with axes and resolution function.
Simple gaussian two-dimensional resolution function.
Generates Python code snippet from domain (C++) objects representing sample construction.
std::string sampleCode(const MultiLayer &sample)
Container for reflectivity resolution data.
virtual double delta() const =0
virtual std::string name() const =0
const IRangedDistribution * distribution() const
Collect the different options for simulation.SimulationOptions.
size_t getMcPoints() const
bool includeSpecular() const
unsigned getHardwareConcurrency() const
unsigned getNumberOfThreads() const
bool isIntegrate() const
bool useAvgMaterials() const
std::string simulationSaveCode(const ISimulation &simulation, const std::string &fname)
Returns a Python script that runs a simulation and saves the result to a file.
std::string simulationPlotCode(const ISimulation &simulation)
Returns a Python script that runs a simulation and plots the result.
Specular reflectometry simulation.
const ISpecularScan * scan() const
Returns internal data handler.
A detector with coordinate axes along angles phi and alpha.
Includes all leave classes below ISimulation.
bool almostEqual(double a, double b)
Returns true if two doubles agree within machine epsilon.
Definition: Algorithms.h:33
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 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 printKvector(const R3 value)
Definition: PyFmt.cpp:195
std::string printScientificDouble(double input)
Definition: PyFmt.cpp:96
std::string printNm(double input)
Definition: PyFmt.cpp:79
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 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 printImportedSymbols(const std::string &code)
Definition: PyFmt.cpp:24