diff --git a/Code/Mantid/Framework/Crystal/CMakeLists.txt b/Code/Mantid/Framework/Crystal/CMakeLists.txt index cfd916ff072e200004d808f817b45a4d92728df4..bfef827dc06223860a2874fe726a355a2711d136 100644 --- a/Code/Mantid/Framework/Crystal/CMakeLists.txt +++ b/Code/Mantid/Framework/Crystal/CMakeLists.txt @@ -37,6 +37,7 @@ set ( SRC_FILES src/OptimizeExtinctionParameters.cpp src/OptimizeLatticeForCellType.cpp src/PeakBackground.cpp + src/PeakClusterProjection.cpp src/PeakHKLErrors.cpp src/PeakIntegration.cpp src/PeakIntensityVsRadius.cpp @@ -106,6 +107,7 @@ set ( INC_FILES inc/MantidCrystal/OptimizeExtinctionParameters.h inc/MantidCrystal/OptimizeLatticeForCellType.h inc/MantidCrystal/PeakBackground.h + inc/MantidCrystal/PeakClusterProjection.h inc/MantidCrystal/PeakHKLErrors.h inc/MantidCrystal/PeakIntegration.h inc/MantidCrystal/PeakIntensityVsRadius.h @@ -169,6 +171,7 @@ set ( TEST_FILES OptimizeCrystalPlacementTest.h OptimizeLatticeForCellTypeTest.h PeakBackgroundTest.h + PeakClusterProjectionTest.h PeakHKLErrorsTest.h PeakIntegrationTest.h PeakIntensityVsRadiusTest.h diff --git a/Code/Mantid/Framework/Crystal/inc/MantidCrystal/PeakClusterProjection.h b/Code/Mantid/Framework/Crystal/inc/MantidCrystal/PeakClusterProjection.h new file mode 100644 index 0000000000000000000000000000000000000000..71296ec2727a29b77e34af45dacbf0570eb345f2 --- /dev/null +++ b/Code/Mantid/Framework/Crystal/inc/MantidCrystal/PeakClusterProjection.h @@ -0,0 +1,68 @@ +#ifndef MANTID_CRYSTAL_PEAKCLUSTERPROJECTION_H_ +#define MANTID_CRYSTAL_PEAKCLUSTERPROJECTION_H_ + +#include "MantidKernel/System.h" +#include "MantidGeometry/MDGeometry/MDTypes.h" +#include "MantidAPI/IMDWorkspace.h" +#include <boost/shared_ptr.hpp> + +namespace Mantid +{ + namespace API + { + class IPeak; + class IMDHistoWorkspace; + class PeakTransform; + } +namespace Crystal +{ + + /** PeakClusterProjection : Maps peaks onto IMDHistoWorkspaces and returns the signal value at the peak center. + + Copyright © 2014 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 PeakClusterProjection + { + public: + /// Constructor + PeakClusterProjection(boost::shared_ptr<Mantid::API::IMDHistoWorkspace>& mdWS) ; + /// Get the signal value at the peak center + Mantid::signal_t signalAtPeakCenter(Mantid::API::IPeak& peak, Mantid::API::MDNormalization normalization = Mantid::API::NoNormalization) const; + /// Destructor + virtual ~PeakClusterProjection(); + private: + // Disabled copy and assignment. + PeakClusterProjection(const PeakClusterProjection&); + PeakClusterProjection& operator=(const PeakClusterProjection&); + + /// Image + boost::shared_ptr<Mantid::API::IMDHistoWorkspace> m_mdWS; + + /// Peak Transform + boost::shared_ptr<Mantid::API::PeakTransform> m_peakTransform; + + }; + + +} // namespace Crystal +} // namespace Mantid + +#endif /* MANTID_CRYSTAL_PEAKCLUSTERPROJECTION_H_ */ diff --git a/Code/Mantid/Framework/Crystal/src/IntegratePeaksUsingClusters.cpp b/Code/Mantid/Framework/Crystal/src/IntegratePeaksUsingClusters.cpp index adab580ee67fe1f6cc827baf5684462e61aee54d..f5bf48ee3bd329b4ae66ca2ccddc754271eea955 100644 --- a/Code/Mantid/Framework/Crystal/src/IntegratePeaksUsingClusters.cpp +++ b/Code/Mantid/Framework/Crystal/src/IntegratePeaksUsingClusters.cpp @@ -47,6 +47,7 @@ For more in-depth analysis, the algorithm will produce debug log messages. #include "MantidCrystal/ICluster.h" #include "MantidCrystal/ConnectedComponentLabeling.h" #include "MantidCrystal/HardThresholdBackground.h" +#include "MantidCrystal/PeakClusterProjection.h" #include "MantidAPI/IMDHistoWorkspace.h" #include "MantidAPI/WorkspaceProperty.h" #include "MantidAPI/IMDIterator.h" diff --git a/Code/Mantid/Framework/Crystal/src/PeakClusterProjection.cpp b/Code/Mantid/Framework/Crystal/src/PeakClusterProjection.cpp new file mode 100644 index 0000000000000000000000000000000000000000..f88341485044492ac92a2048376fe881961a5507 --- /dev/null +++ b/Code/Mantid/Framework/Crystal/src/PeakClusterProjection.cpp @@ -0,0 +1,85 @@ +#include "MantidCrystal/PeakClusterProjection.h" + +#include "MantidKernel/V3D.h" +#include "MantidAPI/IPeak.h" +#include "MantidAPI/IMDHistoWorkspace.h" +#include "MantidAPI/PeakTransformHKL.h" +#include "MantidAPI/PeakTransformQLab.h" +#include "MantidAPI/PeakTransformQSample.h" + +#include <stdexcept> + +using namespace Mantid::Kernel; +using namespace Mantid::API; + +namespace +{ + PeakTransform_sptr makePeakTransform(IMDHistoWorkspace const * const mdWS) + { + const SpecialCoordinateSystem mdCoordinates = mdWS->getSpecialCoordinateSystem(); + PeakTransformFactory_sptr peakTransformFactory; + if (mdCoordinates == QLab) + { + peakTransformFactory = boost::make_shared<PeakTransformQLabFactory>(); + } + else if (mdCoordinates == QSample) + { + peakTransformFactory = boost::make_shared<PeakTransformQSampleFactory>(); + } + else if (mdCoordinates == Mantid::API::HKL) + { + peakTransformFactory = boost::make_shared<PeakTransformHKLFactory>(); + } + const std::string xDim = mdWS->getDimension(0)->getName(); + const std::string yDim = mdWS->getDimension(1)->getName(); + PeakTransform_sptr peakTransform = peakTransformFactory->createTransform(xDim, yDim); + return peakTransform; + } +} + + + +namespace Mantid +{ +namespace Crystal +{ + + + //---------------------------------------------------------------------------------------------- + /** Constructor + */ + PeakClusterProjection::PeakClusterProjection(IMDHistoWorkspace_sptr& mdWS) : m_mdWS(mdWS) + { + auto coordinateSystem = mdWS->getSpecialCoordinateSystem(); + if(coordinateSystem == None) + { + throw std::invalid_argument("Input image IMDHistoWorkspace must have a known special coordinate system."); + } + + // Make a peak transform so that we can understand a peak in the context of the mdworkspace coordinate setup. + m_peakTransform = makePeakTransform(mdWS.get()); + } + + /** + * Get the signal value at the peak center. + * @param peak + * @param normalization : Optional normalization. Off by default. + * @return signal value at peak center. NAN if the peak is not centered on the image. + */ + Mantid::signal_t PeakClusterProjection::signalAtPeakCenter(IPeak& peak, MDNormalization normalization) const + { + const Mantid::Kernel::V3D& center = m_peakTransform->transformPeak(peak); + return m_mdWS->getSignalAtVMD(center, normalization); + } + + //---------------------------------------------------------------------------------------------- + /** Destructor + */ + PeakClusterProjection::~PeakClusterProjection() + { + } + + + +} // namespace Crystal +} // namespace Mantid diff --git a/Code/Mantid/Framework/Crystal/test/IntegratePeaksUsingClustersTest.h b/Code/Mantid/Framework/Crystal/test/IntegratePeaksUsingClustersTest.h index 693981811d8cd2238c6b316a7c5979e8c8f1c17b..2cb77f2779cc4452c91d8fd608fa675fbdcb34ea 100644 --- a/Code/Mantid/Framework/Crystal/test/IntegratePeaksUsingClustersTest.h +++ b/Code/Mantid/Framework/Crystal/test/IntegratePeaksUsingClustersTest.h @@ -60,7 +60,9 @@ namespace auto mdworkspaceAlg = AlgorithmManager::Instance().createUnmanaged("CreateMDWorkspace"); mdworkspaceAlg->setChild(true); mdworkspaceAlg->initialize(); - mdworkspaceAlg->setProperty("Dimensions", 3); + mdworkspaceAlg->setProperty("Dimensionality", 3); + std::vector<int> numbersOfBins = std::vector<int>(3, 10); + mdworkspaceAlg->setProperty("NumberOfBins", numbersOfBins); std::vector<double> extents = boost::assign::list_of(min)(max)(min)(max)(min)(max).convert_to_container<std::vector<double> >(); mdworkspaceAlg->setProperty("Extents", extents); mdworkspaceAlg->setPropertyValue("Names", "H,K,L"); diff --git a/Code/Mantid/Framework/Crystal/test/PeakClusterProjectionTest.h b/Code/Mantid/Framework/Crystal/test/PeakClusterProjectionTest.h new file mode 100644 index 0000000000000000000000000000000000000000..6129b25d2b34fd4db21ff353acc8a4e84f3c46a9 --- /dev/null +++ b/Code/Mantid/Framework/Crystal/test/PeakClusterProjectionTest.h @@ -0,0 +1,108 @@ +#ifndef MANTID_CRYSTAL_PEAKCLUSTERPROJECTIONTEST_H_ +#define MANTID_CRYSTAL_PEAKCLUSTERPROJECTIONTEST_H_ + +#include <cxxtest/TestSuite.h> + +#include "MantidCrystal/PeakClusterProjection.h" + +#include "MantidAPI/IMDHistoWorkspace.h" +#include "MantidAPI/IPeaksWorkspace.h" +#include "MantidAPI/IPeak.h" +#include "MantidAPI/FrameworkManager.h" +#include "MantidAPI/AlgorithmManager.h" + +#include "MantidDataObjects/PeaksWorkspace.h" +#include "MantidTestHelpers/MDEventsTestHelper.h" +#include "MantidTestHelpers/ComponentCreationHelper.h" +#include <boost/math/special_functions/fpclassify.hpp> +#include <boost/assign/list_of.hpp> + +using namespace Mantid::API; +using namespace Mantid::Geometry; +using namespace Mantid::Crystal; +using namespace Mantid::MDEvents; +using namespace Mantid::DataObjects; + +namespace +{ +} + +class PeakClusterProjectionTest: public CxxTest::TestSuite +{ +public: + // This pair of boilerplate methods prevent the suite being created statically + // This means the constructor isn't called when running other tests + static PeakClusterProjectionTest *createSuite() + { + return new PeakClusterProjectionTest(); + } + static void destroySuite(PeakClusterProjectionTest *suite) + { + delete suite; + } + + PeakClusterProjectionTest() + { + FrameworkManager::Instance(); + } + + void test_throws_if_mdws_has_no_coordinate_system() + { + IMDHistoWorkspace_sptr inWS = MDEventsTestHelper::makeFakeMDHistoWorkspace(1, 1, 1); + inWS->setCoordinateSystem(None); + + TSM_ASSERT_THROWS("Must have a known coordinate system", PeakClusterProjection object(inWS), + std::invalid_argument&); + } + + void test_labelAtPeakCenter_nan_if_is_off_image() + { + const double min = -10; // HKL + const double max = 10; // HKL + + auto mdworkspaceAlg = AlgorithmManager::Instance().createUnmanaged("CreateMDHistoWorkspace"); + mdworkspaceAlg->setChild(true); + mdworkspaceAlg->initialize(); + mdworkspaceAlg->setProperty("Dimensionality", 3); + std::vector<int> numbersOfBins(3, 3); + mdworkspaceAlg->setProperty("NumberOfBins", numbersOfBins); + std::vector<double> extents = + boost::assign::list_of(min)(max)(min)(max)(min)(max).convert_to_container<std::vector<double> >(); + mdworkspaceAlg->setProperty("Extents", extents); + std::vector<double> signalValues(27, 1); + mdworkspaceAlg->setProperty("SignalInput", signalValues); + std::vector<double> errorValues(27, 1); + mdworkspaceAlg->setProperty("ErrorInput", errorValues); + mdworkspaceAlg->setPropertyValue("Names", "H,K,L"); + mdworkspaceAlg->setPropertyValue("Units", "-,-,-"); + mdworkspaceAlg->setPropertyValue("OutputWorkspace", "IntegratePeaksMDTest_MDEWS"); + mdworkspaceAlg->execute(); + IMDHistoWorkspace_sptr inWS = mdworkspaceAlg->getProperty("OutputWorkspace"); + + // --- Set speical coordinates on fake mdworkspace -- + auto coordsAlg = AlgorithmManager::Instance().createUnmanaged("SetSpecialCoordinates"); + coordsAlg->setChild(true); + coordsAlg->initialize(); + coordsAlg->setProperty("InputWorkspace", inWS); + coordsAlg->setProperty("SpecialCoordinates", "HKL"); + coordsAlg->execute(); + + Instrument_sptr inst = ComponentCreationHelper::createTestInstrumentRectangular(1, 100, 0.05); + PeaksWorkspace* pPeaksWS = new PeaksWorkspace(); + pPeaksWS->setCoordinateSystem(HKL); + IPeaksWorkspace_sptr peakWS(pPeaksWS); + peakWS->setInstrument(inst); + + Peak outOfBoundsPeak(inst, 15050, 1.0); + outOfBoundsPeak.setHKL(1, 1, 11); + peakWS->addPeak(outOfBoundsPeak); + + PeakClusterProjection projection(inWS); + Mantid::signal_t value = projection.signalAtPeakCenter(outOfBoundsPeak); + + TSM_ASSERT("Should indicate is out of bounds via a NAN.", boost::math::isnan(value)); + } + +}; + +#endif /* MANTID_CRYSTAL_PEAKCLUSTERPROJECTIONTEST_H_ */ diff --git a/Code/Mantid/Framework/MDEvents/src/MDHistoWorkspace.cpp b/Code/Mantid/Framework/MDEvents/src/MDHistoWorkspace.cpp index 28aee6a966d476da3f126cbb995daa32f662e6d6..faac43bdcb76b64c4a7a0dfc37b330bb6f2206de 100644 --- a/Code/Mantid/Framework/MDEvents/src/MDHistoWorkspace.cpp +++ b/Code/Mantid/Framework/MDEvents/src/MDHistoWorkspace.cpp @@ -84,6 +84,7 @@ namespace MDEvents m_numEvents = new signal_t[m_length]; m_masks = new bool[m_length]; m_nEventsContributed = other.m_nEventsContributed; + this->setCoordinateSystem(other.getSpecialCoordinateSystem()); // Now copy all the data for (size_t i=0; i<m_length; ++i) {