diff --git a/Core/Export/SimulationToPython.cpp b/Core/Export/SimulationToPython.cpp index 2f6fd8416e034f11ef67c0e37e79602317384dcb..e82a9f34b305d8b4724ac6feba6a0b473a18b880 100644 --- a/Core/Export/SimulationToPython.cpp +++ b/Core/Export/SimulationToPython.cpp @@ -28,7 +28,6 @@ #include "Device/Beam/FootprintSquare.h" #include "Device/Detector/RectangularDetector.h" #include "Device/Detector/SphericalDetector.h" -#include "Device/ProDetector/RegionOfInterest.h" #include "Device/Resolution/ConvolutionDetectorResolution.h" #include "Device/Resolution/ResolutionFunction2DGaussian.h" #include "Device/Resolution/ScanResolution.h" @@ -40,7 +39,7 @@ using pyfmt::indent; namespace { -//! Returns a function that converts a coordinate to a Python code snippet with appropiate unit +//! Returns a function that converts a coordinate to a Python code snippet with appropriate unit std::function<std::string(double)> printFunc(const IDetector* detector) { if (detector->defaultCoords() == Axes::Coords::MM) @@ -198,13 +197,14 @@ std::string defineDetector(const ISimulation* simulation) throw std::runtime_error("defineDetector() -> Error. Unknown alignment."); } else throw std::runtime_error("defineDetector() -> Error. Unknown detector"); - if (detector->regionOfInterest()) { // #baROI refactor: detector->hasRoi() - // #baROI refactor : detector->roiCoords() + if (detector->hasExplicitRegionOfInterest()) { + const auto xBounds = detector->regionOfInterestBounds(0); + const auto yBounds = detector->regionOfInterestBounds(1); result << indent() << "detector.setRegionOfInterest(" - << printFunc(detector)(detector->regionOfInterest()->getXlow()) << ", " - << printFunc(detector)(detector->regionOfInterest()->getYlow()) << ", " - << printFunc(detector)(detector->regionOfInterest()->getXup()) << ", " - << printFunc(detector)(detector->regionOfInterest()->getYup()) << ")\n"; + << printFunc(detector)(xBounds.first) << ", " + << printFunc(detector)(yBounds.first) << ", " + << printFunc(detector)(xBounds.second) << ", " + << printFunc(detector)(yBounds.second) << ")\n"; } return result.str(); } @@ -356,7 +356,7 @@ std::string defineMasks(const ISimulation* simulation) const IDetector* detector = simulation->instrument().getDetector(); const DetectorMask* detectorMask = detector->detectorMask(); - if (detectorMask && detectorMask->numberOfMasks()) { + if (detectorMask && detectorMask->hasMasks()) { result << "\n"; for (size_t i_mask = 0; i_mask < detectorMask->numberOfMasks(); ++i_mask) { bool mask_value(false); diff --git a/Core/Simulation/OffSpecularSimulation.cpp b/Core/Simulation/OffSpecularSimulation.cpp index 34e1ae786cb3bdf0d7fd2976f8ebd385771b9a4f..624b421f550ab1796cdac135bc363b5a2a1f4c3c 100644 --- a/Core/Simulation/OffSpecularSimulation.cpp +++ b/Core/Simulation/OffSpecularSimulation.cpp @@ -13,6 +13,9 @@ // ************************************************************************************************ #include "Core/Simulation/OffSpecularSimulation.h" +#include "Base/Pixel/RectangularPixel.h" +#include "Device/Detector/RectangularDetector.h" +#include "Device/Detector/SphericalDetector.h" #include "Device/Instrument/CoordSystem2D.h" #include "Param/Distrib/Distributions.h" #include "Sample/SampleBuilderEngine/ISampleBuilder.h" @@ -43,8 +46,8 @@ size_t OffSpecularSimulation::numberOfSimulationElements() const SimulationResult OffSpecularSimulation::result() const { auto data = std::unique_ptr<OutputData<double>>(m_intensity_map.clone()); - OffSpecularCoordinates converter(detector2D(), beam(), *m_alpha_i_axis); - return SimulationResult(*data, converter); + std::unique_ptr<ICoordSystem> coordsSystem(createCoordSystem()); + return SimulationResult(*data, *coordsSystem); } void OffSpecularSimulation::setBeamParameters(double wavelength, const IAxis& alpha_axis, @@ -67,11 +70,23 @@ const IAxis* OffSpecularSimulation::beamAxis() const #ifndef SWIG ICoordSystem* OffSpecularSimulation::createCoordSystem() const { - const IAxis* axis = beamAxis(); - if (!axis) + if (!beamAxis()) throw std::runtime_error("Error in OffSpecularSimulation::createCoordSystem:" " missing inclination angle axis"); - return new OffSpecularCoordinates(detector2D(), beam(), *axis); + + const auto axes = detector2D().axesClippedToRegionOfInterest(); + ASSERT(axes.size() == 2); + const IAxis& yAxis = *axes[1]; + + if (const auto* rect_det = dynamic_cast<const RectangularDetector*>(&detector2D())) { + std::unique_ptr<RectangularPixel> det_pixel(rect_det->regionOfInterestPixel()); + return OffSpecularCoordinates::createForRectangularDetector(beam(), *beamAxis(), *det_pixel, + yAxis); + } else if (dynamic_cast<const SphericalDetector*>(&detector2D())) + return OffSpecularCoordinates::createForSphericalDetector(beam(), *beamAxis(), yAxis); + + ASSERT(0); + return nullptr; } #endif diff --git a/Device/Detector/IDetector.cpp b/Device/Detector/IDetector.cpp index 6bceef47dd6dfdff0ab0b924f6f189141848af0c..aa7e62759de2663ec764c626c77377955e053154 100644 --- a/Device/Detector/IDetector.cpp +++ b/Device/Detector/IDetector.cpp @@ -15,7 +15,6 @@ #include "Device/Detector/IDetector.h" #include "Base/Pixel/SimulationElement.h" #include "Device/ProDetector/DetectorMask.h" -#include "Device/ProDetector/RegionOfInterest.h" #include "Device/Resolution/ConvolutionDetectorResolution.h" IDetector::IDetector() @@ -28,6 +27,7 @@ IDetector::IDetector(const IDetector& other) , INode() , m_axes(other.m_axes) , m_detection_properties(other.m_detection_properties) + , m_explicitROI(other.m_explicitROI) { if (other.m_detector_resolution) setDetectorResolution(*other.m_detector_resolution); @@ -84,6 +84,31 @@ std::unique_ptr<IAxis> IDetector::createAxis(size_t index, size_t n_bins, double return std::make_unique<FixedBinAxis>(axisName(index), n_bins, min, max); } +size_t IDetector::sizeOfExplicitRegionOfInterest() const +{ + if (m_explicitROI.size() != m_axes.size()) + return 0; + + size_t s = 1; + for (const auto& roiOfAxis : m_explicitROI) + s *= roiOfAxis.roiSize; + + return s; +} + +std::pair<double, double> IDetector::boundsOfExplicitRegionOfInterest(size_t iAxis) const +{ + if (iAxis >= dimension()) + throw std::runtime_error( + "IDetector::boundsOfExplicitRegionOfInterest() -> Error. iAxis must be smaller than " + + std::to_string(dimension())); + + if (iAxis < m_explicitROI.size()) + return {m_explicitROI[iAxis].lower, m_explicitROI[iAxis].upper}; + + return {0., 0.}; +} + size_t IDetector::totalSize() const { const size_t dim = dimension(); @@ -97,18 +122,42 @@ size_t IDetector::totalSize() const size_t IDetector::sizeOfRegionOfInterest() const { - if (regionOfInterest() != nullptr) - return regionOfInterest()->roiSize(); + const auto explicitSize = sizeOfExplicitRegionOfInterest(); + return (explicitSize != 0) ? explicitSize : totalSize(); +} + +bool IDetector::hasExplicitRegionOfInterest() const +{ + return !m_axes.empty() && (m_explicitROI.size() == m_axes.size()); +} - return totalSize(); +CloneableVector<IAxis> IDetector::axesClippedToRegionOfInterest() const +{ + CloneableVector<IAxis> result; + for (size_t iAxis = 0; iAxis < m_axes.size(); ++iAxis) { + auto axis = m_axes[iAxis]->clone(); + axis->clip(regionOfInterestBounds(iAxis)); + result.push_back(axis); + } + return result; } size_t IDetector::regionOfInterestIndexToDetectorIndex(const size_t regionOfInterestIndex) const { - if (regionOfInterest() != nullptr) - return regionOfInterest()->detectorIndex(regionOfInterestIndex); + if (!hasExplicitRegionOfInterest()) + return regionOfInterestIndex; - return regionOfInterestIndex; + throw std::runtime_error("IDetector::regionOfInterestIndexToDetectorIndex() -> Error. Not " + "implemented by derived class."); +} + +size_t IDetector::detectorIndexToRegionOfInterestIndex(const size_t detectorIndex) const +{ + if (!hasExplicitRegionOfInterest()) + return detectorIndex; + + throw std::runtime_error("IDetector::detectorIndexToRegionOfInterestIndex() -> Error. Not " + "implemented by derived class."); } void IDetector::setAnalyzerProperties(const kvector_t direction, double efficiency, @@ -130,6 +179,11 @@ void IDetector::setResolutionFunction(const IResolutionFunction2D& resFunc) setDetectorResolution(convFunc); } +void IDetector::resetRegionOfInterest() +{ + m_explicitROI.clear(); +} + void IDetector::applyDetectorResolution(OutputData<double>* p_intensity_map) const { if (!p_intensity_map) @@ -178,11 +232,11 @@ std::unique_ptr<OutputData<double>> IDetector::createDetectorMap() const "Error in IDetector::createDetectorMap: dimensions of the detector are undefined"); std::unique_ptr<OutputData<double>> result(new OutputData<double>); - for (size_t i = 0; i < dim; ++i) - if (auto roi = regionOfInterest()) - result->addAxis(*roi->clipAxisToRoi(i, axis(i))); - else - result->addAxis(axis(i)); + for (size_t iAxis = 0; iAxis < dim; ++iAxis) { + std::unique_ptr<IAxis> tempAxis(axis(iAxis).clone()); + tempAxis->clip(regionOfInterestBounds(iAxis)); + result->addAxis(*tempAxis); + } return result; } @@ -205,6 +259,20 @@ size_t IDetector::numberOfSimulationElements() const return result; } +std::pair<double, double> IDetector::regionOfInterestBounds(size_t iAxis) const +{ + if (iAxis >= m_axes.size()) + throw std::runtime_error( + "IDetector::regionOfInterestBounds() -> Error. iAxis must be smaller than " + + std::to_string(m_axes.size())); + + const auto explicitBounds = boundsOfExplicitRegionOfInterest(iAxis); + if (explicitBounds.first != 0 || explicitBounds.second != 0) + return explicitBounds; + + return m_axes[iAxis]->bounds(); +} + std::vector<const INode*> IDetector::getChildren() const { return std::vector<const INode*>() << &m_detection_properties << m_detector_resolution; @@ -247,3 +315,17 @@ SimulationAreaIterator IDetector::endRegionOfInterestPoints() const { return SimulationAreaIterator::createEnd(this, SimulationAreaIterator::regionOfInterest); } + +/* -- IDetector::RoiOfAxis ----------------------------------------------------------- */ + +IDetector::RoiOfAxis::RoiOfAxis(const IAxis& axis, double _lower, double _upper) +{ + lower = _lower; + upper = _upper; + + lowerIndex = axis.findClosestIndex(lower); + upperIndex = axis.findClosestIndex(upper); + + detectorSize = axis.size(); + roiSize = upperIndex - lowerIndex + 1; +} diff --git a/Device/Detector/IDetector.h b/Device/Detector/IDetector.h index 8218f47dc4f6d3f84e4a1f4b062eec6908a3d157..4fdef6d51cd87ba144e44c451af924e3ecfc6b23 100644 --- a/Device/Detector/IDetector.h +++ b/Device/Detector/IDetector.h @@ -29,9 +29,22 @@ class IDetectorResolution; class IResolutionFunction2D; template <class T> class OutputData; class SimulationElement; -class RegionOfInterest; //! Abstract detector interface. +//! +//! Handles also "region of interest" (ROI). In general, the ROI is the whole +//! detector, and all methods related to ROI work on the whole detector. +//! If a ROI different to the detector size is explicitly set, then ROI-related +//! methods work on this reduced ROI. +//! Therefore, when calling ROI related methods, the distinction between "explicit +//! ROI exists: yes/no" does not have to be made by the caller, but it is handled in here. +//! For access to the whole detector, even if a smaller ROI is explicitly defined, use the +//! non-ROI-related methods like totalSize() or axes(). +//! Any method which is not speaking of "explicit ROI" handles the "implicit ROI", i.e. uses +//! an explicitly set ROI or the whole detector if no explicit ROI exists. +//! To access the explicitly set ROI, use the methods which have the explicit in its +//! name, like sizeOfExplicitRegionOfInterest(). +//! //! @ingroup detector class IDetector : public ICloneable, public INode { @@ -56,18 +69,21 @@ public: void setResolutionFunction(const IResolutionFunction2D& resFunc); //! Resets region of interest making whole detector plane available for the simulation. - virtual void resetRegionOfInterest() = 0; + void resetRegionOfInterest(); + //! Returns detector masks container virtual const DetectorMask* detectorMask() const = 0; std::vector<const INode*> getChildren() const override; //! Iterate over all points within "region of interest", no matter whether they are masked or - //! not. + //! not. If no region of interest is explicitly defined, then the whole detector is taken as + //! "region of interest". void iterateOverRegionOfInterest(std::function<void(const_iterator)> func) const; - //! Iterate over all non-masked points. Points outside of "region of - //! interest" are also treated as "masked". + //! Iterate over all non-masked points within "region of interest". + //! If no region of interest is explicitly defined, then the whole detector is taken as + //! "region of interest". void iterateOverNonMaskedPoints(std::function<void(const_iterator)> func) const; #ifndef SWIG @@ -80,17 +96,24 @@ public: SimulationAreaIterator endNonMaskedPoints() const; //! Create begin-iterator to iterate over all points which lay - //! within the "Region of Interest". + //! within the "Region of Interest". If no region of interest is explicitly + //! defined, then the whole detector is taken as "region of interest". //! No matter whether masked or not. SimulationAreaIterator beginRegionOfInterestPoints() const; //! Create end-iterator to iterate over all points which lay - //! within the "Region of Interest". + //! within the "Region of Interest". If no region of interest is explicitly + //! defined, then the whole detector is taken as "region of interest". //! No matter whether masked or not. SimulationAreaIterator endRegionOfInterestPoints() const; #endif // SWIG + //! The axes of the complete detector. + //! Any region of interest is not taken into account. const CloneableVector<IAxis>& axes() const { return m_axes; } + + //! One axis of the complete detector. + //! Any region of interest is not taken into account. const IAxis& axis(size_t index) const; //! Returns number of defined axes @@ -99,17 +122,26 @@ public: //! Calculate axis index for given global index size_t axisBinIndex(size_t index, size_t selected_axis) const; - //! Returns total number of pixels // #baROI rename to totalPixels + //! Returns total number of pixels. + //! Any region of interest is not taken into account. size_t totalSize() const; //! The size of the "Region of Interest". Same as totalSize() - //! if no region of interest has been set. + //! if no region of interest has been explicitly set. size_t sizeOfRegionOfInterest() const; + //! True if a region of interest is explicitly set. + bool hasExplicitRegionOfInterest() const; + + //! Returns the axes clipped to the region of interest. If no region of interest is explicitly + //! defined, then the whole detector is taken as "region of interest". + CloneableVector<IAxis> axesClippedToRegionOfInterest() const; + //! Convert an index of the region of interest to an index of the detector. //! If no region of interest is set, then the index stays unmodified (since ROI == detector //! area). - size_t regionOfInterestIndexToDetectorIndex(const size_t regionOfInterestIndex) const; + virtual size_t regionOfInterestIndexToDetectorIndex(const size_t regionOfInterestIndex) const; + virtual size_t detectorIndexToRegionOfInterestIndex(const size_t detectorIndex) const; //! Applies the detector resolution to the given intensity maps void applyDetectorResolution(OutputData<double>* p_intensity_map) const; @@ -136,8 +168,10 @@ public: //! Returns number of simulation elements. size_t numberOfSimulationElements() const; - //! Returns region of interest if exists. - virtual const RegionOfInterest* regionOfInterest() const = 0; + //! The lower and upper bound of the region of interest. If no region of interest is explicitly + //! defined, then the whole detector is taken as "region of interest". + // #baROI add unit test for no ROI (whether internal comparison to 0/0 works...) + std::pair<double, double> regionOfInterestBounds(size_t iAxis) const; protected: IDetector(const IDetector& other); @@ -151,6 +185,37 @@ protected: virtual std::unique_ptr<IAxis> createAxis(size_t index, size_t n_bins, double min, double max) const; + //! Return 0 if no ROI has been explicitly set. + //! Size means number of data points. + virtual size_t sizeOfExplicitRegionOfInterest() const; + + //! Lower and upper bound of one axis of an explicitly set ROI. + //! Return 0/0 if no ROI has been explicitly set. + virtual std::pair<double, double> boundsOfExplicitRegionOfInterest(size_t iAxis) const; + +#ifndef SWIG +protected: + //! Keeps RegionOfInterest (ROI) data of one axis + struct RoiOfAxis { + double lower; + double upper; + + // The following values are all pre-computed values. Aim is to speed up repeated + // calculations. + size_t lowerIndex; //!< index corresponding to 'lower' + size_t upperIndex; //!< index corresponding to 'upper' + size_t roiSize; //!< number of bins on axis of ROI + size_t detectorSize; //!< number of bins on axis of detector + + RoiOfAxis(const IAxis& axis, double lower, double upper); + }; + + std::vector<RoiOfAxis> m_explicitROI; //!< an explicitly defined region of interest. + //!< Empty if no ROI has been defined. + //!< Vector index corresponds to axis index in m_axes + +#endif // SWIG + private: void setDataToDetectorMap(OutputData<double>& detectorMap, const std::vector<SimulationElement>& elements) const; diff --git a/Device/Detector/IDetector2D.cpp b/Device/Detector/IDetector2D.cpp index b4118604a1812380e2b863e84650929aa5b99ecd..41cee4b5e1e95f227a74a806917b7ec4a4923af5 100644 --- a/Device/Detector/IDetector2D.cpp +++ b/Device/Detector/IDetector2D.cpp @@ -18,15 +18,26 @@ #include "Device/Beam/Beam.h" #include "Device/Detector/DetectorContext.h" #include "Device/Mask/InfinitePlane.h" -#include "Device/ProDetector/RegionOfInterest.h" + +namespace { + +inline size_t xcoord(size_t index, size_t sizeX, size_t sizeY) +{ + return index / sizeY % sizeX; +} + +inline size_t ycoord(size_t index, size_t sizeY) +{ + return index % sizeY; +} + +} // namespace IDetector2D::IDetector2D() = default; IDetector2D::IDetector2D(const IDetector2D& other) : IDetector(other), m_detector_mask(other.m_detector_mask) { - if (other.regionOfInterest()) - m_region_of_interest.reset(other.regionOfInterest()->clone()); } IDetector2D::~IDetector2D() = default; @@ -39,21 +50,45 @@ void IDetector2D::setDetectorParameters(size_t n_x, double x_min, double x_max, addAxis(*createAxis(1, n_y, y_min, y_max)); } -const RegionOfInterest* IDetector2D::regionOfInterest() const +void IDetector2D::setRegionOfInterest(double xlow, double ylow, double xup, double yup) { - return m_region_of_interest.get(); + ASSERT(dimension() == 2); + + m_explicitROI.clear(); + m_explicitROI.push_back({axis(0), xlow, xup}); + m_explicitROI.push_back({axis(1), ylow, yup}); } -void IDetector2D::setRegionOfInterest(double xlow, double ylow, double xup, double yup) +size_t IDetector2D::regionOfInterestIndexToDetectorIndex(const size_t regionOfInterestIndex) const { - m_region_of_interest = std::make_unique<RegionOfInterest>(axes(), xlow, ylow, xup, yup); - m_detector_mask.initMaskData(axes()); + if (m_explicitROI.size() != 2) + return regionOfInterestIndex; + + const auto& x = m_explicitROI[0]; + const auto& y = m_explicitROI[1]; + + const size_t globalIndex0 = y.lowerIndex + x.lowerIndex * y.detectorSize; + return globalIndex0 + ycoord(regionOfInterestIndex, y.roiSize) + + xcoord(regionOfInterestIndex, x.roiSize, y.roiSize) * y.detectorSize; } -void IDetector2D::resetRegionOfInterest() +size_t IDetector2D::detectorIndexToRegionOfInterestIndex(const size_t detectorIndex) const { - m_region_of_interest.reset(); - m_detector_mask.initMaskData(axes()); + if (m_explicitROI.size() != 2) + return detectorIndex; + + const auto& x = m_explicitROI[0]; + const auto& y = m_explicitROI[1]; + + const size_t ny = ycoord(detectorIndex, y.detectorSize); + if (ny < y.lowerIndex || ny > y.upperIndex) + throw std::runtime_error("IDetector2D::detectorIndexToRegionOfInterestIndex() -> Error."); + + const size_t nx = xcoord(detectorIndex, x.detectorSize, y.detectorSize); + if (nx < x.lowerIndex || nx > x.upperIndex) + throw std::runtime_error("IDetector2D::detectorIndexToRegionOfInterestIndex() -> Error."); + + return ny - y.lowerIndex + (nx - x.lowerIndex) * y.roiSize; } std::vector<size_t> IDetector2D::active_indices() const diff --git a/Device/Detector/IDetector2D.h b/Device/Detector/IDetector2D.h index 2cd34becc32e6bfa0ec5a310ab502b96397eb986..27563770af35598064973b1964ffd26734aa2761 100644 --- a/Device/Detector/IDetector2D.h +++ b/Device/Detector/IDetector2D.h @@ -52,14 +52,12 @@ public: //! Put the mask for all detector channels (i.e. exclude whole detector from the analysis) void maskAll(); - //! Returns region of interest if exists. - const RegionOfInterest* regionOfInterest() const override; - //! Sets rectangular region of interest with lower left and upper right corners defined. void setRegionOfInterest(double xlow, double ylow, double xup, double yup); - //! Resets region of interest making whole detector plane available for the simulation. - void resetRegionOfInterest() override; + virtual size_t + regionOfInterestIndexToDetectorIndex(const size_t regionOfInterestIndex) const override; + virtual size_t detectorIndexToRegionOfInterestIndex(const size_t detectorIndex) const override; //! Returns vector of unmasked detector indices. std::vector<size_t> active_indices() const; @@ -84,7 +82,6 @@ protected: private: DetectorMask m_detector_mask; - std::unique_ptr<RegionOfInterest> m_region_of_interest; }; #endif // BORNAGAIN_DEVICE_DETECTOR_IDETECTOR2D_H diff --git a/Device/Detector/RectangularDetector.cpp b/Device/Detector/RectangularDetector.cpp index db602c91555cb30384142cea7dd59922d09510f8..8fb23d1674cdb5a6efaed07561aa235e4b3c29a4 100644 --- a/Device/Detector/RectangularDetector.cpp +++ b/Device/Detector/RectangularDetector.cpp @@ -18,7 +18,6 @@ #include "Base/Pixel/RectangularPixel.h" #include "Base/Pixel/SimulationElement.h" #include "Device/Beam/Beam.h" -#include "Device/ProDetector/RegionOfInterest.h" #include "Device/Resolution/IDetectorResolution.h" RectangularDetector::RectangularDetector(size_t nxbins, double width, size_t nybins, double height) @@ -163,22 +162,14 @@ RectangularDetector::EDetectorArrangement RectangularDetector::getDetectorArrang RectangularPixel* RectangularDetector::regionOfInterestPixel() const { - const IAxis& u_axis = axis(0); - const IAxis& v_axis = axis(1); - double u_min, v_min, width, height; - auto p_roi = - regionOfInterest(); // #baROI refactor: return x1/y1/x2/y2 instead of class RegionOfInterest - if (p_roi) { - u_min = p_roi->getXlow(); - v_min = p_roi->getYlow(); - width = p_roi->getXup() - p_roi->getXlow(); - height = p_roi->getYup() - p_roi->getYlow(); - } else { - u_min = u_axis.lowerBound(); - v_min = v_axis.lowerBound(); - width = getWidth(); - height = getHeight(); - } + const auto uAxisBoundsROI = regionOfInterestBounds(0); + const auto vAxisBoundsROI = regionOfInterestBounds(1); + + const double u_min = uAxisBoundsROI.first; + const double v_min = vAxisBoundsROI.first; + const double width = uAxisBoundsROI.second - uAxisBoundsROI.first; + const double height = vAxisBoundsROI.second - vAxisBoundsROI.first; + const kvector_t corner_position(m_normal_to_detector + (u_min - m_u0) * m_u_unit + (v_min - m_v0) * m_v_unit); const kvector_t uaxis_vector = width * m_u_unit; diff --git a/Device/Detector/SpecularDetector1D.h b/Device/Detector/SpecularDetector1D.h index cdaecb3febab05492ca543df2c3b4a007cb6ed7d..9b8358168f49ccad0fc0fcec852f1e0b3b1fc6d2 100644 --- a/Device/Detector/SpecularDetector1D.h +++ b/Device/Detector/SpecularDetector1D.h @@ -40,11 +40,6 @@ public: //! Returns detector masks container. const DetectorMask* detectorMask() const override { return nullptr; } - //! Returns region of interest if exists. - const RegionOfInterest* regionOfInterest() const override { return nullptr; } - - void resetRegionOfInterest() override {} - // Set the angular axis. A SpecularDetector1D can only have a single axis void setAxis(const IAxis& axis); diff --git a/Device/Instrument/CoordSystem2D.cpp b/Device/Instrument/CoordSystem2D.cpp index 20668ae5ad6cae0e4a073402ab1784aa71a0ac48..256ce56ee5eba253c555af9115e69c9a5546ecb9 100644 --- a/Device/Instrument/CoordSystem2D.cpp +++ b/Device/Instrument/CoordSystem2D.cpp @@ -13,14 +13,13 @@ // ************************************************************************************************ #include "Device/Instrument/CoordSystem2D.h" +#include "Base/Axis/FixedBinAxis.h" #include "Base/Const/Units.h" #include "Base/Math/Constants.h" #include "Base/Pixel/RectangularPixel.h" +#include "Base/Utils/Assert.h" #include "Device/Beam/Beam.h" #include "Device/Coord/AxisNames.h" -#include "Device/Detector/RectangularDetector.h" -#include "Device/Detector/SphericalDetector.h" -#include "Device/ProDetector/RegionOfInterest.h" #include <algorithm> #include <cmath> #include <stdexcept> @@ -110,31 +109,24 @@ std::unique_ptr<const IAxis> CoordSystem2D::createConvertedAxis(size_t i_axis, return std::make_unique<FixedBinAxis>(axis_name, axis_size, min, max); } -void CoordSystem2D::addDetectorAxis(const IDetector& detector, size_t i_axis) +void CoordSystem2D::addAxis(const IAxis& axis) { - const auto& axis = detector.axis(i_axis); - const auto* roi = detector.regionOfInterest(); - const auto& axis_name = axisName(i_axis); - if (!roi) { - addAxisData(axis_name, axis.lowerBound(), axis.upperBound(), defaultUnits(), axis.size()); - return; - } - auto roi_axis = roi->clipAxisToRoi(i_axis, axis); - addAxisData(axis_name, roi_axis->lowerBound(), roi_axis->upperBound(), defaultUnits(), - roi_axis->size()); + const size_t iNewAxis = m_axes.size(); + addAxisData(axisName(iNewAxis), axis.lowerBound(), axis.upperBound(), defaultUnits(), + axis.size()); } - // ************************************************************************************************ // class SphericalCoords // ************************************************************************************************ -SphericalCoords::SphericalCoords(const SphericalDetector& detector, const Beam& beam) +SphericalCoords::SphericalCoords(const CloneableVector<IAxis>& axes, const Beam& beam) : CoordSystem2D(beam) { - ASSERT(detector.dimension() == 2); - addDetectorAxis(detector, 0); - addDetectorAxis(detector, 1); + ASSERT(axes.size() == 2); + + addAxis(*axes[0]); + addAxis(*axes[1]); } SphericalCoords::SphericalCoords(const SphericalCoords& other) : CoordSystem2D(other) {} @@ -201,13 +193,15 @@ std::vector<std::map<Axes::Coords, std::string>> SphericalCoords::createNameMaps // class ImageCoords // ************************************************************************************************ -ImageCoords::ImageCoords(const RectangularDetector& detector, const Beam& beam) +ImageCoords::ImageCoords(const CloneableVector<IAxis>& axes, + const RectangularPixel& regionOfInterestPixel, const Beam& beam) : CoordSystem2D(beam) { - ASSERT(detector.dimension() == 2); - addDetectorAxis(detector, 0); - addDetectorAxis(detector, 1); - m_detector_pixel.reset(detector.regionOfInterestPixel()); + ASSERT(axes.size() == 2); + + addAxis(*axes[0]); + addAxis(*axes[1]); + m_detector_pixel.reset(regionOfInterestPixel.clone()); } ImageCoords::ImageCoords(const ImageCoords& other) @@ -278,14 +272,14 @@ std::vector<std::map<Axes::Coords, std::string>> ImageCoords::createNameMaps() c // class OffSpecularCoordinates // ************************************************************************************************ -OffSpecularCoordinates::OffSpecularCoordinates(const IDetector2D& detector, const Beam& beam, - const IAxis& alpha_axis) +OffSpecularCoordinates::OffSpecularCoordinates(const Beam& beam, const IAxis& alpha_axis, + double alpha_f_min, double alpha_f_max, size_t nbins) : CoordSystem2D(beam) { - ASSERT(detector.dimension() == 2); addAxisData(axisName(0), alpha_axis.lowerBound(), alpha_axis.upperBound(), defaultUnits(), alpha_axis.size()); - addDetectorYAxis(detector); + + addAxisData(axisName(1), alpha_f_min, alpha_f_max, defaultUnits(), nbins); } OffSpecularCoordinates::OffSpecularCoordinates(const OffSpecularCoordinates& other) @@ -293,7 +287,28 @@ OffSpecularCoordinates::OffSpecularCoordinates(const OffSpecularCoordinates& oth { } -OffSpecularCoordinates::~OffSpecularCoordinates() = default; +OffSpecularCoordinates* +OffSpecularCoordinates::createForRectangularDetector(const Beam& beam, const IAxis& alphaAxis, + const RectangularPixel& detectorPixel, + const IAxis& yAxis) +{ + const auto k00 = detectorPixel.getPosition(0.0, 0.0); + const auto k01 = detectorPixel.getPosition(0.0, 1.0); + const double alpha_f_min = M_PI_2 - k00.theta(); + const double alpha_f_max = M_PI_2 - k01.theta(); + + return new OffSpecularCoordinates(beam, alphaAxis, alpha_f_min, alpha_f_max, yAxis.size()); +} + +OffSpecularCoordinates* OffSpecularCoordinates::createForSphericalDetector(const Beam& beam, + const IAxis& alphaAxis, + const IAxis& yAxis) +{ + const double alpha_f_min = yAxis.lowerBound(); + const double alpha_f_max = yAxis.upperBound(); + + return new OffSpecularCoordinates(beam, alphaAxis, alpha_f_min, alpha_f_max, yAxis.size()); +} OffSpecularCoordinates* OffSpecularCoordinates::clone() const { @@ -322,34 +337,6 @@ std::vector<std::map<Axes::Coords, std::string>> OffSpecularCoordinates::createN return {AxisNames::offSpecularAxis0, AxisNames::offSpecularAxis1}; } -void OffSpecularCoordinates::addDetectorYAxis(const IDetector2D& detector) -{ - const auto& axis = detector.axis(1); - const auto* roi = detector.regionOfInterest(); - const auto& axis_name = axisName(1); - std::unique_ptr<IAxis> new_axis; - if (roi) - new_axis = roi->clipAxisToRoi(1, axis); - else - new_axis.reset(axis.clone()); - ASSERT(new_axis); - - if (const auto* rect_det = dynamic_cast<const RectangularDetector*>(&detector)) { - std::unique_ptr<RectangularPixel> det_pixel(rect_det->regionOfInterestPixel()); - const auto k00 = det_pixel->getPosition(0.0, 0.0); - const auto k01 = det_pixel->getPosition(0.0, 1.0); - const double alpha_f_min = M_PI_2 - k00.theta(); - const double alpha_f_max = M_PI_2 - k01.theta(); - addAxisData(axis_name, alpha_f_min, alpha_f_max, defaultUnits(), new_axis->size()); - } else if (dynamic_cast<const SphericalDetector*>(&detector)) { - const double alpha_f_min = new_axis->lowerBound(); - const double alpha_f_max = new_axis->upperBound(); - addAxisData(axis_name, alpha_f_min, alpha_f_max, defaultUnits(), new_axis->size()); - } else - ASSERT(0); -} - - // ************************************************************************************************ // class DepthProbeCoordinates // ************************************************************************************************ diff --git a/Device/Instrument/CoordSystem2D.h b/Device/Instrument/CoordSystem2D.h index 56c8ac07cba983b0345cb53282e0dc21e8306154..d233aaad15f2426a3320b42a95ce6efdb560d404 100644 --- a/Device/Instrument/CoordSystem2D.h +++ b/Device/Instrument/CoordSystem2D.h @@ -20,15 +20,12 @@ #ifndef BORNAGAIN_DEVICE_INSTRUMENT_COORDSYSTEM2D_H #define BORNAGAIN_DEVICE_INSTRUMENT_COORDSYSTEM2D_H +#include "Base/Types/CloneableVector.h" #include "Base/Vector/Vectors3D.h" #include "Device/Coord/ICoordSystem.h" class Beam; -class IDetector; -class IDetector2D; -class RectangularDetector; class RectangularPixel; -class SphericalDetector; //! Interface for objects that provide axis translations to different units for IDetector objects //! @ingroup simulation_internal @@ -51,9 +48,12 @@ public: std::unique_ptr<const IAxis> createConvertedAxis(size_t i_axis, Axes::Coords units) const override; + //! Adds a copy of the given axis to the axis system. + //! Order of adding defines position of axis (x-axis, y-axis, ...) + void addAxis(const IAxis& axis); + protected: CoordSystem2D(const CoordSystem2D& other); - void addDetectorAxis(const IDetector& detector, size_t i_axis); void addAxisData(std::string name, double min, double max, Axes::Coords default_units, size_t nbins); @@ -83,7 +83,7 @@ private: class SphericalCoords : public CoordSystem2D { public: SphericalCoords() = delete; - SphericalCoords(const SphericalDetector& detector, const Beam& beam); + SphericalCoords(const CloneableVector<IAxis>& axes, const Beam& beam); ~SphericalCoords() override; SphericalCoords* clone() const override; @@ -107,7 +107,8 @@ private: class ImageCoords : public CoordSystem2D { public: ImageCoords() = delete; - ImageCoords(const RectangularDetector& detector, const Beam& beam); + ImageCoords(const CloneableVector<IAxis>& axes, const RectangularPixel& regionOfInterestPixel, + const Beam& beam); ~ImageCoords() override; ImageCoords* clone() const override; @@ -133,20 +134,24 @@ private: class OffSpecularCoordinates : public CoordSystem2D { public: - OffSpecularCoordinates() = delete; - OffSpecularCoordinates(const IDetector2D& detector, const Beam& beam, const IAxis& alpha_axis); - ~OffSpecularCoordinates() override; + static OffSpecularCoordinates* + createForRectangularDetector(const Beam& beam, const IAxis& alphaAxis, + const RectangularPixel& detectorPixel, const IAxis& yAxis); + + static OffSpecularCoordinates* + createForSphericalDetector(const Beam& beam, const IAxis& alphaAxis, const IAxis& yAxis); OffSpecularCoordinates* clone() const override; Axes::Coords defaultUnits() const override; private: + OffSpecularCoordinates() = delete; + OffSpecularCoordinates(const Beam& beam, const IAxis& alphaAxis, double alpha_f_min, + double alpha_f_max, size_t nbins); OffSpecularCoordinates(const OffSpecularCoordinates& other); //!< used by clone() double calculateValue(size_t i_axis, Axes::Coords units, double value) const override; std::vector<std::map<Axes::Coords, std::string>> createNameMaps() const override; - - void addDetectorYAxis(const IDetector2D& detector); }; diff --git a/Device/Instrument/Instrument.cpp b/Device/Instrument/Instrument.cpp index fa81d528d906019d34d5304555ba217ea7c47019..7895afa3098182cdf506efd4c4fc67ccde44f919 100644 --- a/Device/Instrument/Instrument.cpp +++ b/Device/Instrument/Instrument.cpp @@ -13,6 +13,7 @@ // ************************************************************************************************ #include "Device/Instrument/Instrument.h" +#include "Base/Pixel/RectangularPixel.h" #include "Device/Detector/RectangularDetector.h" #include "Device/Detector/SphericalDetector.h" #include "Device/Histo/Histogram2D.h" @@ -118,10 +119,11 @@ CoordSystem2D* Instrument::createScatteringCoords() const // TODO: use virtual fcts in detector classes instead of dynamic casts here if (const auto* const det = dynamic_cast<const SphericalDetector*>(detector)) - return new SphericalCoords(*det, beam()); - - if (const auto* const det = dynamic_cast<const RectangularDetector*>(detector)) - return new ImageCoords(*det, beam()); + return new SphericalCoords(detector->axesClippedToRegionOfInterest(), beam()); + if (const auto* const det = dynamic_cast<const RectangularDetector*>(detector)) { + std::unique_ptr<RectangularPixel> roiPixel(det->regionOfInterestPixel()); + return new ImageCoords(detector->axesClippedToRegionOfInterest(), *roiPixel, beam()); + } ASSERT(0); } diff --git a/Device/ProDetector/RegionOfInterest.cpp b/Device/ProDetector/RegionOfInterest.cpp deleted file mode 100644 index a6837047bcdcde6e9aec6afd96383043938db31e..0000000000000000000000000000000000000000 --- a/Device/ProDetector/RegionOfInterest.cpp +++ /dev/null @@ -1,141 +0,0 @@ -// ************************************************************************************************ -// -// BornAgain: simulate and fit reflection and scattering -// -//! @file Device/ProDetector/RegionOfInterest.cpp -//! @brief Implements class RegionOfInterest. -//! -//! @homepage http://www.bornagainproject.org -//! @license GNU General Public License v3 or higher (see COPYING) -//! @copyright Forschungszentrum Jülich GmbH 2018 -//! @authors Scientific Computing Group at MLZ (see CITATION, AUTHORS) -// -// ************************************************************************************************ - -#include "Device/ProDetector/RegionOfInterest.h" -#include "Base/Axis/IAxis.h" -#include "Base/Utils/Assert.h" -#include "Device/Data/OutputData.h" -#include "Device/Mask/Rectangle.h" - -RegionOfInterest::RegionOfInterest(const CloneableVector<IAxis>& axes, double xlow, double ylow, - double xup, double yup) - : RegionOfInterest(xlow, ylow, xup, yup) -{ - ASSERT(axes.size() == 2); - initFrom(*axes[0], *axes[1]); -} - -RegionOfInterest::RegionOfInterest(double xlow, double ylow, double xup, double yup) - : m_rectangle(new Rectangle(xlow, ylow, xup, yup)) - , m_ax1(0) - , m_ay1(0) - , m_ax2(0) - , m_ay2(0) - , m_glob_index0(0) -{ -} - -RegionOfInterest* RegionOfInterest::clone() const -{ - return new RegionOfInterest(*this); -} - -RegionOfInterest::~RegionOfInterest() = default; - -RegionOfInterest::RegionOfInterest(const RegionOfInterest& other) - : ICloneable() - , m_rectangle(other.m_rectangle->clone()) - , m_ax1(other.m_ax1) - , m_ay1(other.m_ay1) - , m_ax2(other.m_ax2) - , m_ay2(other.m_ay2) - , m_glob_index0(other.m_glob_index0) - , m_detector_dims(other.m_detector_dims) - , m_roi_dims(other.m_roi_dims) -{ -} - -double RegionOfInterest::getXlow() const -{ - return m_rectangle->getXlow(); -} - -double RegionOfInterest::getYlow() const -{ - return m_rectangle->getYlow(); -} - -double RegionOfInterest::getXup() const -{ - return m_rectangle->getXup(); -} - -double RegionOfInterest::getYup() const -{ - return m_rectangle->getYup(); -} - -size_t RegionOfInterest::detectorIndex(size_t roiIndex) const -{ - return m_glob_index0 + ycoord(roiIndex, m_roi_dims) - + xcoord(roiIndex, m_roi_dims) * m_detector_dims[1]; -} - -size_t RegionOfInterest::roiIndex(size_t globalIndex) const -{ - size_t ny = ycoord(globalIndex, m_detector_dims); - if (ny < m_ay1 || ny > m_ay2) - throw std::runtime_error("RegionOfInterest::roiIndex() -> Error."); - - size_t nx = xcoord(globalIndex, m_detector_dims); - if (nx < m_ax1 || nx > m_ax2) - throw std::runtime_error("RegionOfInterest::roiIndex() -> Error."); - - return ny - m_ay1 + (nx - m_ax1) * m_roi_dims[1]; -} - -size_t RegionOfInterest::roiSize() const -{ - return m_roi_dims[0] * m_roi_dims[1]; -} - -size_t RegionOfInterest::detectorSize() const -{ - return m_detector_dims[0] * m_detector_dims[1]; -} - -bool RegionOfInterest::isInROI(size_t detectorIndex) const -{ - size_t ny = ycoord(detectorIndex, m_detector_dims); - if (ny < m_ay1 || ny > m_ay2) - return false; - size_t nx = xcoord(detectorIndex, m_detector_dims); - if (nx < m_ax1 || nx > m_ax2) - return false; - return true; -} - -std::unique_ptr<IAxis> RegionOfInterest::clipAxisToRoi(size_t axis_index, const IAxis& axis) const -{ - size_t nbin1 = (axis_index == 0 ? m_ax1 : m_ay1); - size_t nbin2 = (axis_index == 0 ? m_ax2 : m_ay2); - return std::unique_ptr<IAxis>(new FixedBinAxis( - axis.getName(), nbin2 - nbin1 + 1, axis.bin(nbin1).m_lower, axis.bin(nbin2).m_upper)); -} - -void RegionOfInterest::initFrom(const IAxis& x_axis, const IAxis& y_axis) -{ - m_detector_dims.push_back(x_axis.size()); - m_detector_dims.push_back(y_axis.size()); - - m_ax1 = x_axis.findClosestIndex(getXlow()); - m_ax2 = x_axis.findClosestIndex(getXup()); - m_ay1 = y_axis.findClosestIndex(getYlow()); - m_ay2 = y_axis.findClosestIndex(getYup()); - - m_roi_dims.push_back(m_ax2 - m_ax1 + 1); - m_roi_dims.push_back(m_ay2 - m_ay1 + 1); - - m_glob_index0 = m_ay1 + m_ax1 * m_detector_dims[1]; -} diff --git a/Device/ProDetector/RegionOfInterest.h b/Device/ProDetector/RegionOfInterest.h deleted file mode 100644 index 38c2978bb0a81a12e4978e505f233f3e7bb3e6ba..0000000000000000000000000000000000000000 --- a/Device/ProDetector/RegionOfInterest.h +++ /dev/null @@ -1,94 +0,0 @@ -// ************************************************************************************************ -// -// BornAgain: simulate and fit reflection and scattering -// -//! @file Device/ProDetector/RegionOfInterest.h -//! @brief Defines class RegionOfInterest. -//! -//! @homepage http://www.bornagainproject.org -//! @license GNU General Public License v3 or higher (see COPYING) -//! @copyright Forschungszentrum Jülich GmbH 2018 -//! @authors Scientific Computing Group at MLZ (see CITATION, AUTHORS) -// -// ************************************************************************************************ - -#ifdef SWIG -#error no need to expose this header to Swig -#endif - -#ifndef USER_API -#ifndef BORNAGAIN_DEVICE_PRODETECTOR_REGIONOFINTEREST_H -#define BORNAGAIN_DEVICE_PRODETECTOR_REGIONOFINTEREST_H - -#include "Base/Types/CloneableVector.h" -#include "Base/Types/ICloneable.h" -#include <memory> -#include <vector> - -class Rectangle; -class IAxis; -template <class T> class OutputData; - -//! Defines rectangular area for the detector which will be simulated/fitted. -//! @ingroup detector - -class RegionOfInterest : public ICloneable { -public: - RegionOfInterest(const CloneableVector<IAxis>& axes, double xlow, double ylow, double xup, - double yup); - - RegionOfInterest& operator=(const RegionOfInterest& other) = delete; - RegionOfInterest* clone() const; - ~RegionOfInterest(); - - double getXlow() const; - double getYlow() const; - double getXup() const; - double getYup() const; - - //! Converts roi index to the detector index. - size_t detectorIndex(size_t roiIndex) const; - - //! Converts global detector index to ROI index. - size_t roiIndex(size_t detectorIndex) const; - - //! Number of detector bins in ROI area - size_t roiSize() const; - - //! Number of detector bins. - size_t detectorSize() const; - - bool isInROI(size_t detectorIndex) const; - - std::unique_ptr<IAxis> clipAxisToRoi(size_t axis_index, const IAxis& axis) const; - -private: - RegionOfInterest(double xlow, double ylow, double xup, double yup); - RegionOfInterest(const RegionOfInterest& other); - - size_t xcoord(size_t index, const std::vector<size_t>& dims) const; - size_t ycoord(size_t index, const std::vector<size_t>& dims) const; - - void initFrom(const IAxis& x_axis, const IAxis& y_axis); - - std::unique_ptr<Rectangle> m_rectangle; - //! Number of bins on detector axes corresponding to roi-rectangle. - size_t m_ax1, m_ay1, m_ax2, m_ay2; - //! Detector global index corresponding to the lower left corner of ROI - size_t m_glob_index0; - std::vector<size_t> m_detector_dims; - std::vector<size_t> m_roi_dims; -}; - -inline size_t RegionOfInterest::xcoord(size_t index, const std::vector<size_t>& dims) const -{ - return index / dims[1] % dims[0]; -} - -inline size_t RegionOfInterest::ycoord(size_t index, const std::vector<size_t>& dims) const -{ - return index % dims[1]; -} - -#endif // BORNAGAIN_DEVICE_PRODETECTOR_REGIONOFINTEREST_H -#endif // USER_API diff --git a/GUI/Models/InstrumentItems.cpp b/GUI/Models/InstrumentItems.cpp index 01acf7118c83035b3a5f9c17d2dfa70664541042..cd2f50eb6c64d23b7095202a3db8e46c7f0c71ad 100644 --- a/GUI/Models/InstrumentItems.cpp +++ b/GUI/Models/InstrumentItems.cpp @@ -14,8 +14,11 @@ #include "GUI/Models/InstrumentItems.h" #include "Base/Const/Units.h" +#include "Base/Pixel/RectangularPixel.h" #include "Core/Simulation/DepthProbeSimulation.h" #include "Device/Coord/CoordSystem1D.h" +#include "Device/Detector/RectangularDetector.h" +#include "Device/Detector/SphericalDetector.h" #include "Device/Instrument/CoordSystem2D.h" #include "Device/Instrument/Instrument.h" #include "GUI/Models/BackgroundItems.h" @@ -168,8 +171,7 @@ bool SpecularInstrumentItem::alignedWith(const RealDataItem* item) const { const QString native_units = item->nativeDataUnits(); if (native_units == "nbins") { - return beamItem()->currentInclinationAxisItem()->modelType() - == BasicAxisItem::M_TYPE + return beamItem()->currentInclinationAxisItem()->modelType() == BasicAxisItem::M_TYPE && shape() == item->shape(); } else { auto axis_item = dynamic_cast<PointwiseAxisItem*>(beamItem()->currentInclinationAxisItem()); @@ -348,10 +350,23 @@ ICoordSystem* OffSpecularInstrumentItem::createCoordSystem() const { const auto instrument = createInstrument(); instrument->initDetector(); - auto axis_item = item<BasicAxisItem>(OffSpecularInstrumentItem::P_ALPHA_AXIS); + const auto axis_item = item<BasicAxisItem>(OffSpecularInstrumentItem::P_ALPHA_AXIS); const auto detector2d = dynamic_cast<const IDetector2D*>(instrument->getDetector()); - return new OffSpecularCoordinates(*detector2d, instrument->beam(), - *axis_item->createAxis(Units::deg)); + const auto axes = detector2d->axesClippedToRegionOfInterest(); + ASSERT(axes.size() == 2); + const IAxis& yAxis = *axes[1]; + const Beam& beam = instrument->beam(); + const auto alphaAxis = axis_item->createAxis(Units::deg); + + if (const auto* rectDetector = dynamic_cast<const RectangularDetector*>(detector2d)) { + std::unique_ptr<RectangularPixel> detectorPixel(rectDetector->regionOfInterestPixel()); + return OffSpecularCoordinates::createForRectangularDetector(beam, *alphaAxis, + *detectorPixel, yAxis); + } else if (dynamic_cast<const SphericalDetector*>(detector2d)) + return OffSpecularCoordinates::createForSphericalDetector(beam, *alphaAxis, yAxis); + + ASSERT(0); + return nullptr; } // ************************************************************************************************ @@ -378,10 +393,8 @@ DepthProbeInstrumentItem::DepthProbeInstrumentItem() : InstrumentItem("DepthProb axis->setUpperBound(100.0); axis->titleItem()->setVisible(false); axis->binsItem()->setToolTip("Number of points in scan across sample bulk"); - axis->lowerBoundItem() - ->setToolTip("Starting value below sample horizont in nm"); - axis->upperBoundItem() - ->setToolTip("Ending value above sample horizont in nm"); + axis->lowerBoundItem()->setToolTip("Starting value below sample horizont in nm"); + axis->upperBoundItem()->setToolTip("Ending value above sample horizont in nm"); } SpecularBeamItem* DepthProbeInstrumentItem::beamItem() const @@ -424,14 +437,11 @@ std::unique_ptr<DepthProbeSimulation> DepthProbeInstrumentItem::createSimulation auto depthAxis = depthAxisItem->createAxis(1.0); simulation->setZSpan(depthAxis->size(), depthAxis->lowerBound(), depthAxis->upperBound()); - TransformToDomain::setBeamDistribution( - ParameterDistribution::BeamWavelength, *beamItem()->wavelengthItem(), - *simulation.get()); + TransformToDomain::setBeamDistribution(ParameterDistribution::BeamWavelength, + *beamItem()->wavelengthItem(), *simulation.get()); - TransformToDomain::setBeamDistribution( - ParameterDistribution::BeamInclinationAngle, - *beamItem()->inclinationAngleItem(), - *simulation.get()); + TransformToDomain::setBeamDistribution(ParameterDistribution::BeamInclinationAngle, + *beamItem()->inclinationAngleItem(), *simulation.get()); return simulation; } diff --git a/GUI/Models/MaskItems.cpp b/GUI/Models/MaskItems.cpp index a0bc3b6e73fd50d8276de915922125664e6698f5..cce94698b92cdb2b44e34a5e2c3eca48d2802fa3 100644 --- a/GUI/Models/MaskItems.cpp +++ b/GUI/Models/MaskItems.cpp @@ -82,6 +82,13 @@ RegionOfInterestItem::RegionOfInterestItem() : RectangleItem("RegionOfInterest") setItemValue(P_MASK_VALUE, false); } +std::unique_ptr<IShape2D> RegionOfInterestItem::createShape(double scale) const +{ + auto shape = RectangleItem::createShape(scale); + static_cast<Rectangle*>(shape.get())->setInverted(true); + return shape; +} + /* ------------------------------------------------------------------------- */ const QString PolygonPointItem::P_POSX = "X position"; diff --git a/GUI/Models/MaskItems.h b/GUI/Models/MaskItems.h index 6657d03f889149abfb5d65abe144eda4b6589088..0db27479e5fc3186e67f6bbeebb0e5e340b3ba4a 100644 --- a/GUI/Models/MaskItems.h +++ b/GUI/Models/MaskItems.h @@ -49,6 +49,7 @@ public: class BA_CORE_API_ RegionOfInterestItem : public RectangleItem { public: RegionOfInterestItem(); + virtual std::unique_ptr<IShape2D> createShape(double scale) const; }; class BA_CORE_API_ PolygonPointItem : public SessionItem { diff --git a/GUI/Models/TransformFromDomain.cpp b/GUI/Models/TransformFromDomain.cpp index 462f15e5f74859ed4f555b6bca0430a7bd2d5a7b..12f30eca153a79450ef6b35c7adf87d4963a12c7 100644 --- a/GUI/Models/TransformFromDomain.cpp +++ b/GUI/Models/TransformFromDomain.cpp @@ -28,7 +28,6 @@ #include "Device/Mask/Line.h" #include "Device/Mask/Polygon.h" #include "Device/Mask/Rectangle.h" -#include "Device/ProDetector/RegionOfInterest.h" #include "Device/Resolution/ConvolutionDetectorResolution.h" #include "Device/Resolution/ResolutionFunction2DGaussian.h" #include "Device/Resolution/ScanResolution.h" @@ -439,10 +438,10 @@ void TransformFromDomain::setDetectorMasks(DetectorItem* detector_item, const ISimulation& simulation) { const IDetector* detector = simulation.instrument().getDetector(); - if ((detector->detectorMask() && detector->detectorMask()->numberOfMasks()) - || detector->regionOfInterest()) { // #baROI refactor: hasRegionOfInterest() - detector_item->createMaskContainer(); + if ((detector->detectorMask() && detector->detectorMask()->hasMasks()) + || detector->hasExplicitRegionOfInterest()) { + detector_item->createMaskContainer(); double scale(1.0); if (detector_item->modelType() == "SphericalDetector") scale = 1. / Units::deg; @@ -525,14 +524,15 @@ void TransformFromDomain::setMaskContainer(MaskContainerItem* container_item, } } - if (detector.regionOfInterest()) { + if (detector.hasExplicitRegionOfInterest()) { + const auto xBounds = detector.regionOfInterestBounds(0); + const auto yBounds = detector.regionOfInterestBounds(1); + RegionOfInterestItem* roiItem = new RegionOfInterestItem(); - roiItem->setItemValue(RectangleItem::P_XLOW, - scale * detector.regionOfInterest()->getXlow()); - roiItem->setItemValue(RectangleItem::P_YLOW, - scale * detector.regionOfInterest()->getYlow()); - roiItem->setItemValue(RectangleItem::P_XUP, scale * detector.regionOfInterest()->getXup()); - roiItem->setItemValue(RectangleItem::P_YUP, scale * detector.regionOfInterest()->getYup()); + roiItem->setItemValue(RectangleItem::P_XLOW, scale * xBounds.first); + roiItem->setItemValue(RectangleItem::P_YLOW, scale * yBounds.first); + roiItem->setItemValue(RectangleItem::P_XUP, scale * xBounds.second); + roiItem->setItemValue(RectangleItem::P_YUP, scale * yBounds.second); container_item->insertItem(-1, roiItem); } } diff --git a/GUI/Views/MaskWidgets/MaskResultsPresenter.cpp b/GUI/Views/MaskWidgets/MaskResultsPresenter.cpp index 8276dd8166440a087f5b86ef92ca36f5f4340a74..9438e39b6615cecd62d869728dca026fffed2662 100644 --- a/GUI/Views/MaskWidgets/MaskResultsPresenter.cpp +++ b/GUI/Views/MaskWidgets/MaskResultsPresenter.cpp @@ -14,7 +14,6 @@ #include "GUI/Views/MaskWidgets/MaskResultsPresenter.h" #include "Device/ProDetector/DetectorMask.h" -#include "Device/ProDetector/RegionOfInterest.h" #include "GUI/Models/IntensityDataItem.h" #include "GUI/Models/MaskItems.h" #include "GUI/Models/SessionModel.h" @@ -87,18 +86,13 @@ void MaskResultsPresenter::backup_data() OutputData<double>* MaskResultsPresenter::createMaskPresentation() const { // Requesting mask information - std::unique_ptr<RegionOfInterest> roi; + std::unique_ptr<IShape2D> roi; DetectorMask detectorMask; for (int i_row = m_maskModel->rowCount(m_maskContainerIndex); i_row > 0; --i_row) { QModelIndex itemIndex = m_maskModel->index(i_row - 1, 0, m_maskContainerIndex); if (MaskItem* maskItem = dynamic_cast<MaskItem*>(m_maskModel->itemForIndex(itemIndex))) { if (maskItem->modelType() == "RegionOfInterest") { - double xlow = maskItem->getItemValue(RectangleItem::P_XLOW).toDouble(); - double ylow = maskItem->getItemValue(RectangleItem::P_YLOW).toDouble(); - double xup = maskItem->getItemValue(RectangleItem::P_XUP).toDouble(); - double yup = maskItem->getItemValue(RectangleItem::P_YUP).toDouble(); - roi.reset(new RegionOfInterest(m_intensityDataItem->getOutputData()->axes(), xlow, - ylow, xup, yup)); + roi = maskItem->createShape(); } else { std::unique_ptr<IShape2D> shape(maskItem->createShape()); bool mask_value = maskItem->getItemValue(MaskItem::P_MASK_VALUE).toBool(); @@ -107,14 +101,18 @@ OutputData<double>* MaskResultsPresenter::createMaskPresentation() const } } - if (!detectorMask.hasMasks() && !roi) - return 0; + // ROI mask has to be the last one, it can not be "unmasked" by other shapes + if (roi) + detectorMask.addMask(*roi, true); + + if (!detectorMask.hasMasks()) + return nullptr; OutputData<double>* result = m_intensityDataItem->getOutputData()->clone(); detectorMask.initMaskData(result->axes()); for (size_t i = 0; i < result->getAllocatedSize(); ++i) - if (detectorMask.isMasked(i) || (roi && !roi->isInROI(i))) + if (detectorMask.isMasked(i)) (*result)[i] = 0.0; return result; diff --git a/Tests/UnitTests/Core/Instrument/OffSpecularConverterTest.cpp b/Tests/UnitTests/Core/Instrument/OffSpecularConverterTest.cpp index 1ffad75272ea0cd47ea6c4e648a361826227680a..36d5faa094bb71a7ff265f9a4b2a3b90359a7958 100644 --- a/Tests/UnitTests/Core/Instrument/OffSpecularConverterTest.cpp +++ b/Tests/UnitTests/Core/Instrument/OffSpecularConverterTest.cpp @@ -8,6 +8,14 @@ class OffSpecularCoordinatesTest : public ::testing::Test { public: OffSpecularCoordinatesTest(); + OffSpecularCoordinates* createCoords() + { + const auto axes = m_detector.axesClippedToRegionOfInterest(); + const IAxis& yAxis = *axes[1]; + + return OffSpecularCoordinates::createForSphericalDetector(m_beam, m_alpha_i_axis, yAxis); + } + protected: SphericalDetector m_detector; FixedBinAxis m_alpha_i_axis; @@ -23,61 +31,61 @@ OffSpecularCoordinatesTest::OffSpecularCoordinatesTest() TEST_F(OffSpecularCoordinatesTest, OffSpecularCoordinates) { - OffSpecularCoordinates converter(m_detector, m_beam, m_alpha_i_axis); - - EXPECT_EQ(converter.dimension(), 2u); - - EXPECT_DOUBLE_EQ(converter.calculateMin(0, Axes::Coords::UNDEFINED), 0.0); - EXPECT_DOUBLE_EQ(converter.calculateMin(0, Axes::Coords::NBINS), 0.0); - EXPECT_DOUBLE_EQ(converter.calculateMin(0, Axes::Coords::RADIANS), 0.0); - EXPECT_DOUBLE_EQ(converter.calculateMin(0, Axes::Coords::DEGREES), 0.0); - EXPECT_THROW(converter.calculateMin(0, Axes::Coords::QSPACE), std::runtime_error); - EXPECT_THROW(converter.calculateMin(0, Axes::Coords::MM), std::runtime_error); - - EXPECT_DOUBLE_EQ(converter.calculateMax(0, Axes::Coords::UNDEFINED), 7.0); - EXPECT_DOUBLE_EQ(converter.calculateMax(0, Axes::Coords::NBINS), 51.0); - EXPECT_DOUBLE_EQ(converter.calculateMax(0, Axes::Coords::RADIANS), Units::deg2rad(7.0)); - EXPECT_DOUBLE_EQ(converter.calculateMax(0, Axes::Coords::DEGREES), 7.0); - EXPECT_THROW(converter.calculateMax(0, Axes::Coords::QSPACE), std::runtime_error); - EXPECT_THROW(converter.calculateMax(0, Axes::Coords::MM), std::runtime_error); - - EXPECT_DOUBLE_EQ(converter.calculateMin(1, Axes::Coords::UNDEFINED), -2.0); - EXPECT_DOUBLE_EQ(converter.calculateMin(1, Axes::Coords::NBINS), 0.0); - EXPECT_DOUBLE_EQ(converter.calculateMin(1, Axes::Coords::RADIANS), Units::deg2rad(-2.0)); - EXPECT_DOUBLE_EQ(converter.calculateMin(1, Axes::Coords::DEGREES), -2.0); - EXPECT_THROW(converter.calculateMin(1, Axes::Coords::QSPACE), std::runtime_error); - EXPECT_THROW(converter.calculateMin(1, Axes::Coords::MM), std::runtime_error); - - EXPECT_DOUBLE_EQ(converter.calculateMax(1, Axes::Coords::UNDEFINED), Units::rad2deg(1.5)); - EXPECT_DOUBLE_EQ(converter.calculateMax(1, Axes::Coords::NBINS), 70.0); - EXPECT_DOUBLE_EQ(converter.calculateMax(1, Axes::Coords::RADIANS), 1.5); - EXPECT_DOUBLE_EQ(converter.calculateMax(1, Axes::Coords::DEGREES), Units::rad2deg(1.5)); - EXPECT_THROW(converter.calculateMax(1, Axes::Coords::QSPACE), std::runtime_error); - EXPECT_THROW(converter.calculateMax(1, Axes::Coords::MM), std::runtime_error); - - EXPECT_THROW(converter.calculateMin(2, Axes::Coords::UNDEFINED), std::runtime_error); - EXPECT_THROW(converter.calculateMax(2, Axes::Coords::UNDEFINED), std::runtime_error); - - auto axis = converter.createConvertedAxis(0, Axes::Coords::UNDEFINED); + std::unique_ptr<OffSpecularCoordinates> coords(createCoords()); + + EXPECT_EQ(coords->dimension(), 2u); + + EXPECT_DOUBLE_EQ(coords->calculateMin(0, Axes::Coords::UNDEFINED), 0.0); + EXPECT_DOUBLE_EQ(coords->calculateMin(0, Axes::Coords::NBINS), 0.0); + EXPECT_DOUBLE_EQ(coords->calculateMin(0, Axes::Coords::RADIANS), 0.0); + EXPECT_DOUBLE_EQ(coords->calculateMin(0, Axes::Coords::DEGREES), 0.0); + EXPECT_THROW(coords->calculateMin(0, Axes::Coords::QSPACE), std::runtime_error); + EXPECT_THROW(coords->calculateMin(0, Axes::Coords::MM), std::runtime_error); + + EXPECT_DOUBLE_EQ(coords->calculateMax(0, Axes::Coords::UNDEFINED), 7.0); + EXPECT_DOUBLE_EQ(coords->calculateMax(0, Axes::Coords::NBINS), 51.0); + EXPECT_DOUBLE_EQ(coords->calculateMax(0, Axes::Coords::RADIANS), Units::deg2rad(7.0)); + EXPECT_DOUBLE_EQ(coords->calculateMax(0, Axes::Coords::DEGREES), 7.0); + EXPECT_THROW(coords->calculateMax(0, Axes::Coords::QSPACE), std::runtime_error); + EXPECT_THROW(coords->calculateMax(0, Axes::Coords::MM), std::runtime_error); + + EXPECT_DOUBLE_EQ(coords->calculateMin(1, Axes::Coords::UNDEFINED), -2.0); + EXPECT_DOUBLE_EQ(coords->calculateMin(1, Axes::Coords::NBINS), 0.0); + EXPECT_DOUBLE_EQ(coords->calculateMin(1, Axes::Coords::RADIANS), Units::deg2rad(-2.0)); + EXPECT_DOUBLE_EQ(coords->calculateMin(1, Axes::Coords::DEGREES), -2.0); + EXPECT_THROW(coords->calculateMin(1, Axes::Coords::QSPACE), std::runtime_error); + EXPECT_THROW(coords->calculateMin(1, Axes::Coords::MM), std::runtime_error); + + EXPECT_DOUBLE_EQ(coords->calculateMax(1, Axes::Coords::UNDEFINED), Units::rad2deg(1.5)); + EXPECT_DOUBLE_EQ(coords->calculateMax(1, Axes::Coords::NBINS), 70.0); + EXPECT_DOUBLE_EQ(coords->calculateMax(1, Axes::Coords::RADIANS), 1.5); + EXPECT_DOUBLE_EQ(coords->calculateMax(1, Axes::Coords::DEGREES), Units::rad2deg(1.5)); + EXPECT_THROW(coords->calculateMax(1, Axes::Coords::QSPACE), std::runtime_error); + EXPECT_THROW(coords->calculateMax(1, Axes::Coords::MM), std::runtime_error); + + EXPECT_THROW(coords->calculateMin(2, Axes::Coords::UNDEFINED), std::runtime_error); + EXPECT_THROW(coords->calculateMax(2, Axes::Coords::UNDEFINED), std::runtime_error); + + auto axis = coords->createConvertedAxis(0, Axes::Coords::UNDEFINED); EXPECT_TRUE(dynamic_cast<const FixedBinAxis*>(axis.get())); - EXPECT_EQ(axis->size(), converter.axisSize(0)); - EXPECT_EQ(axis->lowerBound(), converter.calculateMin(0, Axes::Coords::UNDEFINED)); - EXPECT_EQ(axis->upperBound(), converter.calculateMax(0, Axes::Coords::UNDEFINED)); + EXPECT_EQ(axis->size(), coords->axisSize(0)); + EXPECT_EQ(axis->lowerBound(), coords->calculateMin(0, Axes::Coords::UNDEFINED)); + EXPECT_EQ(axis->upperBound(), coords->calculateMax(0, Axes::Coords::UNDEFINED)); - auto axis2 = converter.createConvertedAxis(1, Axes::Coords::RADIANS); + auto axis2 = coords->createConvertedAxis(1, Axes::Coords::RADIANS); EXPECT_TRUE(dynamic_cast<const FixedBinAxis*>(axis2.get())); - EXPECT_EQ(axis2->size(), converter.axisSize(1)); - EXPECT_EQ(axis2->lowerBound(), converter.calculateMin(1, Axes::Coords::RADIANS)); - EXPECT_EQ(axis2->upperBound(), converter.calculateMax(1, Axes::Coords::RADIANS)); + EXPECT_EQ(axis2->size(), coords->axisSize(1)); + EXPECT_EQ(axis2->lowerBound(), coords->calculateMin(1, Axes::Coords::RADIANS)); + EXPECT_EQ(axis2->upperBound(), coords->calculateMax(1, Axes::Coords::RADIANS)); - EXPECT_THROW(converter.createConvertedAxis(2, Axes::Coords::UNDEFINED), std::runtime_error); - EXPECT_THROW(converter.createConvertedAxis(1, Axes::Coords::QSPACE), std::runtime_error); + EXPECT_THROW(coords->createConvertedAxis(2, Axes::Coords::UNDEFINED), std::runtime_error); + EXPECT_THROW(coords->createConvertedAxis(1, Axes::Coords::QSPACE), std::runtime_error); } TEST_F(OffSpecularCoordinatesTest, OffSpecularCoordinatesClone) { - OffSpecularCoordinates converter(m_detector, m_beam, m_alpha_i_axis); - std::unique_ptr<OffSpecularCoordinates> P_clone(converter.clone()); + std::unique_ptr<OffSpecularCoordinates> coords(createCoords()); + std::unique_ptr<OffSpecularCoordinates> P_clone(coords->clone()); EXPECT_EQ(P_clone->dimension(), 2u); diff --git a/Tests/UnitTests/Core/Instrument/RectangularConverterTest.cpp b/Tests/UnitTests/Core/Instrument/RectangularConverterTest.cpp index f3cfcbf42412f7813bc54003db7fc74f981e650c..799bc663e6ef9dcc031f79dcc90608bfa01fe7de 100644 --- a/Tests/UnitTests/Core/Instrument/RectangularConverterTest.cpp +++ b/Tests/UnitTests/Core/Instrument/RectangularConverterTest.cpp @@ -1,4 +1,5 @@ #include "Base/Const/Units.h" +#include "Base/Pixel/RectangularPixel.h" #include "Device/Beam/Beam.h" #include "Device/Detector/RectangularDetector.h" #include "Device/Instrument/CoordSystem2D.h" @@ -40,7 +41,8 @@ ImageCoordsTest::ImageCoordsTest() TEST_F(ImageCoordsTest, ImageCoords) { - ImageCoords converter(m_detector, m_beam); + std::unique_ptr<RectangularPixel> roiPixel(m_detector.regionOfInterestPixel()); + ImageCoords converter(m_detector.axesClippedToRegionOfInterest(), *roiPixel, m_beam); EXPECT_EQ(converter.dimension(), 2u); @@ -98,7 +100,8 @@ TEST_F(ImageCoordsTest, ImageCoords) TEST_F(ImageCoordsTest, ImageCoordsClone) { - ImageCoords converter(m_detector, m_beam); + std::unique_ptr<RectangularPixel> roiPixel(m_detector.regionOfInterestPixel()); + ImageCoords converter(m_detector.axesClippedToRegionOfInterest(), *roiPixel, m_beam); std::unique_ptr<ImageCoords> P_clone(converter.clone()); EXPECT_EQ(P_clone->dimension(), 2u); @@ -149,7 +152,8 @@ TEST_F(ImageCoordsTest, ImageCoordsWithROI) const double roi_ymax = 100; // ymax in roi will be 102 due to binning m_detector.setRegionOfInterest(roi_xmin, roi_ymin, roi_xmax, roi_ymax); - ImageCoords converter(m_detector, m_beam); + std::unique_ptr<RectangularPixel> roiPixel(m_detector.regionOfInterestPixel()); + ImageCoords converter(m_detector.axesClippedToRegionOfInterest(), *roiPixel, m_beam); EXPECT_EQ(converter.calculateMin(0, Axes::Coords::UNDEFINED), 100); EXPECT_EQ(converter.calculateMax(0, Axes::Coords::UNDEFINED), 152); diff --git a/Tests/UnitTests/Core/Instrument/SpecularDetector1DTest.cpp b/Tests/UnitTests/Core/Instrument/SpecularDetector1DTest.cpp index 76d5289a97e3693ff0be611a5b2a4bd97635a01c..d17050c0c37f0834871ecf0666e78db9f331629d 100644 --- a/Tests/UnitTests/Core/Instrument/SpecularDetector1DTest.cpp +++ b/Tests/UnitTests/Core/Instrument/SpecularDetector1DTest.cpp @@ -16,7 +16,7 @@ TEST_F(SpecularDetectorTest, basicBehaviour) // masks, regions of interest, detector resolution EXPECT_EQ(nullptr, detector.detectorMask()); - EXPECT_EQ(nullptr, detector.regionOfInterest()); + EXPECT_FALSE(detector.hasExplicitRegionOfInterest()); EXPECT_EQ(nullptr, detector.detectorResolution()); // checking size and axis diff --git a/Tests/UnitTests/Core/Instrument/SphericalConverterTest.cpp b/Tests/UnitTests/Core/Instrument/SphericalConverterTest.cpp index d4e390f1d35014d9ec26e7f2489a4882ea8ba76a..62db703712cff9aee68717ea2d6affad38bb590e 100644 --- a/Tests/UnitTests/Core/Instrument/SphericalConverterTest.cpp +++ b/Tests/UnitTests/Core/Instrument/SphericalConverterTest.cpp @@ -28,7 +28,7 @@ SphericalCoordsTest::SphericalCoordsTest() TEST_F(SphericalCoordsTest, SphericalCoords) { - SphericalCoords converter(m_detector, m_beam); + SphericalCoords converter(m_detector.axesClippedToRegionOfInterest(), m_beam); EXPECT_EQ(converter.dimension(), 2u); @@ -80,7 +80,7 @@ TEST_F(SphericalCoordsTest, SphericalCoords) TEST_F(SphericalCoordsTest, SphericalCoordsClone) { - SphericalCoords converter(m_detector, m_beam); + SphericalCoords converter(m_detector.axesClippedToRegionOfInterest(), m_beam); std::unique_ptr<SphericalCoords> P_clone(converter.clone()); EXPECT_EQ(P_clone->dimension(), 2u); diff --git a/Tests/UnitTests/Core/Instrument/SphericalDetectorTest.cpp b/Tests/UnitTests/Core/Instrument/SphericalDetectorTest.cpp index 198c68aec9d5710a8197735792e8a8e7ad7b569e..47d1c982ac280b7ae457fa545a16995510a2ad4c 100644 --- a/Tests/UnitTests/Core/Instrument/SphericalDetectorTest.cpp +++ b/Tests/UnitTests/Core/Instrument/SphericalDetectorTest.cpp @@ -3,7 +3,6 @@ #include "Device/Beam/Beam.h" #include "Device/Mask/Polygon.h" #include "Device/Mask/Rectangle.h" -#include "Device/ProDetector/RegionOfInterest.h" #include "Device/Resolution/ConvolutionDetectorResolution.h" #include "Device/Resolution/ResolutionFunction2DGaussian.h" #include "Tests/GTestWrapper/google_test.h" @@ -29,7 +28,7 @@ TEST_F(SphericalDetectorTest, initialState) EXPECT_EQ(nullptr, detector.detectorResolution()); // region of interest - EXPECT_EQ(nullptr, detector.regionOfInterest()); + EXPECT_FALSE(detector.hasExplicitRegionOfInterest()); // behavior ASSERT_THROW(detector.axis(0), std::runtime_error); @@ -92,23 +91,23 @@ TEST_F(SphericalDetectorTest, regionOfInterest) // creating region of interest double xlow(-2.0), ylow(1.0), xup(4.0), yup(3.0); detector.setRegionOfInterest(xlow, ylow, xup, yup); - EXPECT_FALSE(nullptr == detector.regionOfInterest()); - EXPECT_EQ(detector.regionOfInterest()->getXlow(), xlow); - EXPECT_EQ(detector.regionOfInterest()->getYlow(), ylow); - EXPECT_EQ(detector.regionOfInterest()->getXup(), xup); - EXPECT_EQ(detector.regionOfInterest()->getYup(), yup); + EXPECT_TRUE(detector.hasExplicitRegionOfInterest()); + EXPECT_EQ(detector.regionOfInterestBounds(0).first, xlow); + EXPECT_EQ(detector.regionOfInterestBounds(0).second, xup); + EXPECT_EQ(detector.regionOfInterestBounds(1).first, ylow); + EXPECT_EQ(detector.regionOfInterestBounds(1).second, yup); // replacing region of interest with a new one double xlow2(-2.1), ylow2(1.1), xup2(4.1), yup2(3.1); detector.setRegionOfInterest(xlow2, ylow2, xup2, yup2); - EXPECT_EQ(detector.regionOfInterest()->getXlow(), xlow2); - EXPECT_EQ(detector.regionOfInterest()->getYlow(), ylow2); - EXPECT_EQ(detector.regionOfInterest()->getXup(), xup2); - EXPECT_EQ(detector.regionOfInterest()->getYup(), yup2); + EXPECT_EQ(detector.regionOfInterestBounds(0).first, xlow2); + EXPECT_EQ(detector.regionOfInterestBounds(0).second, xup2); + EXPECT_EQ(detector.regionOfInterestBounds(1).first, ylow2); + EXPECT_EQ(detector.regionOfInterestBounds(1).second, yup2); // removing region of interest detector.resetRegionOfInterest(); - EXPECT_TRUE(nullptr == detector.regionOfInterest()); + EXPECT_FALSE(detector.hasExplicitRegionOfInterest()); } // Create detector map in the presence of region of interest. diff --git a/Tests/UnitTests/Core/Mask/RegionOfInterestTest.cpp b/Tests/UnitTests/Core/Mask/RegionOfInterestTest.cpp index 00e6a6c89dec4146386f852811798eb3cdfca3ed..f8a0768ad24f498d5e60f48cb729f7e00b7fba80 100644 --- a/Tests/UnitTests/Core/Mask/RegionOfInterestTest.cpp +++ b/Tests/UnitTests/Core/Mask/RegionOfInterestTest.cpp @@ -1,4 +1,3 @@ -#include "Device/ProDetector/RegionOfInterest.h" #include "Device/Detector/SphericalDetector.h" #include "Tests/GTestWrapper/google_test.h" #include <memory> @@ -16,29 +15,29 @@ TEST_F(RegionOfInterestTest, constructor) // creating region of interest double xlow(-1.9), ylow(1.1), xup(2.9), yup(2.85); - RegionOfInterest roi(detector.axes(), xlow, ylow, xup, yup); - EXPECT_EQ(roi.getXlow(), xlow); - EXPECT_EQ(roi.getYlow(), ylow); - EXPECT_EQ(roi.getXup(), xup); - EXPECT_EQ(roi.getYup(), yup); + detector.setRegionOfInterest(xlow, ylow, xup, yup); + EXPECT_EQ(detector.regionOfInterestBounds(0).first, xlow); + EXPECT_EQ(detector.regionOfInterestBounds(0).second, xup); + EXPECT_EQ(detector.regionOfInterestBounds(1).first, ylow); + EXPECT_EQ(detector.regionOfInterestBounds(1).second, yup); // checking total size of the detector and roi in it - EXPECT_EQ(roi.detectorSize(), 32u); - EXPECT_EQ(roi.roiSize(), 10u); + EXPECT_EQ(detector.totalSize(), 32u); + EXPECT_EQ(detector.sizeOfRegionOfInterest(), 10u); // converting global detector index to local roi index - EXPECT_EQ(roi.roiIndex(5), 0u); - EXPECT_EQ(roi.roiIndex(6), 1u); - EXPECT_EQ(roi.roiIndex(9), 2u); - EXPECT_EQ(roi.roiIndex(21), 8u); - EXPECT_EQ(roi.roiIndex(22), 9u); - EXPECT_THROW(roi.roiIndex(23), std::runtime_error); - - // converting local ro index to global detector index - EXPECT_EQ(roi.detectorIndex(0), 5u); - EXPECT_EQ(roi.detectorIndex(1), 6u); - EXPECT_EQ(roi.detectorIndex(2), 9u); - EXPECT_EQ(roi.detectorIndex(9), 22u); + EXPECT_EQ(detector.detectorIndexToRegionOfInterestIndex(5), 0u); + EXPECT_EQ(detector.detectorIndexToRegionOfInterestIndex(6), 1u); + EXPECT_EQ(detector.detectorIndexToRegionOfInterestIndex(9), 2u); + EXPECT_EQ(detector.detectorIndexToRegionOfInterestIndex(21), 8u); + EXPECT_EQ(detector.detectorIndexToRegionOfInterestIndex(22), 9u); + EXPECT_THROW(detector.detectorIndexToRegionOfInterestIndex(23), std::runtime_error); + + // converting local roi index to global detector index + EXPECT_EQ(detector.regionOfInterestIndexToDetectorIndex(0), 5u); + EXPECT_EQ(detector.regionOfInterestIndexToDetectorIndex(1), 6u); + EXPECT_EQ(detector.regionOfInterestIndexToDetectorIndex(2), 9u); + EXPECT_EQ(detector.regionOfInterestIndexToDetectorIndex(9), 22u); } //! Testing region of interest which is larger than the detector. @@ -51,21 +50,21 @@ TEST_F(RegionOfInterestTest, largeArea) // creating region of interest double xlow(-3.9), ylow(-1.1), xup(6.9), yup(5.85); - RegionOfInterest roi(detector.axes(), xlow, ylow, xup, yup); + detector.setRegionOfInterest(xlow, ylow, xup, yup); // checking total size of the detector and roi in it - EXPECT_EQ(roi.detectorSize(), 32u); - EXPECT_EQ(roi.roiSize(), 32u); + EXPECT_EQ(detector.totalSize(), 32u); + EXPECT_EQ(detector.sizeOfRegionOfInterest(), 32u); + + // converting local roi index to global detector index + EXPECT_EQ(detector.regionOfInterestIndexToDetectorIndex(5), 5u); + EXPECT_EQ(detector.regionOfInterestIndexToDetectorIndex(6), 6u); + EXPECT_EQ(detector.regionOfInterestIndexToDetectorIndex(9), 9u); + EXPECT_EQ(detector.regionOfInterestIndexToDetectorIndex(27), 27u); // converting global detector index to local roi index - EXPECT_EQ(roi.roiIndex(5), 5u); - EXPECT_EQ(roi.roiIndex(6), 6u); - EXPECT_EQ(roi.roiIndex(9), 9u); - EXPECT_EQ(roi.roiIndex(27), 27u); - - // converting local ro index to global detector index - EXPECT_EQ(roi.detectorIndex(0), 0u); - EXPECT_EQ(roi.detectorIndex(27), 27u); + EXPECT_EQ(detector.detectorIndexToRegionOfInterestIndex(0), 0u); + EXPECT_EQ(detector.detectorIndexToRegionOfInterestIndex(27), 27u); } //! Testing clone @@ -78,30 +77,30 @@ TEST_F(RegionOfInterestTest, clone) // creating region of interest double xlow(-1.9), ylow(1.1), xup(2.9), yup(2.85); - RegionOfInterest roi(detector.axes(), xlow, ylow, xup, yup); + detector.setRegionOfInterest(xlow, ylow, xup, yup); - std::unique_ptr<RegionOfInterest> clone(roi.clone()); + std::unique_ptr<SphericalDetector> clone(detector.clone()); - EXPECT_EQ(clone->getXlow(), xlow); - EXPECT_EQ(clone->getYlow(), ylow); - EXPECT_EQ(clone->getXup(), xup); - EXPECT_EQ(clone->getYup(), yup); + EXPECT_EQ(clone->regionOfInterestBounds(0).first, xlow); + EXPECT_EQ(clone->regionOfInterestBounds(0).second, xup); + EXPECT_EQ(clone->regionOfInterestBounds(1).first, ylow); + EXPECT_EQ(clone->regionOfInterestBounds(1).second, yup); // checking total size of the detector and roi in it - EXPECT_EQ(clone->detectorSize(), 32u); - EXPECT_EQ(clone->roiSize(), 10u); + EXPECT_EQ(clone->totalSize(), 32u); + EXPECT_EQ(clone->sizeOfRegionOfInterest(), 10u); // converting global detector index to local roi index - EXPECT_EQ(clone->roiIndex(5), 0u); - EXPECT_EQ(clone->roiIndex(6), 1u); - EXPECT_EQ(clone->roiIndex(9), 2u); - EXPECT_EQ(clone->roiIndex(21), 8u); - EXPECT_EQ(clone->roiIndex(22), 9u); - EXPECT_THROW(clone->roiIndex(23), std::runtime_error); - - // converting local ro index to global detector index - EXPECT_EQ(clone->detectorIndex(0), 5u); - EXPECT_EQ(clone->detectorIndex(1), 6u); - EXPECT_EQ(clone->detectorIndex(2), 9u); - EXPECT_EQ(clone->detectorIndex(9), 22u); + EXPECT_EQ(clone->detectorIndexToRegionOfInterestIndex(5), 0u); + EXPECT_EQ(clone->detectorIndexToRegionOfInterestIndex(6), 1u); + EXPECT_EQ(clone->detectorIndexToRegionOfInterestIndex(9), 2u); + EXPECT_EQ(clone->detectorIndexToRegionOfInterestIndex(21), 8u); + EXPECT_EQ(clone->detectorIndexToRegionOfInterestIndex(22), 9u); + EXPECT_THROW(clone->detectorIndexToRegionOfInterestIndex(23), std::runtime_error); + + // converting local roi index to global detector index + EXPECT_EQ(clone->regionOfInterestIndexToDetectorIndex(0), 5u); + EXPECT_EQ(clone->regionOfInterestIndexToDetectorIndex(1), 6u); + EXPECT_EQ(clone->regionOfInterestIndexToDetectorIndex(2), 9u); + EXPECT_EQ(clone->regionOfInterestIndexToDetectorIndex(9), 22u); } diff --git a/auto/Wrap/libBornAgainDevice.py b/auto/Wrap/libBornAgainDevice.py index 31cff248f12d06ce35071b55d50cfad6583da4c8..424f019a2f55e014359d858c2aed27cbace1bc0a 100644 --- a/auto/Wrap/libBornAgainDevice.py +++ b/auto/Wrap/libBornAgainDevice.py @@ -4040,10 +4040,22 @@ class IDetector(libBornAgainBase.ICloneable, libBornAgainParam.INode): r"""sizeOfRegionOfInterest(IDetector self) -> size_t""" return _libBornAgainDevice.IDetector_sizeOfRegionOfInterest(self) + def hasExplicitRegionOfInterest(self): + r"""hasExplicitRegionOfInterest(IDetector self) -> bool""" + return _libBornAgainDevice.IDetector_hasExplicitRegionOfInterest(self) + + def axesClippedToRegionOfInterest(self): + r"""axesClippedToRegionOfInterest(IDetector self) -> CloneableVector< IAxis >""" + return _libBornAgainDevice.IDetector_axesClippedToRegionOfInterest(self) + def regionOfInterestIndexToDetectorIndex(self, regionOfInterestIndex): r"""regionOfInterestIndexToDetectorIndex(IDetector self, size_t const regionOfInterestIndex) -> size_t""" return _libBornAgainDevice.IDetector_regionOfInterestIndexToDetectorIndex(self, regionOfInterestIndex) + def detectorIndexToRegionOfInterestIndex(self, detectorIndex): + r"""detectorIndexToRegionOfInterestIndex(IDetector self, size_t const detectorIndex) -> size_t""" + return _libBornAgainDevice.IDetector_detectorIndexToRegionOfInterestIndex(self, detectorIndex) + def applyDetectorResolution(self, p_intensity_map): r""" applyDetectorResolution(IDetector self, IntensityData p_intensity_map) @@ -4104,15 +4116,9 @@ class IDetector(libBornAgainBase.ICloneable, libBornAgainParam.INode): """ return _libBornAgainDevice.IDetector_numberOfSimulationElements(self) - def regionOfInterest(self): - r""" - regionOfInterest(IDetector self) -> RegionOfInterest const * - virtual const RegionOfInterest* IDetector::regionOfInterest() const =0 - - Returns region of interest if exists. - - """ - return _libBornAgainDevice.IDetector_regionOfInterest(self) + def regionOfInterestBounds(self, iAxis): + r"""regionOfInterestBounds(IDetector self, size_t iAxis) -> pvacuum_double_t""" + return _libBornAgainDevice.IDetector_regionOfInterestBounds(self, iAxis) # Register IDetector in _libBornAgainDevice: _libBornAgainDevice.IDetector_swigregister(IDetector) @@ -4191,16 +4197,6 @@ class IDetector2D(IDetector): """ return _libBornAgainDevice.IDetector2D_maskAll(self) - def regionOfInterest(self): - r""" - regionOfInterest(IDetector2D self) -> RegionOfInterest const * - const RegionOfInterest * IDetector2D::regionOfInterest() const override - - Returns region of interest if exists. - - """ - return _libBornAgainDevice.IDetector2D_regionOfInterest(self) - def setRegionOfInterest(self, xlow, ylow, xup, yup): r""" setRegionOfInterest(IDetector2D self, double xlow, double ylow, double xup, double yup) @@ -4211,15 +4207,13 @@ class IDetector2D(IDetector): """ return _libBornAgainDevice.IDetector2D_setRegionOfInterest(self, xlow, ylow, xup, yup) - def resetRegionOfInterest(self): - r""" - resetRegionOfInterest(IDetector2D self) - void IDetector2D::resetRegionOfInterest() override - - Resets region of interest making whole detector plane available for the simulation. + def regionOfInterestIndexToDetectorIndex(self, regionOfInterestIndex): + r"""regionOfInterestIndexToDetectorIndex(IDetector2D self, size_t const regionOfInterestIndex) -> size_t""" + return _libBornAgainDevice.IDetector2D_regionOfInterestIndexToDetectorIndex(self, regionOfInterestIndex) - """ - return _libBornAgainDevice.IDetector2D_resetRegionOfInterest(self) + def detectorIndexToRegionOfInterestIndex(self, detectorIndex): + r"""detectorIndexToRegionOfInterestIndex(IDetector2D self, size_t const detectorIndex) -> size_t""" + return _libBornAgainDevice.IDetector2D_detectorIndexToRegionOfInterestIndex(self, detectorIndex) def active_indices(self): r""" diff --git a/auto/Wrap/libBornAgainDevice_wrap.cpp b/auto/Wrap/libBornAgainDevice_wrap.cpp index 91b85a4e1ee4baada1a66a13c34b399861b69528..4fd5ea54c921ba6affd823f05818c3d07b89a6f9 100644 --- a/auto/Wrap/libBornAgainDevice_wrap.cpp +++ b/auto/Wrap/libBornAgainDevice_wrap.cpp @@ -3145,72 +3145,71 @@ namespace Swig { #define SWIGTYPE_p_Rectangle swig_types[45] #define SWIGTYPE_p_RectangularDetector swig_types[46] #define SWIGTYPE_p_RectangularPixel swig_types[47] -#define SWIGTYPE_p_RegionOfInterest swig_types[48] -#define SWIGTYPE_p_ResolutionFunction2DGaussian swig_types[49] -#define SWIGTYPE_p_ScanResolution swig_types[50] -#define SWIGTYPE_p_SimulationResult swig_types[51] -#define SWIGTYPE_p_SphericalDetector swig_types[52] -#define SWIGTYPE_p_VerticalLine swig_types[53] -#define SWIGTYPE_p_allocator_type swig_types[54] -#define SWIGTYPE_p_bool swig_types[55] -#define SWIGTYPE_p_char swig_types[56] -#define SWIGTYPE_p_const_iterator swig_types[57] -#define SWIGTYPE_p_corr_matrix_t swig_types[58] -#define SWIGTYPE_p_difference_type swig_types[59] -#define SWIGTYPE_p_double swig_types[60] -#define SWIGTYPE_p_first_type swig_types[61] -#define SWIGTYPE_p_int swig_types[62] -#define SWIGTYPE_p_iterator swig_types[63] -#define SWIGTYPE_p_key_type swig_types[64] -#define SWIGTYPE_p_long_long swig_types[65] -#define SWIGTYPE_p_mapped_type swig_types[66] -#define SWIGTYPE_p_p_ICoordSystem swig_types[67] -#define SWIGTYPE_p_p_PyObject swig_types[68] -#define SWIGTYPE_p_parameters_t swig_types[69] -#define SWIGTYPE_p_second_type swig_types[70] -#define SWIGTYPE_p_short swig_types[71] -#define SWIGTYPE_p_signed_char swig_types[72] -#define SWIGTYPE_p_size_type swig_types[73] -#define SWIGTYPE_p_std__allocatorT_BasicVector3DT_double_t_t swig_types[74] -#define SWIGTYPE_p_std__allocatorT_BasicVector3DT_std__complexT_double_t_t_t swig_types[75] -#define SWIGTYPE_p_std__allocatorT_double_t swig_types[76] -#define SWIGTYPE_p_std__allocatorT_int_t swig_types[77] -#define SWIGTYPE_p_std__allocatorT_std__complexT_double_t_t swig_types[78] -#define SWIGTYPE_p_std__allocatorT_std__pairT_double_double_t_t swig_types[79] -#define SWIGTYPE_p_std__allocatorT_std__pairT_std__string_const_double_t_t swig_types[80] -#define SWIGTYPE_p_std__allocatorT_std__string_t swig_types[81] -#define SWIGTYPE_p_std__allocatorT_std__vectorT_double_std__allocatorT_double_t_t_t swig_types[82] -#define SWIGTYPE_p_std__allocatorT_std__vectorT_int_std__allocatorT_int_t_t_t swig_types[83] -#define SWIGTYPE_p_std__allocatorT_unsigned_long_t swig_types[84] -#define SWIGTYPE_p_std__complexT_double_t swig_types[85] -#define SWIGTYPE_p_std__functionT_void_fSimulationAreaIterator_const_RF_t swig_types[86] -#define SWIGTYPE_p_std__invalid_argument swig_types[87] -#define SWIGTYPE_p_std__lessT_std__string_t swig_types[88] -#define SWIGTYPE_p_std__mapT_std__string_double_std__lessT_std__string_t_std__allocatorT_std__pairT_std__string_const_double_t_t_t swig_types[89] -#define SWIGTYPE_p_std__pairT_double_double_t swig_types[90] -#define SWIGTYPE_p_std__vectorT_AxisInfo_std__allocatorT_AxisInfo_t_t swig_types[91] -#define SWIGTYPE_p_std__vectorT_BasicVector3DT_double_t_std__allocatorT_BasicVector3DT_double_t_t_t swig_types[92] -#define SWIGTYPE_p_std__vectorT_BasicVector3DT_std__complexT_double_t_t_std__allocatorT_BasicVector3DT_std__complexT_double_t_t_t_t swig_types[93] -#define SWIGTYPE_p_std__vectorT_INode_const_p_std__allocatorT_INode_const_p_t_t swig_types[94] -#define SWIGTYPE_p_std__vectorT_SimulationElement_std__allocatorT_SimulationElement_t_t swig_types[95] -#define SWIGTYPE_p_std__vectorT_double_std__allocatorT_double_t_t swig_types[96] -#define SWIGTYPE_p_std__vectorT_int_std__allocatorT_int_t_t swig_types[97] -#define SWIGTYPE_p_std__vectorT_size_t_std__allocatorT_size_t_t_t swig_types[98] -#define SWIGTYPE_p_std__vectorT_std__complexT_double_t_std__allocatorT_std__complexT_double_t_t_t swig_types[99] -#define SWIGTYPE_p_std__vectorT_std__pairT_double_double_t_std__allocatorT_std__pairT_double_double_t_t_t swig_types[100] -#define SWIGTYPE_p_std__vectorT_std__string_std__allocatorT_std__string_t_t swig_types[101] -#define SWIGTYPE_p_std__vectorT_std__vectorT_double_std__allocatorT_double_t_t_std__allocatorT_std__vectorT_double_std__allocatorT_double_t_t_t_t swig_types[102] -#define SWIGTYPE_p_std__vectorT_std__vectorT_int_std__allocatorT_int_t_t_std__allocatorT_std__vectorT_int_std__allocatorT_int_t_t_t_t swig_types[103] -#define SWIGTYPE_p_std__vectorT_unsigned_int_std__allocatorT_unsigned_int_t_t swig_types[104] -#define SWIGTYPE_p_std__vectorT_unsigned_long_std__allocatorT_unsigned_long_t_t swig_types[105] -#define SWIGTYPE_p_swig__SwigPyIterator swig_types[106] -#define SWIGTYPE_p_unsigned_char swig_types[107] -#define SWIGTYPE_p_unsigned_int swig_types[108] -#define SWIGTYPE_p_unsigned_long_long swig_types[109] -#define SWIGTYPE_p_unsigned_short swig_types[110] -#define SWIGTYPE_p_value_type swig_types[111] -static swig_type_info *swig_types[113]; -static swig_module_info swig_module = {swig_types, 112, 0, 0, 0, 0}; +#define SWIGTYPE_p_ResolutionFunction2DGaussian swig_types[48] +#define SWIGTYPE_p_ScanResolution swig_types[49] +#define SWIGTYPE_p_SimulationResult swig_types[50] +#define SWIGTYPE_p_SphericalDetector swig_types[51] +#define SWIGTYPE_p_VerticalLine swig_types[52] +#define SWIGTYPE_p_allocator_type swig_types[53] +#define SWIGTYPE_p_bool swig_types[54] +#define SWIGTYPE_p_char swig_types[55] +#define SWIGTYPE_p_const_iterator swig_types[56] +#define SWIGTYPE_p_corr_matrix_t swig_types[57] +#define SWIGTYPE_p_difference_type swig_types[58] +#define SWIGTYPE_p_double swig_types[59] +#define SWIGTYPE_p_first_type swig_types[60] +#define SWIGTYPE_p_int swig_types[61] +#define SWIGTYPE_p_iterator swig_types[62] +#define SWIGTYPE_p_key_type swig_types[63] +#define SWIGTYPE_p_long_long swig_types[64] +#define SWIGTYPE_p_mapped_type swig_types[65] +#define SWIGTYPE_p_p_ICoordSystem swig_types[66] +#define SWIGTYPE_p_p_PyObject swig_types[67] +#define SWIGTYPE_p_parameters_t swig_types[68] +#define SWIGTYPE_p_second_type swig_types[69] +#define SWIGTYPE_p_short swig_types[70] +#define SWIGTYPE_p_signed_char swig_types[71] +#define SWIGTYPE_p_size_type swig_types[72] +#define SWIGTYPE_p_std__allocatorT_BasicVector3DT_double_t_t swig_types[73] +#define SWIGTYPE_p_std__allocatorT_BasicVector3DT_std__complexT_double_t_t_t swig_types[74] +#define SWIGTYPE_p_std__allocatorT_double_t swig_types[75] +#define SWIGTYPE_p_std__allocatorT_int_t swig_types[76] +#define SWIGTYPE_p_std__allocatorT_std__complexT_double_t_t swig_types[77] +#define SWIGTYPE_p_std__allocatorT_std__pairT_double_double_t_t swig_types[78] +#define SWIGTYPE_p_std__allocatorT_std__pairT_std__string_const_double_t_t swig_types[79] +#define SWIGTYPE_p_std__allocatorT_std__string_t swig_types[80] +#define SWIGTYPE_p_std__allocatorT_std__vectorT_double_std__allocatorT_double_t_t_t swig_types[81] +#define SWIGTYPE_p_std__allocatorT_std__vectorT_int_std__allocatorT_int_t_t_t swig_types[82] +#define SWIGTYPE_p_std__allocatorT_unsigned_long_t swig_types[83] +#define SWIGTYPE_p_std__complexT_double_t swig_types[84] +#define SWIGTYPE_p_std__functionT_void_fSimulationAreaIterator_const_RF_t swig_types[85] +#define SWIGTYPE_p_std__invalid_argument swig_types[86] +#define SWIGTYPE_p_std__lessT_std__string_t swig_types[87] +#define SWIGTYPE_p_std__mapT_std__string_double_std__lessT_std__string_t_std__allocatorT_std__pairT_std__string_const_double_t_t_t swig_types[88] +#define SWIGTYPE_p_std__pairT_double_double_t swig_types[89] +#define SWIGTYPE_p_std__vectorT_AxisInfo_std__allocatorT_AxisInfo_t_t swig_types[90] +#define SWIGTYPE_p_std__vectorT_BasicVector3DT_double_t_std__allocatorT_BasicVector3DT_double_t_t_t swig_types[91] +#define SWIGTYPE_p_std__vectorT_BasicVector3DT_std__complexT_double_t_t_std__allocatorT_BasicVector3DT_std__complexT_double_t_t_t_t swig_types[92] +#define SWIGTYPE_p_std__vectorT_INode_const_p_std__allocatorT_INode_const_p_t_t swig_types[93] +#define SWIGTYPE_p_std__vectorT_SimulationElement_std__allocatorT_SimulationElement_t_t swig_types[94] +#define SWIGTYPE_p_std__vectorT_double_std__allocatorT_double_t_t swig_types[95] +#define SWIGTYPE_p_std__vectorT_int_std__allocatorT_int_t_t swig_types[96] +#define SWIGTYPE_p_std__vectorT_size_t_std__allocatorT_size_t_t_t swig_types[97] +#define SWIGTYPE_p_std__vectorT_std__complexT_double_t_std__allocatorT_std__complexT_double_t_t_t swig_types[98] +#define SWIGTYPE_p_std__vectorT_std__pairT_double_double_t_std__allocatorT_std__pairT_double_double_t_t_t swig_types[99] +#define SWIGTYPE_p_std__vectorT_std__string_std__allocatorT_std__string_t_t swig_types[100] +#define SWIGTYPE_p_std__vectorT_std__vectorT_double_std__allocatorT_double_t_t_std__allocatorT_std__vectorT_double_std__allocatorT_double_t_t_t_t swig_types[101] +#define SWIGTYPE_p_std__vectorT_std__vectorT_int_std__allocatorT_int_t_t_std__allocatorT_std__vectorT_int_std__allocatorT_int_t_t_t_t swig_types[102] +#define SWIGTYPE_p_std__vectorT_unsigned_int_std__allocatorT_unsigned_int_t_t swig_types[103] +#define SWIGTYPE_p_std__vectorT_unsigned_long_std__allocatorT_unsigned_long_t_t swig_types[104] +#define SWIGTYPE_p_swig__SwigPyIterator swig_types[105] +#define SWIGTYPE_p_unsigned_char swig_types[106] +#define SWIGTYPE_p_unsigned_int swig_types[107] +#define SWIGTYPE_p_unsigned_long_long swig_types[108] +#define SWIGTYPE_p_unsigned_short swig_types[109] +#define SWIGTYPE_p_value_type swig_types[110] +static swig_type_info *swig_types[112]; +static swig_module_info swig_module = {swig_types, 111, 0, 0, 0, 0}; #define SWIG_TypeQuery(name) SWIG_TypeQueryModule(&swig_module, &swig_module, name) #define SWIG_MangledTypeQuery(name) SWIG_MangledTypeQueryModule(&swig_module, &swig_module, name) @@ -36147,6 +36146,52 @@ fail: } +SWIGINTERN PyObject *_wrap_IDetector_hasExplicitRegionOfInterest(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + IDetector *arg1 = (IDetector *) 0 ; + void *argp1 = 0 ; + int res1 = 0 ; + PyObject *swig_obj[1] ; + bool result; + + if (!args) SWIG_fail; + swig_obj[0] = args; + res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_IDetector, 0 | 0 ); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "IDetector_hasExplicitRegionOfInterest" "', argument " "1"" of type '" "IDetector const *""'"); + } + arg1 = reinterpret_cast< IDetector * >(argp1); + result = (bool)((IDetector const *)arg1)->hasExplicitRegionOfInterest(); + resultobj = SWIG_From_bool(static_cast< bool >(result)); + return resultobj; +fail: + return NULL; +} + + +SWIGINTERN PyObject *_wrap_IDetector_axesClippedToRegionOfInterest(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + IDetector *arg1 = (IDetector *) 0 ; + void *argp1 = 0 ; + int res1 = 0 ; + PyObject *swig_obj[1] ; + SwigValueWrapper< CloneableVector< IAxis > > result; + + if (!args) SWIG_fail; + swig_obj[0] = args; + res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_IDetector, 0 | 0 ); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "IDetector_axesClippedToRegionOfInterest" "', argument " "1"" of type '" "IDetector const *""'"); + } + arg1 = reinterpret_cast< IDetector * >(argp1); + result = ((IDetector const *)arg1)->axesClippedToRegionOfInterest(); + resultobj = SWIG_NewPointerObj((new CloneableVector< IAxis >(static_cast< const CloneableVector< IAxis >& >(result))), SWIGTYPE_p_CloneableVectorT_IAxis_t, SWIG_POINTER_OWN | 0 ); + return resultobj; +fail: + return NULL; +} + + SWIGINTERN PyObject *_wrap_IDetector_regionOfInterestIndexToDetectorIndex(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { PyObject *resultobj = 0; IDetector *arg1 = (IDetector *) 0 ; @@ -36177,6 +36222,36 @@ fail: } +SWIGINTERN PyObject *_wrap_IDetector_detectorIndexToRegionOfInterestIndex(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + IDetector *arg1 = (IDetector *) 0 ; + size_t arg2 ; + void *argp1 = 0 ; + int res1 = 0 ; + size_t val2 ; + int ecode2 = 0 ; + PyObject *swig_obj[2] ; + size_t result; + + if (!SWIG_Python_UnpackTuple(args, "IDetector_detectorIndexToRegionOfInterestIndex", 2, 2, swig_obj)) SWIG_fail; + res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_IDetector, 0 | 0 ); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "IDetector_detectorIndexToRegionOfInterestIndex" "', argument " "1"" of type '" "IDetector const *""'"); + } + arg1 = reinterpret_cast< IDetector * >(argp1); + ecode2 = SWIG_AsVal_size_t(swig_obj[1], &val2); + if (!SWIG_IsOK(ecode2)) { + SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "IDetector_detectorIndexToRegionOfInterestIndex" "', argument " "2"" of type '" "size_t""'"); + } + arg2 = static_cast< size_t >(val2); + result = ((IDetector const *)arg1)->detectorIndexToRegionOfInterestIndex(arg2); + resultobj = SWIG_From_size_t(static_cast< size_t >(result)); + return resultobj; +fail: + return NULL; +} + + SWIGINTERN PyObject *_wrap_IDetector_applyDetectorResolution(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { PyObject *resultobj = 0; IDetector *arg1 = (IDetector *) 0 ; @@ -36331,23 +36406,30 @@ fail: } -SWIGINTERN PyObject *_wrap_IDetector_regionOfInterest(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { +SWIGINTERN PyObject *_wrap_IDetector_regionOfInterestBounds(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { PyObject *resultobj = 0; IDetector *arg1 = (IDetector *) 0 ; + size_t arg2 ; void *argp1 = 0 ; int res1 = 0 ; - PyObject *swig_obj[1] ; - RegionOfInterest *result = 0 ; + size_t val2 ; + int ecode2 = 0 ; + PyObject *swig_obj[2] ; + std::pair< double,double > result; - if (!args) SWIG_fail; - swig_obj[0] = args; + if (!SWIG_Python_UnpackTuple(args, "IDetector_regionOfInterestBounds", 2, 2, swig_obj)) SWIG_fail; res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_IDetector, 0 | 0 ); if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "IDetector_regionOfInterest" "', argument " "1"" of type '" "IDetector const *""'"); + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "IDetector_regionOfInterestBounds" "', argument " "1"" of type '" "IDetector const *""'"); } arg1 = reinterpret_cast< IDetector * >(argp1); - result = (RegionOfInterest *)((IDetector const *)arg1)->regionOfInterest(); - resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_RegionOfInterest, 0 | 0 ); + ecode2 = SWIG_AsVal_size_t(swig_obj[1], &val2); + if (!SWIG_IsOK(ecode2)) { + SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "IDetector_regionOfInterestBounds" "', argument " "2"" of type '" "size_t""'"); + } + arg2 = static_cast< size_t >(val2); + result = ((IDetector const *)arg1)->regionOfInterestBounds(arg2); + resultobj = swig::from(static_cast< std::pair< double,double > >(result)); return resultobj; fail: return NULL; @@ -36640,29 +36722,6 @@ fail: } -SWIGINTERN PyObject *_wrap_IDetector2D_regionOfInterest(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - IDetector2D *arg1 = (IDetector2D *) 0 ; - void *argp1 = 0 ; - int res1 = 0 ; - PyObject *swig_obj[1] ; - RegionOfInterest *result = 0 ; - - if (!args) SWIG_fail; - swig_obj[0] = args; - res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_IDetector2D, 0 | 0 ); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "IDetector2D_regionOfInterest" "', argument " "1"" of type '" "IDetector2D const *""'"); - } - arg1 = reinterpret_cast< IDetector2D * >(argp1); - result = (RegionOfInterest *)((IDetector2D const *)arg1)->regionOfInterest(); - resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_RegionOfInterest, 0 | 0 ); - return resultobj; -fail: - return NULL; -} - - SWIGINTERN PyObject *_wrap_IDetector2D_setRegionOfInterest(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { PyObject *resultobj = 0; IDetector2D *arg1 = (IDetector2D *) 0 ; @@ -36716,22 +36775,60 @@ fail: } -SWIGINTERN PyObject *_wrap_IDetector2D_resetRegionOfInterest(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { +SWIGINTERN PyObject *_wrap_IDetector2D_regionOfInterestIndexToDetectorIndex(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { PyObject *resultobj = 0; IDetector2D *arg1 = (IDetector2D *) 0 ; + size_t arg2 ; void *argp1 = 0 ; int res1 = 0 ; - PyObject *swig_obj[1] ; + size_t val2 ; + int ecode2 = 0 ; + PyObject *swig_obj[2] ; + size_t result; - if (!args) SWIG_fail; - swig_obj[0] = args; + if (!SWIG_Python_UnpackTuple(args, "IDetector2D_regionOfInterestIndexToDetectorIndex", 2, 2, swig_obj)) SWIG_fail; res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_IDetector2D, 0 | 0 ); if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "IDetector2D_resetRegionOfInterest" "', argument " "1"" of type '" "IDetector2D *""'"); + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "IDetector2D_regionOfInterestIndexToDetectorIndex" "', argument " "1"" of type '" "IDetector2D const *""'"); } arg1 = reinterpret_cast< IDetector2D * >(argp1); - (arg1)->resetRegionOfInterest(); - resultobj = SWIG_Py_Void(); + ecode2 = SWIG_AsVal_size_t(swig_obj[1], &val2); + if (!SWIG_IsOK(ecode2)) { + SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "IDetector2D_regionOfInterestIndexToDetectorIndex" "', argument " "2"" of type '" "size_t""'"); + } + arg2 = static_cast< size_t >(val2); + result = ((IDetector2D const *)arg1)->regionOfInterestIndexToDetectorIndex(arg2); + resultobj = SWIG_From_size_t(static_cast< size_t >(result)); + return resultobj; +fail: + return NULL; +} + + +SWIGINTERN PyObject *_wrap_IDetector2D_detectorIndexToRegionOfInterestIndex(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + IDetector2D *arg1 = (IDetector2D *) 0 ; + size_t arg2 ; + void *argp1 = 0 ; + int res1 = 0 ; + size_t val2 ; + int ecode2 = 0 ; + PyObject *swig_obj[2] ; + size_t result; + + if (!SWIG_Python_UnpackTuple(args, "IDetector2D_detectorIndexToRegionOfInterestIndex", 2, 2, swig_obj)) SWIG_fail; + res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_IDetector2D, 0 | 0 ); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "IDetector2D_detectorIndexToRegionOfInterestIndex" "', argument " "1"" of type '" "IDetector2D const *""'"); + } + arg1 = reinterpret_cast< IDetector2D * >(argp1); + ecode2 = SWIG_AsVal_size_t(swig_obj[1], &val2); + if (!SWIG_IsOK(ecode2)) { + SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "IDetector2D_detectorIndexToRegionOfInterestIndex" "', argument " "2"" of type '" "size_t""'"); + } + arg2 = static_cast< size_t >(val2); + result = ((IDetector2D const *)arg1)->detectorIndexToRegionOfInterestIndex(arg2); + resultobj = SWIG_From_size_t(static_cast< size_t >(result)); return resultobj; fail: return NULL; @@ -45589,7 +45686,10 @@ static PyMethodDef SwigMethods[] = { "\n" ""}, { "IDetector_sizeOfRegionOfInterest", _wrap_IDetector_sizeOfRegionOfInterest, METH_O, "IDetector_sizeOfRegionOfInterest(IDetector self) -> size_t"}, + { "IDetector_hasExplicitRegionOfInterest", _wrap_IDetector_hasExplicitRegionOfInterest, METH_O, "IDetector_hasExplicitRegionOfInterest(IDetector self) -> bool"}, + { "IDetector_axesClippedToRegionOfInterest", _wrap_IDetector_axesClippedToRegionOfInterest, METH_O, "IDetector_axesClippedToRegionOfInterest(IDetector self) -> CloneableVector< IAxis >"}, { "IDetector_regionOfInterestIndexToDetectorIndex", _wrap_IDetector_regionOfInterestIndexToDetectorIndex, METH_VARARGS, "IDetector_regionOfInterestIndexToDetectorIndex(IDetector self, size_t const regionOfInterestIndex) -> size_t"}, + { "IDetector_detectorIndexToRegionOfInterestIndex", _wrap_IDetector_detectorIndexToRegionOfInterestIndex, METH_VARARGS, "IDetector_detectorIndexToRegionOfInterestIndex(IDetector self, size_t const detectorIndex) -> size_t"}, { "IDetector_applyDetectorResolution", _wrap_IDetector_applyDetectorResolution, METH_VARARGS, "\n" "IDetector_applyDetectorResolution(IDetector self, IntensityData p_intensity_map)\n" "void IDetector::applyDetectorResolution(OutputData< double > *p_intensity_map) const\n" @@ -45632,13 +45732,7 @@ static PyMethodDef SwigMethods[] = { "Returns number of simulation elements. \n" "\n" ""}, - { "IDetector_regionOfInterest", _wrap_IDetector_regionOfInterest, METH_O, "\n" - "IDetector_regionOfInterest(IDetector self) -> RegionOfInterest const *\n" - "virtual const RegionOfInterest* IDetector::regionOfInterest() const =0\n" - "\n" - "Returns region of interest if exists. \n" - "\n" - ""}, + { "IDetector_regionOfInterestBounds", _wrap_IDetector_regionOfInterestBounds, METH_VARARGS, "IDetector_regionOfInterestBounds(IDetector self, size_t iAxis) -> pvacuum_double_t"}, { "IDetector_swigregister", IDetector_swigregister, METH_O, NULL}, { "IDetector2D_clone", _wrap_IDetector2D_clone, METH_O, "\n" "IDetector2D_clone(IDetector2D self) -> IDetector2D\n" @@ -45687,13 +45781,6 @@ static PyMethodDef SwigMethods[] = { "Put the mask for all detector channels (i.e. exclude whole detector from the analysis) \n" "\n" ""}, - { "IDetector2D_regionOfInterest", _wrap_IDetector2D_regionOfInterest, METH_O, "\n" - "IDetector2D_regionOfInterest(IDetector2D self) -> RegionOfInterest const *\n" - "const RegionOfInterest * IDetector2D::regionOfInterest() const override\n" - "\n" - "Returns region of interest if exists. \n" - "\n" - ""}, { "IDetector2D_setRegionOfInterest", _wrap_IDetector2D_setRegionOfInterest, METH_VARARGS, "\n" "IDetector2D_setRegionOfInterest(IDetector2D self, double xlow, double ylow, double xup, double yup)\n" "void IDetector2D::setRegionOfInterest(double xlow, double ylow, double xup, double yup)\n" @@ -45701,13 +45788,8 @@ static PyMethodDef SwigMethods[] = { "Sets rectangular region of interest with lower left and upper right corners defined. \n" "\n" ""}, - { "IDetector2D_resetRegionOfInterest", _wrap_IDetector2D_resetRegionOfInterest, METH_O, "\n" - "IDetector2D_resetRegionOfInterest(IDetector2D self)\n" - "void IDetector2D::resetRegionOfInterest() override\n" - "\n" - "Resets region of interest making whole detector plane available for the simulation. \n" - "\n" - ""}, + { "IDetector2D_regionOfInterestIndexToDetectorIndex", _wrap_IDetector2D_regionOfInterestIndexToDetectorIndex, METH_VARARGS, "IDetector2D_regionOfInterestIndexToDetectorIndex(IDetector2D self, size_t const regionOfInterestIndex) -> size_t"}, + { "IDetector2D_detectorIndexToRegionOfInterestIndex", _wrap_IDetector2D_detectorIndexToRegionOfInterestIndex, METH_VARARGS, "IDetector2D_detectorIndexToRegionOfInterestIndex(IDetector2D self, size_t const detectorIndex) -> size_t"}, { "IDetector2D_active_indices", _wrap_IDetector2D_active_indices, METH_O, "\n" "IDetector2D_active_indices(IDetector2D self) -> std::vector< size_t,std::allocator< size_t > >\n" "std::vector< size_t > IDetector2D::active_indices() const\n" @@ -46791,7 +46873,6 @@ static swig_type_info _swigt__p_RealLimits = {"_p_RealLimits", "RealLimits *", 0 static swig_type_info _swigt__p_Rectangle = {"_p_Rectangle", "Rectangle *", 0, 0, (void*)0, 0}; static swig_type_info _swigt__p_RectangularDetector = {"_p_RectangularDetector", "RectangularDetector *", 0, 0, (void*)0, 0}; static swig_type_info _swigt__p_RectangularPixel = {"_p_RectangularPixel", "RectangularPixel *", 0, 0, (void*)0, 0}; -static swig_type_info _swigt__p_RegionOfInterest = {"_p_RegionOfInterest", "RegionOfInterest *", 0, 0, (void*)0, 0}; static swig_type_info _swigt__p_ResolutionFunction2DGaussian = {"_p_ResolutionFunction2DGaussian", "ResolutionFunction2DGaussian *", 0, 0, (void*)0, 0}; static swig_type_info _swigt__p_ScanResolution = {"_p_ScanResolution", "ScanResolution *", 0, 0, (void*)0, 0}; static swig_type_info _swigt__p_SimulationResult = {"_p_SimulationResult", "SimulationResult *", 0, 0, (void*)0, 0}; @@ -46905,7 +46986,6 @@ static swig_type_info *swig_type_initial[] = { &_swigt__p_Rectangle, &_swigt__p_RectangularDetector, &_swigt__p_RectangularPixel, - &_swigt__p_RegionOfInterest, &_swigt__p_ResolutionFunction2DGaussian, &_swigt__p_ScanResolution, &_swigt__p_SimulationResult, @@ -47019,7 +47099,6 @@ static swig_cast_info _swigc__p_RealLimits[] = { {&_swigt__p_RealLimits, 0, 0, static swig_cast_info _swigc__p_Rectangle[] = { {&_swigt__p_Rectangle, 0, 0, 0},{0, 0, 0, 0}}; static swig_cast_info _swigc__p_RectangularDetector[] = { {&_swigt__p_RectangularDetector, 0, 0, 0},{0, 0, 0, 0}}; static swig_cast_info _swigc__p_RectangularPixel[] = { {&_swigt__p_RectangularPixel, 0, 0, 0},{0, 0, 0, 0}}; -static swig_cast_info _swigc__p_RegionOfInterest[] = { {&_swigt__p_RegionOfInterest, 0, 0, 0},{0, 0, 0, 0}}; static swig_cast_info _swigc__p_ResolutionFunction2DGaussian[] = { {&_swigt__p_ResolutionFunction2DGaussian, 0, 0, 0},{0, 0, 0, 0}}; static swig_cast_info _swigc__p_ScanResolution[] = { {&_swigt__p_ScanResolution, 0, 0, 0},{0, 0, 0, 0}}; static swig_cast_info _swigc__p_SimulationResult[] = { {&_swigt__p_SimulationResult, 0, 0, 0},{0, 0, 0, 0}}; @@ -47133,7 +47212,6 @@ static swig_cast_info *swig_cast_initial[] = { _swigc__p_Rectangle, _swigc__p_RectangularDetector, _swigc__p_RectangularPixel, - _swigc__p_RegionOfInterest, _swigc__p_ResolutionFunction2DGaussian, _swigc__p_ScanResolution, _swigc__p_SimulationResult,