diff --git a/Code/Mantid/Framework/MDEvents/CMakeLists.txt b/Code/Mantid/Framework/MDEvents/CMakeLists.txt index 7c0445966882aa9c3a151ee77daaa15f78dbe6f6..66e6f45beb1fe8c96002d9ec07782b82272d1f71 100644 --- a/Code/Mantid/Framework/MDEvents/CMakeLists.txt +++ b/Code/Mantid/Framework/MDEvents/CMakeLists.txt @@ -42,7 +42,7 @@ set ( SRC_FILES src/MDWSTransform.cpp src/OneStepMDEW.cpp src/QueryMDWorkspace.cpp - src/ReflectometryMDTransform.cpp + src/ReflectometryTransform.cpp src/ReflectometryTransformKiKf.cpp src/ReflectometryTransformP.cpp src/ReflectometryTransformQxQz.cpp @@ -110,7 +110,7 @@ set ( INC_FILES inc/MantidMDEvents/MDWSTransform.h inc/MantidMDEvents/OneStepMDEW.h inc/MantidMDEvents/QueryMDWorkspace.h - inc/MantidMDEvents/ReflectometryMDTransform.h + inc/MantidMDEvents/ReflectometryTransform.h inc/MantidMDEvents/ReflectometryTransformKiKf.h inc/MantidMDEvents/ReflectometryTransformP.h inc/MantidMDEvents/ReflectometryTransformQxQz.h @@ -160,7 +160,9 @@ set ( TEST_FILES OneStepMDEWTest.h QueryMDWorkspaceTest.h ReflectometryTransformQxQzTest.h - Integrate3DEventsTest.h + ReflectometryTransformPTest.h + ReflectometryTransformKiKfTest.h + Integrate3DEventsTest.h SaveIsawQvectorTest.h SkippingPolicyTest.h UnitsConversionHelperTest.h diff --git a/Code/Mantid/Framework/MDEvents/inc/MantidMDEvents/ReflectometryMDTransform.h b/Code/Mantid/Framework/MDEvents/inc/MantidMDEvents/ReflectometryMDTransform.h deleted file mode 100644 index a2277412b20dc91452bbb5f735f5d1022536478f..0000000000000000000000000000000000000000 --- a/Code/Mantid/Framework/MDEvents/inc/MantidMDEvents/ReflectometryMDTransform.h +++ /dev/null @@ -1,62 +0,0 @@ -#ifndef MANTID_MDEVENTS_REFLECTOMETRYMDTRANFORM_H_ -#define MANTID_MDEVENTS_REFLECTOMETRYMDTRANFORM_H_ - -#include "MantidKernel/System.h" -#include "MantidAPI/IEventWorkspace.h" -#include "MantidAPI/IMDEventWorkspace.h" -#include "MantidMDEvents/MDEventFactory.h" -#include "MantidAPI/BoxController.h" - -namespace Mantid -{ -namespace MDEvents -{ - - /** ReflectometryMDTransform : Abstract type for reflectometry transforms to MDWorkspaces. This is a Strategy Design Pattern. - - @date 2012-05-29 - - Copyright © 2012 ISIS Rutherford Appleton Laboratory & NScD Oak Ridge National Laboratory - - This file is part of Mantid. - - Mantid is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - Mantid is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. - - File change history is stored at: <https://github.com/mantidproject/mantid> - Code Documentation is available at: <http://doxygen.mantidproject.org> - */ - class DLLExport ReflectometryMDTransform - { - - private: - - Mantid::API::BoxController_sptr m_boxController; - - protected: - - const size_t m_nbinsx; - const size_t m_nbinsz; - - boost::shared_ptr<MDEventWorkspace2Lean> createWorkspace(Mantid::Geometry::IMDDimension_sptr, Mantid::Geometry::IMDDimension_sptr) const; - - public: - //Execute the strategy to produce the a transformed, output MDWorkspace - virtual Mantid::API::IMDEventWorkspace_sptr execute(Mantid::API::MatrixWorkspace_const_sptr inputWs) const = 0; - - virtual ~ReflectometryMDTransform(); - ReflectometryMDTransform(Mantid::API::BoxController_sptr boxController); - }; -} -} -#endif diff --git a/Code/Mantid/Framework/MDEvents/inc/MantidMDEvents/ReflectometryTransform.h b/Code/Mantid/Framework/MDEvents/inc/MantidMDEvents/ReflectometryTransform.h new file mode 100644 index 0000000000000000000000000000000000000000..a48f0ed9e20f2f961161dbc9d4538b732086a226 --- /dev/null +++ b/Code/Mantid/Framework/MDEvents/inc/MantidMDEvents/ReflectometryTransform.h @@ -0,0 +1,83 @@ +#ifndef MANTID_MDEVENTS_REFLECTOMETRYMDTRANFORM_H_ +#define MANTID_MDEVENTS_REFLECTOMETRYMDTRANFORM_H_ + +#include "MantidKernel/System.h" +#include "MantidAPI/IEventWorkspace.h" +#include "MantidAPI/IMDEventWorkspace.h" +#include "MantidMDEvents/MDEventFactory.h" +#include "MantidAPI/BoxController.h" + +namespace Mantid +{ + namespace API + { + class MatrixWorkspace; + } + namespace MDEvents + { + + /** ReflectometryMDTransform : Abstract type for reflectometry transforms to MDWorkspaces. This is a Strategy Design Pattern. + + @date 2012-05-29 + + Copyright © 2012 ISIS Rutherford Appleton Laboratory & NScD Oak Ridge National Laboratory + + This file is part of Mantid. + + Mantid is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + Mantid is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. + + File change history is stored at: <https://github.com/mantidproject/mantid> + Code Documentation is available at: <http://doxygen.mantidproject.org> + */ + class DLLExport ReflectometryTransform + { + + protected: + + const size_t m_nbinsx; + const size_t m_nbinsz; + + boost::shared_ptr<MDEventWorkspace2Lean> createMDWorkspace(Mantid::Geometry::IMDDimension_sptr, + Mantid::Geometry::IMDDimension_sptr, Mantid::API::BoxController_sptr boxController) const; + + public: + + //Execute the strategy to produce a transformed, output MDWorkspace + virtual Mantid::API::IMDEventWorkspace_sptr executeMD( + Mantid::API::MatrixWorkspace_const_sptr inputWs, + Mantid::API::BoxController_sptr boxController) const = 0; + + //Execute the strategy to produce a transformed, output group of Matrix (2D) Workspaces + virtual Mantid::API::MatrixWorkspace_sptr execute( + Mantid::API::MatrixWorkspace_const_sptr inputWs) const = 0; + + virtual ~ReflectometryTransform(); + ReflectometryTransform(int numberOfBinsQx, int numberOfBinsQz); + }; + + /// Create a new x-axis for the output workspace + MantidVec createXAxis(Mantid::API::MatrixWorkspace* const ws, const double gradQx, + const double cxToUnit, const size_t nBins, const std::string& caption, + const std::string& units); + + /// Create a new y(vertical)-axis for the output workspace + void createVerticalAxis(Mantid::API::MatrixWorkspace* const ws, const MantidVec& xAxisVec, + const double gradQz, const double cyToUnit, const size_t nBins, const std::string& caption, + const std::string& units); + + // Helper typedef for scoped pointer of this type. + typedef boost::shared_ptr<ReflectometryTransform> ReflectometryTransform_sptr; + } +} +#endif diff --git a/Code/Mantid/Framework/MDEvents/inc/MantidMDEvents/ReflectometryTransformKiKf.h b/Code/Mantid/Framework/MDEvents/inc/MantidMDEvents/ReflectometryTransformKiKf.h index 688520b8630af4ca0a39771ee562ceadb360a871..ba8ed83a350081606b544ee3a746e616c00d8389 100644 --- a/Code/Mantid/Framework/MDEvents/inc/MantidMDEvents/ReflectometryTransformKiKf.h +++ b/Code/Mantid/Framework/MDEvents/inc/MantidMDEvents/ReflectometryTransformKiKf.h @@ -5,7 +5,7 @@ #include "MantidKernel/ClassMacros.h" #include "MantidAPI/MatrixWorkspace.h" #include "MantidAPI/IMDEventWorkspace.h" -#include "MantidMDEvents/ReflectometryMDTransform.h" +#include "MantidMDEvents/ReflectometryTransform.h" namespace Mantid { @@ -54,7 +54,7 @@ namespace MDEvents File change history is stored at: <https://github.com/mantidproject/mantid> Code Documentation is available at: <http://doxygen.mantidproject.org> */ - class DLLExport ReflectometryTransformKiKf : public ReflectometryMDTransform + class DLLExport ReflectometryTransformKiKf : public ReflectometryTransform { private: const double m_kiMin; @@ -65,11 +65,14 @@ namespace MDEvents mutable CalculateReflectometryK m_KiCalculation; public: - ReflectometryTransformKiKf(double kiMin, double kiMax, double kfMin, double kfMax, double incidentTheta, Mantid::API::BoxController_sptr boxController); + ReflectometryTransformKiKf(double kiMin, double kiMax, double kfMin, double kfMax, double incidentTheta, int numberOfBinsQx=100, int numberOfBinsQz=100); virtual ~ReflectometryTransformKiKf(); /// Execute transformation - virtual Mantid::API::IMDEventWorkspace_sptr execute(Mantid::API::MatrixWorkspace_const_sptr inputWs) const; + virtual Mantid::API::MatrixWorkspace_sptr execute(Mantid::API::MatrixWorkspace_const_sptr inputWs) const; + + /// Execute transformation + virtual Mantid::API::IMDEventWorkspace_sptr executeMD(Mantid::API::MatrixWorkspace_const_sptr inputWs, Mantid::API::BoxController_sptr boxController) const; private: diff --git a/Code/Mantid/Framework/MDEvents/inc/MantidMDEvents/ReflectometryTransformP.h b/Code/Mantid/Framework/MDEvents/inc/MantidMDEvents/ReflectometryTransformP.h index 12b825cf5d97992b801a75135069776373a870a1..8ee75e61955e45c7a812dc3fa24399867e183bc4 100644 --- a/Code/Mantid/Framework/MDEvents/inc/MantidMDEvents/ReflectometryTransformP.h +++ b/Code/Mantid/Framework/MDEvents/inc/MantidMDEvents/ReflectometryTransformP.h @@ -2,7 +2,7 @@ #define MANTID_MDEVENTS_REFLECTOMETRYTRANSFORMP_H_ #include "MantidKernel/System.h" -#include "MantidMDEvents/ReflectometryMDTransform.h" +#include "MantidMDEvents/ReflectometryTransform.h" namespace Mantid { @@ -68,7 +68,7 @@ namespace MDEvents - /** ReflectometryTransformP : TODO: DESCRIPTION + /** ReflectometryTransformP : Calculates workspace(s) of Pi and Pf based on the input workspace and incident theta angle. @date 2012-06-06 @@ -92,7 +92,7 @@ namespace MDEvents File change history is stored at: <https://github.com/mantidproject/mantid> Code Documentation is available at: <http://doxygen.mantidproject.org> */ - class DLLExport ReflectometryTransformP : public ReflectometryMDTransform + class DLLExport ReflectometryTransformP : public ReflectometryTransform { private: const double m_pSumMin; @@ -105,10 +105,11 @@ namespace MDEvents mutable CalculateReflectometryDiffP m_pDiffCalculation; public: - ReflectometryTransformP(double pSumMin, double pSumMax, double pDiffMin, double pDiffMax, double incidentTheta, Mantid::API::BoxController_sptr boxController); + ReflectometryTransformP(double pSumMin, double pSumMax, double pDiffMin, double pDiffMax, double incidentTheta, int numberOfBinsQx=100, int numberOfBinsQz=100); virtual ~ReflectometryTransformP(); - virtual Mantid::API::IMDEventWorkspace_sptr execute(Mantid::API::MatrixWorkspace_const_sptr inputWs) const; - + virtual Mantid::API::IMDEventWorkspace_sptr executeMD(Mantid::API::MatrixWorkspace_const_sptr inputWs, Mantid::API::BoxController_sptr boxController) const; + /// Execute transformation + virtual Mantid::API::MatrixWorkspace_sptr execute(Mantid::API::MatrixWorkspace_const_sptr inputWs) const; }; diff --git a/Code/Mantid/Framework/MDEvents/inc/MantidMDEvents/ReflectometryTransformQxQz.h b/Code/Mantid/Framework/MDEvents/inc/MantidMDEvents/ReflectometryTransformQxQz.h index 1a6d26c13c566ecca55f278b88fa15254fd16da3..7a2d6d9d6b42d271c6e97b32780c8773ce6476f6 100644 --- a/Code/Mantid/Framework/MDEvents/inc/MantidMDEvents/ReflectometryTransformQxQz.h +++ b/Code/Mantid/Framework/MDEvents/inc/MantidMDEvents/ReflectometryTransformQxQz.h @@ -3,141 +3,148 @@ #include "MantidKernel/System.h" #include "MantidKernel/ClassMacros.h" -#include "MantidMDEvents/ReflectometryMDTransform.h" +#include "MantidMDEvents/ReflectometryTransform.h" #include "MantidMDEvents/CalculateReflectometryQBase.h" namespace Mantid { + namespace MDEvents { /** - Converts from inputs of wavelength, incident theta and final theta to Qx for reflectometry experiments - */ - class CalculateReflectometryQx : public CalculateReflectometryQBase + Converts from inputs of wavelength, incident theta and final theta to Qx for reflectometry experiments + */ + class CalculateReflectometryQx: public CalculateReflectometryQBase { private: double m_cos_theta_i; double m_dirQx; public: /** - Constructor - @param thetaIncident: incident theta value in degrees - */ - CalculateReflectometryQx(const double& thetaIncident): m_cos_theta_i(cos(thetaIncident*to_radians_factor)) + Constructor + @param thetaIncident: incident theta value in degrees + */ + CalculateReflectometryQx(const double& thetaIncident) : + m_cos_theta_i(cos(thetaIncident * to_radians_factor)) { } /** - Setter for the final theta value require for the calculation. Internally pre-calculates and caches to cos theta for speed. - @param thetaFinal: final theta value in degrees - */ + Setter for the final theta value require for the calculation. Internally pre-calculates and caches to cos theta for speed. + @param thetaFinal: final theta value in degrees + */ void setThetaFinal(const double& thetaFinal) { - const double c_cos_theta_f = cos(thetaFinal*to_radians_factor); + const double c_cos_theta_f = cos(thetaFinal * to_radians_factor); m_dirQx = (c_cos_theta_f - m_cos_theta_i); } /** - Executes the calculation to determine Qz - @param wavelength : wavelenght in Anstroms - */ + Executes the calculation to determine Qz + @param wavelength : wavelenght in Anstroms + */ double execute(const double& wavelength) const { - double wavenumber = 2*M_PI/wavelength; + double wavenumber = 2 * M_PI / wavelength; return wavenumber * m_dirQx; } }; /** - Converts from inputs of wavelength, incident theta and final theta to Qz for reflectometry experiments - */ - class CalculateReflectometryQz : public CalculateReflectometryQBase + Converts from inputs of wavelength, incident theta and final theta to Qz for reflectometry experiments + */ + class CalculateReflectometryQz: public CalculateReflectometryQBase { private: double m_sin_theta_i; double m_dirQz; public: /** - Constructor - @param thetaIncident: incident theta value in degrees - */ - CalculateReflectometryQz(const double& thetaIncident): m_sin_theta_i(sin(thetaIncident*to_radians_factor)) + Constructor + @param thetaIncident: incident theta value in degrees + */ + CalculateReflectometryQz(const double& thetaIncident) : + m_sin_theta_i(sin(thetaIncident * to_radians_factor)) { } /** - Setter for the final theta value require for the calculation. Internally pre-calculates and caches to sine theta for speed. - @param thetaFinal: final theta value in degrees - */ + Setter for the final theta value require for the calculation. Internally pre-calculates and caches to sine theta for speed. + @param thetaFinal: final theta value in degrees + */ void setThetaFinal(const double& thetaFinal) { - const double c_sin_theta_f = sin(thetaFinal*to_radians_factor); + const double c_sin_theta_f = sin(thetaFinal * to_radians_factor); m_dirQz = (c_sin_theta_f + m_sin_theta_i); } /** - Executes the calculation to determine Qz - @param wavelength : wavelenght in Anstroms - */ + Executes the calculation to determine Qz + @param wavelength : wavelenght in Anstroms + */ double execute(const double& wavelength) const { - double wavenumber = 2*M_PI/wavelength; + double wavenumber = 2 * M_PI / wavelength; return wavenumber * m_dirQz; } }; - /** ReflectometryTranformQxQz : Type of ReflectometyTransform. Used to convert from an input R vs Wavelength workspace to a 2D MDEvent workspace with dimensions of QxQy. - Transformation is specific for reflectometry purposes. - - @date 2012-05-29 - - Copyright © 2012 ISIS Rutherford Appleton Laboratory & NScD Oak Ridge National Laboratory + /** ReflectometryTranformQxQz : Type of ReflectometyTransform. Used to convert from an input R vs Wavelength workspace to a 2D MDEvent workspace with dimensions of QxQy. + Transformation is specific for reflectometry purposes. - This file is part of Mantid. + @date 2012-05-29 - Mantid is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. + Copyright © 2012 ISIS Rutherford Appleton Laboratory & NScD Oak Ridge National Laboratory - Mantid is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. + This file is part of Mantid. - You should have received a copy of the GNU General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. + Mantid is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. - File change history is stored at: <https://github.com/mantidproject/mantid> - Code Documentation is available at: <http://doxygen.mantidproject.org> - */ - class DLLExport ReflectometryTransformQxQz : public ReflectometryMDTransform - { - private: - const double m_qxMin; - const double m_qxMax; - const double m_qzMin; - const double m_qzMax; - /// Object performing raw calculation to determine Qx - mutable CalculateReflectometryQx m_QxCalculation; - /// Object performing raw calculation to determine Qx - mutable CalculateReflectometryQz m_QzCalculation; - public: + Mantid is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. - /// Constructor - ReflectometryTransformQxQz(double qxMin, double qxMax, double qzMin, double qzMax, double incidentTheta, Mantid::API::BoxController_sptr boxController); - /// Destructor - virtual ~ReflectometryTransformQxQz(); - /// Execute transformation - virtual Mantid::API::IMDEventWorkspace_sptr execute(Mantid::API::MatrixWorkspace_const_sptr inputWs) const; + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. - private: + File change history is stored at: <https://github.com/mantidproject/mantid> + Code Documentation is available at: <http://doxygen.mantidproject.org> + */ + class DLLExport ReflectometryTransformQxQz: public ReflectometryTransform + { + private: + const double m_qxMin; + const double m_qxMax; + const double m_qzMin; + const double m_qzMax; + /// Object performing raw calculation to determine Qx + mutable CalculateReflectometryQx m_QxCalculation; + /// Object performing raw calculation to determine Qx + mutable CalculateReflectometryQz m_QzCalculation; + public: - DISABLE_DEFAULT_CONSTRUCT(ReflectometryTransformQxQz) - DISABLE_COPY_AND_ASSIGN(ReflectometryTransformQxQz) + /// Constructor + ReflectometryTransformQxQz(double qxMin, double qxMax, double qzMin, double qzMax, + double incidentTheta, int numberOfBinsQx = 100, int numberOfBinsQz = 100); + /// Destructor + virtual ~ReflectometryTransformQxQz(); + /// Execute transformation + virtual Mantid::API::MatrixWorkspace_sptr execute( + Mantid::API::MatrixWorkspace_const_sptr inputWs) const; + /// Execute MD transformation + virtual Mantid::API::IMDEventWorkspace_sptr executeMD( + Mantid::API::MatrixWorkspace_const_sptr inputWs, + Mantid::API::BoxController_sptr boxController) const; - }; + private: + DISABLE_DEFAULT_CONSTRUCT(ReflectometryTransformQxQz) + DISABLE_COPY_AND_ASSIGN(ReflectometryTransformQxQz) + }; -} // namespace MDEvents + } // namespace MDEvents } // namespace Mantid #endif /* MANTID_MDEVENTS_REFLECTOMETRYTRANFORMQXQZ_H_ */ diff --git a/Code/Mantid/Framework/MDEvents/src/ConvertToReflectometryQ.cpp b/Code/Mantid/Framework/MDEvents/src/ConvertToReflectometryQ.cpp index 034bdce44281745cfd9e8d1dccde94500d97e563..999f6306ae64b0cdd9cfbc6ecd05bf837f69f9e9 100644 --- a/Code/Mantid/Framework/MDEvents/src/ConvertToReflectometryQ.cpp +++ b/Code/Mantid/Framework/MDEvents/src/ConvertToReflectometryQ.cpp @@ -36,6 +36,7 @@ You will usually want to rebin using [[BinMD]] or [[SliceMD]] after transformati #include "MantidKernel/TimeSeriesProperty.h" #include "MantidKernel/ArrayProperty.h" #include "MantidKernel/ListValidator.h" +#include "MantidKernel/EnabledWhenProperty.h" #include "MantidAPI/FrameworkManager.h" #include "MantidAPI/IEventWorkspace.h" #include "MantidMDEvents/MDEventWorkspace.h" @@ -44,6 +45,7 @@ You will usually want to rebin using [[BinMD]] or [[SliceMD]] after transformati #include "MantidMDEvents/ReflectometryTransformKiKf.h" #include "MantidMDEvents/ReflectometryTransformP.h" #include <boost/shared_ptr.hpp> +#include <boost/make_shared.hpp> using namespace Mantid::Kernel; using namespace Mantid::Geometry; @@ -240,9 +242,23 @@ namespace MDEvents setPropertySettings("IncidentTheta", new Kernel::EnabledWhenProperty("OverrideIncidentTheta", IS_EQUAL_TO, "1") ); - declareProperty(new WorkspaceProperty<IMDEventWorkspace>("OutputWorkspace","",Direction::Output), "Output 2D Workspace."); + declareProperty(new Kernel::PropertyWithValue<bool>("OutputAsMDWorkspace", true), "Generate the output as a MDWorkspace, otherwise a Workspace2D is returned."); + + declareProperty(new WorkspaceProperty<IMDWorkspace>("OutputWorkspace","",Direction::Output), "Output 2D Workspace."); + + + declareProperty(new Kernel::PropertyWithValue<int>("NumberBinsQx", 100), "The number of bins along the qx axis. Optional and only applies to 2D workspaces. Defaults to 100."); + declareProperty(new Kernel::PropertyWithValue<int>("NumberBinsQz", 100), "The number of bins along the qx axis. Optional and only applies to 2D workspaces. Defaults to 100."); + setPropertySettings("NumberBinsQx", new EnabledWhenProperty("OutputAsMDWorkspace", IS_NOT_DEFAULT) ); + setPropertySettings("NumberBinsQz", new EnabledWhenProperty("OutputAsMDWorkspace", IS_NOT_DEFAULT) ); + // Create box controller properties. this->initBoxControllerProps("2,2", 50, 10); + + // Only show box controller properties when a md workspace is returned. + setPropertySettings("SplitInto", new EnabledWhenProperty("OutputAsMDWorkspace", IS_DEFAULT) ); + setPropertySettings("SplitThreshold", new EnabledWhenProperty("OutputAsMDWorkspace", IS_DEFAULT) ); + setPropertySettings("MaxRecursionDepth", new EnabledWhenProperty("OutputAsMDWorkspace", IS_DEFAULT) ); } //---------------------------------------------------------------------------------------------- @@ -251,10 +267,13 @@ namespace MDEvents void ConvertToReflectometryQ::exec() { Mantid::API::MatrixWorkspace_sptr inputWs = getProperty("InputWorkspace"); - bool bUseOwnIncidentTheta = getProperty("OverrideIncidentTheta"); - std::vector<double> extents = getProperty("Extents"); + const bool bUseOwnIncidentTheta = getProperty("OverrideIncidentTheta"); + const std::vector<double> extents = getProperty("Extents"); double incidentTheta = getProperty("IncidentTheta"); - std::string outputDimensions = getPropertyValue("OutputDimensions"); + const std::string outputDimensions = getPropertyValue("OutputDimensions"); + const bool outputAsMDWorkspace = getProperty("OutputAsMDWorkspace"); + const int numberOfBinsQx = getProperty("NumberBinsQx"); + const int numberOfBinsQz = getProperty("NumberBinsQz"); //Validation of input parameters checkInputWorkspace(inputWs); @@ -288,32 +307,42 @@ namespace MDEvents const double dim1min = extents[2]; const double dim1max = extents[3]; - typedef boost::shared_ptr<ReflectometryMDTransform> ReflectometryMDTransform_sptr; - BoxController_sptr bc = boost::make_shared<BoxController>(2); this->setBoxController(bc); //Select the transform strategy. - ReflectometryMDTransform_sptr transform; + ReflectometryTransform_sptr transform; + if(outputDimensions == qSpaceTransform()) { - transform = ReflectometryMDTransform_sptr(new ReflectometryTransformQxQz(dim0min, dim0max, dim1min, dim1max, incidentTheta, bc)); + transform = boost::make_shared<ReflectometryTransformQxQz>(dim0min, dim0max, dim1min, dim1max, incidentTheta, numberOfBinsQx, numberOfBinsQz); } else if(outputDimensions == pSpaceTransform()) { - transform = ReflectometryMDTransform_sptr(new ReflectometryTransformP(dim0min, dim0max, dim1min, dim1max, incidentTheta, bc)); + transform = boost::make_shared<ReflectometryTransformP>(dim0min, dim0max, dim1min, dim1max, incidentTheta, numberOfBinsQx, numberOfBinsQz); } else { - transform = ReflectometryMDTransform_sptr(new ReflectometryTransformKiKf(dim0min, dim0max, dim1min, dim1max, incidentTheta, bc)); + transform = boost::make_shared<ReflectometryTransformKiKf>(dim0min, dim0max, dim1min, dim1max, incidentTheta, numberOfBinsQx, numberOfBinsQz); } - auto outputWS = transform->execute(inputWs); + IMDWorkspace_sptr outputWS; - // Copy ExperimentInfo (instrument, run, sample) to the output WS - ExperimentInfo_sptr ei(inputWs->cloneExperimentInfo()); - uint16_t runIndex = outputWS->addExperimentInfo(ei); - UNUSED_ARG(runIndex); + if(outputAsMDWorkspace) + { + auto outputMDWS = transform->executeMD(inputWs, bc); + + // Copy ExperimentInfo (instrument, run, sample) to the output WS + ExperimentInfo_sptr ei(inputWs->cloneExperimentInfo()); + outputMDWS->addExperimentInfo(ei); + outputWS = outputMDWS; + } + else + { + auto outputWS2D = transform->execute(inputWs); + outputWS2D->copyExperimentInfoFrom(inputWs.get()); + outputWS = outputWS2D; + } //Execute the transform and bind to the output. setProperty("OutputWorkspace", outputWS); diff --git a/Code/Mantid/Framework/MDEvents/src/ReflectometryMDTransform.cpp b/Code/Mantid/Framework/MDEvents/src/ReflectometryMDTransform.cpp deleted file mode 100644 index d1b91a70d5ea3c06b1c5758aa5a4ea4eeeae7f79..0000000000000000000000000000000000000000 --- a/Code/Mantid/Framework/MDEvents/src/ReflectometryMDTransform.cpp +++ /dev/null @@ -1,41 +0,0 @@ -#include "MantidMDEvents/ReflectometryMDTransform.h" - -using namespace Mantid::API; - -namespace Mantid -{ - namespace MDEvents - { - - ReflectometryMDTransform::ReflectometryMDTransform(BoxController_sptr boxController) : - m_boxController(boxController), m_nbinsx(10), m_nbinsz(10) - { - } - - ReflectometryMDTransform::~ReflectometryMDTransform() - { - } - - boost::shared_ptr<MDEventWorkspace2Lean> ReflectometryMDTransform::createWorkspace( - Mantid::Geometry::IMDDimension_sptr a, Mantid::Geometry::IMDDimension_sptr b) const - { - auto ws = boost::make_shared<MDEventWorkspace2Lean>(); - - ws->addDimension(a); - ws->addDimension(b); - - BoxController_sptr wsbc = ws->getBoxController();// Get the box controller - wsbc->setSplitInto(m_boxController->getSplitInto(0)); - wsbc->setMaxDepth(m_boxController->getMaxDepth()); - wsbc->setSplitThreshold(m_boxController->getSplitThreshold()); - - // Initialize the workspace. - ws->initialize(); - - // Start with a MDGridBox. - ws->splitBox(); - return ws; - } - - } -} diff --git a/Code/Mantid/Framework/MDEvents/src/ReflectometryTransform.cpp b/Code/Mantid/Framework/MDEvents/src/ReflectometryTransform.cpp new file mode 100644 index 0000000000000000000000000000000000000000..a575d1f61be6c7b8a7841ddbbd7f95f5c1f1135f --- /dev/null +++ b/Code/Mantid/Framework/MDEvents/src/ReflectometryTransform.cpp @@ -0,0 +1,108 @@ +#include "MantidMDEvents/ReflectometryTransform.h" +#include "MantidAPI/MatrixWorkspace.h" +#include "MantidAPI/NumericAxis.h" +#include "MantidKernel/UnitFactory.h" +#include <boost/shared_ptr.hpp> + +using namespace Mantid::Kernel; +using namespace Mantid::API; + +namespace Mantid +{ + namespace MDEvents + { + + ReflectometryTransform::ReflectometryTransform(int numberOfBinsQx, int numberOfBinsQz) : m_nbinsx(numberOfBinsQx), m_nbinsz(numberOfBinsQz) + { + } + + ReflectometryTransform::~ReflectometryTransform() + { + } + + boost::shared_ptr<MDEventWorkspace2Lean> ReflectometryTransform::createMDWorkspace( + Mantid::Geometry::IMDDimension_sptr a, Mantid::Geometry::IMDDimension_sptr b, BoxController_sptr boxController) const + { + auto ws = boost::make_shared<MDEventWorkspace2Lean>(); + + ws->addDimension(a); + ws->addDimension(b); + + BoxController_sptr wsbc = ws->getBoxController();// Get the box controller + wsbc->setSplitInto(boxController->getSplitInto(0)); + wsbc->setMaxDepth(boxController->getMaxDepth()); + wsbc->setSplitThreshold(boxController->getSplitThreshold()); + + // Initialize the workspace. + ws->initialize(); + + // Start with a MDGridBox. + ws->splitBox(); + return ws; + } + + /** + * Create a new X-Axis for the output workspace + * @param ws : Workspace to attach the axis to + * @param gradX : Gradient used in the linear transform from index to X-scale + * @param cxToUnit : C-offset used in the linear transform + * @param nBins : Number of bins along this axis + * @param caption : Caption for the axis + * @param units : Units label for the axis + * @return Vector containing increments along the axis. + */ + MantidVec createXAxis(MatrixWorkspace* const ws, const double gradX, + const double cxToUnit, const size_t nBins, const std::string& caption, const std::string& units) + { + // Create an X - Axis. + Axis* const xAxis = new NumericAxis(nBins); + ws->replaceAxis(0, xAxis); + auto unitXBasePtr = UnitFactory::Instance().create("Label"); + boost::shared_ptr<Mantid::Kernel::Units::Label> xUnit = boost::dynamic_pointer_cast< + Mantid::Kernel::Units::Label>(unitXBasePtr); + xUnit->setLabel(caption, units); + xAxis->unit() = xUnit; + xAxis->title() = caption; + MantidVec xAxisVec(nBins); + for (size_t i = 0; i < nBins; ++i) + { + double qxIncrement = ((1 / gradX) * ((double)i + 1) + cxToUnit); + xAxis->setValue(i, qxIncrement); + xAxisVec[i] = qxIncrement; + } + return xAxisVec; + } + + + /** + * Create a new Y, or Vertical Axis for the output workspace + * @param ws : Workspace to attache the vertical axis to + * @param xAxisVec : Vector of x axis increments + * @param gradY : Gradient used in linear transform from index to Y-scale + * @param cyToUnit : C-offset used in the linear transform + * @param nBins : Number of bins along the axis + * @param caption : Caption for the axis + * @param units : Units label for the axis + */ + void createVerticalAxis(MatrixWorkspace* const ws, const MantidVec& xAxisVec, + const double gradY, const double cyToUnit, const size_t nBins, const std::string& caption, const std::string& units) + { + // Create a Y (vertical) Axis + Axis* const verticalAxis = new NumericAxis(nBins); + ws->replaceAxis(1, verticalAxis); + auto unitZBasePtr = UnitFactory::Instance().create("Label"); + boost::shared_ptr<Mantid::Kernel::Units::Label> verticalUnit = boost::dynamic_pointer_cast< + Mantid::Kernel::Units::Label>(unitZBasePtr); + verticalAxis->unit() = verticalUnit; + verticalUnit->setLabel(caption, units); + verticalAxis->title() = caption; + for (size_t i = 0; i < nBins; ++i) + { + ws->setX(i, xAxisVec); + double qzIncrement = ((1 / gradY) * ((double)i + 1) + cyToUnit); + verticalAxis->setValue(i, qzIncrement); + } + } + + } +} diff --git a/Code/Mantid/Framework/MDEvents/src/ReflectometryTransformKiKf.cpp b/Code/Mantid/Framework/MDEvents/src/ReflectometryTransformKiKf.cpp index a2279a566c81272b12abf111b8b974f106595675..4c873f644627fc5b1ab421eee963ff2367281914 100644 --- a/Code/Mantid/Framework/MDEvents/src/ReflectometryTransformKiKf.cpp +++ b/Code/Mantid/Framework/MDEvents/src/ReflectometryTransformKiKf.cpp @@ -1,6 +1,7 @@ #include "MantidMDEvents/ReflectometryTransformKiKf.h" #include "MantidMDEvents/MDEventWorkspace.h" #include "MantidGeometry/MDGeometry/MDHistoDimension.h" +#include "MantidDataObjects/Workspace2D.h" #include <stdexcept> using namespace Mantid::Kernel; @@ -19,10 +20,12 @@ namespace MDEvents @param kfMin: min kf value (extent) @param kfMax; max kf value (extent) @param incidentTheta: Predetermined incident theta value - @param boxController: box controller to apply on output workspace. + @param numberOfBinsQx: Number of bins in the qx axis + @param numberOfBinsQz: Number of bins in the qz axis */ - ReflectometryTransformKiKf::ReflectometryTransformKiKf(double kiMin, double kiMax, double kfMin, double kfMax, double incidentTheta, BoxController_sptr boxController) - : ReflectometryMDTransform(boxController), m_kiMin(kiMin), m_kiMax(kiMax), m_kfMin(kfMin), m_kfMax(kfMax), m_KiCalculation(incidentTheta) + ReflectometryTransformKiKf::ReflectometryTransformKiKf(double kiMin, double kiMax, double kfMin, double kfMax, double incidentTheta + , int numberOfBinsQx, int numberOfBinsQz) + : ReflectometryTransform(numberOfBinsQx, numberOfBinsQz), m_kiMin(kiMin), m_kiMax(kiMax), m_kfMin(kfMin), m_kfMax(kfMax), m_KiCalculation(incidentTheta) { if(kiMin >= kiMax) { @@ -49,13 +52,14 @@ namespace MDEvents Execute the transformtion. Generates an output IMDEventWorkspace. @return the constructed IMDEventWorkspace following the transformation. @param ws: Input MatrixWorkspace const shared pointer + @param boxController: box controller to apply on output workspace. */ - Mantid::API::IMDEventWorkspace_sptr ReflectometryTransformKiKf::execute(Mantid::API::MatrixWorkspace_const_sptr inputWs) const + Mantid::API::IMDEventWorkspace_sptr ReflectometryTransformKiKf::executeMD(Mantid::API::MatrixWorkspace_const_sptr inputWs, BoxController_sptr boxController) const { MDHistoDimension_sptr kiDim = MDHistoDimension_sptr(new MDHistoDimension("Ki","ki","(Ang^-1)", static_cast<Mantid::coord_t>(m_kiMin), static_cast<Mantid::coord_t>(m_kiMax), m_nbinsx)); MDHistoDimension_sptr kfDim = MDHistoDimension_sptr(new MDHistoDimension("Kf","kf","(Ang^-1)", static_cast<Mantid::coord_t>(m_kfMin), static_cast<Mantid::coord_t>(m_kfMax), m_nbinsz)); - auto ws = createWorkspace(kiDim, kfDim); + auto ws = createMDWorkspace(kiDim, kfDim, boxController); auto spectraAxis = inputWs->getAxis(1); for(size_t index = 0; index < inputWs->getNumberHistograms(); ++index) @@ -82,6 +86,60 @@ namespace MDEvents return ws; } + /** + * + * @param inputWs : Input Matrix workspace + * @return workspace group containing output matrix workspaces of ki and kf + */ + Mantid::API::MatrixWorkspace_sptr ReflectometryTransformKiKf::execute( + Mantid::API::MatrixWorkspace_const_sptr inputWs) const + { + auto ws = boost::make_shared<Mantid::DataObjects::Workspace2D>(); + + ws->initialize(m_nbinsz, m_nbinsx, m_nbinsx); // Create the output workspace as a distribution + + // Mapping so that ki and kf values calculated can be added to the matrix workspace at the correct index. + const double gradKi = double(m_nbinsx) / (m_kiMax - m_kiMin); // The x - axis + const double gradKf = double(m_nbinsz) / (m_kfMax - m_kfMin); // Actually the y-axis + const double cxToIndex = -gradKi * m_kiMin; + const double czToIndex = -gradKf * m_kfMin; + const double cxToKi = m_kiMin - (1 / gradKi); + const double czToKf = m_kfMin - (1 / gradKf); + + // Create an X - Axis. + MantidVec xAxisVec = createXAxis(ws.get(), gradKi, cxToKi, m_nbinsx, "ki", "1/Angstroms"); + // Create a Y (vertical) Axis + createVerticalAxis(ws.get(), xAxisVec, gradKf, czToKf, m_nbinsz, "kf", "1/Angstroms"); + + // Loop over all entries in the input workspace and calculate ki and kf for each. + auto spectraAxis = inputWs->getAxis(1); + for (size_t index = 0; index < inputWs->getNumberHistograms(); ++index) + { + auto counts = inputWs->readY(index); + auto wavelengths = inputWs->readX(index); + auto errors = inputWs->readE(index); + const size_t nInputBins = wavelengths.size() - 1; + const double theta_final = spectraAxis->getValue(index); + CalculateReflectometryK kfCalculation(theta_final); + //Loop over all bins in spectra + for (size_t binIndex = 0; binIndex < nInputBins; ++binIndex) + { + const double wavelength = 0.5 * (wavelengths[binIndex] + wavelengths[binIndex + 1]); + double _ki = m_KiCalculation.execute(wavelength); + double _kf = kfCalculation.execute(wavelength); + + if (_ki >= m_kiMin && _ki <= m_kiMax && _kf >= m_kfMin && _kf <= m_kfMax) // Check that the calculated ki and kf are in range + { + const int outIndexX = (int)((gradKi * _ki) + cxToIndex); + const int outIndexZ = (int)((gradKf * _kf) + czToIndex); + + ws->dataY(outIndexZ)[outIndexX] += counts[binIndex]; + ws->dataE(outIndexZ)[outIndexX] += errors[binIndex]; + } + } + } + return ws; + } -} // namespace Mantid + } // namespace Mantid } // namespace MDEvents diff --git a/Code/Mantid/Framework/MDEvents/src/ReflectometryTransformP.cpp b/Code/Mantid/Framework/MDEvents/src/ReflectometryTransformP.cpp index e0e241c258aa8e4a00124472dd1d8dc371d5fe25..505dea5cd83be49812567c44123ee5f3e09d664a 100644 --- a/Code/Mantid/Framework/MDEvents/src/ReflectometryTransformP.cpp +++ b/Code/Mantid/Framework/MDEvents/src/ReflectometryTransformP.cpp @@ -2,6 +2,7 @@ #include "MantidKernel/System.h" #include "MantidMDEvents/MDEventWorkspace.h" #include "MantidGeometry/MDGeometry/MDHistoDimension.h" +#include "MantidDataObjects/Workspace2D.h" #include <stdexcept> using namespace Mantid::Kernel; @@ -19,10 +20,12 @@ namespace Mantid @param pDiffMin: p diff min value (extent) @param pDiffMax: p diff max value (extent) @param incidentTheta: Predetermined incident theta value - @param boxController: Box controller to apply on output workspace + @param numberOfBinsQx : Number of bins along the qx axis + @param numberOfBinsQz : Number of bins along the qz axis */ - ReflectometryTransformP::ReflectometryTransformP(double pSumMin, double pSumMax, double pDiffMin, double pDiffMax, double incidentTheta, BoxController_sptr boxController) - : ReflectometryMDTransform(boxController), m_pSumMin(pSumMin), m_pSumMax(pSumMax), m_pDiffMin(pDiffMin), m_pDiffMax(pDiffMax), m_pSumCalculation(incidentTheta), m_pDiffCalculation(incidentTheta) + ReflectometryTransformP::ReflectometryTransformP(double pSumMin, double pSumMax, double pDiffMin, double pDiffMax, double incidentTheta + , int numberOfBinsQx, int numberOfBinsQz ) + : ReflectometryTransform(numberOfBinsQx, numberOfBinsQz), m_pSumMin(pSumMin), m_pSumMax(pSumMax), m_pDiffMin(pDiffMin), m_pDiffMax(pDiffMax), m_pSumCalculation(incidentTheta), m_pDiffCalculation(incidentTheta) { if(pSumMin >= m_pSumMax) { @@ -45,12 +48,12 @@ namespace Mantid { } - Mantid::API::IMDEventWorkspace_sptr ReflectometryTransformP::execute(Mantid::API::MatrixWorkspace_const_sptr inputWs) const + Mantid::API::IMDEventWorkspace_sptr ReflectometryTransformP::executeMD(Mantid::API::MatrixWorkspace_const_sptr inputWs, BoxController_sptr boxController) const { MDHistoDimension_sptr pSumDim = MDHistoDimension_sptr(new MDHistoDimension("Pz_i + Pz_f","sum_pz","(Ang^-1)", static_cast<Mantid::coord_t>(m_pSumMin), static_cast<Mantid::coord_t>(m_pSumMax), m_nbinsx)); MDHistoDimension_sptr pDiffDim = MDHistoDimension_sptr(new MDHistoDimension("Pz_i - Pz_f","diff_pz","(Ang^-1)", static_cast<Mantid::coord_t>(m_pDiffMin), static_cast<Mantid::coord_t>(m_pDiffMax), m_nbinsz)); - auto ws = createWorkspace(pSumDim, pDiffDim); + auto ws = createMDWorkspace(pSumDim, pDiffDim, boxController); auto spectraAxis = inputWs->getAxis(1); for(size_t index = 0; index < inputWs->getNumberHistograms(); ++index) @@ -78,7 +81,61 @@ namespace Mantid return ws; } + /** + * Convert to Pi-Pf, Pi+Pf + * @param inputWs : Input Matrix workspace + * @return workspace group containing output matrix workspaces of ki and kf + */ + Mantid::API::MatrixWorkspace_sptr ReflectometryTransformP::execute( + Mantid::API::MatrixWorkspace_const_sptr inputWs) const + { + auto ws = boost::make_shared<Mantid::DataObjects::Workspace2D>(); + + ws->initialize(m_nbinsz, m_nbinsx, m_nbinsx); // Create the output workspace as a distribution + + // Mapping so that Psum and Pdiff values calculated can be added to the matrix workspace at the correct index. + const double gradPSum = double(m_nbinsx) / (m_pSumMax - m_pSumMin); // The x - axis + const double gradPDiff = double(m_nbinsz) / (m_pDiffMax - m_pDiffMin); // Actually the y-axis + const double cxToIndex = -gradPSum * m_pSumMin; + const double cyToIndex = -gradPDiff * m_pDiffMin; + const double cxToPSum = m_pSumMin - (1 / gradPSum); + const double cyToPDiff = m_pDiffMin - (1 / gradPDiff); + // Create an X - Axis. + MantidVec xAxisVec = createXAxis(ws.get(), gradPSum, cxToPSum, m_nbinsx, "Pi + Pf", "1/Angstroms"); + // Create a Y (vertical) Axis + createVerticalAxis(ws.get(), xAxisVec, gradPDiff, cyToPDiff, m_nbinsz, "Pi - Pf", "1/Angstroms"); + + // Loop over all entries in the input workspace and calculate Psum and Pdiff for each. + auto spectraAxis = inputWs->getAxis(1); + for (size_t index = 0; index < inputWs->getNumberHistograms(); ++index) + { + auto counts = inputWs->readY(index); + auto wavelengths = inputWs->readX(index); + auto errors = inputWs->readE(index); + const size_t nInputBins = wavelengths.size() - 1; + const double theta_final = spectraAxis->getValue(index); + m_pSumCalculation.setThetaFinal(theta_final); + m_pDiffCalculation.setThetaFinal(theta_final); + //Loop over all bins in spectra + for (size_t binIndex = 0; binIndex < nInputBins; ++binIndex) + { + const double wavelength = 0.5 * (wavelengths[binIndex] + wavelengths[binIndex + 1]); + double _pSum = m_pSumCalculation.execute(wavelength); + double _pDiff= m_pDiffCalculation.execute(wavelength); + + if (_pSum >= m_pSumMin && _pSum <= m_pSumMax && _pDiff >= m_pDiffMin && _pDiff <= m_pDiffMax) // Check that the calculated ki and kf are in range + { + const int outIndexX = (int)((gradPSum * _pSum) + cxToIndex); + const int outIndexZ = (int)((gradPDiff * _pDiff) + cyToIndex); + + ws->dataY(outIndexZ)[outIndexX] += counts[binIndex]; + ws->dataE(outIndexZ)[outIndexX] += errors[binIndex]; + } + } + } + return ws; + } } // namespace Mantid } // namespace MDEvents diff --git a/Code/Mantid/Framework/MDEvents/src/ReflectometryTransformQxQz.cpp b/Code/Mantid/Framework/MDEvents/src/ReflectometryTransformQxQz.cpp index 8da107d5d51a79f2bb70913f3ad2cd1d4833499a..805cb3ca13dbf1c2e69655002197cbcf092be73f 100644 --- a/Code/Mantid/Framework/MDEvents/src/ReflectometryTransformQxQz.cpp +++ b/Code/Mantid/Framework/MDEvents/src/ReflectometryTransformQxQz.cpp @@ -1,6 +1,7 @@ #include "MantidMDEvents/ReflectometryTransformQxQz.h" #include "MantidMDEvents/MDEventWorkspace.h" #include "MantidGeometry/MDGeometry/MDHistoDimension.h" +#include "MantidDataObjects/Workspace2D.h" #include <stdexcept> using namespace Mantid::Kernel; @@ -14,69 +15,81 @@ namespace Mantid //---------------------------------------------------------------------------------------------- /** Destructor - */ + */ ReflectometryTransformQxQz::~ReflectometryTransformQxQz() { } /* - Constructor - @param qxMin: min qx value (extent) - @param qxMax: max qx value (extent) - @param qzMin: min qz value (extent) - @param qzMax; max qz value (extent) - @param incidentTheta: Predetermined incident theta value - @param boxController: Box controller to apply to output workspace - */ - ReflectometryTransformQxQz::ReflectometryTransformQxQz(double qxMin, double qxMax, double qzMin, double qzMax, double incidentTheta, BoxController_sptr boxController): - ReflectometryMDTransform(boxController), m_qxMin(qxMin), m_qxMax(qxMax), m_qzMin(qzMin), m_qzMax(qzMax), m_QxCalculation(incidentTheta), m_QzCalculation(incidentTheta) + Constructor + @param qxMin: min qx value (extent) + @param qxMax: max qx value (extent) + @param qzMin: min qz value (extent) + @param qzMax; max qz value (extent) + @param incidentTheta: Predetermined incident theta value + @param numberOfBinsQx : Number of bins along the qx axis + @param numberOfBinsQz : Number of bins along the qz axis + */ + ReflectometryTransformQxQz::ReflectometryTransformQxQz(double qxMin, double qxMax, double qzMin, + double qzMax, double incidentTheta, int numberOfBinsQx, int numberOfBinsQz) : ReflectometryTransform(numberOfBinsQx, numberOfBinsQz), + m_qxMin(qxMin), m_qxMax(qxMax), m_qzMin(qzMin), m_qzMax(qzMax), m_QxCalculation(incidentTheta), m_QzCalculation( + incidentTheta) { - if(qxMin >= qxMax) + if (qxMin >= qxMax) { throw std::invalid_argument("min qx bounds must be < max qx bounds"); } - if(qzMin >= qzMax) + if (qzMin >= qzMax) { throw std::invalid_argument("min qz bounds must be < max qz bounds"); } - if(incidentTheta < 0 || incidentTheta > 90) + if (incidentTheta < 0 || incidentTheta > 90) { throw std::out_of_range("incident theta angle must be > 0 and < 90"); } } /* - Execute the transformtion. Generates an output IMDEventWorkspace. - @return the constructed IMDEventWorkspace following the transformation. - @param ws: Input MatrixWorkspace const shared pointer - */ - IMDEventWorkspace_sptr ReflectometryTransformQxQz::execute(MatrixWorkspace_const_sptr inputWs) const + Execute the transformation. Generates an output IMDEventWorkspace. + @return the constructed IMDEventWorkspace following the transformation. + @param ws: Input MatrixWorkspace, with a vertical axis of signed-theta, and an x-axis of wavelength + @param boxController: Box controller to apply to output workspace + */ + IMDEventWorkspace_sptr ReflectometryTransformQxQz::executeMD(MatrixWorkspace_const_sptr inputWs, + BoxController_sptr boxController) const { - MDHistoDimension_sptr qxDim = MDHistoDimension_sptr(new MDHistoDimension("Qx","qx","(Ang^-1)", static_cast<Mantid::coord_t>(m_qxMin), static_cast<Mantid::coord_t>(m_qxMax), m_nbinsx)); - MDHistoDimension_sptr qzDim = MDHistoDimension_sptr(new MDHistoDimension("Qz","qz","(Ang^-1)", static_cast<Mantid::coord_t>(m_qzMin), static_cast<Mantid::coord_t>(m_qzMax), m_nbinsz)); + MDHistoDimension_sptr qxDim = MDHistoDimension_sptr( + new MDHistoDimension("Qx", "qx", "(Ang^-1)", static_cast<Mantid::coord_t>(m_qxMin), + static_cast<Mantid::coord_t>(m_qxMax), m_nbinsx)); + MDHistoDimension_sptr qzDim = MDHistoDimension_sptr( + new MDHistoDimension("Qz", "qz", "(Ang^-1)", static_cast<Mantid::coord_t>(m_qzMin), + static_cast<Mantid::coord_t>(m_qzMax), m_nbinsz)); - auto ws = createWorkspace(qxDim, qzDim); + auto ws = createMDWorkspace(qxDim, qzDim, boxController); auto spectraAxis = inputWs->getAxis(1); - for(size_t index = 0; index < inputWs->getNumberHistograms(); ++index) + for (size_t index = 0; index < inputWs->getNumberHistograms(); ++index) { auto counts = inputWs->readY(index); auto wavelengths = inputWs->readX(index); auto errors = inputWs->readE(index); - const size_t nInputBins = wavelengths.size() -1; + const size_t nInputBins = wavelengths.size() - 1; const double theta_final = spectraAxis->getValue(index); m_QxCalculation.setThetaFinal(theta_final); m_QzCalculation.setThetaFinal(theta_final); //Loop over all bins in spectra - for(size_t binIndex = 0; binIndex < nInputBins; ++binIndex) + for (size_t binIndex = 0; binIndex < nInputBins; ++binIndex) { - const double& wavelength = 0.5*(wavelengths[binIndex] + wavelengths[binIndex+1]); + const double& wavelength = 0.5 * (wavelengths[binIndex] + wavelengths[binIndex + 1]); double _qx = m_QxCalculation.execute(wavelength); double _qz = m_QzCalculation.execute(wavelength); - double centers[2] = {_qx, _qz}; + double centers[2] = + { _qx, _qz }; - ws->addEvent(MDLeanEvent<2>(float(counts[binIndex]), float(errors[binIndex]*errors[binIndex]), centers)); + ws->addEvent( + MDLeanEvent<2>(float(counts[binIndex]), float(errors[binIndex] * errors[binIndex]), + centers)); } } ws->splitAllIfNeeded(NULL); @@ -84,5 +97,60 @@ namespace Mantid return ws; } + /** + * Execute the transformation. Generates an output Matrix workspace. + * @param inputWs : Input workspace with a vertical axis of signed-theta and an x-axis of wavelength + * @return : A 2D workspace with qz on the vertical axis and qx on the horizontal axis. + */ + MatrixWorkspace_sptr ReflectometryTransformQxQz::execute(MatrixWorkspace_const_sptr inputWs) const + { + auto ws = boost::make_shared<Mantid::DataObjects::Workspace2D>(); + + ws->initialize(m_nbinsz, m_nbinsx, m_nbinsx); // Create the output workspace as a distribution + + // Mapping so that qx and qz values calculated can be added to the matrix workspace at the correct index. + const double gradQx = double(m_nbinsx) / (m_qxMax - m_qxMin); // The x - axis + const double gradQz = double(m_nbinsz) / (m_qzMax - m_qzMin); // Actually the y-axis + const double cxToIndex = -gradQx * m_qxMin; + const double czToIndex = -gradQz * m_qzMin; + const double cxToQ = m_qxMin - ( 1 / gradQx); + const double czToQ = m_qzMin - ( 1 / gradQz); + + // Create an X - Axis. + MantidVec xAxisVec = createXAxis(ws.get(), gradQx, cxToQ, m_nbinsx, "qx", "1/Angstroms"); + // Create a Y (vertical) Axis + createVerticalAxis(ws.get(), xAxisVec, gradQz, czToQ, m_nbinsz, "qz", "1/Angstroms"); + + // Loop over all entries in the input workspace and calculate qx and qz for each. + auto spectraAxis = inputWs->getAxis(1); + for (size_t index = 0; index < inputWs->getNumberHistograms(); ++index) + { + auto counts = inputWs->readY(index); + auto wavelengths = inputWs->readX(index); + auto errors = inputWs->readE(index); + const size_t nInputBins = wavelengths.size() - 1; + const double theta_final = spectraAxis->getValue(index); + m_QxCalculation.setThetaFinal(theta_final); + m_QzCalculation.setThetaFinal(theta_final); + //Loop over all bins in spectra + for (size_t binIndex = 0; binIndex < nInputBins; ++binIndex) + { + const double& wavelength = 0.5 * (wavelengths[binIndex] + wavelengths[binIndex + 1]); + const double _qx = m_QxCalculation.execute(wavelength); + const double _qz = m_QzCalculation.execute(wavelength); + + if (_qx >= m_qxMin && _qx <= m_qxMax && _qz >= m_qzMin && _qz <= m_qzMax) // Check that the calculated qx and qz are in range + { + const int outIndexX = int((gradQx * _qx) + cxToIndex); + const int outIndexZ = int((gradQz * _qz) + czToIndex); + + ws->dataY(outIndexZ)[outIndexX] += counts[binIndex]; + ws->dataE(outIndexZ)[outIndexX] += errors[binIndex]; + } + } + } + return ws; + } + } // namespace Mantid } // namespace MDEvents diff --git a/Code/Mantid/Framework/MDEvents/test/ConvertToReflectometryQTest.h b/Code/Mantid/Framework/MDEvents/test/ConvertToReflectometryQTest.h index 6ee3c2a4a45850eef81e0930049e3452ad874702..577d54d0ed833dbb8ed20aa8572adf2bebaa8188 100644 --- a/Code/Mantid/Framework/MDEvents/test/ConvertToReflectometryQTest.h +++ b/Code/Mantid/Framework/MDEvents/test/ConvertToReflectometryQTest.h @@ -31,7 +31,7 @@ private: Makes the tests much more readable like this. */ - boost::shared_ptr<ConvertToReflectometryQ> make_standard_algorithm(const std::string outputdimensions="Q (lab frame)") + boost::shared_ptr<ConvertToReflectometryQ> make_standard_algorithm(const std::string outputdimensions="Q (lab frame)", bool outputAsMD = true) { MatrixWorkspace_sptr in_ws = WorkspaceCreationHelper::create2DWorkspaceWithFullInstrument(10, 10); in_ws->getAxis(0)->setUnit("Wavelength"); @@ -51,6 +51,7 @@ private: alg->setProperty("OutputDimensions", outputdimensions); alg->setPropertyValue("OutputWorkspace", "OutputTransformedWorkspace"); alg->setProperty("OverrideIncidentTheta", true); + alg->setProperty("OutputAsMDWorkspace", outputAsMD); alg->setProperty("IncidentTheta", 0.5); return alg; } @@ -151,7 +152,7 @@ public: TS_ASSERT_THROWS_NOTHING(alg->execute()); } - void test_execute_qxqz() + void test_execute_qxqz_md() { auto alg = make_standard_algorithm(); alg->execute(); @@ -160,7 +161,7 @@ public: TS_ASSERT_EQUALS(2, ws->getExperimentInfo(0)->run().getLogData().size()); } - void test_execute_kikf() + void test_execute_kikf_md() { auto alg = make_standard_algorithm("K (incident, final)"); TS_ASSERT_THROWS_NOTHING(alg->execute()); @@ -168,7 +169,7 @@ public: TS_ASSERT(ws != NULL); } - void test_execute_pipf() + void test_execute_pipf_md() { auto alg = make_standard_algorithm("P (lab frame)"); TS_ASSERT_THROWS_NOTHING(alg->execute()); @@ -176,6 +177,34 @@ public: TS_ASSERT(ws != NULL); } + void test_execute_qxqz_2D() + { + const bool outputAsMD = false; + auto alg = make_standard_algorithm("Q (lab frame)", outputAsMD); + alg->execute(); + auto ws = boost::dynamic_pointer_cast<Mantid::API::MatrixWorkspace>(Mantid::API::AnalysisDataService::Instance().retrieve("OutputTransformedWorkspace")); + TS_ASSERT(ws != NULL); + TS_ASSERT_EQUALS(2, ws->run().getLogData().size()); + } + + void test_execute_kikf_2D() + { + const bool outputAsMD = false; + auto alg = make_standard_algorithm("K (incident, final)", outputAsMD); + TS_ASSERT_THROWS_NOTHING(alg->execute()); + auto ws = boost::dynamic_pointer_cast<Mantid::API::MatrixWorkspace>(Mantid::API::AnalysisDataService::Instance().retrieve("OutputTransformedWorkspace")); + TS_ASSERT(ws != NULL); + } + + void test_execute_pipf_2D() + { + const bool outputAsMD = false; + auto alg = make_standard_algorithm("P (lab frame)", outputAsMD); + TS_ASSERT_THROWS_NOTHING(alg->execute()); + auto ws = boost::dynamic_pointer_cast<Mantid::API::MatrixWorkspace>(Mantid::API::AnalysisDataService::Instance().retrieve("OutputTransformedWorkspace")); + TS_ASSERT(ws != NULL); + } + void test_box_controller_defaults() { auto alg = make_standard_algorithm(); diff --git a/Code/Mantid/Framework/MDEvents/test/ReflectometryTransformKiKfTest.h b/Code/Mantid/Framework/MDEvents/test/ReflectometryTransformKiKfTest.h index bda446232350127d053cfe384ef79e5cf348f514..96d0f2d06139642e417a826b2347c73c929cb636 100644 --- a/Code/Mantid/Framework/MDEvents/test/ReflectometryTransformKiKfTest.h +++ b/Code/Mantid/Framework/MDEvents/test/ReflectometryTransformKiKfTest.h @@ -13,6 +13,7 @@ using namespace Mantid::MDEvents; +using namespace Mantid::API; class ReflectometryTransformKiKfTest : public CxxTest::TestSuite { @@ -124,4 +125,4 @@ public: }; -#endif /* MANTID_MDEVENTS_REFLECTOMETRYTRANSFORMKIKFTEST_H_ */ \ No newline at end of file +#endif /* MANTID_MDEVENTS_REFLECTOMETRYTRANSFORMKIKFTEST_H_ */ diff --git a/Code/Mantid/Framework/MDEvents/test/ReflectometryTransformPTest.h b/Code/Mantid/Framework/MDEvents/test/ReflectometryTransformPTest.h index b13d711bb48dc2ea165dc1daef76ca00b42c12ab..e1a043d9507b7ca55d2602177f34cada3e82e3d3 100644 --- a/Code/Mantid/Framework/MDEvents/test/ReflectometryTransformPTest.h +++ b/Code/Mantid/Framework/MDEvents/test/ReflectometryTransformPTest.h @@ -138,4 +138,4 @@ public: }; -#endif /* MANTID_MDEVENTS_REFLECTOMETRYTRANSFORMPTEST_H_ */ \ No newline at end of file +#endif /* MANTID_MDEVENTS_REFLECTOMETRYTRANSFORMPTEST_H_ */ diff --git a/Code/Mantid/Framework/MDEvents/test/ReflectometryTransformQxQzTest.h b/Code/Mantid/Framework/MDEvents/test/ReflectometryTransformQxQzTest.h index 841248688855824d5dd032f815038a3be3751feb..15dfe8f852fbc92ccfa3b8a98340f317eb19e78a 100644 --- a/Code/Mantid/Framework/MDEvents/test/ReflectometryTransformQxQzTest.h +++ b/Code/Mantid/Framework/MDEvents/test/ReflectometryTransformQxQzTest.h @@ -33,7 +33,7 @@ public: double qzMin = 1; double qzMax = 2; double incidentTheta = 1; - TS_ASSERT_THROWS(ReflectometryTransformQxQz(qxMin, qxMax, qzMin, qzMax, incidentTheta, boost::make_shared<BoxController>(2)), std::invalid_argument); + TS_ASSERT_THROWS(ReflectometryTransformQxQz(qxMin, qxMax, qzMin, qzMax, incidentTheta), std::invalid_argument); } void test_qxmin_equal_to_qxmax_throws() @@ -43,7 +43,7 @@ public: double qzMin = 1; double qzMax = 2; double incidentTheta = 1; - TS_ASSERT_THROWS(ReflectometryTransformQxQz(qxMin, qxMax, qzMin, qzMax, incidentTheta, boost::make_shared<BoxController>(2)), std::invalid_argument); + TS_ASSERT_THROWS(ReflectometryTransformQxQz(qxMin, qxMax, qzMin, qzMax, incidentTheta), std::invalid_argument); } void test_qzmin_greater_than_qzmax_throws() @@ -53,7 +53,7 @@ public: double qzMin = 2; double qzMax = 1; //Smaller than qzMin! double incidentTheta = 1; - TS_ASSERT_THROWS(ReflectometryTransformQxQz(qxMin, qxMax, qzMin, qzMax, incidentTheta, boost::make_shared<BoxController>(2)), std::invalid_argument); + TS_ASSERT_THROWS(ReflectometryTransformQxQz(qxMin, qxMax, qzMin, qzMax, incidentTheta), std::invalid_argument); } void test_qzmin_equal_to_qzmax_throws() @@ -63,7 +63,7 @@ public: double qzMin = 1; double qzMax = 1; //Equal to qzMin! double incidentTheta = 1; - TS_ASSERT_THROWS(ReflectometryTransformQxQz(qxMin, qxMax, qzMin, qzMax, incidentTheta, boost::make_shared<BoxController>(2)), std::invalid_argument); + TS_ASSERT_THROWS(ReflectometryTransformQxQz(qxMin, qxMax, qzMin, qzMax, incidentTheta), std::invalid_argument); } void test_incident_theta_negative() @@ -73,7 +73,7 @@ public: double qzMin = 1; double qzMax = 3; double incidentTheta = -0.001; //Negative - TS_ASSERT_THROWS(ReflectometryTransformQxQz(qxMin, qxMax, qzMin, qzMax, incidentTheta, boost::make_shared<BoxController>(2)), std::out_of_range); + TS_ASSERT_THROWS(ReflectometryTransformQxQz(qxMin, qxMax, qzMin, qzMax, incidentTheta), std::out_of_range); } void test_incident_theta_too_large() @@ -83,7 +83,7 @@ public: double qzMin = 1; double qzMax = 3; double incidentTheta = 90.001; //Too large - TS_ASSERT_THROWS(ReflectometryTransformQxQz(qxMin, qxMax, qzMin, qzMax, incidentTheta, boost::make_shared<BoxController>(2)), std::out_of_range); + TS_ASSERT_THROWS(ReflectometryTransformQxQz(qxMin, qxMax, qzMin, qzMax, incidentTheta), std::out_of_range); } void test_valid_construction_inputs() @@ -93,7 +93,7 @@ public: double qzMin = 1; double qzMax = 2; double incidentTheta = 1; - TS_ASSERT_THROWS_NOTHING(ReflectometryTransformQxQz(qxMin, qxMax, qzMin, qzMax, incidentTheta, boost::make_shared<BoxController>(2))); + TS_ASSERT_THROWS_NOTHING(ReflectometryTransformQxQz(qxMin, qxMax, qzMin, qzMax, incidentTheta)); } //---- Tests for Qx Calculator ---- //