40 const std::string defineSimulate =
"def run_simulation():\n"
42 + pyfmt::getSampleFunctionName()
44 " simulation = get_simulation()\n"
45 " simulation.setSample(sample)\n"
46 " simulation.runSimulation()\n"
47 " return simulation.result()\n"
51 std::function<std::string(
double)> printFunc(
const IDetector* detector)
54 return pyfmt::printDouble;
56 return pyfmt::printDegrees;
58 "SimulationToPython::defineMasks() -> Error. Unknown detector units.");
62 bool isDefaultDirection(
const kvector_t direction)
75 if (simulation.sample() ==
nullptr)
76 throw std::runtime_error(
"SimulationToPython::generateSimulationCode() -> Error. "
77 "Simulation is not initialized.");
81 return pyfmt::scriptPreamble() + sampleGenerator.generateSampleCode(*simulation.sample())
82 + defineGetSimulation(&simulation) + defineSimulate + defineMain(mainType);
85 std::string SimulationToPython::defineGetSimulation(
const Simulation* simulation)
const
87 std::ostringstream result;
88 result <<
"def get_simulation():\n";
91 result << defineGISASSimulation(gisas);
93 result << defineOffSpecSimulation(offspec);
95 result << defineSpecularSimulation(spec);
97 throw std::runtime_error(
"SimulationToPython::defineGetSimulation() -> Error. "
98 "Wrong simulation type");
104 std::string SimulationToPython::defineGISASSimulation(
const GISASSimulation* simulation)
const
106 std::ostringstream result;
107 result <<
pyfmt::indent() <<
"simulation = ba.GISASSimulation()\n";
108 result << defineDetector(simulation);
109 result << defineDetectorResolutionFunction(simulation);
110 result << defineDetectorPolarizationAnalysis(simulation);
111 result << defineGISASBeam(*simulation);
112 result << defineParameterDistributions(simulation);
113 result << defineMasks(simulation);
114 result << defineSimulationOptions(simulation);
115 result << defineBackground(simulation);
119 std::string SimulationToPython::defineOffSpecSimulation(
const OffSpecSimulation* simulation)
const
121 std::ostringstream result;
122 result <<
pyfmt::indent() <<
"simulation = ba.OffSpecSimulation()\n";
123 result << defineDetector(simulation);
124 result << defineDetectorResolutionFunction(simulation);
125 result << defineDetectorPolarizationAnalysis(simulation);
126 result << defineOffSpecBeam(*simulation);
127 result << defineParameterDistributions(simulation);
128 result << defineMasks(simulation);
129 result << defineSimulationOptions(simulation);
130 result << defineBackground(simulation);
134 std::string SimulationToPython::defineSpecularSimulation(
const SpecularSimulation* simulation)
const
136 std::ostringstream result;
137 result <<
pyfmt::indent() <<
"simulation = ba.SpecularSimulation()\n";
138 result << defineDetectorPolarizationAnalysis(simulation);
139 result << defineSpecularScan(*simulation);
140 result << defineParameterDistributions(simulation);
141 result << defineSimulationOptions(simulation);
142 result << defineBackground(simulation);
146 std::string SimulationToPython::defineDetector(
const Simulation* simulation)
const
148 const IDetector*
const detector = simulation->instrument().getDetector();
151 "detector must be two-dimensional for GISAS");
152 std::ostringstream result;
153 result << std::setprecision(12);
156 result <<
pyfmt::indent() <<
"simulation.setDetectorParameters(";
157 for (
size_t index = 0; index < det->dimension(); ++index) {
160 result << det->getAxis(index).size() <<
", "
161 << pyfmt::printDegrees(det->getAxis(index).getMin()) <<
", "
162 << pyfmt::printDegrees(det->getAxis(index).getMax());
167 result <<
pyfmt::indent() <<
"detector = ba.RectangularDetector(" << det->getNbinsX()
168 <<
", " << pyfmt::printDouble(det->getWidth()) <<
", " << det->getNbinsY() <<
", "
169 << pyfmt::printDouble(det->getHeight()) <<
")\n";
170 if (det->getDetectorArrangment() == RectangularDetector::GENERIC) {
172 << pyfmt::printKvector(det->getNormalVector()) <<
", "
173 << pyfmt::printDouble(det->getU0()) <<
", " << pyfmt::printDouble(det->getV0());
174 if (!isDefaultDirection(det->getDirectionVector()))
175 result <<
", " << pyfmt::printKvector(det->getDirectionVector());
177 }
else if (det->getDetectorArrangment() == RectangularDetector::PERPENDICULAR_TO_SAMPLE) {
178 result <<
pyfmt::indent() <<
"detector.setPerpendicularToSampleX("
179 << pyfmt::printDouble(det->getDistance()) <<
", "
180 << pyfmt::printDouble(det->getU0()) <<
", " << pyfmt::printDouble(det->getV0())
182 }
else if (det->getDetectorArrangment()
183 == RectangularDetector::PERPENDICULAR_TO_DIRECT_BEAM) {
184 result <<
pyfmt::indent() <<
"detector.setPerpendicularToDirectBeam("
185 << pyfmt::printDouble(det->getDistance()) <<
", "
186 << pyfmt::printDouble(det->getU0()) <<
", " << pyfmt::printDouble(det->getV0())
188 }
else if (det->getDetectorArrangment()
189 == RectangularDetector::PERPENDICULAR_TO_REFLECTED_BEAM) {
190 result <<
pyfmt::indent() <<
"detector.setPerpendicularToReflectedBeam("
191 << pyfmt::printDouble(det->getDistance()) <<
", "
192 << pyfmt::printDouble(det->getU0()) <<
", " << pyfmt::printDouble(det->getV0())
194 }
else if (det->getDetectorArrangment()
195 == RectangularDetector::PERPENDICULAR_TO_REFLECTED_BEAM_DPOS) {
196 result <<
pyfmt::indent() <<
"detector.setPerpendicularToReflectedBeam("
197 << pyfmt::printDouble(det->getDistance()) <<
")\n";
198 result <<
pyfmt::indent() <<
"detector.setDirectBeamPosition("
199 << pyfmt::printDouble(det->getDirectBeamU0()) <<
", "
200 << pyfmt::printDouble(det->getDirectBeamV0()) <<
")\n";
203 "SimulationToPython::defineDetector() -> Error. Unknown alignment.");
205 result <<
pyfmt::indent() <<
"simulation.setDetector(detector)\n";
210 result <<
pyfmt::indent() <<
"simulation.setRegionOfInterest("
220 std::string SimulationToPython::defineDetectorResolutionFunction(
const Simulation* simulation)
const
222 std::ostringstream result;
223 const IDetector* detector = simulation->instrument().getDetector();
228 p_convfunc->getResolutionFunction2D())) {
229 result <<
pyfmt::indent() <<
"simulation.setDetectorResolutionFunction(";
230 result <<
"ba.ResolutionFunction2DGaussian(";
231 result << printFunc(detector)(resfunc->getSigmaX()) <<
", ";
232 result << printFunc(detector)(resfunc->getSigmaY()) <<
"))\n";
235 "SimulationToPython::defineDetectorResolutionFunction() -> Error. "
236 "Unknown detector resolution function");
239 "SimulationToPython::defineDetectorResolutionFunction() -> Error. "
240 "Not a ConvolutionDetectorResolution function");
246 SimulationToPython::defineDetectorPolarizationAnalysis(
const Simulation* simulation)
const
248 std::ostringstream result;
249 const IDetector* detector = simulation->instrument().getDetector();
252 double analyzer_total_transmission =
255 if (analyzer_direction.
mag() > 0.0) {
256 std::string direction_name =
"analyzer_direction";
257 result <<
pyfmt::indent() << direction_name <<
" = kvector_t("
258 << pyfmt::printDouble(analyzer_direction.
x()) <<
", "
259 << pyfmt::printDouble(analyzer_direction.
y()) <<
", "
260 << pyfmt::printDouble(analyzer_direction.
z()) <<
")\n";
261 result <<
pyfmt::indent() <<
"simulation.setAnalyzerProperties(" << direction_name <<
", "
262 << pyfmt::printDouble(analyzer_efficiency) <<
", "
263 << pyfmt::printDouble(analyzer_total_transmission) <<
")\n";
268 std::string SimulationToPython::defineGISASBeam(
const GISASSimulation& simulation)
const
270 std::ostringstream result;
271 const Beam& beam = simulation.instrument().getBeam();
274 << pyfmt::printNm(beam.getWavelength()) <<
", " << pyfmt::printDegrees(beam.getAlpha())
275 <<
", " << pyfmt::printDegrees(beam.getPhi()) <<
")\n";
277 result << defineBeamPolarization(beam);
278 result << defineBeamIntensity(beam);
283 std::string SimulationToPython::defineOffSpecBeam(
const OffSpecSimulation& simulation)
const
285 std::ostringstream result;
286 const Beam& beam = simulation.instrument().getBeam();
288 const std::string axis_def =
pyfmt::indent() +
"alpha_i_axis = ";
289 result << axis_def << simulation.
beamAxis()->pyString(
"rad", axis_def.size()) <<
"\n";
292 << pyfmt::printNm(beam.getWavelength()) <<
", "
293 <<
"alpha_i_axis, " << pyfmt::printDegrees(beam.getPhi()) <<
")\n";
295 result << defineBeamPolarization(beam);
296 result << defineBeamIntensity(beam);
300 std::string SimulationToPython::defineSpecularScan(
const SpecularSimulation& simulation)
const
302 std::ostringstream result;
305 throw std::runtime_error(
"Error SimulationToPython::defineSpecularScan: passed simulation "
306 "does not contain any scan");
307 result << *scan <<
"\n";
310 result << defineBeamIntensity(simulation.instrument().getBeam());
315 std::string SimulationToPython::defineBeamPolarization(
const Beam& beam)
const
317 std::ostringstream result;
318 auto bloch_vector = beam.getBlochVector();
319 if (bloch_vector.mag() > 0.0) {
320 std::string beam_polarization =
"beam_polarization";
321 result <<
pyfmt::indent() << beam_polarization <<
" = kvector_t("
322 << pyfmt::printDouble(bloch_vector.x()) <<
", "
323 << pyfmt::printDouble(bloch_vector.y()) <<
", "
324 << pyfmt::printDouble(bloch_vector.z()) <<
")\n";
325 result <<
pyfmt::indent() <<
"simulation.setBeamPolarization(" << beam_polarization
331 std::string SimulationToPython::defineBeamIntensity(
const Beam& beam)
const
333 std::ostringstream result;
335 if (beam_intensity > 0.0)
337 << pyfmt::printScientificDouble(beam_intensity) <<
")\n";
341 std::string SimulationToPython::defineParameterDistributions(
const Simulation* simulation)
const
343 std::ostringstream result;
344 const std::vector<ParameterDistribution>& distributions =
345 simulation->getDistributionHandler().getDistributions();
346 if (distributions.empty())
348 for (
size_t i = 0; i < distributions.size(); ++i) {
349 std::string main_par_name = distributions[i].getMainParameterName();
353 size_t nbr_samples = distributions[i].getNbrSamples();
354 double sigma_factor = distributions[i].getSigmaFactor();
356 std::string s_distr =
"distr_" + std::to_string(i + 1);
361 result <<
pyfmt::indent() <<
"simulation.addParameterDistribution(\"" << main_par_name
362 <<
"\", " << s_distr <<
", " << nbr_samples <<
", "
363 << pyfmt::printDouble(sigma_factor)
369 std::string SimulationToPython::defineMasks(
const Simulation* simulation)
const
371 std::ostringstream result;
372 result << std::setprecision(12);
374 const IDetector* detector = simulation->instrument().getDetector();
376 if (detectorMask && detectorMask->numberOfMasks()) {
378 for (
size_t i_mask = 0; i_mask < detectorMask->numberOfMasks(); ++i_mask) {
379 bool mask_value(
false);
380 const IShape2D* shape = detectorMask->getMaskShape(i_mask, mask_value);
382 printFunc(detector));
389 std::string SimulationToPython::defineSimulationOptions(
const Simulation* simulation)
const
391 std::ostringstream result;
392 result << std::setprecision(12);
395 if (options.getHardwareConcurrency() != options.getNumberOfThreads())
396 result <<
pyfmt::indent() <<
"simulation.getOptions().setNumberOfThreads("
397 << options.getNumberOfThreads() <<
")\n";
398 if (options.isIntegrate())
399 result <<
pyfmt::indent() <<
"simulation.getOptions().setMonteCarloIntegration(True, "
400 << options.getMcPoints() <<
")\n";
401 if (options.useAvgMaterials())
402 result <<
pyfmt::indent() <<
"simulation.getOptions().setUseAvgMaterials(True)\n";
403 if (options.includeSpecular())
404 result <<
pyfmt::indent() <<
"simulation.getOptions().setIncludeSpecular(True)\n";
408 std::string SimulationToPython::defineBackground(
const Simulation* simulation)
const
410 std::ostringstream result;
412 auto p_bg = simulation->background();
414 if (p_constant_bg->backgroundValue() > 0.0) {
415 result <<
pyfmt::indent() <<
"background = ba.ConstantBackground("
416 << pyfmt::printScientificDouble(p_constant_bg->backgroundValue()) <<
")\n";
417 result <<
pyfmt::indent() <<
"simulation.setBackground(background)\n";
420 result <<
pyfmt::indent() <<
"background = ba.PoissonNoiseBackground()\n";
421 result <<
pyfmt::indent() <<
"simulation.setBackground(background)\n";
430 result =
"if __name__ == '__main__': \n"
431 " result = run_simulation()\n"
432 " ba.plot_simulation_result(result)\n";
434 result =
"if __name__ == '__main__': \n"
435 " result = run_simulation()\n"
437 " if len(sys.argv)<2:\n"
438 " exit(\"File name is required\")\n"
439 " ba.IntensityDataIOFactory.writeSimulationResult(result, sys.argv[1])\n";
441 throw std::runtime_error(
"SimulationToPython::defineMain() -> Error. Unknown main type.");
Defines and implements namespace algo with some algorithms.
Defines class ConstantBackground.
Defines class ConvolutionDetectorResolution.
Defines class GISASSimulation.
Defines namespace INodeUtils.
Declares and implements pure virtual class ISpecularScan.
Defines class OffSpecSimulation.
Defines namespace ParameterUtils.
std::string poolParameterUnits(const IParameterized &node, const std::string &parName)
Returns units of main parameter.
Defines class PoissonNoiseBackground.
Defines namespace pyfmt2.
Defines functions in namespace pyfmt.
Defines functions in namespace pyfmt.
Defines class RectangularDetector.
Defines class RegionOfInterest.
Defines class ResolutionFunction2DGaussian.
Defines class SampleToPython.
Defines class SimulationToPython.
Defines class SpecularSimulation.
Defines class SphericalDetector.
double mag() const
Returns magnitude of the vector.
T z() const
Returns z-component in cartesian coordinate system.
T y() const
Returns y-component in cartesian coordinate system.
T x() const
Returns x-component in cartesian coordinate system.
Beam defined by wavelength, direction and intensity.
double getIntensity() const
Returns the beam intensity in neutrons/sec.
Class representing a constant background signal.
Convolutes the intensity in 1 or 2 dimensions with a resolution function.
double analyzerEfficiency() const
will always return positive value
kvector_t analyzerDirection() const
Retrieve the analyzer characteristics.
Collection of detector masks.
Main class to run a Grazing-Incidence Small-Angle Scattering simulation.
Interface for detector resolution algorithms.
Abstract detector interface.
virtual const DetectorMask * detectorMask() const =0
Returns detector masks container.
size_t dimension() const
Returns actual dimensionality of the detector (number of defined axes)
const IDetectorResolution * detectorResolution() const
Returns a pointer to detector resolution object.
virtual const RegionOfInterest * regionOfInterest() const =0
Returns region of interest if exists.
virtual Axes::Units defaultAxesUnits() const
Return default axes units.
const DetectionProperties & detectionProperties() const
Returns detection properties.
Basic class for all shapes in 2D.
Pure virtual base class for all types of specular scans.
Main class to run an off-specular simulation.
const IAxis * beamAxis() const
Returns axis of the beam.
Class representing Poisson noise on top of the scattered intensity.
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.
Collect the different options for simulation.
@ SAVE_DATA
main function saves intensity data
@ RUN_SIMULATION
main function runs simulation
std::string generateSimulationCode(const Simulation &simulation, EMainType mainType)
Returns a Python script that sets up a simulation and runs it if invoked as main program.
Pure virtual base class of OffSpecularSimulation, GISASSimulation and SpecularSimulation.
Main class to run a specular simulation.
const ISpecularScan * dataHandler() const
Returns internal data handler.
A spherical detector with axes and resolution function.
bool almostEqual(double a, double b)
Returns true if two doubles agree within machine epsilon.
std::string printDistribution(const IDistribution1D &par_distr, const std::string &units)
Prints distribution with constructor parameters in given units.
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 "runSimulation".
std::string indent(size_t width)
Returns a string of blanks with given width.
std::string printRealLimitsArg(const RealLimits &limits, const std::string &units)
Prints RealLimits in the form of argument (in the context of ParameterDistribution and similar).