16 #include "Base/Const/Units.h"
17 #include "Base/Util/Assert.h"
18 #include "Device/Beam/Beam.h"
19 #include "Device/Beam/FootprintGauss.h"
20 #include "Device/Beam/FootprintSquare.h"
21 #include "Device/Detector/RectangularDetector.h"
22 #include "Device/Detector/SphericalDetector.h"
23 #include "Device/Mask/DetectorMask.h"
24 #include "Device/Mask/Ellipse.h"
25 #include "Device/Mask/InfinitePlane.h"
26 #include "Device/Mask/Line.h"
27 #include "Device/Mask/Polygon.h"
28 #include "Device/Mask/Rectangle.h"
29 #include "Device/Resolution/ConvolutionDetectorResolution.h"
30 #include "Device/Resolution/ResolutionFunction2DGaussian.h"
48 #include "Param/Distrib/Distributions.h"
49 #include "Param/Distrib/RangedDistributions.h"
50 #include "Param/Node/NodeUtils.h"
51 #include "Resample/Options/SimulationOptions.h"
52 #include "Sim/Background/ConstantBackground.h"
53 #include "Sim/Background/PoissonBackground.h"
54 #include "Sim/Scan/AlphaScan.h"
55 #include "Sim/Scan/ScanResolution.h"
56 #include "Sim/Simulation/includeSimulations.h"
60 void setMaskContainer(
MaskItems* destMaskItems,
const IDetector& detector,
double scale)
62 const auto* detectorMask = detector.detectorMask();
63 for (
size_t i_mask = 0; i_mask < detectorMask->numberOfMasks(); ++i_mask) {
64 const MaskPattern* pat = detectorMask->patternAt(i_mask);
65 IShape2D* shape = pat->shape;
66 bool mask_value = pat->doMask;
68 if (
const auto* ellipse =
dynamic_cast<const Ellipse*
>(shape)) {
70 ellipseItem->setXCenter(scale * ellipse->getCenterX());
71 ellipseItem->setYCenter(scale * ellipse->getCenterY());
72 ellipseItem->setXRadius(scale * ellipse->radiusX());
73 ellipseItem->setYRadius(scale * ellipse->radiusY());
74 ellipseItem->setAngle(scale * ellipse->getTheta());
75 ellipseItem->setMaskValue(mask_value);
79 else if (
const auto* rectangle =
dynamic_cast<const Rectangle*
>(shape)) {
81 rectangleItem->setXLow(scale * rectangle->getXlow());
82 rectangleItem->setYLow(scale * rectangle->getYlow());
83 rectangleItem->setXUp(scale * rectangle->getXup());
84 rectangleItem->setYUp(scale * rectangle->getYup());
85 rectangleItem->setMaskValue(mask_value);
89 else if (
const auto* polygon =
dynamic_cast<const Polygon*
>(shape)) {
91 std::vector<double> xpos, ypos;
92 polygon->getPoints(xpos, ypos);
93 for (
size_t i_point = 0; i_point < xpos.size(); ++i_point)
94 polygonItem->addPoint(scale * xpos[i_point], scale * ypos[i_point]);
96 polygonItem->setMaskValue(mask_value);
97 polygonItem->setIsClosed(
true);
102 else if (
const auto* vline =
dynamic_cast<const VerticalLine*
>(shape)) {
104 lineItem->setPosX(scale * vline->getXpos());
105 lineItem->setMaskValue(mask_value);
109 else if (
const auto* hline =
dynamic_cast<const HorizontalLine*
>(shape)) {
111 lineItem->setPosY(scale * hline->getYpos());
112 lineItem->setMaskValue(mask_value);
116 else if (
const auto* plane =
dynamic_cast<const InfinitePlane*
>(shape)) {
119 planeItem->setMaskValue(mask_value);
124 throw Error(
"Cannot convert detector mask from core to GUI: Unknown shape");
127 if (detector.hasExplicitRegionOfInterest()) {
128 const auto xBounds = detector.regionOfInterestBounds(0);
129 const auto yBounds = detector.regionOfInterestBounds(1);
132 roiItem->setXLow(scale * xBounds.first);
133 roiItem->setYLow(scale * yBounds.first);
134 roiItem->setXUp(scale * xBounds.second);
135 roiItem->setYUp(scale * yBounds.second);
140 void setDetectorMasks(
DetectorItem* detector_item,
const ISimulation2D& simulation)
142 const IDetector& detector = simulation.detector();
143 if ((detector.detectorMask() && detector.detectorMask()->hasMasks())
144 || detector.hasExplicitRegionOfInterest()) {
146 setMaskContainer(&detector_item->
maskItems(), detector, scale);
150 void setFootprintFactor(
const IFootprintFactor* footprint,
SpecularBeamItem* beam_item)
154 if (
const auto*
const gaussian_fp =
dynamic_cast<const FootprintGauss*
>(footprint))
156 else if (
const auto*
const square_fp =
dynamic_cast<const FootprintSquare*
>(footprint))
163 const IDistribution1D* p_distribution = par_distr.getDistribution();
166 if (
const auto* distr =
dynamic_cast<const DistributionGate*
>(p_distribution)) {
168 distr_gate_item->
setRange(factor * distr->min(), factor * distr->max());
169 distItem = distr_gate_item;
170 }
else if (
const auto* distr =
dynamic_cast<const DistributionLorentz*
>(p_distribution)) {
172 distr_lorentz_item->setMean(factor * distr->mean());
173 distr_lorentz_item->setHwhm(factor * distr->hwhm());
174 distItem = distr_lorentz_item;
175 }
else if (
const auto* distr =
dynamic_cast<const DistributionGaussian*
>(p_distribution)) {
177 distr_gauss_item->setMean(factor * distr->mean());
178 distr_gauss_item->setStandardDeviation(factor * distr->getStdDev());
179 distItem = distr_gauss_item;
180 }
else if (
const auto* distr =
dynamic_cast<const DistributionLogNormal*
>(p_distribution)) {
181 auto* distr_lognorm_item =
183 distr_lognorm_item->setMedian(factor * distr->getMedian());
184 distr_lognorm_item->setScaleParameter(distr->getScalePar());
185 distItem = distr_lognorm_item;
186 }
else if (
const auto* distr =
dynamic_cast<const DistributionCosine*
>(p_distribution)) {
188 distr_cos_item->setMean(factor * distr->mean());
189 distr_cos_item->setSigma(factor * distr->sigma());
190 distItem = distr_cos_item;
191 }
else if (
const auto* distr =
dynamic_cast<const DistributionTrapezoid*
>(p_distribution)) {
193 distr_trapez_item->setCenter(factor * distr->mean());
194 distr_trapez_item->setLeftWidth(factor * distr->getLeftWidth());
195 distr_trapez_item->setMiddleWidth(factor * distr->getMiddleWidth());
196 distr_trapez_item->setRightWidth(factor * distr->getRightWidth());
197 distItem = distr_trapez_item;
199 throw Error(
"setDistribution: -> unknown distribution");
201 distItem->setNumberOfSamples((
int)par_distr.nDraws());
204 distItem->setSigmaFactor(par_distr.sigmaFactor());
207 distItem->
setLimits(par_distr.getLimits().scaledLimits(factor));
211 const ParameterDistribution& parameter_distribution)
213 ASSERT(beam_distribution_item);
215 if (parameter_distribution.getMinValue() < parameter_distribution.getMaxValue()) {
217 "setItemFromSample(BeamDistributionItem* "
218 "beamDistributionItem,"
219 "const ParameterDistribution& parameterDistribution) -> Error. ParameterDistribution "
220 "with defined min,max are not yet implemented in GUI");
223 const double unit_factor = 1.0 / beam_distribution_item->
scaleFactor();
224 setDistribution(beam_distribution_item, parameter_distribution, unit_factor);
227 void addDistributionToBeamItem(ParameterDistribution::WhichParameter which,
229 const ParameterDistribution& distribution)
231 if (distribution.whichParameter() != which)
234 setItemFromSample(item, distribution);
238 const IRangedDistribution& ranged,
double mean,
double std_dev)
240 if (!distributionItem)
242 ParameterDistribution par_distr(ParameterDistribution::None,
243 *ranged.distribution(mean, std_dev), ranged.nSamples(),
244 ranged.sigmaFactor(), ranged.limits());
245 setItemFromSample(distributionItem, par_distr);
248 void setGISASBeamItem(
BeamItem* beam_item,
const ScatteringSimulation& simulation)
251 const Beam& beam = simulation.beam();
253 beam_item->setIntensity(beam.intensity());
259 const std::vector<ParameterDistribution>& distributions = simulation.getDistributions();
260 for (
size_t i = 0; i < distributions.size(); ++i) {
262 addDistributionToBeamItem(ParameterDistribution::BeamWavelength,
264 addDistributionToBeamItem(ParameterDistribution::BeamInclinationAngle,
266 addDistributionToBeamItem(ParameterDistribution::BeamAzimuthalAngle,
271 void setOffspecBeamItem(
BeamItem* beam_item,
const OffspecSimulation& simulation)
273 const Beam& beam = simulation.beam();
275 beam_item->setIntensity(beam.intensity());
282 void setAxisItem(
BasicAxisItem* item,
const IAxis& axis,
double factor)
284 if (!
dynamic_cast<const FixedBinAxis*
>(&axis))
285 throw Error(
"setAxisItem() -> Error. Unexpected axis");
290 item->
setTitle(QString::fromStdString(axis.axisName()));
296 const IAxis& phi_axis = detector.axis(0);
297 const IAxis& alpha_axis = detector.axis(1);
299 auto& phiAxis = detectorItem->phiAxis();
300 phiAxis.setNbins(phi_axis.size());
301 phiAxis.setMin(Units::rad2deg(phi_axis.min()));
302 phiAxis.setMax(Units::rad2deg(phi_axis.max()));
304 auto& alphaAxis = detectorItem->alphaAxis();
305 alphaAxis.setNbins(alpha_axis.size());
306 alphaAxis.setMin(Units::rad2deg(alpha_axis.min()));
307 alphaAxis.setMax(Units::rad2deg(alpha_axis.max()));
311 const RectangularDetector& detector)
314 detectorItem->
setXSize(detector.xSize());
315 detectorItem->setWidth(detector.width());
317 detectorItem->
setYSize(detector.ySize());
318 detectorItem->setHeight(detector.height());
321 if (detector.getDetectorArrangment() == RectangularDetector::GENERIC) {
322 R3 normal = detector.getNormalVector();
323 detectorItem->setNormalVector(normal);
325 R3 direction = detector.getDirectionVector();
326 detectorItem->setDirectionVector(direction);
328 detectorItem->setU0(detector.getU0());
329 detectorItem->setV0(detector.getV0());
332 else if (detector.getDetectorArrangment() == RectangularDetector::PERPENDICULAR_TO_SAMPLE) {
333 detectorItem->setDistance(detector.getDistance());
334 detectorItem->setU0(detector.getU0());
335 detectorItem->setV0(detector.getV0());
336 }
else if (detector.getDetectorArrangment()
337 == RectangularDetector::PERPENDICULAR_TO_DIRECT_BEAM) {
338 detectorItem->setDistance(detector.getDistance());
339 detectorItem->setU0(detector.getU0());
340 detectorItem->setV0(detector.getV0());
341 }
else if (detector.getDetectorArrangment()
342 == RectangularDetector::PERPENDICULAR_TO_REFLECTED_BEAM) {
343 detectorItem->setDistance(detector.getDistance());
344 detectorItem->setU0(detector.getU0());
345 detectorItem->setV0(detector.getV0());
346 }
else if (detector.getDetectorArrangment()
347 == RectangularDetector::PERPENDICULAR_TO_REFLECTED_BEAM_DPOS) {
348 detectorItem->setDistance(detector.getDistance());
349 detectorItem->setU0(detector.getDirectBeamU0());
350 detectorItem->setV0(detector.getDirectBeamV0());
352 throw Error(
"setItemFromSample(RectangularDetectorItem* "
354 "Error. Unknown detector arrangement");
358 void setDetectorGeometry(
Instrument2DItem* instrument_item,
const IDetector& detector)
360 if (
const auto* det =
dynamic_cast<const SphericalDetector*
>(&detector)) {
362 setSphericalDetector(item, *det);
363 }
else if (
const auto* det =
dynamic_cast<const RectangularDetector*
>(&detector)) {
365 setRectangularDetector(item, *det);
367 throw Error(
"setDetectorGeometry() -> Unknown detector type.");
371 void setDetectorResolution(
DetectorItem* detector_item,
const IDetector& detector)
373 const IDetectorResolution* p_resfunc = detector.detectorResolution();
378 if (
const auto* p_convfunc =
dynamic_cast<const ConvolutionDetectorResolution*
>(p_resfunc)) {
379 if (
const auto* resfunc =
dynamic_cast<const ResolutionFunction2DGaussian*
>(
380 p_convfunc->getResolutionFunction2D())) {
384 item->setSigmaX(scale * resfunc->sigmaX());
385 item->setSigmaY(scale * resfunc->sigmaY());
387 throw Error(
"setDetectorResolution() -> Error. "
388 "Unknown detector resolution function");
391 throw Error(
"setDetectorResolution() -> Error. "
392 "Not a ConvolutionDetectorResolution function");
396 void setPolarizerAnalyzer(
Instrument2DItem* instrument_item,
const ISimulation2D& simulation)
398 instrument_item->setPolarization(simulation.beam().polVector());
400 const IDetector& detector = simulation.detector();
401 double total_transmission = detector.analyzer().totalTransmission();
402 if (total_transmission <= 0.0)
405 R3 analyzer_dir = detector.analyzer().analyzerDirection();
406 double efficiency = detector.analyzer().analyzerEfficiency();
407 instrument_item->setAnalyzerDirection(analyzer_dir);
408 instrument_item->setAnalyzerEfficiency(efficiency);
409 instrument_item->setAnalyzerTotalTransmission(total_transmission);
412 void updateDetector(
Instrument2DItem* instrument_item,
const ISimulation2D& simulation)
414 const IDetector& detector = simulation.detector();
415 setDetectorGeometry(instrument_item, detector);
419 setDetectorResolution(detector_item, detector);
420 setDetectorMasks(detector_item, simulation);
421 setPolarizerAnalyzer(instrument_item, simulation);
424 void setBackground(
InstrumentItem* instrument_item,
const ISimulation& simulation)
426 const auto* p_bg = simulation.background();
427 if (
const auto* p_constant_bg =
dynamic_cast<const ConstantBackground*
>(p_bg)) {
429 double value = p_constant_bg->backgroundValue();
430 constant_bg_item->setBackgroundValue(value);
431 }
else if (
dynamic_cast<const PoissonBackground*
>(p_bg))
438 setGISASBeamItem(result->beamItem(), simulation);
439 updateDetector(result, simulation);
447 setOffspecBeamItem(result->beamItem(), simulation);
448 updateDetector(result, simulation);
450 const double factor = 1. / Units::deg;
451 result->alphaAxis().setNbins(simulation.beamAxis()->size());
452 result->alphaAxis().setMin(factor * simulation.beamAxis()->min());
453 result->alphaAxis().setMax(factor * simulation.beamAxis()->max());
463 const ISpecularScan* scan = simulation.scan();
465 beam_item->setIntensity(1.0);
471 setAxisItem(axis_item, *scan->coordinateAxis(), 1. / Units::deg);
473 setFootprintFactor(scan->footprintFactor(), beam_item);
475 const auto* alphaScan =
dynamic_cast<const AlphaScan*
>(scan);
479 const auto* resolution = alphaScan->wavelengthResolution();
480 if (!resolution->empty()) {
481 double mean = alphaScan->wavelength();
482 double std_dev = resolution->stdDevs(mean, 1).front();
487 resolution = alphaScan->angleResolution();
488 if (resolution && !resolution->empty()) {
489 double std_dev = resolution->stdDevs(0.0, 1).front();
504 if (
const auto* gisasSimulation =
dynamic_cast<const ScatteringSimulation*
>(&simulation))
505 item = createGISASInstrumentItem(*gisasSimulation);
506 else if (
const auto* offspecSimulation =
dynamic_cast<const OffspecSimulation*
>(&simulation))
507 item = createOffspecInstrumentItem(*offspecSimulation);
508 else if (
const auto* spec_simulation =
dynamic_cast<const SpecularSimulation*
>(&simulation))
509 item = createSpecularInstrumentItem(*spec_simulation);
513 setBackground(item, simulation);
524 if (simulation.options().isIntegrate())
526 static_cast<unsigned>(simulation.options().getMcPoints()));
528 result->setUseAnalytical();
530 result->setUseAverageMaterials(simulation.options().useAvgMaterials());
531 result->setIncludeSpecularPeak(simulation.options().includeSpecular());
Defines various axis items.
Defines BackgroundItem classes.
Defines class BeamAngleItems.
Defines class BeamWavelengthItem.
Defines class InstrumentCollection.
Defines class InstrumentItem and all its children.
Defines class GUISampleBuilder.
Defines namespace GUI::Model::ObjectBuilder.
Defines MaskItems classes.
Defines class MesoCrystalItem.
Defines class ParticleItem.
Defines class ParticleLayoutItem.
Defines class RectangularDetectorItem.
Defines family of ResolutionFunctionItem.
Defines class SimulationOptionsItem.
Defines class SphericalDetectorItem.
void setBinCount(size_t value)
void setLowerBound(double value)
void setUpperBound(double value)
void setTitle(const QString &title)
The BeamDistributionItem handles wavelength, inclination and azimuthal parameter distribution for Bea...
T * setDistributionType()
DistributionItem * distribution() const
virtual double scaleFactor() const
virtual BeamDistributionItem * inclinationAngleItem() const
void setWavelength(double value)
BeamAzimuthalAngleItem * azimuthalAngleItem() const
virtual void setInclinationAngle(double value)
void setAzimuthalAngle(double value)
BeamWavelengthItem * wavelengthItem() const
virtual double axesToCoreUnitsFactor() const
Scales the values provided by axes (to perform deg->rad conversion on the way to domain).
T * setResolutionFunctionType()
void setRange(double min, double max)
bool hasSigmaFactor() const
virtual void setLimits(const RealLimits &limits)
DetectorItem * detectorItem() const
void emplace_back(InstrumentItem *item)
Abstract base class for instrument-specific item classes.
void insertMask(int index, MaskItem *maskItem)
Takes ownership of maskItem.
void setXSize(size_t nx) override
sets the size of x-axis of the detector
void setYSize(size_t ny) override
sets the size of y-axis of the detector
void setDetectorAlignment(RectangularDetector::EDetectorArrangement alignment)
The SimulationOptionsItem class holds simulation status (run policy, number of threads,...
void setUseMonteCarloIntegration(unsigned numberOfPoints)
void setSquareFootprint(double value)
void setInclinationAngle(double value) override
BasicAxisItem * inclinationAxis() const
void setGaussianFootprint(double value)
SpecularBeamInclinationItem * inclinationAngleItem() const override