diff --git a/Code/Mantid/Framework/API/CMakeLists.txt b/Code/Mantid/Framework/API/CMakeLists.txt index 8c24cfb88fecc34355c8fad07a0d006103cfc774..cb0f64f204dab590634520d2651c29554c5e17e3 100644 --- a/Code/Mantid/Framework/API/CMakeLists.txt +++ b/Code/Mantid/Framework/API/CMakeLists.txt @@ -56,6 +56,7 @@ set ( SRC_FILES src/IFunction1DSpectrum.cpp src/IFunctionMD.cpp src/IFunctionMW.cpp + src/ILatticeFunction.cpp src/ILiveListener.cpp src/IMDEventWorkspace.cpp src/IMDHistoWorkspace.cpp @@ -76,6 +77,7 @@ set ( SRC_FILES src/ImplicitFunctionParserFactory.cpp src/InstrumentDataService.cpp src/JointDomain.cpp + src/LatticeDomain.cpp src/LinearScale.cpp src/LiveListenerFactory.cpp src/LogManager.cpp @@ -212,6 +214,7 @@ set ( INC_FILES inc/MantidAPI/IFunctionMD.h inc/MantidAPI/IFunctionMW.h inc/MantidAPI/IFunctionWithLocation.h + inc/MantidAPI/ILatticeFunction.h inc/MantidAPI/ILiveListener.h inc/MantidAPI/IMDEventWorkspace.h inc/MantidAPI/IMDHistoWorkspace.h @@ -242,6 +245,7 @@ set ( INC_FILES inc/MantidAPI/InstrumentDataService.h inc/MantidAPI/Jacobian.h inc/MantidAPI/JointDomain.h + inc/MantidAPI/LatticeDomain.h inc/MantidAPI/LinearScale.h inc/MantidAPI/LiveListenerFactory.h inc/MantidAPI/LogManager.h @@ -340,6 +344,7 @@ set ( TEST_FILES IFunction1DSpectrumTest.h IFunction1DTest.h IFunctionMDTest.h + ILatticeFunctionTest.h ILiveListenerTest.h IMDWorkspaceTest.h ISpectrumTest.h @@ -348,6 +353,7 @@ set ( TEST_FILES ImplicitFunctionParserFactoryTest.h IncreasingAxisValidatorTest.h InstrumentDataServiceTest.h + LatticeDomainTest.h LiveListenerFactoryTest.h LogManagerTest.h MDGeometryTest.h diff --git a/Code/Mantid/Framework/API/inc/MantidAPI/ILatticeFunction.h b/Code/Mantid/Framework/API/inc/MantidAPI/ILatticeFunction.h new file mode 100644 index 0000000000000000000000000000000000000000..ec65576109d6a10ba09412df9c207bad46897741 --- /dev/null +++ b/Code/Mantid/Framework/API/inc/MantidAPI/ILatticeFunction.h @@ -0,0 +1,74 @@ +#ifndef MANTID_API_ILATTICEFUNCTION_H_ +#define MANTID_API_ILATTICEFUNCTION_H_ + +#include "MantidAPI/DllConfig.h" +#include "MantidAPI/FunctionParameterDecorator.h" +#include "MantidAPI/LatticeDomain.h" +#include "MantidGeometry/Crystal/UnitCell.h" + +namespace Mantid { +namespace API { + +/** ILatticeFunction + + This abstract class defines the interface for a function that calculates + values based on HKL-values and a lattice. Currently the only implementation + is CurveFitting::LatticeFunction. + + @author Michael Wedel, Paul Scherrer Institut - SINQ + @date 15/04/2015 + + Copyright © 2015 PSI-NXMM + + 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 MANTID_API_DLL ILatticeFunction : public FunctionParameterDecorator { +public: + ILatticeFunction(); + virtual ~ILatticeFunction() {} + + void function(const FunctionDomain &domain, FunctionValues &values) const; + void functionDeriv(const FunctionDomain &domain, Jacobian &jacobian); + + /// Function that should calculate d-values for the HKLs provided in the + /// domain. + virtual void functionLattice(const LatticeDomain &latticeDomain, + FunctionValues &values) const = 0; + + virtual void functionDerivLattice(const LatticeDomain &latticeDomain, + Jacobian &jacobian); + + /// A string that names the crystal system. + virtual void setCrystalSystem(const std::string &crystalSystem) = 0; + + /// Set the function parameters according to the supplied unit cell. + virtual void setUnitCell(const std::string &unitCellString) = 0; + /// Overload to set unit cell directly from UnitCell object. + virtual void setUnitCell(const Geometry::UnitCell &unitCell) = 0; + + /// Returns a unit cell object created from the function parameters + virtual Geometry::UnitCell getUnitCell() const = 0; +}; + +typedef boost::shared_ptr<ILatticeFunction> ILatticeFunction_sptr; + +} // namespace API +} // namespace Mantid + +#endif /* MANTID_API_ILATTICEFUNCTION_H_ */ diff --git a/Code/Mantid/Framework/API/inc/MantidAPI/LatticeDomain.h b/Code/Mantid/Framework/API/inc/MantidAPI/LatticeDomain.h new file mode 100644 index 0000000000000000000000000000000000000000..6df77d39914a11068ef786830ce9ecffb4c25ef6 --- /dev/null +++ b/Code/Mantid/Framework/API/inc/MantidAPI/LatticeDomain.h @@ -0,0 +1,55 @@ +#ifndef MANTID_API_LATTICEDOMAIN_H_ +#define MANTID_API_LATTICEDOMAIN_H_ + +#include "MantidAPI/DllConfig.h" +#include "MantidAPI/FunctionDomain.h" +#include "MantidKernel/V3D.h" + +namespace Mantid { +namespace API { + +/** LatticeDomain + + This domain stores V3D-objects as HKLs instead of double-values. It can be + used to refine lattice parameters from HKL/d-pairs. + + @author Michael Wedel, Paul Scherrer Institut - SINQ + @date 15/04/2015 + + Copyright © 2015 PSI-NXMM + + 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 MANTID_API_DLL LatticeDomain : public FunctionDomain { +public: + LatticeDomain(const std::vector<Kernel::V3D> &hkls); + virtual ~LatticeDomain() {} + + size_t size() const; + + const Kernel::V3D &operator[](size_t i) const; + +protected: + std::vector<Kernel::V3D> m_hkls; +}; + +} // namespace API +} // namespace Mantid + +#endif /* MANTID_API_LATTICEDOMAIN_H_ */ diff --git a/Code/Mantid/Framework/API/src/Algorithm.cpp b/Code/Mantid/Framework/API/src/Algorithm.cpp index 4a41e7e1182d395a9c5b5a5caf12883808328c7f..878f4b3abe717291ca545ce5da93526e912e0b94 100644 --- a/Code/Mantid/Framework/API/src/Algorithm.cpp +++ b/Code/Mantid/Framework/API/src/Algorithm.cpp @@ -884,7 +884,8 @@ IAlgorithm_sptr Algorithm::fromString(const std::string &input) { } catch (boost::bad_lexical_cast &) { } } - IAlgorithm_sptr alg = AlgorithmManager::Instance().create(algName, version); + IAlgorithm_sptr alg = AlgorithmManager::Instance().createUnmanaged(algName, version); + alg->initialize(); if (boost::regex_search(input, what, propExp, boost::match_not_null)) { std::string _propStr = what[1]; diff --git a/Code/Mantid/Framework/API/src/ILatticeFunction.cpp b/Code/Mantid/Framework/API/src/ILatticeFunction.cpp new file mode 100644 index 0000000000000000000000000000000000000000..b9c9875567a085bec7ed5db19cf7b8da31773381 --- /dev/null +++ b/Code/Mantid/Framework/API/src/ILatticeFunction.cpp @@ -0,0 +1,71 @@ +#include "MantidAPI/ILatticeFunction.h" + +namespace Mantid { +namespace API { + +using namespace Geometry; + +ILatticeFunction::ILatticeFunction() : FunctionParameterDecorator() {} + +/** + * Implementation of IFunction::function + * + * The implementation tries to cast the supplied domain to LatticeDomain, + * and calls functionLattice, which needs to be implemented in subclasses. + * + * @param domain :: A FunctionDomain of type LatticeDomain + * @param values :: Function values. + */ +void ILatticeFunction::function(const FunctionDomain &domain, + FunctionValues &values) const { + try { + const LatticeDomain &latticeDomain = + dynamic_cast<const LatticeDomain &>(domain); + + functionLattice(latticeDomain, values); + } + catch (std::bad_cast) { + throw std::invalid_argument( + "ILatticeFunction expects domain of type LatticeDomain."); + } +} + +/** + * Implementation of IFunction::functionDeriv + * + * Just like the function-method, the domain is checked for correct type. If + * functionDerivLattice has not been implemented, numerical derivatives are + * calculated. + * + * @param domain :: A FunctionDomain of type LatticeDomain + * @param jacobian :: Jacobian matrix + */ +void ILatticeFunction::functionDeriv(const FunctionDomain &domain, + Jacobian &jacobian) { + try { + const LatticeDomain &latticeDomain = + dynamic_cast<const LatticeDomain &>(domain); + + functionDerivLattice(latticeDomain, jacobian); + } + catch (std::bad_cast) { + throw std::invalid_argument( + "ILatticeFunction expects domain of type LatticeDomain."); + } + catch (Kernel::Exception::NotImplementedError) { + calNumericalDeriv(domain, jacobian); + } +} + +/// Default implementation, throws NotImplementedError. +void ILatticeFunction::functionDerivLattice(const LatticeDomain &latticeDomain, + Jacobian &jacobian) { + UNUSED_ARG(latticeDomain); + UNUSED_ARG(jacobian); + + throw Kernel::Exception::NotImplementedError( + "FunctionLatticeDeriv is not implemented for this function."); +} + +} // namespace API +} // namespace Mantid diff --git a/Code/Mantid/Framework/API/src/LatticeDomain.cpp b/Code/Mantid/Framework/API/src/LatticeDomain.cpp new file mode 100644 index 0000000000000000000000000000000000000000..cff999587ecddf8444834f8625bf4f6eaf207efc --- /dev/null +++ b/Code/Mantid/Framework/API/src/LatticeDomain.cpp @@ -0,0 +1,20 @@ +#include "MantidAPI/LatticeDomain.h" +#include "MantidKernel/Exception.h" +namespace Mantid { +namespace API { + +LatticeDomain::LatticeDomain(const std::vector<Kernel::V3D> &hkls) + : m_hkls(hkls) {} + +size_t LatticeDomain::size() const { return m_hkls.size(); } + +const Kernel::V3D &LatticeDomain::operator[](size_t i) const { + if (i >= m_hkls.size()) { + throw Kernel::Exception::IndexError(i, m_hkls.size() - 1, + "Index exceeds size of LatticeDomain."); + } + return m_hkls[i]; +} + +} // namespace API +} // namespace Mantid diff --git a/Code/Mantid/Framework/API/test/AlgorithmPropertyTest.h b/Code/Mantid/Framework/API/test/AlgorithmPropertyTest.h index 5f6edfe417a3fea264827aec9397c95c05c506f8..56a9b45649ff16a0bce439b5f478338ff6d67356 100644 --- a/Code/Mantid/Framework/API/test/AlgorithmPropertyTest.h +++ b/Code/Mantid/Framework/API/test/AlgorithmPropertyTest.h @@ -114,7 +114,7 @@ public: { AlgorithmProperty testProp("CalculateStep"); TS_ASSERT_EQUALS(testProp.setValue("ComplexSum()"), - "AlgorithmManager:: Unable to create algorithm ComplexSum Algorithm not registered ComplexSum"); + "Algorithm not registered ComplexSum"); } void test_Alg_With_An_AlgorithmProperty_Accepts_Another_Algorithm() diff --git a/Code/Mantid/Framework/API/test/ILatticeFunctionTest.h b/Code/Mantid/Framework/API/test/ILatticeFunctionTest.h new file mode 100644 index 0000000000000000000000000000000000000000..a1d67bac27580d9c701bc043d5d49c8e42331582 --- /dev/null +++ b/Code/Mantid/Framework/API/test/ILatticeFunctionTest.h @@ -0,0 +1,113 @@ +#ifndef MANTID_API_ILATTICEFUNCTIONTEST_H_ +#define MANTID_API_ILATTICEFUNCTIONTEST_H_ + +#include <cxxtest/TestSuite.h> +#include <gtest/gtest.h> +#include <gmock/gmock.h> + +#include "MantidAPI/ILatticeFunction.h" + +using Mantid::API::ILatticeFunction; +using Mantid::Kernel::V3D; + +using namespace Mantid::API; + +using ::testing::_; +using ::testing::Mock; +using ::testing::Return; + +class ILatticeFunctionTest : 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 ILatticeFunctionTest *createSuite() { + return new ILatticeFunctionTest(); + } + static void destroySuite(ILatticeFunctionTest *suite) { delete suite; } + + void testFunctionLatticeIsCalled() { + /* This test makes sure that functionLattice is called when the correct + * domain type is supplied. It uses the mock function defined below. + */ + MockLatticeFunction fn; + EXPECT_CALL(fn, functionLattice(_, _)).Times(1); + + LatticeDomain domain(getTestHKLs()); + FunctionValues values(domain); + + fn.function(domain, values); + + TS_ASSERT(Mock::VerifyAndClearExpectations(&fn)); + } + + void testFunctionDerivLatticeIsCalled() { + /* Just as above, this test checks that functionDerivLattice is called + * correctly. In addition to the mocked function, also MockJacobian is used. + */ + MockLatticeFunction fn; + EXPECT_CALL(fn, functionDerivLattice(_, _)).Times(1); + + LatticeDomain domain(getTestHKLs()); + MockJacobian jacobian; + + fn.functionDeriv(domain, jacobian); + + TS_ASSERT(Mock::VerifyAndClearExpectations(&fn)); + } + + void testWrongDomainTypeThrows() { + // This test makes sure that wrong domain types throw an exception. + MockLatticeFunction fn; + + MockDomain wrongDomain; + EXPECT_CALL(wrongDomain, size()).WillRepeatedly(Return(1)); + FunctionValues values(wrongDomain); + + TS_ASSERT_THROWS(fn.function(wrongDomain, values), std::invalid_argument); + + MockJacobian jacobian; + TS_ASSERT_THROWS(fn.functionDeriv(wrongDomain, jacobian), + std::invalid_argument); + } + +private: + std::vector<V3D> getTestHKLs() { + std::vector<V3D> hkls; + hkls.push_back(V3D(1, 1, 0)); + + return hkls; + } + + // Mock function to check whether the correct methods are called + class MockLatticeFunction : public ILatticeFunction { + public: + MockLatticeFunction() : ILatticeFunction() {} + ~MockLatticeFunction() {} + + MOCK_CONST_METHOD0(name, std::string()); + MOCK_CONST_METHOD2(functionLattice, + void(const LatticeDomain &, FunctionValues &)); + + MOCK_METHOD2(functionDerivLattice, void(const LatticeDomain &, Jacobian &)); + + MOCK_METHOD1(setCrystalSystem, void(const std::string &)); + MOCK_METHOD1(setUnitCell, void(const std::string &)); + MOCK_METHOD1(setUnitCell, void(const Mantid::Geometry::UnitCell &)); + MOCK_CONST_METHOD0(getUnitCell, Mantid::Geometry::UnitCell()); + }; + + // Mock jacobian for being able to test derivative calls + class MockJacobian : public Jacobian { + public: + MOCK_METHOD3(set, void(size_t, size_t, double)); + MOCK_METHOD2(get, double(size_t, size_t)); + }; + + // Mock domain to simulate a wrong domain type + class MockDomain : public FunctionDomain { + public: + MOCK_CONST_METHOD0(size, size_t()); + }; +}; + +#endif /* MANTID_API_ILATTICEFUNCTIONTEST_H_ */ diff --git a/Code/Mantid/Framework/API/test/LatticeDomainTest.h b/Code/Mantid/Framework/API/test/LatticeDomainTest.h new file mode 100644 index 0000000000000000000000000000000000000000..95c9f318e905e47edef732390c3d1eca433d8f5a --- /dev/null +++ b/Code/Mantid/Framework/API/test/LatticeDomainTest.h @@ -0,0 +1,61 @@ +#ifndef MANTID_API_LATTICEDOMAINTEST_H_ +#define MANTID_API_LATTICEDOMAINTEST_H_ + +#include <cxxtest/TestSuite.h> + +#include "MantidAPI/LatticeDomain.h" +#include "MantidKernel/Exception.h" + +using Mantid::API::LatticeDomain; +using Mantid::Kernel::V3D; +using Mantid::Kernel::Exception::IndexError; + +using namespace Mantid::API; + +class LatticeDomainTest : 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 LatticeDomainTest *createSuite() { return new LatticeDomainTest(); } + static void destroySuite(LatticeDomainTest *suite) { delete suite; } + + void testConstruction() { + std::vector<V3D> hkls; + hkls.push_back(V3D(1, 1, 1)); + hkls.push_back(V3D(2, 1, 0)); + hkls.push_back(V3D(0, 0, 1)); + + TS_ASSERT_THROWS_NOTHING(LatticeDomain domain(hkls)); + + std::vector<V3D> empty; + TS_ASSERT_THROWS_NOTHING(LatticeDomain domain(empty)); + } + + void testSize() { + std::vector<V3D> hkls; + hkls.push_back(V3D(1, 1, 1)); + hkls.push_back(V3D(2, 1, 0)); + hkls.push_back(V3D(0, 0, 1)); + + LatticeDomain domain(hkls); + + TS_ASSERT_EQUALS(domain.size(), hkls.size()); + } + + void testAccess() { + std::vector<V3D> hkls; + hkls.push_back(V3D(1, 1, 1)); + hkls.push_back(V3D(2, 1, 0)); + hkls.push_back(V3D(0, 0, 1)); + + LatticeDomain domain(hkls); + + TS_ASSERT_THROWS_NOTHING(domain[0]); + TS_ASSERT_THROWS_NOTHING(domain[1]); + TS_ASSERT_THROWS_NOTHING(domain[2]); + + TS_ASSERT_THROWS(domain[3], IndexError) + } +}; + +#endif /* MANTID_API_LATTICEDOMAINTEST_H_ */ diff --git a/Code/Mantid/Framework/Crystal/src/SaveHKL.cpp b/Code/Mantid/Framework/Crystal/src/SaveHKL.cpp index 4abaee69a3a9eb0aa97db33a14e7c5e26a5b309b..0055f7fd97b526cda586c2491194610b44dd9174 100644 --- a/Code/Mantid/Framework/Crystal/src/SaveHKL.cpp +++ b/Code/Mantid/Framework/Crystal/src/SaveHKL.cpp @@ -283,7 +283,8 @@ void SaveHKL::exec() { std::string bankName = p.getBankName(); int nCols, nRows; sizeBanks(bankName, nCols, nRows); - if (widthBorder != EMPTY_INT() && + // peaks with detectorID=-1 are from LoadHKL + if (widthBorder != EMPTY_INT() && p.getDetectorID() != -1 && (p.getCol() < widthBorder || p.getRow() < widthBorder || p.getCol() > (nCols - widthBorder) || p.getRow() > (nRows - widthBorder))){ diff --git a/Code/Mantid/Framework/CurveFitting/CMakeLists.txt b/Code/Mantid/Framework/CurveFitting/CMakeLists.txt index 987301cf78bcd134fa4d89bb421996bfaa8c2a63..c60bcf76181e2c4767500287ab874c7fbb1388c7 100644 --- a/Code/Mantid/Framework/CurveFitting/CMakeLists.txt +++ b/Code/Mantid/Framework/CurveFitting/CMakeLists.txt @@ -24,6 +24,7 @@ set ( SRC_FILES src/CostFuncFitting.cpp src/CostFuncLeastSquares.cpp src/CostFuncRwp.cpp + src/CostFuncUnweightedLeastSquares.cpp src/CubicSpline.cpp src/DampingMinimizer.cpp src/DeltaFunction.cpp @@ -53,6 +54,8 @@ set ( SRC_FILES src/GaussianComptonProfile.cpp src/GramCharlierComptonProfile.cpp src/IkedaCarpenterPV.cpp + src/LatticeDomainCreator.cpp + src/LatticeFunction.cpp src/LeBailFit.cpp src/LeBailFunction.cpp src/LevenbergMarquardtMDMinimizer.cpp @@ -135,6 +138,7 @@ set ( INC_FILES inc/MantidCurveFitting/CostFuncFitting.h inc/MantidCurveFitting/CostFuncLeastSquares.h inc/MantidCurveFitting/CostFuncRwp.h + inc/MantidCurveFitting/CostFuncUnweightedLeastSquares.h inc/MantidCurveFitting/CubicSpline.h inc/MantidCurveFitting/DampingMinimizer.h inc/MantidCurveFitting/DeltaFunction.h @@ -144,7 +148,7 @@ set ( INC_FILES inc/MantidCurveFitting/DllConfig.h inc/MantidCurveFitting/DynamicKuboToyabe.h inc/MantidCurveFitting/EndErfc.h - inc/MantidCurveFitting/EstimatePeakErrors.h + inc/MantidCurveFitting/EstimatePeakErrors.h inc/MantidCurveFitting/ExpDecay.h inc/MantidCurveFitting/ExpDecayMuon.h inc/MantidCurveFitting/ExpDecayOsc.h @@ -168,6 +172,8 @@ set ( INC_FILES inc/MantidCurveFitting/GramCharlierComptonProfile.h inc/MantidCurveFitting/IkedaCarpenterPV.h inc/MantidCurveFitting/Jacobian.h + inc/MantidCurveFitting/LatticeDomainCreator.h + inc/MantidCurveFitting/LatticeFunction.h inc/MantidCurveFitting/LeBailFit.h inc/MantidCurveFitting/LeBailFunction.h inc/MantidCurveFitting/LevenbergMarquardtMDMinimizer.h @@ -244,6 +250,7 @@ set ( TEST_FILES ConvertToYSpaceTest.h ConvolutionTest.h ConvolveWorkspacesTest.h + CostFuncUnweightedLeastSquaresTest.h CubicSplineTest.h DampingMinimizerTest.h DeltaFunctionTest.h @@ -251,7 +258,7 @@ set ( TEST_FILES DiffSphereTest.h DynamicKuboToyabeTest.h EndErfcTest.h - EstimatePeakErrorsTest.h + EstimatePeakErrorsTest.h ExpDecayMuonTest.h ExpDecayOscTest.h ExpDecayTest.h @@ -274,6 +281,8 @@ set ( TEST_FILES IPeakFunctionCentreParameterNameTest.h IPeakFunctionIntensityTest.h IkedaCarpenterPVTest.h + LatticeDomainCreatorTest.h + LatticeFunctionTest.h LeBailFitTest.h LeBailFunctionTest.h LeastSquaresTest.h diff --git a/Code/Mantid/Framework/CurveFitting/inc/MantidCurveFitting/CostFuncUnweightedLeastSquares.h b/Code/Mantid/Framework/CurveFitting/inc/MantidCurveFitting/CostFuncUnweightedLeastSquares.h new file mode 100644 index 0000000000000000000000000000000000000000..17fc016bb426d6e2c37c534c89f796124d3bb7a5 --- /dev/null +++ b/Code/Mantid/Framework/CurveFitting/inc/MantidCurveFitting/CostFuncUnweightedLeastSquares.h @@ -0,0 +1,59 @@ +#ifndef MANTID_CURVEFITTING_COSTFUNCUNWEIGHTEDLEASTSQUARES_H_ +#define MANTID_CURVEFITTING_COSTFUNCUNWEIGHTEDLEASTSQUARES_H_ + +#include "MantidKernel/System.h" +#include "MantidCurveFitting/CostFuncLeastSquares.h" + +namespace Mantid { +namespace CurveFitting { + +/** @class CostFuncUnweightedLeastSquares + * + In contrast to CostFuncLeastSquares, this variant of the cost function + assumes that there are no weights attached to the values, so all observations + will have unit weights. + + The covariance matrix is multiplied with the variance of the residuals. + + @author Michael Wedel, Paul Scherrer Institut - SINQ + @date 03/03/2015 + + Copyright © 2015 PSI-NXMM + + 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 CostFuncUnweightedLeastSquares : public CostFuncLeastSquares { +public: + CostFuncUnweightedLeastSquares(); + virtual ~CostFuncUnweightedLeastSquares() {} + + std::string name() const { return "Unweighted least squares"; } + std::string shortName() const { return "Chi-sq-unw."; } + +protected: + void calActiveCovarianceMatrix(GSLMatrix &covar, double epsrel); + std::vector<double> getFitWeights(API::FunctionValues_sptr values) const; + + double getResidualVariance() const; +}; + +} // namespace CurveFitting +} // namespace Mantid + +#endif /* MANTID_CURVEFITTING_COSTFUNCUNWEIGHTEDLEASTSQUARES_H_ */ diff --git a/Code/Mantid/Framework/CurveFitting/inc/MantidCurveFitting/LatticeDomainCreator.h b/Code/Mantid/Framework/CurveFitting/inc/MantidCurveFitting/LatticeDomainCreator.h new file mode 100644 index 0000000000000000000000000000000000000000..290a8347fd0e6cd13fc79731ed575fc140879a71 --- /dev/null +++ b/Code/Mantid/Framework/CurveFitting/inc/MantidCurveFitting/LatticeDomainCreator.h @@ -0,0 +1,81 @@ +#ifndef MANTID_CURVEFITTING_LATTICEDOMAINCREATOR_H_ +#define MANTID_CURVEFITTING_LATTICEDOMAINCREATOR_H_ + +#include "MantidKernel/System.h" +#include "MantidAPI/IDomainCreator.h" +#include "MantidAPI/Workspace.h" +#include "MantidAPI/IPeaksWorkspace.h" + +namespace Mantid { +namespace CurveFitting { + +/** LatticeDomainCreator + + Domain creator for LatticeDomain, which processes IPeaksWorkspace or + an ITableWorkspace with certain columns (HKL, d). + + @author Michael Wedel, Paul Scherrer Institut - SINQ + @date 15/04/2015 + + Copyright © 2015 PSI-NXMM + + 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 LatticeDomainCreator : public API::IDomainCreator { +public: + LatticeDomainCreator(Kernel::IPropertyManager *manager, + const std::string &workspacePropertyName, + DomainType domainType = Simple); + + virtual ~LatticeDomainCreator() {} + + virtual void createDomain(boost::shared_ptr<API::FunctionDomain> &domain, + boost::shared_ptr<API::FunctionValues> &values, + size_t i0); + + virtual API::Workspace_sptr createOutputWorkspace( + const std::string &baseName, + API::IFunction_sptr function, + boost::shared_ptr<API::FunctionDomain> domain, + boost::shared_ptr<API::FunctionValues> values, + const std::string &outputWorkspacePropertyName); + + virtual size_t getDomainSize() const; + +protected: + void setWorkspaceFromPropertyManager(); + void + createDomainFromPeaksWorkspace(const API::IPeaksWorkspace_sptr &workspace, + boost::shared_ptr<API::FunctionDomain> &domain, + boost::shared_ptr<API::FunctionValues> &values, + size_t i0); + + void createDomainFromPeakTable(const API::ITableWorkspace_sptr &workspace, + boost::shared_ptr<API::FunctionDomain> &domain, + boost::shared_ptr<API::FunctionValues> &values, + size_t i0); + + std::string m_workspacePropertyName; + API::Workspace_sptr m_workspace; +}; + +} // namespace CurveFitting +} // namespace Mantid + +#endif /* MANTID_CURVEFITTING_LATTICEDOMAINCREATOR_H_ */ diff --git a/Code/Mantid/Framework/CurveFitting/inc/MantidCurveFitting/LatticeFunction.h b/Code/Mantid/Framework/CurveFitting/inc/MantidCurveFitting/LatticeFunction.h new file mode 100644 index 0000000000000000000000000000000000000000..dda2fcf1d8358f0e60023c855a4eb5080a758447 --- /dev/null +++ b/Code/Mantid/Framework/CurveFitting/inc/MantidCurveFitting/LatticeFunction.h @@ -0,0 +1,72 @@ +#ifndef MANTID_CURVEFITTING_LATTICEFUNCTION_H_ +#define MANTID_CURVEFITTING_LATTICEFUNCTION_H_ + +#include "MantidKernel/System.h" +#include "MantidAPI/ILatticeFunction.h" + +#include "MantidCurveFitting/PawleyFunction.h" + +namespace Mantid { +namespace CurveFitting { + +/** LatticeFunction + + LatticeFunction implements API::ILatticeFunction. Internally it uses + a PawleyParameterFunction to expose appropriate lattice parameters for each + crystal system. + + For each HKL in the supplied LatticeDomain, the function method calculates + the d-value using the UnitCell that is generated from the function parameters. + + @author Michael Wedel, Paul Scherrer Institut - SINQ + @date 15/04/2015 + + Copyright © 2015 PSI-NXMM + + 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 LatticeFunction : public API::ILatticeFunction { +public: + LatticeFunction(); + virtual ~LatticeFunction() {} + + std::string name() const { return "LatticeFunction"; } + + void functionLattice(const API::LatticeDomain &latticeDomain, + API::FunctionValues &values) const; + + void setCrystalSystem(const std::string &crystalSystem); + void setUnitCell(const std::string &unitCellString); + void setUnitCell(const Geometry::UnitCell &unitCell); + Geometry::UnitCell getUnitCell() const; + +protected: + void init(); + void beforeDecoratedFunctionSet(const API::IFunction_sptr &fn); + +private: + PawleyParameterFunction_sptr m_cellParameters; +}; + +typedef boost::shared_ptr<LatticeFunction> LatticeFunction_sptr; + +} // namespace CurveFitting +} // namespace Mantid + +#endif /* MANTID_CURVEFITTING_LATTICEFUNCTION_H_ */ diff --git a/Code/Mantid/Framework/CurveFitting/inc/MantidCurveFitting/PawleyFit.h b/Code/Mantid/Framework/CurveFitting/inc/MantidCurveFitting/PawleyFit.h index 4c00d9b1c35c99de7bb46b96796ea4400fc13f58..455df893d86d5afafc4a473e538a13125d3b0cff 100644 --- a/Code/Mantid/Framework/CurveFitting/inc/MantidCurveFitting/PawleyFit.h +++ b/Code/Mantid/Framework/CurveFitting/inc/MantidCurveFitting/PawleyFit.h @@ -9,7 +9,27 @@ namespace Mantid { namespace CurveFitting { -/** PawleyFit +/** @class V3DFromHKLColumnExtractor + + Small helper class to extract HKLs as V3D from table columns. The table + column can either store V3D directly, or a string with various separators: + , ; [ ] (space) + +*/ +struct DLLExport V3DFromHKLColumnExtractor { + Kernel::V3D operator()(const API::Column_const_sptr &hklColumn, + size_t i) const; + +protected: + Kernel::V3D getHKLFromV3DColumn(const API::Column_const_sptr &hklColumn, + size_t i) const; + Kernel::V3D getHKLFromStringColumn(const API::Column_const_sptr &hklColumn, + size_t i) const; + + Kernel::V3D getHKLFromString(const std::string &hklString) const; +}; + +/** @class PawleyFit This algorithm uses the Pawley-method to refine lattice parameters using a powder diffractogram and a list of unique Miller indices. From the initial @@ -59,10 +79,6 @@ protected: const Kernel::Unit_sptr &unit, double startX, double endX) const; - Kernel::V3D getHKLFromColumn(size_t i, - const API::Column_const_sptr &hklColumn) const; - Kernel::V3D getHkl(const std::string &hklString) const; - API::ITableWorkspace_sptr getLatticeFromFunction(const PawleyFunction_sptr &pawleyFn) const; API::ITableWorkspace_sptr diff --git a/Code/Mantid/Framework/CurveFitting/inc/MantidCurveFitting/PawleyFunction.h b/Code/Mantid/Framework/CurveFitting/inc/MantidCurveFitting/PawleyFunction.h index a015b74a52fc59377592ae5cae5a15b5f3edd5c9..bd042c8a4cbd02c7da0ce01cc5eeb58b22022ecc 100644 --- a/Code/Mantid/Framework/CurveFitting/inc/MantidCurveFitting/PawleyFunction.h +++ b/Code/Mantid/Framework/CurveFitting/inc/MantidCurveFitting/PawleyFunction.h @@ -62,6 +62,10 @@ protected: void createCrystalSystemParameters( Geometry::PointGroup::CrystalSystem crystalSystem); + + void addLengthConstraint(const std::string ¶meterName); + void addAngleConstraint(const std::string ¶meterName); + void setCenterParameterNameFromFunction( const API::IPeakFunction_sptr &profileFunction); diff --git a/Code/Mantid/Framework/CurveFitting/src/CostFuncUnweightedLeastSquares.cpp b/Code/Mantid/Framework/CurveFitting/src/CostFuncUnweightedLeastSquares.cpp new file mode 100644 index 0000000000000000000000000000000000000000..bf6bd0770dca89b13150ce6021ffd74d1af7923c --- /dev/null +++ b/Code/Mantid/Framework/CurveFitting/src/CostFuncUnweightedLeastSquares.cpp @@ -0,0 +1,85 @@ +#include "MantidCurveFitting/CostFuncUnweightedLeastSquares.h" + +#include "MantidKernel/Logger.h" +#include <iomanip> +#include <cmath> + +namespace Mantid { +namespace CurveFitting { + +namespace { +/// static logger +Kernel::Logger g_log("CostFuncUnweightedLeastSquares"); +} + +DECLARE_COSTFUNCTION(CostFuncUnweightedLeastSquares, Unweighted least squares) + +CostFuncUnweightedLeastSquares::CostFuncUnweightedLeastSquares() + : CostFuncLeastSquares() {} + +void CostFuncUnweightedLeastSquares::calActiveCovarianceMatrix(GSLMatrix &covar, + double epsrel) { + CostFuncLeastSquares::calActiveCovarianceMatrix(covar, epsrel); + + double variance = getResidualVariance(); + covar *= variance; + + if (g_log.is(Kernel::Logger::Priority::PRIO_INFORMATION)) { + g_log.information() << "== Final covariance matrix (H^-1) ==" << std::endl; + + std::ios::fmtflags prevState = g_log.information().flags(); + g_log.information() << std::left << std::fixed; + + for (size_t i = 0; i < covar.size1(); ++i) { + for (size_t j = 0; j < covar.size2(); ++j) { + g_log.information() << std::setw(10); + g_log.information() << covar.get(i, j) << " "; + } + g_log.information() << std::endl; + } + g_log.information().flags(prevState); + } +} + +/// Return unit weights for all data points. +std::vector<double> CostFuncUnweightedLeastSquares::getFitWeights( + API::FunctionValues_sptr values) const { + return std::vector<double>(values->size(), 1.0); +} + +/// Calculates the residual variance from the internally stored FunctionValues. +double CostFuncUnweightedLeastSquares::getResidualVariance() const { + if (!m_values || m_values->size() == 0) { + return 0; + } + + double sum = 0.0; + for (size_t i = 0; i < m_values->size(); ++i) { + double difference = m_values->getCalculated(i) - m_values->getFitData(i); + sum += difference * difference; + } + + double degreesOfFreedom = static_cast<double>(m_values->size() - nParams()); + double residualVariance = sum / degreesOfFreedom; + + if (g_log.is(Kernel::Logger::Priority::PRIO_INFORMATION)) { + g_log.information() << "== Statistics of residuals ==" << std::endl; + std::ios::fmtflags prevState = g_log.information().flags(); + g_log.information() << std::left << std::fixed << std::setw(10); + g_log.information() << "Residual sum of squares: " << sum << std::endl; + g_log.information() << "Residual variance: " << residualVariance + << std::endl; + g_log.information() << "Residual standard deviation: " + << sqrt(residualVariance) << std::endl; + g_log.information() << "Degrees of freedom: " + << static_cast<size_t>(degreesOfFreedom) << std::endl; + g_log.information() << "Number of observations: " << m_values->size() + << std::endl; + g_log.information().flags(prevState); + } + + return residualVariance; +} + +} // namespace CurveFitting +} // namespace Mantid diff --git a/Code/Mantid/Framework/CurveFitting/src/Fit.cpp b/Code/Mantid/Framework/CurveFitting/src/Fit.cpp index 691c124409b3ae99a5e9cba7499b0da0d525bcd7..0ec88050d9ac3cd29d04d9fdd211aa94e46dcf44 100644 --- a/Code/Mantid/Framework/CurveFitting/src/Fit.cpp +++ b/Code/Mantid/Framework/CurveFitting/src/Fit.cpp @@ -8,6 +8,7 @@ #include "MantidCurveFitting/MultiDomainCreator.h" #include "MantidCurveFitting/Convolution.h" #include "MantidCurveFitting/SeqDomainSpectrumCreator.h" +#include "MantidCurveFitting/LatticeDomainCreator.h" #include "MantidAPI/FuncMinimizerFactory.h" #include "MantidAPI/IFuncMinimizer.h" @@ -22,6 +23,7 @@ #include "MantidAPI/IFunctionMW.h" #include "MantidAPI/IFunctionMD.h" #include "MantidAPI/IFunction1DSpectrum.h" +#include "MantidAPI/ILatticeFunction.h" #include "MantidAPI/MultiDomainFunction.h" #include "MantidAPI/ITableWorkspace.h" @@ -156,23 +158,29 @@ void Fit::addWorkspace(const std::string &workspacePropertyName, IDomainCreator *creator = NULL; setDomainType(); - if (boost::dynamic_pointer_cast<const API::MatrixWorkspace>(ws) && - !boost::dynamic_pointer_cast<API::IFunctionMD>(fun)) { - /* IFunction1DSpectrum needs a different domain creator. If a function - * implements that type, we need to react appropriately at this point. - * Otherwise, the default creator FitMW is used. - */ - if (boost::dynamic_pointer_cast<API::IFunction1DSpectrum>(fun)) { - creator = new SeqDomainSpectrumCreator(this, workspacePropertyName); - } else { - creator = new FitMW(this, workspacePropertyName, m_domainType); - } + // ILatticeFunction requires API::LatticeDomain. + if (boost::dynamic_pointer_cast<API::ILatticeFunction>(fun)) { + creator = new LatticeDomainCreator(this, workspacePropertyName); } else { - try { - creator = API::DomainCreatorFactory::Instance().createDomainCreator( - "FitMD", this, workspacePropertyName, m_domainType); - } catch (Kernel::Exception::NotFoundError &) { - throw std::invalid_argument("Unsupported workspace type" + ws->id()); + if (boost::dynamic_pointer_cast<const API::MatrixWorkspace>(ws) && + !boost::dynamic_pointer_cast<API::IFunctionMD>(fun)) { + /* IFunction1DSpectrum needs a different domain creator. If a function + * implements that type, we need to react appropriately at this point. + * Otherwise, the default creator FitMW is used. + */ + if (boost::dynamic_pointer_cast<API::IFunction1DSpectrum>(fun)) { + creator = new SeqDomainSpectrumCreator(this, workspacePropertyName); + } else { + creator = new FitMW(this, workspacePropertyName, m_domainType); + } + } else { + try { + creator = API::DomainCreatorFactory::Instance().createDomainCreator( + "FitMD", this, workspacePropertyName, m_domainType); + } + catch (Kernel::Exception::NotFoundError &) { + throw std::invalid_argument("Unsupported workspace type" + ws->id()); + } } } @@ -227,25 +235,35 @@ void Fit::addWorkspaces() { const std::string workspacePropertyName = (**prop).name(); API::Workspace_const_sptr ws = getProperty(workspacePropertyName); IDomainCreator *creator = NULL; - if (boost::dynamic_pointer_cast<const API::MatrixWorkspace>(ws) && - !boost::dynamic_pointer_cast<API::IFunctionMD>(m_function)) { - /* IFunction1DSpectrum needs a different domain creator. If a function - * implements that type, we need to react appropriately at this point. - * Otherwise, the default creator FitMW is used. - */ - if (boost::dynamic_pointer_cast<API::IFunction1DSpectrum>(m_function)) { - creator = new SeqDomainSpectrumCreator(this, workspacePropertyName); - } else { - creator = new FitMW(this, workspacePropertyName, m_domainType); - } - } else { // don't know what to do with this workspace - try { - creator = API::DomainCreatorFactory::Instance().createDomainCreator( - "FitMD", this, workspacePropertyName, m_domainType); - } catch (Kernel::Exception::NotFoundError &) { - throw std::invalid_argument("Unsupported workspace type" + ws->id()); + + // ILatticeFunction requires API::LatticeDomain. + if (boost::dynamic_pointer_cast<API::ILatticeFunction>(m_function)) { + creator = new LatticeDomainCreator(this, workspacePropertyName); + } else { + if (boost::dynamic_pointer_cast<const API::MatrixWorkspace>(ws) && + !boost::dynamic_pointer_cast<API::IFunctionMD>(m_function)) { + /* IFunction1DSpectrum needs a different domain creator. If a function + * implements that type, we need to react appropriately at this point. + * Otherwise, the default creator FitMW is used. + */ + if (boost::dynamic_pointer_cast<API::IFunction1DSpectrum>( + m_function)) { + creator = new SeqDomainSpectrumCreator(this, workspacePropertyName); + } else { + creator = new FitMW(this, workspacePropertyName, m_domainType); + } + } else { // don't know what to do with this workspace + try { + creator = API::DomainCreatorFactory::Instance().createDomainCreator( + "FitMD", this, workspacePropertyName, m_domainType); + } + catch (Kernel::Exception::NotFoundError &) { + throw std::invalid_argument("Unsupported workspace type" + + ws->id()); + } } } + const size_t n = std::string("InputWorkspace").size(); const std::string suffix = (workspacePropertyName.size() > n) ? workspacePropertyName.substr(n) @@ -294,7 +312,7 @@ void Fit::init() { "the fitting function."); declareProperty("Constraints", "", Kernel::Direction::Input); getPointerToProperty("Constraints")->setDocumentation("List of constraints"); - auto mustBePositive = boost::shared_ptr<Kernel::BoundedValidator<int>>( + auto mustBePositive = boost::shared_ptr<Kernel::BoundedValidator<int> >( new Kernel::BoundedValidator<int>()); mustBePositive->setLower(0); declareProperty( diff --git a/Code/Mantid/Framework/CurveFitting/src/LatticeDomainCreator.cpp b/Code/Mantid/Framework/CurveFitting/src/LatticeDomainCreator.cpp new file mode 100644 index 0000000000000000000000000000000000000000..e8a6895f00b48773059704c6253d8e8bb899ef49 --- /dev/null +++ b/Code/Mantid/Framework/CurveFitting/src/LatticeDomainCreator.cpp @@ -0,0 +1,286 @@ +#include "MantidCurveFitting/LatticeDomainCreator.h" + +#include "MantidAPI/ILatticeFunction.h" +#include "MantidAPI/IPeak.h" +#include "MantidAPI/LatticeDomain.h" +#include "MantidAPI/TableRow.h" +#include "MantidAPI/WorkspaceFactory.h" + +#include "MantidDataObjects/Peak.h" +#include "MantidCurveFitting/PawleyFit.h" + +namespace Mantid { +namespace CurveFitting { + +using namespace API; +using namespace Kernel; +using namespace DataObjects; + +/// Constructor +LatticeDomainCreator::LatticeDomainCreator( + Kernel::IPropertyManager *manager, const std::string &workspacePropertyName, + API::IDomainCreator::DomainType domainType) + : IDomainCreator(manager, + std::vector<std::string>(1, workspacePropertyName), + domainType), + m_workspace() { + m_workspacePropertyName = m_workspacePropertyNames.front(); +} + +/** + * Creates a LatticeDomain from the assigned Workspace + * + * This function uses the internally stored workspace which can either be an + * IPeaksWorkspace or a TableWorkspace with HKL and d-values to create a + * LatticeDomain. It also assigns fit data to the supplied value object. If + * null-pointers are passed, new objects are allocated. + * + * Reflections where HKL is (000) are ignored, so the final domain size may + * be smaller than the number of rows in the input workspace. + * + * @param domain :: Pointer to outgoing FunctionDomain instance. + * @param values :: Pointer to outgoing FunctionValues object. + * @param i0 :: Size offset for values object if it already contains data. + */ +void LatticeDomainCreator::createDomain( + boost::shared_ptr<API::FunctionDomain> &domain, + boost::shared_ptr<API::FunctionValues> &values, size_t i0) { + setWorkspaceFromPropertyManager(); + + API::IPeaksWorkspace_sptr peaksWorkspace = + boost::dynamic_pointer_cast<IPeaksWorkspace>(m_workspace); + if (peaksWorkspace) { + createDomainFromPeaksWorkspace(peaksWorkspace, domain, values, i0); + } else { + API::ITableWorkspace_sptr tableWorkspace = + boost::dynamic_pointer_cast<ITableWorkspace>(m_workspace); + if (tableWorkspace) { + createDomainFromPeakTable(tableWorkspace, domain, values, i0); + } + } +} + +/** + * Creates an output workspace from calculated and observed values + * + * This method creates a table workspace for an ILatticeFunction, containing + * observed and calculated d-values for each HKL, as well as the difference + * between those two values. + * + * @param baseName :: Basename for output workspace. + * @param function :: An ILatticeFunction + * @param domain :: Pointer to LatticeDomain instance. + * @param values :: Pointer to FunctionValues instance. + * @param outputWorkspacePropertyName :: Name of output workspace property. + * @return TableWorkspace with calculated and observed d-values. + */ +Workspace_sptr LatticeDomainCreator::createOutputWorkspace( + const std::string &baseName, IFunction_sptr function, + boost::shared_ptr<FunctionDomain> domain, + boost::shared_ptr<FunctionValues> values, + const std::string &outputWorkspacePropertyName) { + + boost::shared_ptr<LatticeDomain> latticeDomain = + boost::dynamic_pointer_cast<LatticeDomain>(domain); + if (!latticeDomain) { + throw std::invalid_argument("LatticeDomain is required."); + } + + ILatticeFunction_sptr latticeFunction = + boost::dynamic_pointer_cast<ILatticeFunction>(function); + if (!latticeFunction) { + throw std::invalid_argument( + "LatticeDomainCreator can only process ILatticeFunction."); + } + + // Calculate function values again. + latticeFunction->functionLattice(*latticeDomain, *values); + + ITableWorkspace_sptr tableWorkspace = + WorkspaceFactory::Instance().createTable(); + + if (tableWorkspace) { + tableWorkspace->addColumn("V3D", "HKL"); + tableWorkspace->addColumn("double", "d(obs)"); + tableWorkspace->addColumn("double", "d(calc)"); + tableWorkspace->addColumn("double", "d(obs) - d(calc)"); + + for (size_t i = 0; i < values->size(); ++i) { + double dObs = values->getFitData(i); + double dCalc = values->getCalculated(i); + + TableRow newRow = tableWorkspace->appendRow(); + newRow << (*latticeDomain)[i] << dObs << dCalc << dObs - dCalc; + } + } + + if (m_manager && !outputWorkspacePropertyName.empty()) { + declareProperty( + new WorkspaceProperty<ITableWorkspace>(outputWorkspacePropertyName, "", + Kernel::Direction::Output), + "Result workspace"); + + m_manager->setPropertyValue(outputWorkspacePropertyName, + baseName + "Workspace"); + m_manager->setProperty(outputWorkspacePropertyName, tableWorkspace); + } + + return tableWorkspace; +} + +size_t LatticeDomainCreator::getDomainSize() const { + API::IPeaksWorkspace_sptr peaksWorkspace = + boost::dynamic_pointer_cast<IPeaksWorkspace>(m_workspace); + if (peaksWorkspace) { + return peaksWorkspace->getNumberPeaks(); + } + + API::ITableWorkspace_sptr tableWorkspace = + boost::dynamic_pointer_cast<ITableWorkspace>(m_workspace); + if (tableWorkspace) { + return tableWorkspace->rowCount(); + } + + return 0; +} + +/// Get the workspace with peak data from the property manager. +void LatticeDomainCreator::setWorkspaceFromPropertyManager() { + if (!m_manager) { + throw std::invalid_argument( + "PropertyManager not set in LatticeDomainCreator."); + } + + try { + m_workspace = m_manager->getProperty(m_workspacePropertyName); + } + catch (Kernel::Exception::NotFoundError) { + throw std::invalid_argument( + "Could not extract workspace from PropertyManager."); + } +} + +/// Creates a LatticeDomain from an IPeaksWorkspace, using HKL and d-values. +void LatticeDomainCreator::createDomainFromPeaksWorkspace( + const API::IPeaksWorkspace_sptr &workspace, + boost::shared_ptr<API::FunctionDomain> &domain, + boost::shared_ptr<API::FunctionValues> &values, size_t i0) { + if (!workspace) { + throw std::invalid_argument( + "This function only works on an IPeaksWorkspace-object."); + } + + size_t peakCount = workspace->getNumberPeaks(); + + if (peakCount < 1) { + throw std::range_error("Cannot create a domain for 0 peaks."); + } + + std::vector<V3D> hkls; + hkls.reserve(peakCount); + + std::vector<double> dSpacings; + dSpacings.reserve(peakCount); + + for (size_t i = 0; i < peakCount; ++i) { + IPeak *currentPeak = workspace->getPeakPtr(static_cast<int>(i)); + V3D hkl = currentPeak->getHKL(); + + if (hkl != V3D(0, 0, 0)) { + hkls.push_back(hkl); + dSpacings.push_back(currentPeak->getDSpacing()); + } + } + + LatticeDomain *latticeDomain = new LatticeDomain(hkls); + domain.reset(latticeDomain); + + if (!values) { + FunctionValues *functionValues = new FunctionValues(*domain); + values.reset(functionValues); + } else { + values->expand(i0 + latticeDomain->size()); + } + + values->setFitData(dSpacings); + + // Set unit weights. + values->setFitWeights(1.0); +} + +/** + * Creates a domain from an ITableWorkspace + * + * This method creates a LatticeDomain from a table workspace that contains two + * columns, HKL and d. HKL can either be a V3D-column or a string column, + * containing three integers separated by space, comma, semi-colon and + * optionally surrounded by []. The d-column can be double or a string that can + * be parsed as a double number. + * + * @param workspace :: ITableWorkspace with format specified above. + * @param domain :: Pointer to outgoing FunctionDomain instance. + * @param values :: Pointer to outgoing FunctionValues object. + * @param i0 :: Size offset for values object if it already contains data. + */ +void LatticeDomainCreator::createDomainFromPeakTable( + const ITableWorkspace_sptr &workspace, + boost::shared_ptr<FunctionDomain> &domain, + boost::shared_ptr<FunctionValues> &values, size_t i0) { + + size_t peakCount = workspace->rowCount(); + + if (peakCount < 1) { + throw std::range_error("Cannot create a domain for 0 peaks."); + } + + try { + Column_const_sptr hklColumn = workspace->getColumn("HKL"); + Column_const_sptr dColumn = workspace->getColumn("d"); + + std::vector<V3D> hkls; + hkls.reserve(peakCount); + + std::vector<double> dSpacings; + dSpacings.reserve(peakCount); + + V3DFromHKLColumnExtractor extractor; + + for (size_t i = 0; i < peakCount; ++i) { + try { + V3D hkl = extractor(hklColumn, i); + + if (hkl != V3D(0, 0, 0)) { + hkls.push_back(hkl); + + double d = (*dColumn)[i]; + dSpacings.push_back(d); + } + } + catch (std::bad_alloc) { + // do nothing. + } + } + + LatticeDomain *latticeDomain = new LatticeDomain(hkls); + domain.reset(latticeDomain); + + if (!values) { + FunctionValues *functionValues = new FunctionValues(*domain); + values.reset(functionValues); + } else { + values->expand(i0 + latticeDomain->size()); + } + + values->setFitData(dSpacings); + + values->setFitWeights(1.0); + } + catch (std::runtime_error) { + // Column does not exist + throw std::runtime_error("Can not process table, the following columns are " + "required: HKL, d."); + } +} + +} // namespace CurveFitting +} // namespace Mantid diff --git a/Code/Mantid/Framework/CurveFitting/src/LatticeFunction.cpp b/Code/Mantid/Framework/CurveFitting/src/LatticeFunction.cpp new file mode 100644 index 0000000000000000000000000000000000000000..895327b1d97f18dcb4252531b56b780828c0a84b --- /dev/null +++ b/Code/Mantid/Framework/CurveFitting/src/LatticeFunction.cpp @@ -0,0 +1,77 @@ +#include "MantidCurveFitting/LatticeFunction.h" +#include "MantidAPI/FunctionFactory.h" +#include "MantidGeometry/Crystal/UnitCell.h" + +namespace Mantid { +namespace CurveFitting { + +using namespace API; +using namespace Geometry; + +DECLARE_FUNCTION(LatticeFunction) + +LatticeFunction::LatticeFunction() : ILatticeFunction(), m_cellParameters() {} + +/// Calculates d-values using the internally stored cell parameters +void LatticeFunction::functionLattice(const LatticeDomain &latticeDomain, + FunctionValues &values) const { + throwIfNoFunctionSet(); + + UnitCell cell = m_cellParameters->getUnitCellFromParameters(); + double zeroShift = m_cellParameters->getParameter("ZeroShift"); + + for (size_t i = 0; i < values.size(); ++i) { + values.setCalculated(i, cell.d(latticeDomain[i]) + zeroShift); + } +} + +/// Assigns the crystal system to the internally stored function. Number of +/// parameters may change after this function call. +void LatticeFunction::setCrystalSystem(const std::string &crystalSystem) { + throwIfNoFunctionSet(); + + m_cellParameters->setAttributeValue("CrystalSystem", crystalSystem); +} + +/// Sets the unit cell parameters from a string that can be parsed by +/// Geometry::strToUnitCell. +void LatticeFunction::setUnitCell(const std::string &unitCellString) { + throwIfNoFunctionSet(); + + m_cellParameters->setParametersFromUnitCell(strToUnitCell(unitCellString)); +} + +/// Sets the unit cell parameters from a UnitCell object. +void LatticeFunction::setUnitCell(const UnitCell &unitCell) { + throwIfNoFunctionSet(); + + m_cellParameters->setParametersFromUnitCell(unitCell); +} + +/// Returns a UnitCell object constructed from the function parameters. +UnitCell LatticeFunction::getUnitCell() const { + throwIfNoFunctionSet(); + + return m_cellParameters->getUnitCellFromParameters(); +} + +/// Sets the decorated function to expose parameters +void LatticeFunction::init() { + setDecoratedFunction("PawleyParameterFunction"); +} + +/// Checks that the decorated function is a PawleyParameterFunction. +void LatticeFunction::beforeDecoratedFunctionSet(const IFunction_sptr &fn) { + PawleyParameterFunction_sptr paramFn = + boost::dynamic_pointer_cast<PawleyParameterFunction>(fn); + + if (!paramFn) { + throw std::invalid_argument( + "LatticeFunction can only decorate a PawleyParameterFunction."); + } + + m_cellParameters = paramFn; +} + +} // namespace CurveFitting +} // namespace Mantid diff --git a/Code/Mantid/Framework/CurveFitting/src/PawleyFit.cpp b/Code/Mantid/Framework/CurveFitting/src/PawleyFit.cpp index 11a110f20013093857770a0b029f87931656e4a0..e3291e7fb7182c029c049022884139f11368690d 100644 --- a/Code/Mantid/Framework/CurveFitting/src/PawleyFit.cpp +++ b/Code/Mantid/Framework/CurveFitting/src/PawleyFit.cpp @@ -72,6 +72,8 @@ void PawleyFit::addHKLsToFunction(PawleyFunction_sptr &pawleyFn, pawleyFn->clearPeaks(); try { + V3DFromHKLColumnExtractor extractor; + Column_const_sptr hklColumn = tableWs->getColumn("HKL"); Column_const_sptr dColumn = tableWs->getColumn("d"); Column_const_sptr intensityColumn = tableWs->getColumn("Intensity"); @@ -79,7 +81,7 @@ void PawleyFit::addHKLsToFunction(PawleyFunction_sptr &pawleyFn, for (size_t i = 0; i < tableWs->rowCount(); ++i) { try { - V3D hkl = getHKLFromColumn(i, hklColumn); + V3D hkl = extractor(hklColumn, i); double d = (*dColumn)[i]; double center = getTransformedCenter(d, unit); @@ -102,36 +104,6 @@ void PawleyFit::addHKLsToFunction(PawleyFunction_sptr &pawleyFn, } } -/// Tries to extract Miller indices as V3D from column. -V3D PawleyFit::getHKLFromColumn(size_t i, - const Column_const_sptr &hklColumn) const { - if (hklColumn->type() == "V3D") { - return hklColumn->cell<V3D>(i); - } - - return getHkl(hklColumn->cell<std::string>(i)); -} - -/// Try to extract a V3D from the given string with different separators. -V3D PawleyFit::getHkl(const std::string &hklString) const { - auto delimiters = boost::is_any_of(" ,[];"); - - std::string workingCopy = boost::trim_copy_if(hklString, delimiters); - std::vector<std::string> indicesStr; - boost::split(indicesStr, workingCopy, delimiters); - - if (indicesStr.size() != 3) { - throw std::invalid_argument("Input string cannot be parsed as HKL."); - } - - V3D hkl; - hkl.setX(boost::lexical_cast<double>(indicesStr[0])); - hkl.setY(boost::lexical_cast<double>(indicesStr[1])); - hkl.setZ(boost::lexical_cast<double>(indicesStr[2])); - - return hkl; -} - /// Creates a table containing the cell parameters stored in the supplied /// function. ITableWorkspace_sptr @@ -401,5 +373,49 @@ void PawleyFit::exec() { setProperty("ReducedChiSquare", chiSquare); } +/// Tries to extract Miller indices as V3D from column. +V3D V3DFromHKLColumnExtractor::operator()(const Column_const_sptr &hklColumn, + size_t i) const { + if (hklColumn->type() == "V3D") { + return getHKLFromV3DColumn(hklColumn, i); + } + + return getHKLFromStringColumn(hklColumn, i); +} + +/// Returns the i-th cell of a V3D column. +V3D V3DFromHKLColumnExtractor::getHKLFromV3DColumn( + const Column_const_sptr &hklColumn, size_t i) const { + return hklColumn->cell<V3D>(i); +} + +/// Pass the cell value as string to getHKLFromString. +V3D V3DFromHKLColumnExtractor::getHKLFromStringColumn( + const Column_const_sptr &hklColumn, size_t i) const { + + return getHKLFromString(hklColumn->cell<std::string>(i)); +} + +/// Try to extract a V3D from the given string with different separators. +V3D V3DFromHKLColumnExtractor::getHKLFromString(const std::string &hklString) + const { + auto delimiters = boost::is_any_of(" ,[];"); + + std::string workingCopy = boost::trim_copy_if(hklString, delimiters); + std::vector<std::string> indicesStr; + boost::split(indicesStr, workingCopy, delimiters); + + if (indicesStr.size() != 3) { + throw std::invalid_argument("Input string cannot be parsed as HKL."); + } + + V3D hkl; + hkl.setX(boost::lexical_cast<double>(indicesStr[0])); + hkl.setY(boost::lexical_cast<double>(indicesStr[1])); + hkl.setZ(boost::lexical_cast<double>(indicesStr[2])); + + return hkl; +} + } // namespace CurveFitting } // namespace Mantid diff --git a/Code/Mantid/Framework/CurveFitting/src/PawleyFunction.cpp b/Code/Mantid/Framework/CurveFitting/src/PawleyFunction.cpp index 781e67b9c6325c37a1f27bebd12a40e468edcca5..01230f49b7e3521510d78639b44a36b90d0699eb 100644 --- a/Code/Mantid/Framework/CurveFitting/src/PawleyFunction.cpp +++ b/Code/Mantid/Framework/CurveFitting/src/PawleyFunction.cpp @@ -1,6 +1,9 @@ #include "MantidCurveFitting/PawleyFunction.h" #include "MantidAPI/FunctionFactory.h" + +#include "MantidCurveFitting/BoundaryConstraint.h" + #include "MantidKernel/UnitConversion.h" #include "MantidKernel/UnitFactory.h" @@ -173,7 +176,8 @@ void PawleyParameterFunction::setProfileFunction( * This method takes the name of a crystal system (case insensitive) and stores * it. Furthermore it creates the necessary parameters, which means that after * calling this function, PawleyParameterFunction potentially exposes a - * different number of parameters. + * different number of parameters. The parameters are constrained to physically + * meaningful values (angles between 0 and 180 degrees, cell edges above 0). * * @param crystalSystem :: Crystal system, case insensitive. */ @@ -212,30 +216,43 @@ void PawleyParameterFunction::createCrystalSystemParameters( switch (crystalSystem) { case PointGroup::Cubic: declareParameter("a", 1.0); + addLengthConstraint("a"); break; case PointGroup::Hexagonal: case PointGroup::Tetragonal: declareParameter("a", 1.0); declareParameter("c", 1.0); + addLengthConstraint("a"); + addLengthConstraint("c"); break; case PointGroup::Orthorhombic: declareParameter("a", 1.0); declareParameter("b", 1.0); declareParameter("c", 1.0); + addLengthConstraint("a"); + addLengthConstraint("b"); + addLengthConstraint("c"); break; case PointGroup::Monoclinic: declareParameter("a", 1.0); declareParameter("b", 1.0); declareParameter("c", 1.0); + addLengthConstraint("a"); + addLengthConstraint("b"); + addLengthConstraint("c"); + declareParameter("Beta", 90.0); + addAngleConstraint("Beta"); break; case PointGroup::Trigonal: declareParameter("a", 1.0); declareParameter("Alpha", 90.0); + addLengthConstraint("a"); + addAngleConstraint("Alpha"); break; default: @@ -243,16 +260,40 @@ void PawleyParameterFunction::createCrystalSystemParameters( declareParameter("a", 1.0); declareParameter("b", 1.0); declareParameter("c", 1.0); + addLengthConstraint("a"); + addLengthConstraint("b"); + addLengthConstraint("c"); declareParameter("Alpha", 90.0); declareParameter("Beta", 90.0); declareParameter("Gamma", 90.0); + addAngleConstraint("Alpha"); + addAngleConstraint("Beta"); + addAngleConstraint("Gamma"); break; } declareParameter("ZeroShift", 0.0); } +/// Adds a default constraint so that cell edge lengths can not be less than 0. +void +PawleyParameterFunction::addLengthConstraint(const std::string ¶meterName) { + BoundaryConstraint *cellEdgeConstraint = + new BoundaryConstraint(this, parameterName, 0.0, true); + cellEdgeConstraint->setPenaltyFactor(1e12); + addConstraint(cellEdgeConstraint); +} + +/// Adds a default constraint so cell angles are in the range 0 to 180. +void +PawleyParameterFunction::addAngleConstraint(const std::string ¶meterName) { + BoundaryConstraint *cellAngleConstraint = + new BoundaryConstraint(this, parameterName, 0.0, 180.0, true); + cellAngleConstraint->setPenaltyFactor(1e12); + addConstraint(cellAngleConstraint); +} + /// Tries to extract and store the center parameter name from the function. void PawleyParameterFunction::setCenterParameterNameFromFunction( const IPeakFunction_sptr &profileFunction) { diff --git a/Code/Mantid/Framework/CurveFitting/test/CostFuncUnweightedLeastSquaresTest.h b/Code/Mantid/Framework/CurveFitting/test/CostFuncUnweightedLeastSquaresTest.h new file mode 100644 index 0000000000000000000000000000000000000000..aaff2f3e849b65ef7c289b95cb94cd6d0c185777 --- /dev/null +++ b/Code/Mantid/Framework/CurveFitting/test/CostFuncUnweightedLeastSquaresTest.h @@ -0,0 +1,84 @@ +#ifndef MANTID_CURVEFITTING_COSTFUNCUNWEIGHTEDLEASTSQUARESTEST_H_ +#define MANTID_CURVEFITTING_COSTFUNCUNWEIGHTEDLEASTSQUARESTEST_H_ + +#include <cxxtest/TestSuite.h> +#include "MantidAPI/FunctionDomain1D.h" +#include "MantidAPI/FunctionFactory.h" + +#include "MantidCurveFitting/CostFuncUnweightedLeastSquares.h" + +#include <boost/make_shared.hpp> + +using Mantid::CurveFitting::CostFuncUnweightedLeastSquares; +using namespace Mantid::API; + +class CostFuncUnweightedLeastSquaresTest : 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 CostFuncUnweightedLeastSquaresTest *createSuite() { + return new CostFuncUnweightedLeastSquaresTest(); + } + static void destroySuite(CostFuncUnweightedLeastSquaresTest *suite) { + delete suite; + } + + void testGetFitWeights() { + /* The test makes sure that the returned weights are always 1.0 */ + FunctionDomain1DVector d1d(std::vector<double>(20, 1.0)); + FunctionValues_sptr values = boost::make_shared<FunctionValues>(d1d); + + for (size_t i = 0; i < values->size(); ++i) { + values->setFitWeight(i, static_cast<double>(i)); + } + + TestableCostFuncUnweightedLeastSquares uwls; + + std::vector<double> weights = uwls.getFitWeights(values); + + TS_ASSERT_EQUALS(weights.size(), values->size()); + for (size_t i = 0; i < weights.size(); ++i) { + TS_ASSERT_EQUALS(weights[i], 1.0); + } + } + + void testGetResidualVariance() { + /* Make sure that the calculated residuals variance is correct. The + * test uses dummy values for which the sum of residuals is known. + */ + FunctionDomain1DVector d1d(std::vector<double>(10, 1.0)); + FunctionValues_sptr values = boost::make_shared<FunctionValues>(d1d); + + // Data generated with numpy.random.normal(loc=2.0, scale=0.25, size=10) + double obsValues[10] = { 1.9651563160778176, 1.9618188576389295, + 1.9565961107376706, 2.0049055113975252, + 2.0747505383068865, 2.0666404554638578, + 1.7854026688169637, 2.266075963037971, + 1.8656602424955859, 1.8132221813342393 }; + + for (size_t i = 0; i < 10; ++i) { + values->setCalculated(2.0); + values->setFitData(i, obsValues[i]); + } + + // Function has 1 parameter, so degrees of freedom = 9 + IFunction_sptr fn = + FunctionFactory::Instance().createFunction("FlatBackground"); + FunctionDomain_sptr domain = + boost::make_shared<FunctionDomain1DVector>(d1d); + + TestableCostFuncUnweightedLeastSquares uwls; + uwls.setFittingFunction(fn, domain, values); + + double variance = uwls.getResidualVariance(); + TS_ASSERT_DELTA(variance, 0.0204877770575, 1e-13); + } + +private: + class TestableCostFuncUnweightedLeastSquares + : public CostFuncUnweightedLeastSquares { + friend class CostFuncUnweightedLeastSquaresTest; + }; +}; + +#endif /* MANTID_CURVEFITTING_COSTFUNCUNWEIGHTEDLEASTSQUARESTEST_H_ */ diff --git a/Code/Mantid/Framework/CurveFitting/test/LatticeDomainCreatorTest.h b/Code/Mantid/Framework/CurveFitting/test/LatticeDomainCreatorTest.h new file mode 100644 index 0000000000000000000000000000000000000000..f2b11bcb8881f0949ef3fa668212619d9e1a5da2 --- /dev/null +++ b/Code/Mantid/Framework/CurveFitting/test/LatticeDomainCreatorTest.h @@ -0,0 +1,233 @@ +#ifndef MANTID_CURVEFITTING_LATTICEDOMAINCREATORTEST_H_ +#define MANTID_CURVEFITTING_LATTICEDOMAINCREATORTEST_H_ + +#include <cxxtest/TestSuite.h> + +#include "MantidAPI/FunctionFactory.h" +#include "MantidAPI/LatticeDomain.h" +#include "MantidCurveFitting/LatticeDomainCreator.h" +#include "MantidCurveFitting/LatticeFunction.h" +#include "MantidDataObjects/PeaksWorkspace.h" +#include "MantidTestHelpers/WorkspaceCreationHelper.h" + +using Mantid::CurveFitting::LatticeDomainCreator; +using Mantid::CurveFitting::LatticeFunction; +using Mantid::Kernel::V3D; + +using namespace Mantid::API; +using namespace Mantid::DataObjects; + +class LatticeDomainCreatorTest : 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 LatticeDomainCreatorTest *createSuite() { + return new LatticeDomainCreatorTest(); + } + static void destroySuite(LatticeDomainCreatorTest *suite) { delete suite; } + + void testGetDomainSizeIPeaksWorkspace() { + Workspace_sptr peaksWs = boost::dynamic_pointer_cast<Workspace>( + WorkspaceCreationHelper::createPeaksWorkspace(5)); + + TestableLatticeDomainCreator dc; + TS_ASSERT_THROWS_NOTHING(dc.setWorkspace(peaksWs)); + + TS_ASSERT_EQUALS(dc.getDomainSize(), 5); + } + + void testGetDomainSizeTableWorkspace() { + ITableWorkspace_sptr table = getValidTableWs(); + + TestableLatticeDomainCreator dc; + TS_ASSERT_THROWS_NOTHING(dc.setWorkspace(table)); + + TS_ASSERT_EQUALS(dc.getDomainSize(), 3); + } + + void testCreateDomainTableWs() { + ITableWorkspace_sptr table = getValidTableWs(); + + TestableLatticeDomainCreator dc; + + FunctionDomain_sptr domain; + FunctionValues_sptr values; + + TS_ASSERT_THROWS_NOTHING( + dc.createDomainFromPeakTable(table, domain, values, 0)); + + TS_ASSERT_EQUALS(domain->size(), 3); + TS_ASSERT_EQUALS(values->size(), 3); + + boost::shared_ptr<LatticeDomain> latticeDomain = + boost::dynamic_pointer_cast<LatticeDomain>(domain); + + TS_ASSERT(latticeDomain); + + TS_ASSERT_EQUALS((*latticeDomain)[0], V3D(1, 1, 1)); + TS_ASSERT_EQUALS((*latticeDomain)[1], V3D(2, 2, 0)); + TS_ASSERT_EQUALS((*latticeDomain)[2], V3D(3, 1, 1)); + + TS_ASSERT_EQUALS(values->getFitData(0), 3.135702); + TS_ASSERT_EQUALS(values->getFitData(1), 1.920217); + TS_ASSERT_EQUALS(values->getFitData(2), 1.637567); + + TS_ASSERT_EQUALS(values->getFitWeight(0), 1.0); + TS_ASSERT_EQUALS(values->getFitWeight(1), 1.0); + TS_ASSERT_EQUALS(values->getFitWeight(2), 1.0); + } + + void testCreateDomainHKL000() { + ITableWorkspace_sptr table = getValidTableWs(); + TableRow newRow = table->appendRow(); + newRow << V3D(0, 0, 0) << 0.0; + + TestableLatticeDomainCreator dc; + + FunctionDomain_sptr domain; + FunctionValues_sptr values; + + TS_ASSERT_THROWS_NOTHING( + dc.createDomainFromPeakTable(table, domain, values, 0)); + + // Domain size should still be 3, because 0, 0, 0 can not be used + TS_ASSERT_EQUALS(domain->size(), 3); + TS_ASSERT_EQUALS(values->size(), 3); + } + + void testCreateDomainTableWsInvalid() { + ITableWorkspace_sptr invalid = getInvalidTableWs(); + ITableWorkspace_sptr empty = getEmptyTableWs(); + + TestableLatticeDomainCreator dc; + + FunctionDomain_sptr domain; + FunctionValues_sptr values; + + TS_ASSERT_THROWS(dc.createDomainFromPeakTable(invalid, domain, values, 0), + std::runtime_error); + + TS_ASSERT_THROWS(dc.createDomainFromPeakTable(empty, domain, values, 0), + std::range_error); + } + + void testCreateDomainPeaksWorkspace() { + IPeaksWorkspace_sptr peaksWs = boost::dynamic_pointer_cast<IPeaksWorkspace>( + WorkspaceCreationHelper::createPeaksWorkspace(2)); + peaksWs->getPeak(0).setHKL(V3D(1, 1, 1)); + peaksWs->getPeak(1).setHKL(V3D(2, 2, 0)); + + TestableLatticeDomainCreator dc; + + FunctionDomain_sptr domain; + FunctionValues_sptr values; + + TS_ASSERT_THROWS_NOTHING( + dc.createDomainFromPeaksWorkspace(peaksWs, domain, values, 0)); + + TS_ASSERT_EQUALS(domain->size(), 2); + TS_ASSERT_EQUALS(values->size(), 2); + + boost::shared_ptr<LatticeDomain> latticeDomain = + boost::dynamic_pointer_cast<LatticeDomain>(domain); + + TS_ASSERT(latticeDomain); + + TS_ASSERT_EQUALS((*latticeDomain)[0], V3D(1, 1, 1)); + TS_ASSERT_EQUALS((*latticeDomain)[1], V3D(2, 2, 0)); + + TS_ASSERT_EQUALS(values->getFitData(0), peaksWs->getPeak(0).getDSpacing()); + TS_ASSERT_EQUALS(values->getFitData(1), peaksWs->getPeak(1).getDSpacing()); + + TS_ASSERT_EQUALS(values->getFitWeight(0), 1.0); + TS_ASSERT_EQUALS(values->getFitWeight(1), 1.0); + } + + void testCreateOutputWorkspace() { + ITableWorkspace_sptr table = getValidTableWs(); + + // Function that does nothing. + IFunction_sptr fn = boost::make_shared<EmptyLatticeFunction>(); + FunctionDomain_sptr domain; + FunctionValues_sptr values; + + // Make domain and values + TestableLatticeDomainCreator dc; + dc.createDomainFromPeakTable(table, domain, values, 0); + + values->setCalculated(0, 3.125702); + values->setCalculated(1, 1.930217); + values->setCalculated(2, 1.627567); + + Workspace_sptr outputWs; + TS_ASSERT_THROWS_NOTHING( + outputWs = dc.createOutputWorkspace("base", fn, domain, values, "pp")); + + ITableWorkspace_sptr tableWs = + boost::dynamic_pointer_cast<ITableWorkspace>(outputWs); + TS_ASSERT(tableWs); + + TS_ASSERT_EQUALS(tableWs->rowCount(), 3); + TS_ASSERT_DELTA(tableWs->cell<double>(0, 3), 0.01, 1e-6); + TS_ASSERT_DELTA(tableWs->cell<double>(1, 3), -0.01, 1e-6); + TS_ASSERT_DELTA(tableWs->cell<double>(2, 3), 0.01, 1e-6); + } + +private: + ITableWorkspace_sptr getValidTableWs() { + ITableWorkspace_sptr table = WorkspaceFactory::Instance().createTable(); + table->addColumn("V3D", "HKL"); + table->addColumn("double", "d"); + + TableRow newRow = table->appendRow(); + newRow << V3D(1, 1, 1) << 3.135702; + newRow = table->appendRow(); + newRow << V3D(2, 2, 0) << 1.920217; + newRow = table->appendRow(); + newRow << V3D(3, 1, 1) << 1.637567; + + return table; + } + + ITableWorkspace_sptr getEmptyTableWs() { + ITableWorkspace_sptr table = WorkspaceFactory::Instance().createTable(); + table->addColumn("V3D", "HKL"); + table->addColumn("double", "d"); + + return table; + } + + ITableWorkspace_sptr getInvalidTableWs() { + ITableWorkspace_sptr table = WorkspaceFactory::Instance().createTable(); + table->addColumn("V3D", "HKL"); + + TableRow newRow = table->appendRow(); + newRow << V3D(1, 1, 1); + newRow = table->appendRow(); + newRow << V3D(2, 2, 0); + newRow = table->appendRow(); + newRow << V3D(3, 1, 1); + + return table; + } + + class TestableLatticeDomainCreator : public LatticeDomainCreator { + friend class LatticeDomainCreatorTest; + + public: + TestableLatticeDomainCreator() : LatticeDomainCreator(NULL, "") {} + + void setWorkspace(const Workspace_sptr &ws) { m_workspace = ws; } + }; + + class EmptyLatticeFunction : public LatticeFunction { + public: + void functionLattice(const LatticeDomain &latticeDomain, + FunctionValues &values) const { + UNUSED_ARG(latticeDomain); + UNUSED_ARG(values); + } + }; +}; + +#endif /* MANTID_CURVEFITTING_LATTICEDOMAINCREATORTEST_H_ */ diff --git a/Code/Mantid/Framework/CurveFitting/test/LatticeFunctionTest.h b/Code/Mantid/Framework/CurveFitting/test/LatticeFunctionTest.h new file mode 100644 index 0000000000000000000000000000000000000000..3bf49ea7a72c9467f5ddd5eabadbf2e5a8370851 --- /dev/null +++ b/Code/Mantid/Framework/CurveFitting/test/LatticeFunctionTest.h @@ -0,0 +1,156 @@ +#ifndef MANTID_CURVEFITTING_LATTICEFUNCTIONTEST_H_ +#define MANTID_CURVEFITTING_LATTICEFUNCTIONTEST_H_ + +#include <cxxtest/TestSuite.h> + +#include "MantidCurveFitting/LatticeFunction.h" +#include "MantidAPI/AlgorithmManager.h" +#include "MantidAPI/FunctionFactory.h" +#include "MantidAPI/LatticeDomain.h" +#include "MantidAPI/TableRow.h" +#include "MantidGeometry/Crystal/UnitCell.h" + +using Mantid::CurveFitting::LatticeFunction; +using Mantid::Kernel::V3D; +using Mantid::Geometry::UnitCell; +using Mantid::Geometry::unitCellToStr; + +using namespace Mantid::API; + +class LatticeFunctionTest : 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 LatticeFunctionTest *createSuite() { + return new LatticeFunctionTest(); + } + static void destroySuite(LatticeFunctionTest *suite) { delete suite; } + + void testSetCrystalSystem() { + LatticeFunction fn; + fn.initialize(); + + TS_ASSERT_THROWS_NOTHING(fn.setCrystalSystem("Cubic")); + TS_ASSERT_THROWS_NOTHING(fn.setCrystalSystem("Tetragonal")); + TS_ASSERT_THROWS_NOTHING(fn.setCrystalSystem("triclinic")); + + TS_ASSERT_THROWS(fn.setCrystalSystem("DoesNotExist"), + std::invalid_argument); + + fn.setCrystalSystem("Cubic"); + // a and ZeroShift + TS_ASSERT_EQUALS(fn.nParams(), 2); + + fn.setCrystalSystem("Hexagonal"); + // a, c and ZeroShift + TS_ASSERT_EQUALS(fn.nParams(), 3); + + /* The basic functionality is covered by the tests for + * PawleyParameterFunction. + */ + } + + void testSetUnitCellString() { + LatticeFunction fn; + fn.initialize(); + + TS_ASSERT_THROWS_NOTHING(fn.setUnitCell("1.0 2.0 3.0 90 100 110")); + TS_ASSERT_EQUALS(fn.getParameter("a"), 1.0); + TS_ASSERT_EQUALS(fn.getParameter("b"), 2.0); + TS_ASSERT_EQUALS(fn.getParameter("c"), 3.0); + TS_ASSERT_EQUALS(fn.getParameter("Alpha"), 90.0); + TS_ASSERT_EQUALS(fn.getParameter("Beta"), 100.0); + TS_ASSERT_EQUALS(fn.getParameter("Gamma"), 110.0); + + TS_ASSERT_THROWS_NOTHING(fn.setUnitCell("1.0 2.0 3.0")); + TS_ASSERT_EQUALS(fn.getParameter("a"), 1.0); + TS_ASSERT_EQUALS(fn.getParameter("b"), 2.0); + TS_ASSERT_EQUALS(fn.getParameter("c"), 3.0); + TS_ASSERT_EQUALS(fn.getParameter("Alpha"), 90.0); + TS_ASSERT_EQUALS(fn.getParameter("Beta"), 90.0); + TS_ASSERT_EQUALS(fn.getParameter("Gamma"), 90.0); + } + + void testSetUnitCellUnitCell() { + LatticeFunction fn; + fn.initialize(); + + TS_ASSERT_THROWS_NOTHING(fn.setUnitCell(UnitCell(1, 2, 3, 90, 100, 110))); + TS_ASSERT_EQUALS(fn.getParameter("a"), 1.0); + TS_ASSERT_EQUALS(fn.getParameter("b"), 2.0); + TS_ASSERT_EQUALS(fn.getParameter("c"), 3.0); + TS_ASSERT_EQUALS(fn.getParameter("Alpha"), 90.0); + TS_ASSERT_EQUALS(fn.getParameter("Beta"), 100.0); + TS_ASSERT_EQUALS(fn.getParameter("Gamma"), 110.0); + } + + void testGetUnitCell() { + LatticeFunction fn; + fn.initialize(); + + UnitCell cell(1, 2, 3, 90, 100, 110); + TS_ASSERT_THROWS_NOTHING(fn.setUnitCell(cell)); + + TS_ASSERT_EQUALS(unitCellToStr(fn.getUnitCell()), unitCellToStr(cell)); + } + + void testFunctionValues() { + LatticeFunction fn; + fn.initialize(); + + // Al2O3, from PoldiCreatePeaksFromCell system test. + fn.setCrystalSystem("Hexagonal"); + fn.setParameter("a", 4.7605); + fn.setParameter("c", 12.9956); + + std::vector<V3D> hkls; + hkls.push_back(V3D(1, 0, -2)); + hkls.push_back(V3D(1, 0, 4)); + hkls.push_back(V3D(0, 0, 6)); + hkls.push_back(V3D(5, -2, -5)); + + LatticeDomain domain(hkls); + FunctionValues values(domain); + + // Calculate d-values + TS_ASSERT_THROWS_NOTHING(fn.function(domain, values)); + + // Check values. + TS_ASSERT_DELTA(values[0], 3.481144, 1e-6); + TS_ASSERT_DELTA(values[1], 2.551773, 1e-6); + TS_ASSERT_DELTA(values[2], 2.165933, 1e-6); + TS_ASSERT_DELTA(values[3], 0.88880, 1e-5); + } + + void testFitExampleTable() { + // Fit Silicon lattice with three peaks. + ITableWorkspace_sptr table = WorkspaceFactory::Instance().createTable(); + table->addColumn("V3D", "HKL"); + table->addColumn("double", "d"); + + TableRow newRow = table->appendRow(); + newRow << V3D(1, 1, 1) << 3.135702; + newRow = table->appendRow(); + newRow << V3D(2, 2, 0) << 1.920217; + newRow = table->appendRow(); + newRow << V3D(3, 1, 1) << 1.637567; + + IFunction_sptr fn = + FunctionFactory::Instance().createFunction("LatticeFunction"); + fn->setAttributeValue("CrystalSystem", "Cubic"); + fn->addTies("ZeroShift=0.0"); + fn->setParameter("a", 5); + + IAlgorithm_sptr fit = AlgorithmManager::Instance().create("Fit"); + fit->setProperty("Function", fn); + fit->setProperty("InputWorkspace", table); + fit->setProperty("CostFunction", "Unweighted least squares"); + fit->setProperty("CreateOutput", true); + fit->execute(); + + TS_ASSERT_DELTA(fn->getParameter("a"), 5.4311946, 1e-6); + TS_ASSERT_LESS_THAN(fn->getError(0), 1e-6); + } +}; + +#endif /* MANTID_CURVEFITTING_LATTICEFUNCTIONTEST_H_ */ diff --git a/Code/Mantid/Framework/CurveFitting/test/PawleyFitTest.h b/Code/Mantid/Framework/CurveFitting/test/PawleyFitTest.h index 30b0ca92e8d438ed7550f85384bfff6bb6d7469c..3c99605f3d889689ca20cd3a8f375a4c09f0a93f 100644 --- a/Code/Mantid/Framework/CurveFitting/test/PawleyFitTest.h +++ b/Code/Mantid/Framework/CurveFitting/test/PawleyFitTest.h @@ -12,6 +12,7 @@ #include "MantidTestHelpers/WorkspaceCreationHelper.h" using Mantid::CurveFitting::PawleyFit; +using Mantid::CurveFitting::V3DFromHKLColumnExtractor; using namespace Mantid::API; using namespace Mantid::Kernel; @@ -23,17 +24,17 @@ public: static void destroySuite(PawleyFitTest *suite) { delete suite; } void testGetHKL() { - TestablePawleyFit pfit; + TestableV3DFromHKLColumnExtractor extractor; V3D referenceHKL(1, 2, 3); - TS_ASSERT_EQUALS(pfit.getHkl("1 2 3"), referenceHKL); - TS_ASSERT_EQUALS(pfit.getHkl(" 1 2 3 "), referenceHKL); - TS_ASSERT_EQUALS(pfit.getHkl("1 2 3"), referenceHKL); - TS_ASSERT_EQUALS(pfit.getHkl("1,2,3"), referenceHKL); - TS_ASSERT_EQUALS(pfit.getHkl("1;2;3"), referenceHKL); - TS_ASSERT_EQUALS(pfit.getHkl("[1,2,3]"), referenceHKL); - TS_ASSERT_EQUALS(pfit.getHkl("[1;2 3]"), referenceHKL); + TS_ASSERT_EQUALS(extractor.getHKLFromString("1 2 3"), referenceHKL); + TS_ASSERT_EQUALS(extractor.getHKLFromString(" 1 2 3 "), referenceHKL); + TS_ASSERT_EQUALS(extractor.getHKLFromString("1 2 3"), referenceHKL); + TS_ASSERT_EQUALS(extractor.getHKLFromString("1,2,3"), referenceHKL); + TS_ASSERT_EQUALS(extractor.getHKLFromString("1;2;3"), referenceHKL); + TS_ASSERT_EQUALS(extractor.getHKLFromString("[1,2,3]"), referenceHKL); + TS_ASSERT_EQUALS(extractor.getHKLFromString("[1;2 3]"), referenceHKL); } void testFitHexagonalCellQ() { @@ -152,6 +153,10 @@ private: ~TestablePawleyFit() {} }; + class TestableV3DFromHKLColumnExtractor : public V3DFromHKLColumnExtractor { + friend class PawleyFitTest; + }; + ITableWorkspace_sptr getHCPTable() { ITableWorkspace_sptr tableWs = WorkspaceFactory::Instance().createTable(); tableWs->addColumn("V3D", "HKL"); diff --git a/Code/Mantid/Framework/DataHandling/inc/MantidDataHandling/LoadNexusMonitors.h b/Code/Mantid/Framework/DataHandling/inc/MantidDataHandling/LoadNexusMonitors.h index 61fc044f5bb3b2131e8d5255cf199f16631a91f0..4d2fb2d8cee94871611ad9febb313c67bee14009 100644 --- a/Code/Mantid/Framework/DataHandling/inc/MantidDataHandling/LoadNexusMonitors.h +++ b/Code/Mantid/Framework/DataHandling/inc/MantidDataHandling/LoadNexusMonitors.h @@ -80,6 +80,9 @@ private: /// is it possible to open the file? bool canOpenAsNeXus(const std::string &fname); + /// split multi period histogram workspace into a workspace group + void splitMutiPeriodHistrogramData(const size_t numPeriods); + /// The name and path of the input file std::string filename; /// The workspace being filled out diff --git a/Code/Mantid/Framework/DataHandling/src/LoadEventNexus.cpp b/Code/Mantid/Framework/DataHandling/src/LoadEventNexus.cpp index 3af9cf516d245aac17cbfa9735c6e9e40482ba3c..16e56ec9f5e7e2a614f5b250fe5d97a2f55553f0 100644 --- a/Code/Mantid/Framework/DataHandling/src/LoadEventNexus.cpp +++ b/Code/Mantid/Framework/DataHandling/src/LoadEventNexus.cpp @@ -5,6 +5,7 @@ #include <boost/random/mersenne_twister.hpp> #include <boost/random/uniform_real.hpp> +#include <boost/shared_ptr.hpp> #include <boost/shared_array.hpp> #include "MantidKernel/ArrayProperty.h" @@ -2365,16 +2366,37 @@ void LoadEventNexus::runLoadMonitors() { loadMonitors->setPropertyValue("MonitorsAsEvents", this->getProperty("MonitorsAsEvents")); loadMonitors->execute(); - MatrixWorkspace_sptr mons = loadMonitors->getProperty("OutputWorkspace"); - this->declareProperty(new WorkspaceProperty<>("MonitorWorkspace", - mon_wsname, - Direction::Output), - "Monitors from the Event NeXus file"); - this->setProperty("MonitorWorkspace", mons); - // Set the internal monitor workspace pointer as well - WS->setMonitorWorkspace(mons); - - filterDuringPause(mons); + Workspace_sptr monsOut = loadMonitors->getProperty("OutputWorkspace"); + this->declareProperty(new WorkspaceProperty<Workspace>("MonitorWorkspace", + mon_wsname, + Direction::Output), + "Monitors from the Event NeXus file"); + this->setProperty("MonitorWorkspace", monsOut); + //The output will either be a group workspace or a matrix workspace + MatrixWorkspace_sptr mons = boost::dynamic_pointer_cast<MatrixWorkspace>(monsOut); + if (mons) { + // Set the internal monitor workspace pointer as well + WS->setMonitorWorkspace(mons); + + filterDuringPause(mons); + } else { + WorkspaceGroup_sptr monsGrp = boost::dynamic_pointer_cast<WorkspaceGroup>(monsOut); + if (monsGrp) { + //declare a property for each member of the group + for (int i = 0; i < monsGrp->getNumberOfEntries(); i++) + { + std::stringstream ssWsName; + ssWsName << mon_wsname << "_" << i+1; + std::stringstream ssPropName; + ssPropName << "MonitorWorkspace" << "_" << i+1; + this->declareProperty(new WorkspaceProperty<MatrixWorkspace>(ssPropName.str(), + ssWsName.str(), + Direction::Output), + "Monitors from the Event NeXus file"); + this->setProperty(ssPropName.str(), monsGrp->getItem(i)); + } + } + } } catch (...) { g_log.error("Error while loading the monitors from the file. File may " "contain no monitors."); diff --git a/Code/Mantid/Framework/DataHandling/src/LoadNexusMonitors.cpp b/Code/Mantid/Framework/DataHandling/src/LoadNexusMonitors.cpp index 7bf7f6bcf216a6de9e91f27126262e4d921bfdbc..fe371b2416c965c6047e17266275b333b746c8c1 100644 --- a/Code/Mantid/Framework/DataHandling/src/LoadNexusMonitors.cpp +++ b/Code/Mantid/Framework/DataHandling/src/LoadNexusMonitors.cpp @@ -1,10 +1,11 @@ #include "MantidDataHandling/LoadNexusMonitors.h" #include "MantidDataHandling/LoadEventNexus.h" +#include "MantidDataHandling/ISISRunLogs.h" #include "MantidAPI/FileProperty.h" +#include "MantidAPI/WorkspaceGroup.h" #include "MantidKernel/ConfigService.h" #include "MantidKernel/DateAndTime.h" #include "MantidKernel/UnitFactory.h" - #include <Poco/File.h> #include <Poco/Path.h> #include <boost/lexical_cast.hpp> @@ -15,6 +16,8 @@ using Mantid::DataObjects::EventWorkspace; using Mantid::DataObjects::EventWorkspace_sptr; +using Mantid::API::WorkspaceGroup; +using Mantid::API::WorkspaceGroup_sptr; namespace Mantid { namespace DataHandling { @@ -42,7 +45,7 @@ void LoadNexusMonitors::init() { "attempt to load. The file extension must either be .nxs or .NXS"); declareProperty( - new API::WorkspaceProperty<API::MatrixWorkspace>( + new API::WorkspaceProperty<API::Workspace>( "OutputWorkspace", "", Kernel::Direction::Output), "The name of the output workspace in which to load the NeXus monitors."); @@ -91,6 +94,7 @@ void LoadNexusMonitors::exec() { std::vector<std::string> monitorNames; size_t numHistMon = 0; size_t numEventMon = 0; + size_t numPeriods = 0; // we want to sort monitors by monitor_number if they are present std::map<int, std::string> monitorNumber2Name; prog1.report(); @@ -136,6 +140,13 @@ void LoadNexusMonitors::exec() { file.closeData(); monitorNumber2Name[monitorNo] = entry_name; } + if((numPeriods == 0) && (inner_entries.find("period_index") != inner_entries.end())) { + MantidVec period_data; + file.openData("period_index"); + file.getDataCoerce(period_data); + file.closeData(); + numPeriods = period_data.size(); + } } file.closeGroup(); // close NXmonitor } @@ -144,8 +155,13 @@ void LoadNexusMonitors::exec() { this->nMonitors = monitorNames.size(); // Nothing to do - if (0 == nMonitors) - return; + if (0 == nMonitors) { + //previous version just used to return, but that + //threw an error when the OutputWorkspace property was not set. + //and the error message was confusing. + //This has changed to throw a specific error. + throw std::invalid_argument(this->filename + " does not contain any monitors"); + } // With this property you can make the exception that even if there's event // data, monitors will be loaded @@ -414,10 +430,16 @@ void LoadNexusMonitors::exec() { WS->getSpectrum(i)->setSpectrumNo(spectra_numbers[i]); WS->getSpectrum(i)->setDetectorID(detector_numbers[i]); } - // add filename WS->mutableRun().addProperty("Filename", this->filename); - this->setProperty("OutputWorkspace", this->WS); + + //if multiperiod histogram data + if ((numPeriods > 1) && (!useEventMon)) { + splitMutiPeriodHistrogramData(numPeriods); + } + else { + this->setProperty("OutputWorkspace", this->WS); + } } /** @@ -535,5 +557,91 @@ bool LoadNexusMonitors::canOpenAsNeXus(const std::string &fname) { return res; } +/** + * Splits multiperiod histogram data into seperate workspaces and puts them in a group + * + * @param numPeriods :: number of periods + **/ +void LoadNexusMonitors::splitMutiPeriodHistrogramData(const size_t numPeriods) { + + //protection - we should not have entered the routine if these are not true + // More than 1 period + if (numPeriods < 2) { + g_log.warning() << "Attempted to split multiperiod histogram workspace with " + << numPeriods << "periods, aborted." << std::endl; + return; + } + + // Y array should be divisible by the number of periods + if (this->WS->blocksize() % numPeriods != 0) { + g_log.warning() << "Attempted to split multiperiod histogram workspace with " + << this->WS->blocksize() << "data entries, into " << numPeriods << "periods." + " Aborted."<< std::endl; + return; + } + + WorkspaceGroup_sptr wsGroup(new WorkspaceGroup); + size_t yLength = this->WS->blocksize() / numPeriods; + size_t xLength = yLength + 1; + size_t numSpectra = this->WS->getNumberHistograms(); + ISISRunLogs monLogCreator(this->WS->run(), static_cast<int>(numPeriods)); + for (size_t i = 0; i < numPeriods; i++) + { + //create the period workspace + API::MatrixWorkspace_sptr wsPeriod = API::WorkspaceFactory::Instance().create( + this->WS, + numSpectra, + xLength, + yLength); + + //assign x values - restart at start for all periods + for (size_t specIndex = 0; specIndex < numSpectra; specIndex++) { + MantidVec& outputVec = wsPeriod->dataX(specIndex); + const MantidVec& inputVec = this->WS->readX(specIndex); + for (size_t index = 0; index < xLength; index++) { + outputVec[index] = inputVec[index]; + } + } + + //assign y values - use the values offset by the period number + for (size_t specIndex = 0; specIndex < numSpectra; specIndex++) { + MantidVec& outputVec = wsPeriod->dataY(specIndex); + const MantidVec& inputVec = this->WS->readY(specIndex); + for (size_t index = 0; index < yLength; index++) { + outputVec[index] = inputVec[(yLength * i) + index]; + } + } + + //assign E values + for (size_t specIndex = 0; specIndex < numSpectra; specIndex++) { + MantidVec& outputVec = wsPeriod->dataE(specIndex); + const MantidVec& inputVec = this->WS->readE(specIndex); + for (size_t index = 0; index < yLength; index++) { + outputVec[index] = inputVec[(yLength * i) + index]; + } + } + + //add period logs + monLogCreator.addPeriodLogs(static_cast<int>(i+1), wsPeriod->mutableRun()); + + //add to workspace group + wsGroup->addWorkspace(wsPeriod); + + //create additional output workspace property + std::stringstream ssWsName; + ssWsName << this->WS->name() << "_" << i+1; + std::stringstream ssPropName; + ssPropName << "OutputWorkspace" << "_" << i+1; + declareProperty( + new API::WorkspaceProperty<API::Workspace>( + ssPropName.str(), ssWsName.str(), Kernel::Direction::Output), + "Additional output workspace for multi period monitors."); + setProperty(ssPropName.str(),wsPeriod); + } + + // set the output workspace + this->setProperty("OutputWorkspace", wsGroup); +} + } // end DataHandling } // end Mantid diff --git a/Code/Mantid/Framework/DataObjects/src/MDHistoWorkspaceIterator.cpp b/Code/Mantid/Framework/DataObjects/src/MDHistoWorkspaceIterator.cpp index 01fe7b9409855076b624d70ee95e67903a0e3f7f..13259fca9787d46bf2a330c6e9f86753fbfdc082 100644 --- a/Code/Mantid/Framework/DataObjects/src/MDHistoWorkspaceIterator.cpp +++ b/Code/Mantid/Framework/DataObjects/src/MDHistoWorkspaceIterator.cpp @@ -536,7 +536,8 @@ MDHistoWorkspaceIterator::findNeighbourIndexesByWidth(const std::vector<int>& wi // Filter out indexes that are are not actually neighbours. // Accumulate neighbour indexes. - std::vector<size_t> neighbourIndexes; + std::vector<size_t> neighbourIndexes(permutationsVertexTouching.size()); + size_t nextFree = 0; for (size_t i = 0; i < permutationsVertexTouching.size(); ++i) { if (permutationsVertexTouching[i] == 0) { continue; @@ -546,9 +547,10 @@ MDHistoWorkspaceIterator::findNeighbourIndexesByWidth(const std::vector<int>& wi if (neighbour_index < m_ws->getNPoints() && Utils::isNeighbourOfSubject(m_nd, neighbour_index, m_index, m_indexMaker, m_indexMax, widths) ) { - neighbourIndexes.push_back(neighbour_index); + neighbourIndexes[nextFree++] = neighbour_index; } } + neighbourIndexes.resize(nextFree); // Remove duplicates std::sort(neighbourIndexes.begin(), neighbourIndexes.end()); diff --git a/Code/Mantid/Framework/Geometry/src/Math/Acomp.cpp b/Code/Mantid/Framework/Geometry/src/Math/Acomp.cpp index e324cc001390b151194b6a7a26cf4bff32ffacd7..0788103182bd08ed8d4202180f43ed171f722ee3 100644 --- a/Code/Mantid/Framework/Geometry/src/Math/Acomp.cpp +++ b/Code/Mantid/Framework/Geometry/src/Math/Acomp.cpp @@ -6,6 +6,7 @@ #include "MantidGeometry/Math/RotCounter.h" #include <algorithm> #include <iostream> +#include <functional> namespace Mantid { diff --git a/Code/Mantid/Framework/Geometry/src/Math/BnId.cpp b/Code/Mantid/Framework/Geometry/src/Math/BnId.cpp index c1e3193dfbabb825234c56bf6e847179630d3036..25a999388cb556f39dac36496cb77df09b1f7b84 100644 --- a/Code/Mantid/Framework/Geometry/src/Math/BnId.cpp +++ b/Code/Mantid/Framework/Geometry/src/Math/BnId.cpp @@ -9,6 +9,7 @@ #include <sstream> #include <algorithm> #include <iterator> +#include <functional> #include "MantidGeometry/Math/BnId.h" diff --git a/Code/Mantid/Framework/Geometry/src/Math/PolyBase.cpp b/Code/Mantid/Framework/Geometry/src/Math/PolyBase.cpp index fae868d89f9cfbd05d959126c1725a640f00464d..eac6ba5b99a7b0fb476bc5bed2e86b2f2860906f 100644 --- a/Code/Mantid/Framework/Geometry/src/Math/PolyBase.cpp +++ b/Code/Mantid/Framework/Geometry/src/Math/PolyBase.cpp @@ -4,6 +4,7 @@ #include <vector> #include <algorithm> #include <iterator> +#include <functional> #include <gsl/gsl_poly.h> #include "MantidKernel/Exception.h" diff --git a/Code/Mantid/Framework/Kernel/inc/MantidKernel/Utils.h b/Code/Mantid/Framework/Kernel/inc/MantidKernel/Utils.h index e53ef353320531563f25afcfef32b993c83153e8..d83377b96dcd4bfe9c4fb90c84915c5ee2b992db 100644 --- a/Code/Mantid/Framework/Kernel/inc/MantidKernel/Utils.h +++ b/Code/Mantid/Framework/Kernel/inc/MantidKernel/Utils.h @@ -289,23 +289,18 @@ inline void getIndicesFromLinearIndex(const size_t linear_index, * @param widths : width in pixels per dimension * @return True if the are neighbours, otherwise false. */ -inline bool isNeighbourOfSubject(const size_t ndims, - const size_t neighbour_linear_index, - const size_t *subject_indices, - const size_t *num_bins, - const size_t *index_max, const std::vector<int>& widths) { - std::vector<size_t> neighbour_indices(ndims); - Utils::NestedForLoop::GetIndicesFromLinearIndex(ndims, neighbour_linear_index, - num_bins, index_max, - &neighbour_indices.front()); - +inline bool +isNeighbourOfSubject(const size_t ndims, const size_t neighbour_linear_index, + const size_t *subject_indices, const size_t *num_bins, + const size_t *index_max, const std::vector<int> &widths) { for (size_t ind = 0; ind < ndims; ++ind) { - long double diff = - std::abs(static_cast<long double>(subject_indices[ind]) - - static_cast<long double>(neighbour_indices[ind])); - if (diff > widths[ind]/2) { + size_t neigh_index = + (neighbour_linear_index / num_bins[ind]) % index_max[ind]; + const long double subj = static_cast<long double>(subject_indices[ind]); + const long double neigh = static_cast<long double>(neigh_index); + const long double diff = std::abs(subj - neigh); + if (diff > widths[ind] / 2) return false; - } } return true; } diff --git a/Code/Mantid/Framework/Kernel/src/Statistics.cpp b/Code/Mantid/Framework/Kernel/src/Statistics.cpp index 795a1cc009b951303d64a141c6ae2340e4317ac9..5cefc6fec5e06c3243e70f66c777face67f059da 100644 --- a/Code/Mantid/Framework/Kernel/src/Statistics.cpp +++ b/Code/Mantid/Framework/Kernel/src/Statistics.cpp @@ -9,6 +9,7 @@ #include <numeric> #include <sstream> #include <stdexcept> +#include <functional> namespace Mantid { diff --git a/Code/Mantid/Framework/SINQ/inc/MantidSINQ/PoldiFitPeaks2D.h b/Code/Mantid/Framework/SINQ/inc/MantidSINQ/PoldiFitPeaks2D.h index a7217d53e063a97becbcd694f891652508413fdc..b408a1fc3d3829e0904a0f74e3348ccdfae0ba2a 100644 --- a/Code/Mantid/Framework/SINQ/inc/MantidSINQ/PoldiFitPeaks2D.h +++ b/Code/Mantid/Framework/SINQ/inc/MantidSINQ/PoldiFitPeaks2D.h @@ -75,7 +75,11 @@ protected: Poldi2DFunction_sptr getFunctionPawley(std::string profileFunctionName, - const PoldiPeakCollection_sptr &peakCollection) const; + const PoldiPeakCollection_sptr &peakCollection); + + std::string getRefinedStartingCell(const std::string &initialCell, + const std::string &crystalSystem, + const PoldiPeakCollection_sptr &peakCollection); PoldiPeak_sptr getPeakFromPeakFunction(API::IPeakFunction_sptr profileFunction, @@ -99,7 +103,7 @@ protected: PoldiPeakCollection_sptr getPeakCollectionFromFunction(const API::IFunction_sptr &fitFunction); Poldi2DFunction_sptr getFunctionFromPeakCollection( - const PoldiPeakCollection_sptr &peakCollection) const; + const PoldiPeakCollection_sptr &peakCollection); void addBackgroundTerms(Poldi2DFunction_sptr poldi2DFunction) const; API::IAlgorithm_sptr diff --git a/Code/Mantid/Framework/SINQ/inc/MantidSINQ/PoldiUtilities/PoldiMockInstrumentHelpers.h b/Code/Mantid/Framework/SINQ/inc/MantidSINQ/PoldiUtilities/PoldiMockInstrumentHelpers.h index 16e9961504594011889ba82136daed035440e580..b78bd093181ee11405158e54c5e2b469e05a7c5b 100644 --- a/Code/Mantid/Framework/SINQ/inc/MantidSINQ/PoldiUtilities/PoldiMockInstrumentHelpers.h +++ b/Code/Mantid/Framework/SINQ/inc/MantidSINQ/PoldiUtilities/PoldiMockInstrumentHelpers.h @@ -515,16 +515,16 @@ public: PoldiPeakCollection_sptr peaks( new PoldiPeakCollection(PoldiPeakCollection::Integral)); peaks->addPeak(PoldiPeak::create( - MillerIndices(0, 0, 0), UncertainValue(1.108644), + MillerIndices(4, 2, 2), UncertainValue(1.108644), UncertainValue(1.926395655), UncertainValue(0.002475747))); peaks->addPeak(PoldiPeak::create( - MillerIndices(0, 0, 0), UncertainValue(1.637539), + MillerIndices(3, 1, 1), UncertainValue(1.637539), UncertainValue(4.773980141), UncertainValue(0.002516417))); peaks->addPeak(PoldiPeak::create( - MillerIndices(0, 0, 0), UncertainValue(1.920200), + MillerIndices(2, 2, 0), UncertainValue(1.920200), UncertainValue(9.370919228), UncertainValue(0.002444439))); peaks->addPeak(PoldiPeak::create( - MillerIndices(0, 0, 0), UncertainValue(1.245958), + MillerIndices(3, 3, 1), UncertainValue(1.245958), UncertainValue(1.758037806), UncertainValue(0.002696334))); peaks->setProfileFunctionName("Gaussian"); diff --git a/Code/Mantid/Framework/SINQ/src/PoldiFitPeaks2D.cpp b/Code/Mantid/Framework/SINQ/src/PoldiFitPeaks2D.cpp index d1bd62548f5d7a926540a957fb8d66ecfe9df3ea..8a6fca0481d1817c6815e22e4caf8577e1ed6794 100644 --- a/Code/Mantid/Framework/SINQ/src/PoldiFitPeaks2D.cpp +++ b/Code/Mantid/Framework/SINQ/src/PoldiFitPeaks2D.cpp @@ -15,8 +15,11 @@ #include "MantidSINQ/PoldiUtilities/PoldiPeakCollection.h" #include "MantidSINQ/PoldiUtilities/PoldiInstrumentAdapter.h" #include "MantidSINQ/PoldiUtilities/PoldiDeadWireDecorator.h" + +#include "MantidAPI/ILatticeFunction.h" #include "MantidAPI/IPeakFunction.h" #include "MantidAPI/IPawleyFunction.h" +#include "MantidGeometry/Crystal/UnitCell.h" #include "MantidSINQ/PoldiUtilities/Poldi2DFunction.h" @@ -416,13 +419,13 @@ Poldi2DFunction_sptr PoldiFitPeaks2D::getFunctionIndividualPeaks( * * This function creates a PawleyFunction using the supplied profile function * name and the crystal system as well as initial cell from the input - *properties - * of the algorithm and wraps it in a Poldi2DFunction. + * properties of the algorithm and wraps it in a Poldi2DFunction. + * + * The cell is refined using LatticeFunction to get better starting values. * * Because the peak intensities are integral at this step but PawleyFunction * expects peak heights, a profile function is created and - *setIntensity/height- - * methods are used to convert. + * setIntensity/height-methods are used to convert. * * @param profileFunctionName :: Profile function name for PawleyFunction. * @param peakCollection :: Peak collection with peaks to be used in the fit. @@ -430,7 +433,7 @@ Poldi2DFunction_sptr PoldiFitPeaks2D::getFunctionIndividualPeaks( */ Poldi2DFunction_sptr PoldiFitPeaks2D::getFunctionPawley( std::string profileFunctionName, - const PoldiPeakCollection_sptr &peakCollection) const { + const PoldiPeakCollection_sptr &peakCollection) { Poldi2DFunction_sptr mdFunction(new Poldi2DFunction); boost::shared_ptr<PoldiSpectrumPawleyFunction> poldiPawleyFunction = @@ -452,7 +455,8 @@ Poldi2DFunction_sptr PoldiFitPeaks2D::getFunctionPawley( pawleyFunction->setCrystalSystem(crystalSystem); std::string initialCell = getProperty("InitialCell"); - pawleyFunction->setUnitCell(initialCell); + pawleyFunction->setUnitCell( + getRefinedStartingCell(initialCell, crystalSystem, peakCollection)); IPeakFunction_sptr pFun = boost::dynamic_pointer_cast<IPeakFunction>( FunctionFactory::Instance().createFunction(profileFunctionName)); @@ -474,6 +478,61 @@ Poldi2DFunction_sptr PoldiFitPeaks2D::getFunctionPawley( return mdFunction; } +/** + * Tries to refine the initial cell using the supplied peaks + * + * This method tries to refine the initial unit cell using the indexed peaks + * that are supplied in the PoldiPeakCollection. If there are unindexed peaks, + * the cell will not be refined at all, instead the unmodified initial cell + * is returned. + * + * @param initialCell :: String with the initial unit cell + * @param crystalSystem :: Crystal system name + * @param peakCollection :: Collection of bragg peaks, must be indexed + * + * @return String for refined unit cell + */ +std::string PoldiFitPeaks2D::getRefinedStartingCell( + const std::string &initialCell, const std::string &crystalSystem, + const PoldiPeakCollection_sptr &peakCollection) { + + Geometry::UnitCell cell = Geometry::strToUnitCell(initialCell); + + ILatticeFunction_sptr latticeFunction = + boost::dynamic_pointer_cast<ILatticeFunction>( + FunctionFactory::Instance().createFunction("LatticeFunction")); + + latticeFunction->setCrystalSystem(crystalSystem); + latticeFunction->fix(latticeFunction->parameterIndex("ZeroShift")); + latticeFunction->setUnitCell(cell); + + // Remove errors from d-values + PoldiPeakCollection_sptr clone = peakCollection->clone(); + for (size_t i = 0; i < clone->peakCount(); ++i) { + PoldiPeak_sptr peak = clone->peak(i); + + // If there are unindexed peaks, don't refine, just return the initial cell + if(peak->hkl() == MillerIndices()) { + return initialCell; + } + + peak->setD(UncertainValue(peak->d().value())); + } + + TableWorkspace_sptr peakTable = clone->asTableWorkspace(); + + IAlgorithm_sptr fit = createChildAlgorithm("Fit"); + fit->setProperty("Function", + boost::static_pointer_cast<IFunction>(latticeFunction)); + fit->setProperty("InputWorkspace", peakTable); + fit->setProperty("CostFunction", "Unweighted least squares"); + fit->execute(); + + Geometry::UnitCell refinedCell = latticeFunction->getUnitCell(); + + return Geometry::unitCellToStr(refinedCell); +} + /** * Constructs a proper function from a peak collection * @@ -485,7 +544,7 @@ Poldi2DFunction_sptr PoldiFitPeaks2D::getFunctionPawley( * @return Poldi2DFunction with one PoldiSpectrumDomainFunction per peak */ Poldi2DFunction_sptr PoldiFitPeaks2D::getFunctionFromPeakCollection( - const PoldiPeakCollection_sptr &peakCollection) const { + const PoldiPeakCollection_sptr &peakCollection) { std::string profileFunctionName = getProperty("PeakProfileFunction"); bool pawleyFit = getProperty("PawleyFit"); diff --git a/Code/Mantid/Framework/SINQ/test/PoldiFitPeaks2DTest.h b/Code/Mantid/Framework/SINQ/test/PoldiFitPeaks2DTest.h index 88f8e3f7f6a6d8091fa3ca2809cd59489089b625..4eb4a00e1339592e0bcd548fd1ca026df564344a 100644 --- a/Code/Mantid/Framework/SINQ/test/PoldiFitPeaks2DTest.h +++ b/Code/Mantid/Framework/SINQ/test/PoldiFitPeaks2DTest.h @@ -322,6 +322,39 @@ public: TS_ASSERT_EQUALS(funConstant->nFunctions(), 1); } + void testGetRefinedStartingCell() { + // Get Silicon peaks for testing + PoldiPeakCollection_sptr peaks = PoldiPeakCollectionHelpers::createPoldiPeakCollectionNormalized(); + + TestablePoldiFitPeaks2D alg; + + std::string refinedCell; + TS_ASSERT_THROWS_NOTHING( + refinedCell = alg.getRefinedStartingCell( + "5.4 5.4 5.4 90 90 90", + "Cubic", peaks)); + + UnitCell cell = strToUnitCell(refinedCell); + TS_ASSERT_DELTA(cell.a(), 5.43111972, 1e-8); + + // With less accurate starting parameters the result should not change + TS_ASSERT_THROWS_NOTHING( + refinedCell = alg.getRefinedStartingCell( + "5 5 5 90 90 90", + "Cubic", peaks)); + + cell = strToUnitCell(refinedCell); + TS_ASSERT_DELTA(cell.a(), 5.43111972, 1e-8); + + // Adding an unindexed peak should make the function return the initial + peaks->addPeak(PoldiPeak::create(UncertainValue(1.0))); + TS_ASSERT_THROWS_NOTHING( + refinedCell = alg.getRefinedStartingCell( + "5 5 5 90 90 90", + "Cubic", peaks)); + TS_ASSERT_EQUALS(refinedCell, "5 5 5 90 90 90"); + } + private: PoldiInstrumentAdapter_sptr m_instrument; PoldiTimeTransformer_sptr m_timeTransformer; diff --git a/Code/Mantid/Framework/WorkflowAlgorithms/src/DgsConvertToEnergyTransfer.cpp b/Code/Mantid/Framework/WorkflowAlgorithms/src/DgsConvertToEnergyTransfer.cpp index 643c68fa0c224c341f035d3ac669c0a0104e56e9..a53fdd1f244980b7e9f648600b64bdc9536e7875 100644 --- a/Code/Mantid/Framework/WorkflowAlgorithms/src/DgsConvertToEnergyTransfer.cpp +++ b/Code/Mantid/Framework/WorkflowAlgorithms/src/DgsConvertToEnergyTransfer.cpp @@ -199,7 +199,14 @@ void DgsConvertToEnergyTransfer::exec() { loadmon->setProperty(fileProp, runFileName); loadmon->setProperty("OutputWorkspace", monWsName); loadmon->executeAsChildAlg(); - monWS = loadmon->getProperty("OutputWorkspace"); + Workspace_sptr monWSOutput = loadmon->getProperty("OutputWorkspace"); + // the algorithm can return a group workspace if the file is multi period + monWS = boost::dynamic_pointer_cast<MatrixWorkspace>(monWSOutput); + if ((monWSOutput) && (!monWS)) { + //this was a group workspace - DGSReduction does not support multi period data yet + throw Exception::NotImplementedError( + "The file contains multi period data, support for this is not implemented in DGSReduction yet"); + } } // Calculate Ei diff --git a/Code/Mantid/Framework/WorkflowAlgorithms/src/EQSANSLoad.cpp b/Code/Mantid/Framework/WorkflowAlgorithms/src/EQSANSLoad.cpp index 5979526d9cf6e210b5739384de23cb02afffdfd1..8a2fcae8bfed5f8d2db29916532b8aa1a1a571dc 100644 --- a/Code/Mantid/Framework/WorkflowAlgorithms/src/EQSANSLoad.cpp +++ b/Code/Mantid/Framework/WorkflowAlgorithms/src/EQSANSLoad.cpp @@ -515,7 +515,13 @@ void EQSANSLoad::exec() { // Get monitor workspace as necessary std::string mon_wsname = getPropertyValue("OutputWorkspace") + "_monitors"; if (loadMonitors && loadAlg->existsProperty("MonitorWorkspace")) { - MatrixWorkspace_sptr monWS = loadAlg->getProperty("MonitorWorkspace"); + Workspace_sptr monWSOutput = loadAlg->getProperty("MonitorWorkspace"); + MatrixWorkspace_sptr monWS = boost::dynamic_pointer_cast<MatrixWorkspace>(monWSOutput); + if ((monWSOutput) && (!monWS)) { + //this was a group workspace - EQSansLoad does not support multi period data yet + throw Exception::NotImplementedError( + "The file contains multi period data, support for this is not implemented in EQSANSLoad yet"); + } declareProperty(new WorkspaceProperty<>("MonitorWorkspace", mon_wsname, Direction::Output), "Monitors from the Event NeXus file"); diff --git a/Code/Mantid/MantidPlot/CMakeLists.txt b/Code/Mantid/MantidPlot/CMakeLists.txt index 9f29500113401f8df91ae1b8a4b3e41ae73b640c..d56c8dcc52b525973bb1f9a90cca805918575fb7 100644 --- a/Code/Mantid/MantidPlot/CMakeLists.txt +++ b/Code/Mantid/MantidPlot/CMakeLists.txt @@ -851,21 +851,14 @@ copy_files_to_dir ( "${PY_FILES}" set( MTDPLOTPY_FILES __init__.py proxies.py + pyplot.py + qtiplot.py ) copy_files_to_dir ( "${MTDPLOTPY_FILES}" ${CMAKE_CURRENT_SOURCE_DIR}/pymantidplot ${CMAKE_LIBRARY_OUTPUT_DIRECTORY}/${CMAKE_CFG_INTDIR}/pymantidplot MTDPLOT_INSTALL_FILES ) -set( FUTURE_FILES - __init__.py - pyplot.py -) -copy_files_to_dir ( "${FUTURE_FILES}" - ${CMAKE_CURRENT_SOURCE_DIR}/pymantidplot/future - ${CMAKE_LIBRARY_OUTPUT_DIRECTORY}/${CMAKE_CFG_INTDIR}/pymantidplot/future - MTDPLOT_FUTURE_INSTALL_FILES ) - # IPython scripts set( IPY_FILES __init__.py @@ -883,7 +876,7 @@ copy_files_to_dir ( "${IPY_FILES}" add_executable ( MantidPlot ${WIN_CONSOLE} MACOSX_BUNDLE ${ALL_SRC} src/main.cpp ${INC_FILES} ${QTIPLOT_C_SRC} ${UI_HDRS} ${RES_FILES} ${MANTID_RC_FILE} - ${PYTHON_INSTALL_FILES} ${MTDPLOT_INSTALL_FILES} ${CONFIG_RESET_SCRIPT_FILE} ${MTDPLOT_FUTURE_INSTALL_FILES} ${IPYTHON_INSTALL_FILES} + ${PYTHON_INSTALL_FILES} ${MTDPLOT_INSTALL_FILES} ${CONFIG_RESET_SCRIPT_FILE} ${IPYTHON_INSTALL_FILES} ) # Library dependencies @@ -959,7 +952,7 @@ set ( MANTIDPLOT_TEST_PY_FILES MantidPlotMdiSubWindowTest.py MantidPlotTiledWindowTest.py MantidPlotInputArgsCheck.py - MantidPlotFuturePyplotGeneralTest.py + MantidPlotPyplotGeneralTest.py ) if ( 0 ) @@ -1025,9 +1018,6 @@ install ( FILES ${PY_FILES} DESTINATION ${BIN_DIR} ) foreach(PY_FILE ${MTDPLOTPY_FILES} ) install ( FILES pymantidplot/${PY_FILE} DESTINATION ${BIN_DIR}/pymantidplot ) endforeach() -foreach(FUT_PY_FILE ${FUTURE_FILES} ) - install ( FILES pymantidplot/future/${FUT_PY_FILE} DESTINATION ${BIN_DIR}/pymantidplot/future ) -endforeach() foreach(PY_FILE ${IPY_FILES} ) install ( FILES ipython_widget/${PY_FILE} DESTINATION ${BIN_DIR}/ipython_widget ) endforeach() diff --git a/Code/Mantid/MantidPlot/mantidplot.py b/Code/Mantid/MantidPlot/mantidplot.py index e710b1a0e074d9559e17a802f1b3e8594836efdc..ee4980b5b44c35c39726d40a1b847a98cb0bdbf0 100644 --- a/Code/Mantid/MantidPlot/mantidplot.py +++ b/Code/Mantid/MantidPlot/mantidplot.py @@ -10,3 +10,15 @@ try: from pymantidplot import * except ImportError: raise ImportError('Could not import mantidplot (when trying to import pymantidplot). Something is broken in this installation, please check.') + +try: + # import pyplot and also bring it into the standard MantidPlot namespace + import pymantidplot.pyplot + from pymantidplot.pyplot import * +except ImportError: + raise ImportError('Could not import pymantidplot.pyplot. Something is broken in this installation, please check.') + +try: + import pymantidplot.qtiplot +except ImportError: + raise ImportError('Could not import pymantidplot.qtiplot. Something is broken in this installation, please check.') diff --git a/Code/Mantid/MantidPlot/pymantidplot/__init__.py b/Code/Mantid/MantidPlot/pymantidplot/__init__.py index 4efc74e7e20a04943e3235885b8157bd6a69a99f..4e624105398350cd560133150e97c367fbf5a396 100644 --- a/Code/Mantid/MantidPlot/pymantidplot/__init__.py +++ b/Code/Mantid/MantidPlot/pymantidplot/__init__.py @@ -183,23 +183,6 @@ def newTiledWindow(name=None): else: return new_proxy(proxies.TiledWindowProxy, _qti.app.newTiledWindow, name) -#----------------------------------------------------------------------------- -# Intercept qtiplot "plot" command and forward to plotSpectrum for a workspace -def plot(source, *args, **kwargs): - """Create a new plot given a workspace, table or matrix. - - Args: - source: what to plot; if it is a Workspace, will - call plotSpectrum() - - Returns: - A handle to the created Graph widget. - """ - if hasattr(source, '_getHeldObject') and isinstance(source._getHeldObject(), QtCore.QObject): - return new_proxy(proxies.Graph,_qti.app.plot, source._getHeldObject(), *args, **kwargs) - else: - return plotSpectrum(source, *args, **kwargs) - #---------------------------------------------------------------------------------------------------- def plotSpectrum(source, indices, error_bars = False, type = -1, window = None, clearWindow = False, waterfall = False): diff --git a/Code/Mantid/MantidPlot/pymantidplot/future/__init__.py b/Code/Mantid/MantidPlot/pymantidplot/future/__init__.py deleted file mode 100644 index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..0000000000000000000000000000000000000000 diff --git a/Code/Mantid/MantidPlot/pymantidplot/future/pyplot.py b/Code/Mantid/MantidPlot/pymantidplot/pyplot.py similarity index 91% rename from Code/Mantid/MantidPlot/pymantidplot/future/pyplot.py rename to Code/Mantid/MantidPlot/pymantidplot/pyplot.py index 62813a5f99d43a391dd5c40bcca15c5976819cee..78254a217a834b431def7b0f1a414869f43a46fd 100644 --- a/Code/Mantid/MantidPlot/pymantidplot/future/pyplot.py +++ b/Code/Mantid/MantidPlot/pymantidplot/pyplot.py @@ -10,17 +10,8 @@ plot options. The module is at a very early stage of development and provides limited functionality. This is very much work in progress at the -moment. The module is subject to changes and it is for now included in -Mantid as a 'future' import. Feedback is very much welcome! - -To use this new functionality you first need to import the new pyplot module: - -.. code-block:: python - - from pymantidplot.future.pyplot import * - -Please do not forget this step, otherwise you may get arcane error -messages from functions of the old mantidplot Python CLI. +moment. The module is subject to changes and feedback is very much +welcome! Simple plots can be created and manipulated with a handul of commands. See the following examples. @@ -65,7 +56,7 @@ Plot a Mantid workspace You can pass one or more workspaces to the plot function. By default it will plot the spectra of the workspace(s), selecting them by the indices specified in the second argument. This behavior is similar to -he plotSpectrum function of the traditional mantidplot module. This is +the plotSpectrum function of the traditional mantidplot module. This is a simple example that produces plots of spectra: .. code-block:: python @@ -77,11 +68,49 @@ a simple example that produces plots of spectra: # 3 spectra plot plot(ws, [100, 101, 102]) +======================== +Different types of plots +======================== + +The plot() function provides a unified interface to different types of +plots, including specific graphs of spectra, bins, multidimensional +workspaces, etc. These specific types of plots are explained in the +next sections. plot() makes a guess as to what tool to use to plot a +workspace. For example, if you pass an MD workspace it will make an MD +plot. But you can request a specific type of plot by specifying a +keyword argument ('tool'). The following tools (or different types of +plots) are supported: + ++------------------------+------------------------------------------------------------+-----------------------+ +| Tool | tool= parameter values (all are equivalent aliases) | Old similar function | ++========================+============================================================+=======================+ +| plot spectra (default) | 'plot_spectrum', 'spectrum', 'plot_sp', 'sp' | plotSpectrum | ++------------------------+------------------------------------------------------------+-----------------------+ +| plot bins | 'plot_bin', 'bin' | plotBin | ++------------------------+------------------------------------------------------------+-----------------------+ +| plot MD | 'plot_md', 'md' | plotMD | ++------------------------+------------------------------------------------------------+-----------------------+ + +The last column of the table lists the functions that produce similar +plots in the traditional MantidPlot Python plotting interface. For the +time being this module only supports these types of specific +plots. Note that the traditional plotting interface of MantidPlot +provides support for many more specific types of plots. These or +similar ones will be added in this module in future releases: + +* plot2D +* plot3D +* plotSlice +* instrumentWindow +* waterFallPlot +* mergePlots +* stemPlot + Plot spectra using workspace objects and workspace names -------------------------------------------------------- It is also possible to pass workspace names to plot, as in the -following example: +following example where we plot a few spectra: .. code-block:: python @@ -108,11 +137,14 @@ names in the list passed to plot: Here, the plot function is making a guess and plotting the spectra of these workspaces (instead of the bins or anything else). You can make -that choice more explicit by specifying the 'tool' argument: +that choice more explicit by specifying the 'tool' argument. In this +case we use 'plot_spectrum' (which also has shorter aliases: +'spectrum', or simply 'sp' as listed in the table above): .. code-block:: python plot(['MAR11060', loq], [800, 900], tool='plot_spectrum') + plot(['MAR11060', loq], [801, 901], tool='sp') Alternatively, you can use the plot_spectrum command, which is equivalent to the plot command with the keyword argument @@ -126,7 +158,7 @@ Plotting bins ------------- To plot workspace bins you can use the keyword 'tool' with the value -'plot_bin', like this: +'plot_bin' (or equivalent 'bin'), like this: .. code-block:: python @@ -143,7 +175,7 @@ Plotting MD workspaces ---------------------- Similarly, to plot MD workspaces you can use the keyword 'tool' with -the value 'plot_md', like this: +the value 'plot_md' (or 'md' as a short alias), like this: .. code-block:: python @@ -161,8 +193,9 @@ to the Mantid (http://www.mantidproject.org/MBC_MDWorkspaces) for a more real example, which necessarily gets more complicated and data intensive. +========================= Changing style properties -------------------------- +========================= You can modify the style of your plots. For example like this (for a full list of options currently supported, see below). @@ -273,9 +306,9 @@ results. Multi-plot commands ------------------- -In this version of future.pyplot there is limited support for -multi-plot commands (as in pyplot and matlab). For example, you can -type commands like the following: +In this version of pyplot there is limited support for multi-plot +commands (as in pyplot and matlab). For example, you can type commands +like the following: .. code-block:: python @@ -368,11 +401,35 @@ to the more object oriented methods described above. For example, the function xlabel is equivalent to the method set_xlabel applied on the Axes object for the current figure. +This module is by default imported into the standard MantidPlot +namespace. You can use the functions and classes included here without +any prefix or adding this module name prefix (pymantidplot.pyplot), as +in the following example: + +.. code-block:: python + + # Two equivalent lines: + pymantidplot.pyplot.plot([1, 3, 2]) + plot([1, 3, 2]) + +Note that the plot() function of this module has replaced the +traditional plot() function of MantidPlot which has been moved into a +package called qtiplot. To use it you can do as follows: + +.. code-block:: python + + pymantidplot.qtiplot.plot('MAR11060', [800, 801]) + # or if you prefer shorter prefixes: + import pymantidplot.qtiplot as qtiplt + qtiplt.plot('MAR11060', [800, 801]) + + Below is the reference documentation of the classes and functions included in this module. """ -# Copyright © 2007-2014 ISIS Rutherford Appleton Laboratory & NScD Oak Ridge National Laboratory +# Copyright © 2014-2015 ISIS Rutherford Appleton Laboratory, NScD +# Oak Ridge National Laboratory & European Spallation Source # # This file is part of Mantid. # Mantid is free software; you can redistribute it and/or modify @@ -394,7 +451,7 @@ included in this module. try: import _qti except ImportError: - raise ImportError('The \'mantidplot\' and \'pymantidplot.future.pyplot\' modules can only be used from within MantidPlot.') + raise ImportError('The \'mantidplot\' and \'pymantidplot.pyplot\' modules can only be used from within MantidPlot.') import numpy as np from PyQt4 import Qt, QtGui, QtCore @@ -404,13 +461,6 @@ from mantid.api import mtd from mantid.simpleapi import CreateWorkspace as CreateWorkspace import mantidplot -print ("You are loading '" + __name__ + "', which is an experimental module." + -""" -Please note: this module is at a very early stage of development and -provides limited functionality. It is work in progress and is subject -to change. Feedback is very much welcome! Please let us know any wishes -and suggestions.""") - class Line2D(): """ A very minimal replica of matplotlib.Line.Line2D. The true Line2D @@ -1225,19 +1275,21 @@ def __plot_as_array(*args, **kwargs): return __list_of_lines_from_graph(graph) def __plot_with_tool(tool, *args, **kwargs): - bin_tool_name = 'plot_bin' - spectrum_tool_name = 'plot_spectrum' - md_tool_name = 'plot_md' + bin_tool_names = ['plot_bin', 'bin'] + spectrum_tool_names = ['plot_spectrum', 'plot_sp', 'spectrum', 'sp'] + md_tool_names = ['plot_md', 'md'] - if bin_tool_name == tool or spectrum_tool_name == tool: - if len(args) < 2: - raise ValueError("To plot using %s as a tool you need to give at least two parameters"%tool) + if len(args) < 2: + if tool in bin_tool_names: + raise ValueError("To plot bins (using '%s' as tool) you need to give at least two parameters, where the second parameter selects the bins"%tool) + elif tool in spectrum_tool_names: + raise ValueError("To plot spectra (using '%s' as tool) you need to give at least two parameters, where the second parameter selects the spectrum(a)"%tool) - if bin_tool_name == tool: + if tool in bin_tool_names: return plot_bin(args[0], args[1], *args[2:], **kwargs) - elif md_tool_name == tool: + elif tool in md_tool_names: return plot_md(args[0], *args[1:], **kwargs) - elif spectrum_tool_name == tool: + elif tool in spectrum_tool_names: return plot_spectrum(args[0], args[1], *args[2:], **kwargs) # here you would add slice/spectrum/instrument viewer, etc. and maybe you'll want to put them in a dict else: @@ -1363,11 +1415,11 @@ def plot(*args, **kwargs): parameters, for example: linewidth, linestyle, marker, color. An important keyword argument is tool. At the moment the - following values are supported: + following values are supported (they have long and short aliases): - * plot_spectrum (default for workspaces) - * plot_bin - * plot_md + * To plot spectra: 'plot_spectrum' OR 'spectrum' OR 'plot_sp' OR 'sp' (default for workspaces). + * To plot bins: 'plot_bin' OR 'bin' + * To do an MD plot: 'plot_md' OR 'md' Please see the documentation of this module (use help()) for more details. diff --git a/Code/Mantid/MantidPlot/pymantidplot/qtiplot.py b/Code/Mantid/MantidPlot/pymantidplot/qtiplot.py new file mode 100644 index 0000000000000000000000000000000000000000..378cfc074d06941b3bc0e49ffadff11c17bfe5ad --- /dev/null +++ b/Code/Mantid/MantidPlot/pymantidplot/qtiplot.py @@ -0,0 +1,35 @@ +""" +MantidPlot module with functions specific to the traditional, +qti-based MantidPlot Python plotting interface + +As with other MantidPlot modules, this has to run from within MantidPlot + +""" +# Require MantidPlot +try: + import _qti +except ImportError: + raise ImportError('The "mantidplot.qtiplot" module can only be used from within MantidPlot.') + +import pymantidplot +from PyQt4 import QtCore + +#----------------------------------------------------------------------------- +# Intercept qtiplot "plot" command and forward to plotSpectrum for a workspace +# +# This function has been moved inside qtiplot when pymantidplot.pyplot (which +# has another plot() function) was imported into the standard MantidPlot namespace +def plot(source, *args, **kwargs): + """Create a new plot given a workspace, table or matrix. + + Args: + source: what to plot; if it is a Workspace, will + call plotSpectrum() + + Returns: + A handle to the created Graph widget. + """ + if hasattr(source, '_getHeldObject') and isinstance(source._getHeldObject(), QtCore.QObject): + return pymantidplot.proxies.new_proxy(pymantidplot.proxies.Graph,_qti.app.plot, source._getHeldObject(), *args, **kwargs) + else: + return pymantidplot.plotSpectrum(source, *args, **kwargs) diff --git a/Code/Mantid/MantidPlot/test/MantidPlot1DPlotTest.py b/Code/Mantid/MantidPlot/test/MantidPlot1DPlotTest.py index 9f30dff27a0ba10eb14830bade7394e3f902d017..8f8ac606adddecef727912acb44ded5feae4f1ce 100644 --- a/Code/Mantid/MantidPlot/test/MantidPlot1DPlotTest.py +++ b/Code/Mantid/MantidPlot/test/MantidPlot1DPlotTest.py @@ -74,7 +74,7 @@ class MantidPlot1DPlotTest(unittest.TestCase): t.setCell(3, i, i+2) t.setCell(4, i, i+4) - g = plot(t, (2,3,4), Layer.Line) + g = pymantidplot.qtiplot.plot(t, (2,3,4), Layer.Line) self.g = g l = g.activeLayer() # Plot columns 2, 3 and 4 for i in range(0, l.numCurves()): diff --git a/Code/Mantid/MantidPlot/test/MantidPlotProxiesTest.py b/Code/Mantid/MantidPlot/test/MantidPlotProxiesTest.py index b1c355684955c2ed5555e66e5536ad542573ae6c..31c614b211bae9c580d2becfe6afd402e744add3 100644 --- a/Code/Mantid/MantidPlot/test/MantidPlotProxiesTest.py +++ b/Code/Mantid/MantidPlot/test/MantidPlotProxiesTest.py @@ -137,7 +137,7 @@ class MantidPlotProxiesTest(unittest.TestCase): self.try_closing(iv, "getInstrumentView()") def test_convertToWaterfall(self): - g = plot(workspace("IRS26173"),(0,1,2,3,4)) + g = pymantidplot.qtiplot.plot(workspace("IRS26173"),(0,1,2,3,4)) convertToWaterfall(g) self.try_closing(g, "convertToWaterfall()") diff --git a/Code/Mantid/MantidPlot/test/MantidPlotFuturePyplotGeneralTest.py b/Code/Mantid/MantidPlot/test/MantidPlotPyplotGeneralTest.py similarity index 77% rename from Code/Mantid/MantidPlot/test/MantidPlotFuturePyplotGeneralTest.py rename to Code/Mantid/MantidPlot/test/MantidPlotPyplotGeneralTest.py index ebf9ecafc84242265281fc5d6265f22d8b45144d..e18de9c6307920c4749a63c30dff9ae08f73bc0b 100644 --- a/Code/Mantid/MantidPlot/test/MantidPlotFuturePyplotGeneralTest.py +++ b/Code/Mantid/MantidPlot/test/MantidPlotPyplotGeneralTest.py @@ -1,4 +1,4 @@ -"""General tests for the basic interface of mantidplot.future.pyplot +"""General tests for the basic interface of mantidplot.pyplot Tests correct creation of output lines from plots (with correct Figure, Graph, etc. data), and proper handling (exception) of wrong @@ -11,9 +11,6 @@ import time import numpy as np from PyQt4 import QtGui, QtCore -# Future pyplot -from pymantidplot.future.pyplot import * - # =============== Create fake workspaces to plot ======================= X1 = np.linspace(0,10, 100) Y1 = 1000*(np.sin(X1)**2) + X1*10 @@ -51,7 +48,7 @@ mdSignal = np.sin(range(0,100,1)) errInput = mdSignal/20.5 CreateMDHistoWorkspace(Dimensionality="1", Names='x', Units='m', Extents='0,10', NumberOfBins=len(mdSignal), SignalInput=mdSignal, ErrorInput=errInput, OutputWorkspace=MDWWorkspaceName) -class MantidPlotFuturePyplotGeneralTest(unittest.TestCase): +class MantidPlotPyplotGeneralTest(unittest.TestCase): def setUp(self): self.g = None @@ -89,32 +86,36 @@ class MantidPlotFuturePyplotGeneralTest(unittest.TestCase): self.close_win_by_graph(lines[0]._graph) def test_plot_spectrum_ok(self): - lines = plot(WorkspaceName2D, [0, 1], tool='plot_spectrum') - self.check_output_lines(lines, 2) - self.close_win(lines) - lines_spec = plot_spectrum(WorkspaceName2D, [0, 1]) self.check_output_lines(lines_spec, 2) self.close_win(lines_spec) - if self.assertTrue(len(lines) == len(lines_spec)): - for i in range(0, len(lines)): - self.assertEqual(lines[i].get_xdata(), lines_spec[i].get_xdata()) - self.assertEqual(lines[i].get_ydata(), lines_spec[i].get_ydata()) + tool_names = ['plot_spectrum', 'plot_sp', 'spectrum', 'sp'] + for tname in tool_names: + lines = plot(WorkspaceName2D, [0, 1], tool=tname) + self.check_output_lines(lines, 2) + self.close_win(lines) - def test_plot_bin_ok(self): - lines = plot(WorkspaceName2D, [0, 1, 2], tool='plot_bin') - self.check_output_lines(lines, 3) - self.close_win(lines) + if self.assertTrue(len(lines) == len(lines_spec)): + for i in range(0, len(lines)): + self.assertEqual(lines[i].get_xdata(), lines_spec[i].get_xdata()) + self.assertEqual(lines[i].get_ydata(), lines_spec[i].get_ydata()) + def test_plot_bin_ok(self): lines_bin = plot_bin(WorkspaceName2D, [0, 1, 2]) self.check_output_lines(lines_bin, 3) self.close_win(lines_bin) - if self.assertTrue(len(lines) == len(lines_bin)): - for i in range(0, len(lines)): - self.assertEqual(lines[i].get_xdata(), lines2_bin[i].get_xdata()) - self.assertEqual(lines[i].get_ydata(), lines2_bin[i].get_ydata()) + tool_names = ['plot_bin', 'bin'] + for tname in tool_names: + lines = plot(WorkspaceName2D, [0, 1, 2], tool=tname) + self.check_output_lines(lines, 3) + self.close_win(lines) + + if self.assertTrue(len(lines) == len(lines_bin)): + for i in range(0, len(lines)): + self.assertEqual(lines[i].get_xdata(), lines2_bin[i].get_xdata()) + self.assertEqual(lines[i].get_ydata(), lines2_bin[i].get_ydata()) def test_lines_get_data(self): y = [0.2, 0.5, 0.1, 0.6] @@ -134,18 +135,20 @@ class MantidPlotFuturePyplotGeneralTest(unittest.TestCase): self.assertEqual(len(lines), 1) self.close_win(lines) - lines = plot(MDWWorkspaceName, tool='plot_md') - self.assertEqual(len(lines), 1) - self.close_win(lines) + tool_names = ['plot_md', 'md'] + for tnames in tool_names: + lines = plot(MDWWorkspaceName, tool='plot_md') + self.assertEqual(len(lines), 1) + self.close_win(lines) # now see what happens with non-md workspaces try: - self.assertRaises(ValueError, plot(WorkspaceName2D, tool='plot_md'), "wont see this") + self.assertRaises(ValueError, plot(WorkspaceName2D, tool='plot_md'), "won't see this") except: print "Failed, as it should" try: - self.assertRaises(ValueError, plot_md(WorkspaceName2D), "wont see this") + self.assertRaises(ValueError, plot_md(WorkspaceName2D), "won't see this") except: print "Failed, as it should" @@ -169,20 +172,22 @@ class MantidPlotFuturePyplotGeneralTest(unittest.TestCase): self.close_win(lines) def test_plot_with_style_args(self): + # note that these tests also use various aliases for the tool name 'plot_spectrum' + # Not adding all the possible combinations here, as this suite is becoming time consuming lines = plot(WorkspaceName2D, [0,1], '--g', tool='plot_spectrum') self.check_output_lines(lines, 2) self.close_win(lines) - lines = plot(WorkspaceName2D, [0,1], 'y:>', tool='plot_spectrum') + lines = plot(WorkspaceName2D, [0,1], 'y:>', tool='plot_sp') self.check_output_lines(lines, 2) self.close_win(lines) def test_plot_with_style_args_and_kwargs(self): - lines = plot(WorkspaceName2D, [0,1], '-.m', tool='plot_spectrum') + lines = plot(WorkspaceName2D, [0,1], '-.m', tool='spectrum') self.check_output_lines(lines, 2) self.close_win(lines) - lines = plot(WorkspaceName2D, [0,1], 'r-.>', tool='plot_spectrum') + lines = plot(WorkspaceName2D, [0,1], 'r-.>', tool='sp') self.check_output_lines(lines, 2) self.close_win(lines) @@ -191,11 +196,11 @@ class MantidPlotFuturePyplotGeneralTest(unittest.TestCase): self.check_output_lines(lines, 2) self.close_win(lines) - lines = plot(WorkspaceName2D, [0,1], tool='plot_spectrum', linewidth=3, linestyle='-.', marker='v') + lines = plot(WorkspaceName2D, [0,1], tool='plot_sp', linewidth=3, linestyle='-.', marker='v') self.check_output_lines(lines, 2) self.close_win(lines) - lines = plot(SecondWorkspaceName2D, [0,1, 2], tool='plot_spectrum', linewidth=3, linestyle='-.', marker='v') + lines = plot(SecondWorkspaceName2D, [0,1, 2], tool='sp', linewidth=3, linestyle='-.', marker='v') self.check_output_lines(lines, 3) self.close_win(lines) @@ -221,4 +226,4 @@ class MantidPlotFuturePyplotGeneralTest(unittest.TestCase): print "Failed, as it should" # Run the unit tests -mantidplottests.runTests(MantidPlotFuturePyplotGeneralTest) +mantidplottests.runTests(MantidPlotPyplotGeneralTest) diff --git a/Code/Mantid/MantidQt/CustomInterfaces/src/Muon/ALCDataLoadingPresenter.cpp b/Code/Mantid/MantidQt/CustomInterfaces/src/Muon/ALCDataLoadingPresenter.cpp index a9eee4fe131641d2b8289e3b4273e13f8b229a96..44525f8a6f09b1ebe01568c097f683a630de738e 100644 --- a/Code/Mantid/MantidQt/CustomInterfaces/src/Muon/ALCDataLoadingPresenter.cpp +++ b/Code/Mantid/MantidQt/CustomInterfaces/src/Muon/ALCDataLoadingPresenter.cpp @@ -6,6 +6,8 @@ #include "MantidQtCustomInterfaces/Muon/MuonAnalysisHelper.h" #include "MantidQtAPI/AlgorithmInputHistory.h" +#include <Poco/ActiveResult.h> + #include <QApplication> #include <QFileInfo> #include <QDir> @@ -87,7 +89,17 @@ namespace CustomInterfaces } alg->setPropertyValue("OutputWorkspace", "__NotUsed"); - alg->execute(); + + // Execute async so we can show progress bar + Poco::ActiveResult<bool> result(alg->executeAsync()); + while( !result.available() ) + { + QCoreApplication::processEvents(); + } + if (!result.error().empty()) + { + throw std::runtime_error(result.error()); + } m_loadedData = alg->getProperty("OutputWorkspace"); diff --git a/Code/Mantid/Testing/SystemTests/tests/analysis/CodeConventions.py b/Code/Mantid/Testing/SystemTests/tests/analysis/CodeConventions.py index ed6448af74601dcc3d328add7a295ea60e0049ca..ee72b67ef86ec7fbd4c947ea9cb0f7857fc398c2 100644 --- a/Code/Mantid/Testing/SystemTests/tests/analysis/CodeConventions.py +++ b/Code/Mantid/Testing/SystemTests/tests/analysis/CodeConventions.py @@ -58,6 +58,7 @@ FUNC_BAD_PARAMS = { "StretchedExpFT":("height", "tau", "beta"), "PawleyParameterFunction":("a","b","c"), "PawleyFunction":("f0.a","f0.b","f0.c", "f0.Alpha", "f0.Beta", "f0.Gamma", "f0.ZeroShift"), + "LatticeFunction":("a","b","c") } class Algorithms(stresstesting.MantidStressTest): diff --git a/Code/Mantid/Testing/SystemTests/tests/analysis/POLDIFitPeaks2DTest.py b/Code/Mantid/Testing/SystemTests/tests/analysis/POLDIFitPeaks2DTest.py index 3d127c8a9938a0d968744d9b75f6a6b7457afc26..ba5ecf119d0d020e6bfdcaa9a15f4d5baf6bc9bb 100644 --- a/Code/Mantid/Testing/SystemTests/tests/analysis/POLDIFitPeaks2DTest.py +++ b/Code/Mantid/Testing/SystemTests/tests/analysis/POLDIFitPeaks2DTest.py @@ -93,7 +93,7 @@ class POLDIFitPeaks2DPawleyTest(stresstesting.MantidStressTest): si_refs = PoldiCreatePeaksFromCell("F d -3 m", "Si 0 0 0", a=5.431, LatticeSpacingMin=0.7) indexed = PoldiIndexKnownCompounds(peaks_ref, "si_refs") - DeleteTableRows("indexed_si_refs", "10-30") + DeleteTableRows("indexed_si_refs", "8-30") fit2d, fit1d, peaks_ref_2d, cell = PoldiFitPeaks2D('si_data_6904', 'indexed_si_refs', PawleyFit=True, diff --git a/Code/Mantid/Testing/SystemTests/tests/analysis/UnweightedLeastSquaresTest.py b/Code/Mantid/Testing/SystemTests/tests/analysis/UnweightedLeastSquaresTest.py new file mode 100644 index 0000000000000000000000000000000000000000..d1d819298fa396304adcc1e78ce752bab3f578f8 --- /dev/null +++ b/Code/Mantid/Testing/SystemTests/tests/analysis/UnweightedLeastSquaresTest.py @@ -0,0 +1,136 @@ +# pylint: disable=no-init,invalid-name,too-few-public-methods +# +# These system test perform some of the fits provided by NIST for non-linear +# least square systems that can be found here: +# http://www.itl.nist.gov/div898/strd/nls/nls_main.shtml +import stresstesting +from mantid.simpleapi import * + + +def runFit(x, y, fn): + ws = CreateWorkspace(x, y) + + Fit(fn, ws, Output='ws', + Minimizer='Levenberg-Marquardt', + CostFunction="Unweighted least squares") + + param_table = mtd['ws_Parameters'] + + params = param_table.column(1)[:-1] + errors = param_table.column(2)[:-1] + + return params, errors + + +class LeastSquaresNISTRat43Test(stresstesting.MantidStressTest): + def runTest(self): + x = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15] + y = [16.08, 33.83, 65.8, 97.2, 191.55, 326.2, 386.87, 520.53, 590.03, 651.92, 724.93, 699.56, 689.96, 637.56, + 717.41] + + function = 'name=UserFunction,Formula=b1/((1+exp(b2-b3*x))^(1/b4)),b1=700,b2=5,b3=0.75,b4=1.3' + + params, errors = runFit(x, y, function) + + expected_params = [6.9964151270E+02, 5.2771253025E+00, 7.5962938329E-01, 1.2792483859E+00] + expected_errors = [1.6302297817E+01, 2.0828735829E+00, 1.9566123451E-01, 6.8761936385E-01] + + for err, expected in zip(errors, expected_errors): + self.assertDelta(err / expected - 1.0, 0.0, 3e-2) + + for val, expected in zip(params, expected_params): + self.assertDelta(val / expected - 1.0, 0.0, 3e-3) + + +class LeastSquaresNISTGauss3Test(stresstesting.MantidStressTest): + def runTest(self): + x = [1.000000, 2.000000, 3.000000, 4.000000, 5.000000, 6.000000, 7.000000, 8.000000, 9.000000, 10.000000, + 11.00000, 12.00000, 13.00000, 14.00000, 15.00000, 16.00000, 17.00000, 18.00000, 19.00000, 20.00000, + 21.00000, 22.00000, 23.00000, 24.00000, 25.00000, 26.00000, 27.00000, 28.00000, 29.00000, 30.00000, + 31.00000, 32.00000, 33.00000, 34.00000, 35.00000, 36.00000, 37.00000, 38.00000, 39.00000, 40.00000, + 41.00000, 42.00000, 43.00000, 44.00000, 45.00000, 46.00000, 47.00000, 48.00000, 49.00000, 50.00000, + 51.00000, 52.00000, 53.00000, 54.00000, 55.00000, 56.00000, 57.00000, 58.00000, 59.00000, 60.00000, + 61.00000, 62.00000, 63.00000, 64.00000, 65.00000, 66.00000, 67.00000, 68.00000, 69.00000, 70.00000, + 71.00000, 72.00000, 73.00000, 74.00000, 75.00000, 76.00000, 77.00000, 78.00000, 79.00000, 80.00000, + 81.00000, 82.00000, 83.00000, 84.00000, 85.00000, 86.00000, 87.00000, 88.00000, 89.00000, 90.00000, + 91.00000, 92.00000, 93.00000, 94.00000, 95.00000, 96.00000, 97.00000, 98.00000, 99.00000, 100.00000, + 101.00000, 102.00000, 103.00000, 104.00000, 105.00000, 106.0000, 107.0000, 108.0000, 109.0000, 110.0000, + 111.0000, 112.0000, 113.0000, 114.0000, 115.0000, 116.0000, 117.0000, 118.0000, 119.0000, 120.0000, + 121.0000, 122.0000, 123.0000, 124.0000, 125.0000, 126.0000, 127.0000, 128.0000, 129.0000, 130.0000, + 131.0000, 132.0000, 133.0000, 134.0000, 135.0000, 136.0000, 137.0000, 138.0000, 139.0000, 140.0000, + 141.0000, 142.0000, 143.0000, 144.0000, 145.0000, 146.0000, 147.0000, 148.0000, 149.0000, 150.0000, + 151.0000, 152.0000, 153.0000, 154.0000, 155.0000, 156.0000, 157.0000, 158.0000, 159.0000, 160.0000, + 161.0000, 162.0000, 163.0000, 164.0000, 165.0000, 166.0000, 167.0000, 168.0000, 169.0000, 170.0000, + 171.0000, 172.0000, 173.0000, 174.0000, 175.0000, 176.0000, 177.0000, 178.0000, 179.0000, 180.0000, + 181.0000, 182.0000, 183.0000, 184.0000, 185.0000, 186.0000, 187.0000, 188.0000, 189.0000, 190.0000, + 191.0000, 192.0000, 193.0000, 194.0000, 195.0000, 196.0000, 197.0000, 198.0000, 199.0000, 200.0000, + 201.0000, 202.0000, 203.0000, 204.0000, 205.0000, 206.0000, 207.0000, 208.0000, 209.0000, 210.0000, + 211.0000, 212.0000, 213.0000, 214.0000, 215.0000, 216.0000, 217.0000, 218.0000, 219.0000, 220.0000, + 221.0000, 222.0000, 223.0000, 224.0000, 225.0000, 226.0000, 227.0000, 228.0000, 229.0000, 230.0000, + 231.0000, 232.0000, 233.0000, 234.0000, 235.0000, 236.0000, 237.0000, 238.0000, 239.0000, 240.0000, + 241.0000, 242.0000, 243.0000, 244.0000, 245.0000, 246.0000, 247.0000, 248.0000, 249.0000, 250.0000] + y = [97.58776, 97.76344, 96.56705, 92.52037, 91.15097, 95.21728, 90.21355, 89.29235, 91.51479, 89.60965, + 86.56187, 85.55315, 87.13053, 85.67938, 80.04849, 82.18922, 87.24078, 80.79401, 81.28564, 81.56932, + 79.22703, 79.43259, 77.90174, 76.75438, 77.17338, 74.27296, 73.11830, 73.84732, 72.47746, 71.92128, + 66.91962, 67.93554, 69.55841, 69.06592, 66.53371, 63.87094, 69.70526, 63.59295, 63.35509, 59.99747, + 62.64843, 65.77345, 59.10141, 56.57750, 61.15313, 54.30767, 62.83535, 56.52957, 56.98427, 58.11459, + 58.69576, 58.23322, 54.90490, 57.91442, 56.96629, 51.13831, 49.27123, 52.92668, 54.47693, 51.81710, + 51.05401, 52.51731, 51.83710, 54.48196, 49.05859, 50.52315, 50.32755, 46.44419, 50.89281, 52.13203, + 49.78741, 49.01637, 54.18198, 53.17456, 53.20827, 57.43459, 51.95282, 54.20282, 57.46687, 53.60268, + 58.86728, 57.66652, 63.71034, 65.24244, 65.10878, 69.96313, 68.85475, 73.32574, 76.21241, 78.06311, + 75.37701, 87.54449, 89.50588, 95.82098, 97.48390, 100.86070, 102.48510, 105.7311, 111.3489, 111.0305, + 110.1920, 118.3581, 118.8086, 122.4249, 124.0953, 125.9337, 127.8533, 131.0361, 133.3343, 135.1278, + 131.7113, 131.9151, 132.1107, 127.6898, 133.2148, 128.2296, 133.5902, 127.2539, 128.3482, 124.8694, + 124.6031, 117.0648, 118.1966, 119.5408, 114.7946, 114.2780, 120.3484, 114.8647, 111.6514, 110.1826, + 108.4461, 109.0571, 106.5308, 109.4691, 106.8709, 107.3192, 106.9000, 109.6526, 107.1602, 108.2509, + 104.96310, 109.3601, 107.6696, 99.77286, 104.96440, 106.1376, 106.5816, 100.12860, 101.66910, 96.44254, + 97.34169, 96.97412, 90.73460, 93.37949, 82.12331, 83.01657, 78.87360, 74.86971, 72.79341, 65.14744, + 67.02127, 60.16136, 57.13996, 54.05769, 50.42265, 47.82430, 42.85748, 42.45495, 38.30808, 36.95794, + 33.94543, 34.19017, 31.66097, 23.56172, 29.61143, 23.88765, 22.49812, 24.86901, 17.29481, 18.09291, + 15.34813, 14.77997, 13.87832, 12.88891, 16.20763, 16.29024, 15.29712, 14.97839, 12.11330, 14.24168, + 12.53824, 15.19818, 11.70478, 15.83745, 10.035850, 9.307574, 12.86800, 8.571671, 11.60415, 12.42772, + 11.23627, 11.13198, 7.761117, 6.758250, 14.23375, 10.63876, 8.893581, 11.55398, 11.57221, 11.58347, + 9.724857, 11.43854, 11.22636, 10.170150, 12.50765, 6.200494, 9.018902, 10.80557, 13.09591, 3.914033, + 9.567723, 8.038338, 10.230960, 9.367358, 7.695937, 6.118552, 8.793192, 7.796682, 12.45064, 10.61601, + 6.001000, 6.765096, 8.764652, 4.586417, 8.390782, 7.209201, 10.012090, 7.327461, 6.525136, 2.840065, + 10.323710, 4.790035, 8.376431, 6.263980, 2.705892, 8.362109, 8.983507, 3.362469, 1.182678, 4.875312] + + function = ("name=UserFunction,Formula=b1*exp(-b2*x) + b3*exp( -(x-b4)^2 / b5^2 ) + b6*exp( -(x-b7)^2 / b8^2 )," + "b1=94.9,b2=0.009,b3=90.1,b4=113.0,b5=20.0,b6=73.8,b7=140.0,b8=20.0") + + expected_params = [9.8940368970E+01, 1.0945879335E-02, 1.0069553078E+02, 1.1163619459E+02, 2.3300500029E+01, + 7.3705031418E+01, 1.4776164251E+02, 1.9668221230E+01] + + expected_errors = [5.3005192833E-01, 1.2554058911E-04, 8.1256587317E-01, 3.5317859757E-01, 3.6584783023E-01, + 1.2091239082E+00, 4.0488183351E-01, 3.7806634336E-01] + + params, errors = runFit(x, y, function) + + for err, expected in zip(errors, expected_errors): + self.assertDelta(err / expected - 1.0, 0.0, 1e-2) + + for val, expected in zip(params, expected_params): + self.assertDelta(val / expected - 1.0, 0.0, 2e-5) + + +class LeastSquaresNISTMGH09Test(stresstesting.MantidStressTest): + def runTest(self): + x = [4.000000E+00, 2.000000E+00, 1.000000E+00, 5.000000E-01, 2.500000E-01, 1.670000E-01, 1.250000E-01, + 1.000000E-01, 8.330000E-02, 7.140000E-02, 6.250000E-02] + + y = [1.957000E-01, 1.947000E-01, 1.735000E-01, 1.600000E-01, 8.440000E-02, 6.270000E-02, 4.560000E-02, + 3.420000E-02, 3.230000E-02, 2.350000E-02, 2.460000E-02] + + # Second set of starting parameters. + function = 'name=UserFunction,Formula=b1*(x^2+x*b2) / (x^2+x*b3+b4),b1=0.25,b2=0.39,b3=0.415,b4=0.39' + + params, errors = runFit(x, y, function) + + expected_params = [1.9280693458E-01,1.9128232873E-01,1.2305650693E-01,1.3606233068E-01] + expected_errors = [1.1435312227E-02,1.9633220911E-01,8.0842031232E-02,9.0025542308E-02] + + for err, expected in zip(errors, expected_errors): + self.assertDelta(err / expected - 1.0, 0.0, 1e-3) + + for val, expected in zip(params, expected_params): + self.assertDelta(val / expected - 1.0, 0.0, 3e-4) diff --git a/Code/Mantid/Vates/ParaviewPlugins/ParaViewFilters/ScaleWorkspace/vtkScaleWorkspace.cxx b/Code/Mantid/Vates/ParaviewPlugins/ParaViewFilters/ScaleWorkspace/vtkScaleWorkspace.cxx index e9b15021d609133cb6f51eed9b88836e0b8f1f2e..cb73097af1a5fd6acf1c30ef7db50a9c97f5cd6e 100644 --- a/Code/Mantid/Vates/ParaviewPlugins/ParaViewFilters/ScaleWorkspace/vtkScaleWorkspace.cxx +++ b/Code/Mantid/Vates/ParaviewPlugins/ParaViewFilters/ScaleWorkspace/vtkScaleWorkspace.cxx @@ -19,6 +19,8 @@ vtkScaleWorkspace::vtkScaleWorkspace() : m_xScaling(1), m_yScaling(1), m_zScaling(1), + m_minValue(0.1), + m_maxValue(0.1), m_specialCoordinates(-1), m_metadataJsonManager(new MetadataJsonManager()), m_vatesConfigurations(new VatesConfigurations()) diff --git a/Code/Mantid/Vates/VatesAPI/inc/MantidVatesAPI/CompositePeaksPresenterVsi.h b/Code/Mantid/Vates/VatesAPI/inc/MantidVatesAPI/CompositePeaksPresenterVsi.h index e09ab823f093e074c2673f2d81f87efca2a72f7e..21bf69a640492aa98c745276b90eb062d87361fe 100644 --- a/Code/Mantid/Vates/VatesAPI/inc/MantidVatesAPI/CompositePeaksPresenterVsi.h +++ b/Code/Mantid/Vates/VatesAPI/inc/MantidVatesAPI/CompositePeaksPresenterVsi.h @@ -23,7 +23,7 @@ public: } std::vector<Mantid::API::IPeaksWorkspace_sptr> getPeaksWorkspaces() const; virtual std::vector<bool> getViewablePeaks() const; - virtual void updateViewFrustum(ViewFrustum frustum); + virtual void updateViewFrustum(ViewFrustum_const_sptr frustum); virtual std::string getFrame() const; virtual std::string getPeaksWorkspaceName() const{ throw std::runtime_error( diff --git a/Code/Mantid/Vates/VatesAPI/inc/MantidVatesAPI/ConcretePeaksPresenterVsi.h b/Code/Mantid/Vates/VatesAPI/inc/MantidVatesAPI/ConcretePeaksPresenterVsi.h index e6b6a6cfa7c71e58138d7dc10052de9140e68ad5..a3d72ca061f994cb264b802f1cbfbfca50f48cb6 100644 --- a/Code/Mantid/Vates/VatesAPI/inc/MantidVatesAPI/ConcretePeaksPresenterVsi.h +++ b/Code/Mantid/Vates/VatesAPI/inc/MantidVatesAPI/ConcretePeaksPresenterVsi.h @@ -15,11 +15,11 @@ namespace VATES { class DLLExport ConcretePeaksPresenterVsi : public PeaksPresenterVsi { public: ConcretePeaksPresenterVsi(Mantid::API::IPeaksWorkspace_sptr peaksWorkspace, - ViewFrustum frustum, std::string wsFrame); + ViewFrustum_const_sptr frustum, std::string wsFrame); ~ConcretePeaksPresenterVsi(); virtual Mantid::API::IPeaksWorkspace_sptr getPeaksWorkspace() const; virtual std::vector<bool> getViewablePeaks() const; - virtual void updateViewFrustum(ViewFrustum frustum); + virtual void updateViewFrustum(ViewFrustum_const_sptr frustum); virtual std::string getFrame() const; virtual std::string getPeaksWorkspaceName() const; virtual void @@ -35,7 +35,7 @@ private: /// Viewable Peaks mutable std::vector<bool> m_viewablePeaks; /// The viewable region - ViewFrustum m_viewableRegion; + ViewFrustum_const_sptr m_viewableRegion; /// The peaks workspace Mantid::API::IPeaksWorkspace_sptr m_peaksWorkspace; /// The frame diff --git a/Code/Mantid/Vates/VatesAPI/inc/MantidVatesAPI/NullPeaksPresenterVsi.h b/Code/Mantid/Vates/VatesAPI/inc/MantidVatesAPI/NullPeaksPresenterVsi.h index c8c04fd18c79619c52cc87e6d4b09ef0d3c735a2..900dae7fd983792eaec7abfb57cdce4c4cbfb20a 100644 --- a/Code/Mantid/Vates/VatesAPI/inc/MantidVatesAPI/NullPeaksPresenterVsi.h +++ b/Code/Mantid/Vates/VatesAPI/inc/MantidVatesAPI/NullPeaksPresenterVsi.h @@ -23,7 +23,7 @@ public: throw std::runtime_error( "NullPeaksPresenterVsi does not implement this method. Misused"); } - virtual void updateViewFrustum(ViewFrustum) {} + virtual void updateViewFrustum(ViewFrustum_const_sptr) {} virtual std::string getFrame() const { throw std::runtime_error( "NullPeaksPresenterVsi does not implement this method. Misused"); diff --git a/Code/Mantid/Vates/VatesAPI/inc/MantidVatesAPI/PeaksPresenterVsi.h b/Code/Mantid/Vates/VatesAPI/inc/MantidVatesAPI/PeaksPresenterVsi.h index 3f891f3f236ce118d8eb87f61431d0b70da469fa..78eb1b79904582eebd4e61a0fea202927c9f3d87 100644 --- a/Code/Mantid/Vates/VatesAPI/inc/MantidVatesAPI/PeaksPresenterVsi.h +++ b/Code/Mantid/Vates/VatesAPI/inc/MantidVatesAPI/PeaksPresenterVsi.h @@ -5,19 +5,19 @@ #include "MantidAPI/IPeaksWorkspace.h" #include "MantidKernel/V3D.h" #include "MantidKernel/SpecialCoordinateSystem.h" +#include "MantidVatesAPI/ViewFrustum.h" #include <vector> #include <string> namespace Mantid { namespace VATES { -class ViewFrustum; class DLLExport PeaksPresenterVsi { public: virtual ~PeaksPresenterVsi(){}; virtual std::vector<bool> getViewablePeaks() const = 0; virtual Mantid::API::IPeaksWorkspace_sptr getPeaksWorkspace() const = 0; - virtual void updateViewFrustum(ViewFrustum frustum) = 0; + virtual void updateViewFrustum(ViewFrustum_const_sptr frustum) = 0; virtual std::string getFrame() const = 0; virtual std::string getPeaksWorkspaceName() const = 0; virtual void getPeaksInfo(Mantid::API::IPeaksWorkspace_sptr peaksWorkspace, diff --git a/Code/Mantid/Vates/VatesAPI/inc/MantidVatesAPI/ViewFrustum.h b/Code/Mantid/Vates/VatesAPI/inc/MantidVatesAPI/ViewFrustum.h index d6e6847ff2beca6d86f5c505fa32c976d8fcad8a..b145c50bf3c772d099a09541aec4a0cdfc716281 100644 --- a/Code/Mantid/Vates/VatesAPI/inc/MantidVatesAPI/ViewFrustum.h +++ b/Code/Mantid/Vates/VatesAPI/inc/MantidVatesAPI/ViewFrustum.h @@ -7,6 +7,7 @@ #include <cmath> #include <cfloat> #include <vector> +#include <boost/shared_ptr.hpp> namespace Mantid { @@ -23,9 +24,9 @@ class DLLExport FrustumPlane m_paramB(paramB), m_paramC(paramC), m_paramD(paramD){} - FrustumPlane(const FrustumPlane<I, T>& other) : m_paramA(other.m_paramA), + FrustumPlane(const FrustumPlane<I, T>& other) : m_paramA(other.m_paramA), m_paramB(other.m_paramB), - m_paramC(other.m_paramC), + m_paramC(other.m_paramC), m_paramD(other.m_paramD){} T A() {return m_paramA;} T B() {return m_paramB;} @@ -170,6 +171,10 @@ class DLLExport ViewFrustum matrix.setColumn(1, vec1); matrix.setColumn(2, vec2); } + +/// shared pointer to the view frustum +typedef boost::shared_ptr<Mantid::VATES::ViewFrustum> ViewFrustum_sptr; +typedef boost::shared_ptr<const Mantid::VATES::ViewFrustum> ViewFrustum_const_sptr; } } #endif \ No newline at end of file diff --git a/Code/Mantid/Vates/VatesAPI/src/CompositePeaksPresenterVsi.cpp b/Code/Mantid/Vates/VatesAPI/src/CompositePeaksPresenterVsi.cpp index 65f3bdf799d4f2569b9ae597c5b33c5fa651c0ca..28fb29794111f5aa86ed69f22843e9857c65d356 100644 --- a/Code/Mantid/Vates/VatesAPI/src/CompositePeaksPresenterVsi.cpp +++ b/Code/Mantid/Vates/VatesAPI/src/CompositePeaksPresenterVsi.cpp @@ -17,7 +17,7 @@ CompositePeaksPresenterVsi::~CompositePeaksPresenterVsi() {} * Update the view frustum * @param frustum The view frustum */ -void CompositePeaksPresenterVsi::updateViewFrustum(ViewFrustum frustum) { +void CompositePeaksPresenterVsi::updateViewFrustum(ViewFrustum_const_sptr frustum) { for (std::vector<PeaksPresenterVsi_sptr>::iterator it = m_peaksPresenters.begin(); it != m_peaksPresenters.end(); ++it) { diff --git a/Code/Mantid/Vates/VatesAPI/src/ConcretePeaksPresenterVsi.cpp b/Code/Mantid/Vates/VatesAPI/src/ConcretePeaksPresenterVsi.cpp index 92b1c23384e2abc2dfd4a1d65ac8dc9b003397c0..c5a1a259e69ec446093a80e8d11b3f72f3f4318c 100644 --- a/Code/Mantid/Vates/VatesAPI/src/ConcretePeaksPresenterVsi.cpp +++ b/Code/Mantid/Vates/VatesAPI/src/ConcretePeaksPresenterVsi.cpp @@ -17,7 +17,7 @@ namespace VATES { * @param frame The coordinate frame */ ConcretePeaksPresenterVsi::ConcretePeaksPresenterVsi( - Mantid::API::IPeaksWorkspace_sptr peaksWorkspace, ViewFrustum frustum, + Mantid::API::IPeaksWorkspace_sptr peaksWorkspace, ViewFrustum_const_sptr frustum, std::string frame) : m_viewableRegion(frustum), m_peaksWorkspace(peaksWorkspace), m_frame(frame) {} @@ -29,7 +29,7 @@ ConcretePeaksPresenterVsi::~ConcretePeaksPresenterVsi() {} * Update the view frustum * @param frustum The view frustum. */ -void ConcretePeaksPresenterVsi::updateViewFrustum(ViewFrustum frustum) { +void ConcretePeaksPresenterVsi::updateViewFrustum(ViewFrustum_const_sptr frustum) { m_viewableRegion = frustum; } @@ -44,7 +44,7 @@ std::vector<bool> ConcretePeaksPresenterVsi::getViewablePeaks() const{ if (this->m_peaksWorkspace->getNumberPeaks() >= 1) { double effectiveRadius = 1e-2; - std::string viewable = m_viewableRegion.toExtentsAsString(); + std::string viewable = m_viewableRegion->toExtentsAsString(); Mantid::API::IPeaksWorkspace_sptr peaksWS = m_peaksWorkspace; Mantid::API::IAlgorithm_sptr alg = diff --git a/Code/Mantid/Vates/VatesAPI/src/vtkSplatterPlotFactory.cpp b/Code/Mantid/Vates/VatesAPI/src/vtkSplatterPlotFactory.cpp index d777525c7668bc2f5f15af19fbe01bdd01e68973..11b8aecd891edc293b9e7fa29c91816081d108f6 100644 --- a/Code/Mantid/Vates/VatesAPI/src/vtkSplatterPlotFactory.cpp +++ b/Code/Mantid/Vates/VatesAPI/src/vtkSplatterPlotFactory.cpp @@ -65,6 +65,8 @@ namespace VATES m_buildSortedList(true), m_wsName(""), dataSet(NULL), slice(false), sliceMask(NULL), sliceImplicitFunction(NULL), m_time(0.0), + m_minValue(0.1), + m_maxValue(0.1), m_metaDataExtractor(new MetaDataExtractorUtils()), m_metadataJsonManager(new MetadataJsonManager()), m_vatesConfigurations(new VatesConfigurations()) diff --git a/Code/Mantid/Vates/VatesAPI/test/CompositePeaksPresenterVsiTest.h b/Code/Mantid/Vates/VatesAPI/test/CompositePeaksPresenterVsiTest.h index a237129ebf5a1bb0f24e777e2ebbc645639f36b8..0db214886e04ca7fb23eb84d0834876a31c068d1 100644 --- a/Code/Mantid/Vates/VatesAPI/test/CompositePeaksPresenterVsiTest.h +++ b/Code/Mantid/Vates/VatesAPI/test/CompositePeaksPresenterVsiTest.h @@ -4,10 +4,13 @@ #include <cxxtest/TestSuite.h> #include "MantidVatesAPI/CompositePeaksPresenterVsi.h" #include "MantidVatesAPI/ConcretePeaksPresenterVsi.h" +#include "MantidVatesAPI/ViewFrustum.h" #include "MantidAPI/IPeaksWorkspace.h" #include "MantidDataObjects/PeaksWorkspace.h" + #include <boost/shared_ptr.hpp> +#include <boost/make_shared.hpp> #include <stdexcept> #include "MockObjects.h" @@ -58,9 +61,10 @@ public: TopPlane top(0.0, -1.0, 0.0, 1.0); FarPlane farPlane(0.0, 0.0, 1.0, 1.0); NearPlane nearPlane(0.0, 0.0, -1.0,1.0); - ViewFrustum frustum(left, right, bottom, top, farPlane, nearPlane); + ViewFrustum_const_sptr frustum = boost::make_shared<const Mantid::VATES::ViewFrustum>(left, right, bottom, top, farPlane, nearPlane); boost::shared_ptr<MockPeaksWorkspaceComposite> pw_ptr(new MockPeaksWorkspaceComposite()); + std::string name = "pw1"; PeaksPresenterVsi_sptr p1(new ConcretePeaksPresenterVsi(pw_ptr, frustum, frame)); @@ -92,7 +96,7 @@ public: TopPlane top(0.0, -1.0, 0.0, 1.0); FarPlane farPlane(0.0, 0.0, 1.0, 1.0); NearPlane nearPlane(0.0, 0.0, -1.0,1.0); - ViewFrustum frustum(left, right, bottom, top, farPlane, nearPlane); + ViewFrustum_const_sptr frustum = boost::make_shared<const Mantid::VATES::ViewFrustum>(left, right, bottom, top, farPlane, nearPlane); boost::shared_ptr<MockPeaksWorkspaceComposite> pw_ptr(new MockPeaksWorkspaceComposite()); std::string name = "pw1"; diff --git a/Code/Mantid/Vates/VatesAPI/test/ConcretePeaksPresenterVsiTest.h b/Code/Mantid/Vates/VatesAPI/test/ConcretePeaksPresenterVsiTest.h index 0d0126ce10ecdacd0439353cacae27b39b18ca79..de24ad83113c7bca671c0ac576d832c10f00b632 100644 --- a/Code/Mantid/Vates/VatesAPI/test/ConcretePeaksPresenterVsiTest.h +++ b/Code/Mantid/Vates/VatesAPI/test/ConcretePeaksPresenterVsiTest.h @@ -12,6 +12,7 @@ #include "MantidKernel/V3D.h" #include "MockObjects.h" #include <boost/shared_ptr.hpp> +#include <boost/make_shared.hpp> #include <cxxtest/TestSuite.h> #include <gmock/gmock.h> @@ -53,7 +54,7 @@ public: TopPlane top(0.0, -1.0, 0.0, 1.0); FarPlane farPlane(0.0, 0.0, 1.0, 1.0); NearPlane nearPlane(0.0, 0.0, -1.0,1.0); - ViewFrustum frustum(left, right, bottom, top, farPlane, nearPlane); + ViewFrustum_const_sptr frustum = boost::make_shared<const Mantid::VATES::ViewFrustum>(left, right, bottom, top, farPlane, nearPlane); boost::shared_ptr<MockPeaksWorkspaceConcrete> pw_ptr(new MockPeaksWorkspaceConcrete()); // Act @@ -73,7 +74,7 @@ public: TopPlane top(0.0, -1.0, 0.0, 1.0); FarPlane farPlane(0.0, 0.0, 1.0, 1.0); NearPlane nearPlane(0.0, 0.0, -1.0,1.0); - ViewFrustum frustum(left, right, bottom, top, farPlane, nearPlane); + ViewFrustum_const_sptr frustum = boost::make_shared<const Mantid::VATES::ViewFrustum>(left, right, bottom, top, farPlane, nearPlane); Mantid::Kernel::V3D coordinate(1,0,0); double peakRadius = 10; diff --git a/Code/Mantid/Vates/VatesSimpleGui/ViewWidgets/inc/MantidVatesSimpleGuiViewWidgets/BackgroundRgbProvider.h b/Code/Mantid/Vates/VatesSimpleGui/ViewWidgets/inc/MantidVatesSimpleGuiViewWidgets/BackgroundRgbProvider.h index af7acf36ababd5d5d47457b8f3d50f1af811b556..9abe0658755e6e6d35998106b14229feec902ead 100644 --- a/Code/Mantid/Vates/VatesSimpleGui/ViewWidgets/inc/MantidVatesSimpleGuiViewWidgets/BackgroundRgbProvider.h +++ b/Code/Mantid/Vates/VatesSimpleGui/ViewWidgets/inc/MantidVatesSimpleGuiViewWidgets/BackgroundRgbProvider.h @@ -95,9 +95,8 @@ namespace Mantid /** * Callback function for background color changing events *@param caller Calling object. - *@param vtkNotUsed Not used. */ - static void backgroundColorChangeCallbackFunction(vtkObject* caller, long unsigned int vtkNotUsed(eventId), void* vtkNotUsed(clientData), void* vtkNotUsed(callData)); + static void backgroundColorChangeCallbackFunction(vtkObject* caller, long unsigned int, void*, void*); static QColor currentBackgroundColor; diff --git a/Code/Mantid/Vates/VatesSimpleGui/ViewWidgets/inc/MantidVatesSimpleGuiViewWidgets/CameraManager.h b/Code/Mantid/Vates/VatesSimpleGui/ViewWidgets/inc/MantidVatesSimpleGuiViewWidgets/CameraManager.h index 9f0c5f9cdba1f3738e983b1ec7b3e91e874db78e..8b2aa618458c0691ca56bb15cf6eff3096751108 100644 --- a/Code/Mantid/Vates/VatesSimpleGui/ViewWidgets/inc/MantidVatesSimpleGuiViewWidgets/CameraManager.h +++ b/Code/Mantid/Vates/VatesSimpleGui/ViewWidgets/inc/MantidVatesSimpleGuiViewWidgets/CameraManager.h @@ -4,6 +4,7 @@ #include "MantidVatesSimpleGuiViewWidgets/WidgetDllOption.h" #include "MantidVatesAPI/ViewFrustum.h" + namespace Mantid { namespace Vates @@ -45,7 +46,7 @@ public: ~CameraManager(); - Mantid::VATES::ViewFrustum getCurrentViewFrustum(); + Mantid::VATES::ViewFrustum_const_sptr getCurrentViewFrustum(); void setCameraToPeak(double xpos, double ypos, double zpos, double peakRadius); }; diff --git a/Code/Mantid/Vates/VatesSimpleGui/ViewWidgets/src/AutoScaleRangeGenerator.cpp b/Code/Mantid/Vates/VatesSimpleGui/ViewWidgets/src/AutoScaleRangeGenerator.cpp index dda4962e0b2f563ca9e73e4f6ee75c38b4607ad1..bfcb18543b917b898e16362ad268a9ec84b156d6 100644 --- a/Code/Mantid/Vates/VatesSimpleGui/ViewWidgets/src/AutoScaleRangeGenerator.cpp +++ b/Code/Mantid/Vates/VatesSimpleGui/ViewWidgets/src/AutoScaleRangeGenerator.cpp @@ -165,6 +165,9 @@ namespace SimpleGui // Set the color scale output VsiColorScale vsiColorScale; + // Initialize log scale to false + vsiColorScale.useLogScale = false; + // If either the min or max value are at the end of the double spectrum, we might only have a peak Ws visible, // we need to hedge for that if (minValue == DBL_MAX || maxValue == -DBL_MAX) { diff --git a/Code/Mantid/Vates/VatesSimpleGui/ViewWidgets/src/BackgroundRgbProvider.cpp b/Code/Mantid/Vates/VatesSimpleGui/ViewWidgets/src/BackgroundRgbProvider.cpp index 59b0757a017629cff5dc453b01656a09b1bf9f23..b423af988aae5d2476b3b2146637de34c74da557 100644 --- a/Code/Mantid/Vates/VatesSimpleGui/ViewWidgets/src/BackgroundRgbProvider.cpp +++ b/Code/Mantid/Vates/VatesSimpleGui/ViewWidgets/src/BackgroundRgbProvider.cpp @@ -134,7 +134,7 @@ namespace Mantid view->getViewProxy()->GetProperty("Background")->AddObserver(vtkCommand::ModifiedEvent, backgroundColorChangeCallback); } - void BackgroundRgbProvider::backgroundColorChangeCallbackFunction(vtkObject* caller, long unsigned int vtkNotUsed(eventId), void* vtkNotUsed(clientData), void* vtkNotUsed(callData)) + void BackgroundRgbProvider::backgroundColorChangeCallbackFunction(vtkObject* caller, long unsigned int, void*, void*) { // Extract the background color and persist it vtkSMDoubleVectorProperty* background =vtkSMDoubleVectorProperty::SafeDownCast(caller); diff --git a/Code/Mantid/Vates/VatesSimpleGui/ViewWidgets/src/CameraManager.cpp b/Code/Mantid/Vates/VatesSimpleGui/ViewWidgets/src/CameraManager.cpp index 3d7469bd39811eefe1f859046940631c425f1ff5..2c691f7aba0456e0522492bf758df0c407732a73 100644 --- a/Code/Mantid/Vates/VatesSimpleGui/ViewWidgets/src/CameraManager.cpp +++ b/Code/Mantid/Vates/VatesSimpleGui/ViewWidgets/src/CameraManager.cpp @@ -12,7 +12,7 @@ #include <vtkCamera.h> #include <vtkRenderer.h> #include <vtkRenderWindow.h> - +#include <boost/make_shared.hpp> namespace Mantid { namespace Vates @@ -30,7 +30,7 @@ namespace Mantid /** * Get the plane equation for the view frustum. */ - Mantid::VATES::ViewFrustum CameraManager::getCurrentViewFrustum() + Mantid::VATES::ViewFrustum_const_sptr CameraManager::getCurrentViewFrustum() { double left[4]; double right[4]; @@ -87,12 +87,13 @@ namespace Mantid near[k] = planes[k + 16]; far[k] = planes[k + 20]; } - Mantid::VATES::ViewFrustum frustum(Mantid::VATES::LeftPlane(left[0], left[1], left[2], left[3]), - Mantid::VATES::RightPlane(right[0], right[1], right[2], right[3]), - Mantid::VATES::BottomPlane(bottom[0], bottom[1], bottom[2], bottom[3]), - Mantid::VATES::TopPlane(top[0], top[1], top[2], top[3]), - Mantid::VATES::FarPlane(far[0], far[1], far[2], far[3]), - Mantid::VATES::NearPlane(near[0], near[1], near[2], near[3])); + + Mantid::VATES::ViewFrustum_const_sptr frustum = boost::make_shared<const Mantid::VATES::ViewFrustum>(Mantid::VATES::LeftPlane(left[0], left[1], left[2], left[3]), + Mantid::VATES::RightPlane(right[0], right[1], right[2], right[3]), + Mantid::VATES::BottomPlane(bottom[0], bottom[1], bottom[2], bottom[3]), + Mantid::VATES::TopPlane(top[0], top[1], top[2], top[3]), + Mantid::VATES::FarPlane(far[0], far[1], far[2], far[3]), + Mantid::VATES::NearPlane(near[0], near[1], near[2], near[3])); return frustum; } diff --git a/Code/Mantid/Vates/VatesSimpleGui/ViewWidgets/src/MdViewerWidget.cpp b/Code/Mantid/Vates/VatesSimpleGui/ViewWidgets/src/MdViewerWidget.cpp index 99be28d3772a8aa732c42ff4023a760033f5ad95..84ce08bc165a314faa0b56afdfb94a85246232ca 100644 --- a/Code/Mantid/Vates/VatesSimpleGui/ViewWidgets/src/MdViewerWidget.cpp +++ b/Code/Mantid/Vates/VatesSimpleGui/ViewWidgets/src/MdViewerWidget.cpp @@ -136,7 +136,7 @@ REGISTER_VATESGUI(MdViewerWidget) */ MdViewerWidget::MdViewerWidget() : VatesViewerInterface(), currentView(NULL), dataLoader(NULL), hiddenView(NULL), lodAction(NULL), screenShot(NULL), viewLayout(NULL), - viewSettings(NULL), m_rebinAlgorithmDialogProvider(this), m_rebinnedWorkspaceIdentifier("_tempvsi") + viewSettings(NULL), initialView(ModeControlWidget::STANDARD), m_rebinAlgorithmDialogProvider(this), m_rebinnedWorkspaceIdentifier("_tempvsi") { //this will initialize the ParaView application if needed. VatesParaViewApplication::instance(); diff --git a/Code/Mantid/Vates/VatesSimpleGui/ViewWidgets/src/PeaksTableControllerVsi.cpp b/Code/Mantid/Vates/VatesSimpleGui/ViewWidgets/src/PeaksTableControllerVsi.cpp index 5cdd8552c9ec1cfe196150910aeec261ad0b6ea0..e4ff626d0f817b66f6b3fd9ddd8b5bf063ad0864 100644 --- a/Code/Mantid/Vates/VatesSimpleGui/ViewWidgets/src/PeaksTableControllerVsi.cpp +++ b/Code/Mantid/Vates/VatesSimpleGui/ViewWidgets/src/PeaksTableControllerVsi.cpp @@ -11,6 +11,7 @@ #include "MantidKernel/V3D.h" #include "MantidKernel/SpecialCoordinateSystem.h" #include "MantidKernel/Logger.h" +#include "MantidVatesAPI/ViewFrustum.h" #include "MantidVatesAPI/PeaksPresenterVsi.h" #include "MantidVatesAPI/NullPeaksPresenterVsi.h" #include "MantidVatesAPI/ConcretePeaksPresenterVsi.h" @@ -72,7 +73,7 @@ PeaksTableControllerVsi::PeaksTableControllerVsi( boost::shared_ptr<CameraManager> cameraManager, QWidget *parent) : QWidget(parent), m_cameraManager(cameraManager), m_presenter(new Mantid::VATES::CompositePeaksPresenterVsi()), - m_peaksTabWidget(NULL), m_peakMarker(NULL) { + m_peaksTabWidget(NULL), m_peakMarker(NULL), m_coordinateSystem(Mantid::Kernel::SpecialCoordinateSystem::QLab) { m_peakTransformSelector.registerCandidate( boost::make_shared<Mantid::API::PeakTransformHKLFactory>()); m_peakTransformSelector.registerCandidate( @@ -266,8 +267,7 @@ void PeaksTableControllerVsi::updatePeakWorkspaceColor() { * Update the view region for the presenters */ void PeaksTableControllerVsi::updateViewableArea() { - Mantid::VATES::ViewFrustum frustum = m_cameraManager->getCurrentViewFrustum(); - m_presenter->updateViewFrustum(frustum); + m_presenter->updateViewFrustum(m_cameraManager->getCurrentViewFrustum()); } /** diff --git a/Code/Mantid/Vates/VatesSimpleGui/ViewWidgets/src/PeaksWidget.cpp b/Code/Mantid/Vates/VatesSimpleGui/ViewWidgets/src/PeaksWidget.cpp index 33aaf8f0aa1178662246bfc7a61dbb9a45af39a7..e70f9497873d16d93e8dd085eebdfdf5fe026842 100644 --- a/Code/Mantid/Vates/VatesSimpleGui/ViewWidgets/src/PeaksWidget.cpp +++ b/Code/Mantid/Vates/VatesSimpleGui/ViewWidgets/src/PeaksWidget.cpp @@ -21,7 +21,7 @@ Constructor */ PeaksWidget::PeaksWidget(Mantid::API::IPeaksWorkspace_sptr ws, const std::string &coordinateSystem, QWidget *parent) - : QWidget(parent), m_ws(ws), m_coordinateSystem(coordinateSystem) { + : QWidget(parent), m_ws(ws), m_coordinateSystem(coordinateSystem), m_originalTableWidth(1) { ui.setupUi(this); } diff --git a/Code/Mantid/docs/README.md b/Code/Mantid/docs/README.md index 393d032b3b2a928f34481aecb7a42d042a300908..48345f2aa1372c4683bf4bc574be6150bf305336 100644 --- a/Code/Mantid/docs/README.md +++ b/Code/Mantid/docs/README.md @@ -13,4 +13,4 @@ or `pip`: This may require admin privileges on some environments. -CMake produces a `docs-html` target that is used to build the documentation. The output files will appear in a `html` sub directory of the main `build/docs` directory. \ No newline at end of file +CMake produces a `docs-html` target that is used to build the documentation (only if you set the cmake variable DOCS_HTML=ON). The output files will appear in a `html` sub directory of the main `build/docs` directory. \ No newline at end of file diff --git a/Code/Mantid/docs/source/api/python/index.rst b/Code/Mantid/docs/source/api/python/index.rst index ba45b9030ec576c463003caa06c4dc23d67292ba..3f115b1cdd0e52e4762de558007bb72666509cca 100644 --- a/Code/Mantid/docs/source/api/python/index.rst +++ b/Code/Mantid/docs/source/api/python/index.rst @@ -24,13 +24,13 @@ Changes between version 1.0 and 2.0 of the API are described :ref:`here <pythona changes -Future plotting interface -------------------------- +Matplotlib-like plotting interface +---------------------------------- .. toctree:: :maxdepth: 1 - mantidplot.future.pyplot <mantidplot/future/pyplot/index> + mantidplot.pyplot <mantidplot/pyplot/index> Techniques ---------- diff --git a/Code/Mantid/docs/source/api/python/mantidplot/future/index.rst b/Code/Mantid/docs/source/api/python/mantidplot/future/index.rst deleted file mode 100644 index b2b6083bd4f9f3e5d2d06b20b074092bd18c6a68..0000000000000000000000000000000000000000 --- a/Code/Mantid/docs/source/api/python/mantidplot/future/index.rst +++ /dev/null @@ -1,15 +0,0 @@ -============================================ - :mod:`mantidplot.future` --- future imports -============================================ - -.. module:: mantidplot.future - -This module includes future imports. - -Submodules -########## - -.. toctree:: - :maxdepth: 1 - - pyplot/index diff --git a/Code/Mantid/docs/source/api/python/mantidplot/future/pyplot/index.rst b/Code/Mantid/docs/source/api/python/mantidplot/future/pyplot/index.rst deleted file mode 100644 index c54b9646e1d76df862f5d9d5ce7636ba6d000a76..0000000000000000000000000000000000000000 --- a/Code/Mantid/docs/source/api/python/mantidplot/future/pyplot/index.rst +++ /dev/null @@ -1,15 +0,0 @@ -================================================= - :mod:`future.pyplot` --- Future plotting package -================================================= - -New plotting interface ----------------------- - -This package provides a simple command line interface to the Mantid -plotting functionality, resembling matplotlib and its pyplot package -(http://matplotlib.org). The module is subject to changes and it is -provided as a 'future' import. Feedback is very much welcome! - -.. automodule:: pymantidplot.future.pyplot - :members: - :show-inheritance: diff --git a/Code/Mantid/docs/source/api/python/mantidplot/index.rst b/Code/Mantid/docs/source/api/python/mantidplot/index.rst index ad217305f362da992e0244291d9d458a7949e1d3..31b5f9d120165ea27a353a7a7c40f5132cb6a394 100644 --- a/Code/Mantid/docs/source/api/python/mantidplot/index.rst +++ b/Code/Mantid/docs/source/api/python/mantidplot/index.rst @@ -79,4 +79,4 @@ Submodules .. toctree:: :maxdepth: 1 - future/index + pyplot/index diff --git a/Code/Mantid/docs/source/api/python/mantidplot/pyplot/index.rst b/Code/Mantid/docs/source/api/python/mantidplot/pyplot/index.rst new file mode 100644 index 0000000000000000000000000000000000000000..824d782aa05e6b6b660935b266beaf008c64d629 --- /dev/null +++ b/Code/Mantid/docs/source/api/python/mantidplot/pyplot/index.rst @@ -0,0 +1,15 @@ +=================================================== + :mod:`pyplot` --- Matplotlib-like plotting package +=================================================== + +New plotting interface +---------------------- + +This package provides a simple command line interface to the Mantid +plotting functionality, resembling matplotlib and its pyplot package +(http://matplotlib.org). The module is subject to changes and feedback +is very much welcome! + +.. automodule:: pymantidplot.pyplot + :members: + :show-inheritance: diff --git a/Code/Mantid/docs/source/fitfunctions/LatticeFunction.rst b/Code/Mantid/docs/source/fitfunctions/LatticeFunction.rst new file mode 100644 index 0000000000000000000000000000000000000000..1ee418b638b3eccbabf6140b5f04de034d5bbf58 --- /dev/null +++ b/Code/Mantid/docs/source/fitfunctions/LatticeFunction.rst @@ -0,0 +1,81 @@ +.. _func-LatticeFunction: + +=============== +LatticeFunction +=============== + +.. index:: LatticeFunction + +Description +----------- + +After a list of Bragg reflections has been indexed, it is often necessary to refine the unit cell parameters that have +been used to assign indices. LatticeFunction can be used to achieve that task with :ref:`algm-Fit`. The function can +work with a PeaksWorkspace or with a TableWorkspace that contains two columns named `HKL` and `d` (see +:ref:`algm-PawleyFit` for specification of the table). + +After setting the `CrystalSystem` attribute to one of the seven crystal systems, the function exposes the +corresponding lattice parameters, as well as a `ZeroShift`. In most cases it's recommended to fix this additional +parameter as this is often taken care of in earlier steps of the data reduction. + +Usage +----- + +.. include:: ../usagedata-note.txt + +The following script demonstrates how the function can be used. The algorithm :ref:`algm-PoldiCreatePeaksFromCell` is +used to generate Bragg reflections that are expected for the crystal structure of Silicon. + +.. testcode:: ExSiliconTheoretical + + import numpy as np + + # Create Silicon peaks for indexing + peaks_Si = PoldiCreatePeaksFromCell( + SpaceGroup="F d -3 m", + a=5.4311946, + Atoms="Si 0 0 0", + LatticeSpacingMin=0.7) + + # Fit a cubic cell, starting parameter is 5 + Fit(Function="name=LatticeFunction,CrystalSystem=Cubic,a=5", + InputWorkspace=peaks_Si, + Ties="ZeroShift=0.0", + CreateOutput=True, + Output="Si", + CostFunction="Unweighted least squares") + + # Print the refined lattice parameter with error estimate + parameters = AnalysisDataService.retrieve("Si_Parameters") + + a_true = 5.4311946 + a = np.round(parameters.cell(0, 1), 7) + a_err = np.round(parameters.cell(0, 2), 7) + + print "Refined lattice parameter: a =", a, "+/-", a_err + print "Difference from expected value: a_observed - a_expected =", np.round(a - a_true, 7) + print "Is this difference within the standard deviation?", "Yes" if np.fabs(a - a_true) < a_err else "No" + +Executing the script produces some output with information about the fit: + +.. testoutput:: ExSiliconTheoretical + + Refined lattice parameter: a = 5.4311944 +/- 3e-07 + Difference from expected value: a_observed - a_expected = -2e-07 + Is this difference within the standard deviation? Yes + +In addition there is also an output workspace, which contains information about the peaks used for the fit and how +well the peak positions calculated from the fitted parameters match the observed positions. + +.. testcleanup:: ExSiliconTheoretical + + DeleteWorkspace("peaks_Si") + DeleteWorkspace("Si_Parameters") + DeleteWorkspace("Si_Workspace") + DeleteWorkspace("Si_NormalisedCovarianceMatrix") + +.. attributes:: + +.. properties:: + +.. categories:: diff --git a/Code/Mantid/scripts/SANS/isis_reduction_steps.py b/Code/Mantid/scripts/SANS/isis_reduction_steps.py index 65bf57953fed2fbf5700accf26ae28a7c81927c0..3fc28fb0f1c919bd62895073bd45ebe31abcacb5 100644 --- a/Code/Mantid/scripts/SANS/isis_reduction_steps.py +++ b/Code/Mantid/scripts/SANS/isis_reduction_steps.py @@ -154,8 +154,8 @@ class LoadRun(object): if monitor_ws_name in mtd: DeleteWorkspace(monitor_ws_name) - loader_name = outWs.getHistory().lastAlgorithm().getProperty('LoaderName').value - + last_algorithm = outWs.getHistory().lastAlgorithm() + loader_name = last_algorithm.getProperty('LoaderName').value if loader_name == 'LoadRaw': self._loadSampleDetails(workspace) diff --git a/Code/Tools/Pylint/pylint.cfg b/Code/Tools/Pylint/pylint.cfg index 45bc53816b56ed31ae0c707a46246217cedc1172..eec53d4f7b22bdfd67bc5e8f1c30b956fa6be060 100644 --- a/Code/Tools/Pylint/pylint.cfg +++ b/Code/Tools/Pylint/pylint.cfg @@ -45,8 +45,9 @@ load-plugins= # C0326 - Spaces around equality and commas # W0401 - Wildcard imports # R0201 - Method could be used as a function. All algorithms do this in the category method +# R0801 - Similar lines in different files # -disable=W0142,I0011,F0401,W0614,E0602,C0111,C0326,W0401,R0201 +disable=W0142,I0011,F0401,W0614,E0602,C0111,C0326,W0401,R0201,R0801 [REPORTS]