diff --git a/Core/Instrument/IDetector.cpp b/Core/Instrument/IDetector.cpp index af2d862ad083dd3392ce3c8820279a9938c87cac..7b5d41277f21bb9ce84faadb926c2a98effad309 100644 --- a/Core/Instrument/IDetector.cpp +++ b/Core/Instrument/IDetector.cpp @@ -1,5 +1,8 @@ +#include "IAxis.h" #include "IDetector.h" #include "OutputData.h" +#include "IDetectorResolution.h" +#include "ConvolutionDetectorResolution.h" IDetector::IDetector() { @@ -10,10 +13,14 @@ IDetector::IDetector(const IDetector& other) : m_axes(other.m_axes) , m_detection_properties(other.m_detection_properties) { + if(other.mP_detector_resolution) + setDetectorResolution(*other.mP_detector_resolution); setName(other.getName()); registerChild(&m_detection_properties); } +IDetector::~IDetector() = default; + void IDetector::addAxis(const IAxis& axis) { m_axes.push_back(axis.clone()); @@ -69,6 +76,38 @@ void IDetector::setAnalyzerProperties(const kvector_t direction, double efficien m_detection_properties.setAnalyzerProperties(direction, efficiency, total_transmission); } +void IDetector::setDetectorResolution(const IDetectorResolution& p_detector_resolution) +{ + mP_detector_resolution.reset(p_detector_resolution.clone()); + registerChild(mP_detector_resolution.get()); +} + +// TODO: pass dimension-independent argument to this function +void IDetector::setResolutionFunction(const IResolutionFunction2D& resFunc) +{ + ConvolutionDetectorResolution convFunc(resFunc); + setDetectorResolution(convFunc); +} + +void IDetector::applyDetectorResolution(OutputData<double> *p_intensity_map) const +{ + if (!p_intensity_map) + throw std::runtime_error("IDetector::applyDetectorResolution() -> " + "Error! Null pointer to intensity map"); + if (mP_detector_resolution) + mP_detector_resolution->applyDetectorResolution(p_intensity_map); +} + +void IDetector::removeDetectorResolution() +{ + mP_detector_resolution.reset(); +} + +const IDetectorResolution* IDetector::detectorResolution() const +{ + return mP_detector_resolution.get(); +} + void IDetector::initOutputData(OutputData<double> &data) const { data.clear(); for (size_t i = 0; i < dimension(); ++i) @@ -76,6 +115,33 @@ void IDetector::initOutputData(OutputData<double> &data) const { data.setAllTo(0.); } +OutputData<double>* +IDetector::createDetectorIntensity(const std::vector<SimulationElement>& elements, const Beam& beam, + AxesUnits units_type) const +{ + std::unique_ptr<OutputData<double>> detectorMap(createDetectorMap(beam, units_type)); + if (!detectorMap) + throw Exceptions::RuntimeErrorException("Instrument::createDetectorIntensity:" + "can't create detector map."); + + if (mP_detector_resolution) { + if (units_type != AxesUnits::DEFAULT) { + std::unique_ptr<OutputData<double>> defaultMap( + createDetectorMap(beam, AxesUnits::DEFAULT)); + setDataToDetectorMap(*defaultMap, elements); + applyDetectorResolution(defaultMap.get()); + detectorMap->setRawDataVector(defaultMap->getRawDataVector()); + } else { + setDataToDetectorMap(*detectorMap, elements); + applyDetectorResolution(detectorMap.get()); + } + } else { + setDataToDetectorMap(*detectorMap, elements); + } + + return detectorMap.release(); +} + void IDetector::checkAxesUnits(AxesUnits units) const { if(units == AxesUnits::DEFAULT) @@ -94,7 +160,7 @@ void IDetector::checkAxesUnits(AxesUnits units) const } } -void IDetector::calculateAxisRange(size_t axis_index, const Beam& beam, AxesUnits units, +void IDetector::calculateAxisRange(size_t axis_index, const Beam&, AxesUnits units, double& amin, double& amax) const { if (units == AxesUnits::DEFAULT) { @@ -128,6 +194,5 @@ std::unique_ptr<OutputData<double>> IDetector::createDetectorMap(const Beam& bea std::vector<const INode*> IDetector::getChildren() const { - return std::vector<const INode*>() << &m_detection_properties; + return std::vector<const INode*>() << &m_detection_properties << mP_detector_resolution; } - diff --git a/Core/Instrument/IDetector.h b/Core/Instrument/IDetector.h index 4298ae53dc0efa77172e2784afd24d065dd447ab..c993f97d876b9bbd127700b55ac37948b3c66f97 100644 --- a/Core/Instrument/IDetector.h +++ b/Core/Instrument/IDetector.h @@ -17,12 +17,15 @@ #define IDETECTOR_H_ #include "DetectionProperties.h" -#include "IAxis.h" #include "ICloneable.h" #include "INode.h" #include "SafePointerVector.h" template<class T> class OutputData; +class IAxis; +class IDetectorResolution; +class IResolutionFunction2D; +class SimulationElement; //! Wrapper for detector axes units, required for a better representation of //! detector axes units in python @@ -41,7 +44,7 @@ class BA_CORE_API_ IDetector : public ICloneable, public INode { public: IDetector(); - virtual ~IDetector() = default; + virtual ~IDetector(); void clear() {m_axes.clear();} @@ -62,6 +65,19 @@ public: void setAnalyzerProperties(const kvector_t direction, double efficiency, double total_transmission); + //! Sets the detector resolution + void setDetectorResolution(const IDetectorResolution& p_detector_resolution); + void setResolutionFunction(const IResolutionFunction2D& resFunc); + + //! Applies the detector resolution to the given intensity maps + void applyDetectorResolution(OutputData<double>* p_intensity_map) const; + + //! Removes detector resolution function. + void removeDetectorResolution(); + + //! Returns a pointer to detector resolution object + const IDetectorResolution* detectorResolution() const; + #ifndef SWIG //! Returns empty detector map in given axes units. std::unique_ptr<OutputData<double>> createDetectorMap(const Beam& beam, AxesUnits units) const; @@ -73,13 +89,18 @@ public: //! Inits axes of OutputData to match the detector and sets values to zero. virtual void initOutputData(OutputData<double>& data) const; + //! Returns new intensity map with detector resolution applied and axes in requested units + OutputData<double>* createDetectorIntensity(const std::vector<SimulationElement>& elements, + const Beam& beam, + AxesUnits units_type = AxesUnits::DEFAULT) const; + //! Return default axes units virtual AxesUnits getDefaultAxesUnits() const {return AxesUnits::DEFAULT;} //! Returns vector of valid axes units virtual std::vector<AxesUnits> getValidAxesUnits() const {return {AxesUnits::NBINS};} - virtual std::vector<const INode*> getChildren() const; + virtual std::vector<const INode*> getChildren() const override; protected: IDetector(const IDetector& other); @@ -103,8 +124,13 @@ private: //! Checks if given unit is valid for the detector. Throws exception if it is not the case. void checkAxesUnits(AxesUnits units) const; + virtual void + setDataToDetectorMap(OutputData<double>& detectorMap, + const std::vector<SimulationElement>& elements) const = 0; + SafePointerVector<IAxis> m_axes; DetectionProperties m_detection_properties; + std::unique_ptr<IDetectorResolution> mP_detector_resolution; }; #endif /* IDETECTOR_H_ */ diff --git a/Core/Instrument/IDetector2D.cpp b/Core/Instrument/IDetector2D.cpp index 52f71f28d6a47b5c16e6a680a20c92d213fe24cd..ecc1b8290a785d28c2edf00bab90e652323e0801 100644 --- a/Core/Instrument/IDetector2D.cpp +++ b/Core/Instrument/IDetector2D.cpp @@ -15,7 +15,6 @@ #include "IDetector2D.h" #include "Beam.h" -#include "IDetectorResolution.h" #include "InfinitePlane.h" #include "SimulationElement.h" #include "SimulationArea.h" @@ -23,7 +22,6 @@ #include "Units.h" #include "RegionOfInterest.h" #include "Exceptions.h" -#include "ConvolutionDetectorResolution.h" #include "DetectorFunctions.h" IDetector2D::IDetector2D() = default; @@ -32,8 +30,6 @@ IDetector2D::IDetector2D(const IDetector2D &other) : IDetector(other) , m_detector_mask(other.m_detector_mask) { - if(other.mP_detector_resolution) - setDetectorResolution(*other.mP_detector_resolution); if(other.regionOfInterest()) m_region_of_interest.reset(other.regionOfInterest()->clone()); } @@ -55,41 +51,6 @@ void IDetector2D::setDetectorAxes(const IAxis &axis0, const IAxis &axis1) addAxis(axis1); } -void IDetector2D::applyDetectorResolution(OutputData<double> *p_intensity_map) const -{ - if (!p_intensity_map) - throw Exceptions::NullPointerException("IDetector2D::applyDetectorResolution() -> " - "Error! Null pointer to intensity map"); - if (mP_detector_resolution) - mP_detector_resolution->applyDetectorResolution(p_intensity_map); -} - -OutputData<double> *IDetector2D::createDetectorIntensity( - const std::vector<SimulationElement> &elements, - const Beam &beam, AxesUnits units_type) const -{ - std::unique_ptr<OutputData<double>> detectorMap(createDetectorMap(beam, units_type)); - if(!detectorMap) - throw Exceptions::RuntimeErrorException("Instrument::createDetectorIntensity:" - "can't create detector map."); - - if (mP_detector_resolution) { - if(units_type != AxesUnits::DEFAULT) { - std::unique_ptr<OutputData<double>> defaultMap(createDetectorMap(beam, AxesUnits::DEFAULT)); - setDataToDetectorMap(*defaultMap, elements); - applyDetectorResolution(defaultMap.get()); - detectorMap->setRawDataVector(defaultMap->getRawDataVector()); - } else { - setDataToDetectorMap(*detectorMap, elements); - applyDetectorResolution(detectorMap.get()); - } - } else { - setDataToDetectorMap(*detectorMap, elements); - } - - return detectorMap.release(); -} - const RegionOfInterest *IDetector2D::regionOfInterest() const { return m_region_of_interest.get(); @@ -197,13 +158,6 @@ size_t IDetector2D::numberOfSimulationElements() const return result; } -std::vector<const INode*> IDetector2D::getChildren() const -{ - std::vector<const INode*> result = IDetector::getChildren(); - result << mP_detector_resolution; - return result; -} - std::unique_ptr<IAxis> IDetector2D::constructAxis(size_t axis_index, const Beam &beam, AxesUnits units) const { @@ -263,25 +217,3 @@ void IDetector2D::setDataToDetectorMap(OutputData<double> &detectorMap, } -void IDetector2D::setDetectorResolution(const IDetectorResolution& p_detector_resolution) -{ - mP_detector_resolution.reset(p_detector_resolution.clone()); - registerChild(mP_detector_resolution.get()); -} - -void IDetector2D::setResolutionFunction(const IResolutionFunction2D& resFunc) -{ - ConvolutionDetectorResolution convFunc(resFunc); - setDetectorResolution(convFunc); -} - -void IDetector2D::removeDetectorResolution() -{ - mP_detector_resolution.reset(); -} - -const IDetectorResolution* IDetector2D::detectorResolution() const -{ - return mP_detector_resolution.get(); -} - diff --git a/Core/Instrument/IDetector2D.h b/Core/Instrument/IDetector2D.h index 7742f7985241ab3f7a9f24ff68474542717ca238..8ef40ca5593ab33423539679d0fd77db7182ca11 100644 --- a/Core/Instrument/IDetector2D.h +++ b/Core/Instrument/IDetector2D.h @@ -19,18 +19,12 @@ #include "IDetector.h" #include "Beam.h" #include "DetectorMask.h" -#include "SafePointerVector.h" -#include "DetectionProperties.h" #include <memory> class Beam; -class IAxis; -class IDetectorResolution; -class IResolutionFunction2D; class IPixel; class IShape2D; class RegionOfInterest; -class SimulationElement; //! Abstract 2D detector interface. //! @ingroup simulation @@ -55,18 +49,6 @@ public: //! Sets detector parameters using axes void setDetectorAxes(const IAxis& axis0, const IAxis& axis1); - //! Sets the detector resolution - void setDetectorResolution(const IDetectorResolution& p_detector_resolution); - void setResolutionFunction(const IResolutionFunction2D& resFunc); - - //! Removes detector resolution function. - void removeDetectorResolution(); - - //! Applies the detector resolution to the given intensity maps - void applyDetectorResolution(OutputData<double>* p_intensity_map) const; - - const IDetectorResolution* detectorResolution() const; - //! Removes all masks from the detector void removeMasks(); @@ -97,10 +79,6 @@ public: SimulationElement getSimulationElement(size_t index, const Beam& beam) const; #endif - //! Returns new intensity map with detector resolution applied and axes in requested units - OutputData<double>* createDetectorIntensity(const std::vector<SimulationElement> &elements, - const Beam& beam, AxesUnits units_type=AxesUnits::DEFAULT) const; - //! Returns region of interest if exists. const RegionOfInterest* regionOfInterest() const; @@ -113,8 +91,6 @@ public: //! Returns number of simulation elements. size_t numberOfSimulationElements() const; - virtual std::vector<const INode*> getChildren() const override; - protected: IDetector2D(const IDetector2D& other); @@ -137,12 +113,12 @@ protected: //! returned. This corresponds to an overflow index. virtual size_t getIndexOfSpecular(const Beam& beam) const=0; - std::unique_ptr<IDetectorResolution> mP_detector_resolution; DetectorMask m_detector_mask; private: - void setDataToDetectorMap(OutputData<double> &detectorMap, - const std::vector<SimulationElement> &elements) const; + virtual void + setDataToDetectorMap(OutputData<double>& detectorMap, + const std::vector<SimulationElement>& elements) const override; std::unique_ptr<RegionOfInterest> m_region_of_interest; }; diff --git a/Tests/UnitTests/Core/Detector/SphericalDetectorTest.h b/Tests/UnitTests/Core/Detector/SphericalDetectorTest.h index 675b05fb03cc747644c1d2d76b26b7904526fadd..fe462c68c7e366d0e0eb2c34c94988fa2961d35b 100644 --- a/Tests/UnitTests/Core/Detector/SphericalDetectorTest.h +++ b/Tests/UnitTests/Core/Detector/SphericalDetectorTest.h @@ -49,7 +49,7 @@ TEST_F(SphericalDetectorTest, initialState) ASSERT_THROW(detector.getAxis(0), std::runtime_error); OutputData<double>* p_intensity_map(nullptr); ASSERT_THROW(detector.applyDetectorResolution(p_intensity_map), - Exceptions::NullPointerException); + std::runtime_error); } // Construction of the detector with axes.