diff --git a/Framework/Algorithms/test/RemoveExpDecayTest.h b/Framework/Algorithms/test/RemoveExpDecayTest.h index e4d20a3f95e44748f4f7128fdadcd112f6d298f5..136e48cf707bef934f0138026a1ad26eebee85b7 100644 --- a/Framework/Algorithms/test/RemoveExpDecayTest.h +++ b/Framework/Algorithms/test/RemoveExpDecayTest.h @@ -3,11 +3,11 @@ #include <cxxtest/TestSuite.h> #include "MantidAPI/FrameworkManager.h" -#include "MantidAlgorithms/RemoveExpDecay.h" +#include "MantidAPI/AlgorithmManager.h" #include "MantidTestHelpers/WorkspaceCreationHelper.h" -using namespace Mantid::Algorithms; using namespace Mantid::API; +using Mantid::MantidVec; const std::string outputName = "MuonRemoveExpDecay_Output"; @@ -21,52 +21,165 @@ public: RemoveExpDecayTest() { FrameworkManager::Instance(); } void testInit() { - MuonRemoveExpDecay alg; - alg.initialize(); - TS_ASSERT(alg.isInitialized()) + IAlgorithm_sptr alg = AlgorithmManager::Instance().create("RemoveExpDecay"); + alg->initialize(); + TS_ASSERT(alg->isInitialized()) } - void testExecute() { - auto ws = WorkspaceCreationHelper::Create2DWorkspace(1, 1); - - MuonRemoveExpDecay alg; - TS_ASSERT_THROWS_NOTHING(alg.initialize()); - TS_ASSERT(alg.isInitialized()); - alg.setChild(true); - alg.setProperty("InputWorkspace", ws); - alg.setPropertyValue("OutputWorkspace", outputName); - alg.setPropertyValue("Spectra", "0"); - TS_ASSERT_THROWS_NOTHING(alg.execute()); - TS_ASSERT(alg.isExecuted()) + void test_Execute() { + + auto ws = createWorkspace(1, 50); + + IAlgorithm_sptr alg = AlgorithmManager::Instance().create("RemoveExpDecay"); + alg->initialize(); + alg->setChild(true); + alg->setProperty("InputWorkspace", ws); + alg->setPropertyValue("OutputWorkspace", outputName); + TS_ASSERT_THROWS_NOTHING(alg->execute()); + TS_ASSERT(alg->isExecuted()); + + MatrixWorkspace_sptr outWS = alg->getProperty("OutputWorkspace"); } - void testExecuteWhereSepctraNotSet() { - auto ws = WorkspaceCreationHelper::Create2DWorkspace(1, 1); - - MuonRemoveExpDecay alg; - TS_ASSERT_THROWS_NOTHING(alg.initialize()); - TS_ASSERT(alg.isInitialized()); - alg.setChild(true); - alg.setProperty("InputWorkspace", ws); - alg.setPropertyValue("OutputWorkspace", outputName); - TS_ASSERT_THROWS_NOTHING(alg.execute()); - TS_ASSERT(alg.isExecuted()) + void test_EmptySpectrumList() { + + auto ws = createWorkspace(2, 50); + + IAlgorithm_sptr alg = AlgorithmManager::Instance().create("RemoveExpDecay"); + alg->initialize(); + alg->setChild(true); + alg->setProperty("InputWorkspace", ws); + alg->setPropertyValue("OutputWorkspace", outputName); + TS_ASSERT_THROWS_NOTHING(alg->execute()); + TS_ASSERT(alg->isExecuted()); + + MatrixWorkspace_sptr outWS = alg->getProperty("OutputWorkspace"); + + // First spectrum + // Test some X values + TS_ASSERT_DELTA(outWS->readX(0)[10], 0.2000, 0.0001); + TS_ASSERT_DELTA(outWS->readX(0)[19], 0.3800, 0.0001); + TS_ASSERT_DELTA(outWS->readX(0)[49], 0.9800, 0.0001); + // Test some Y values + TS_ASSERT_DELTA(outWS->readY(0)[10], -0.0992, 0.0001); + TS_ASSERT_DELTA(outWS->readY(0)[19], -0.0111, 0.0001); + TS_ASSERT_DELTA(outWS->readY(0)[49], -0.0622, 0.0001); + // Test some E values + TS_ASSERT_DELTA(outWS->readE(0)[10], 0.0054, 0.0001); + TS_ASSERT_DELTA(outWS->readE(0)[19], 0.0059, 0.0001); + TS_ASSERT_DELTA(outWS->readE(0)[49], 0.0077, 0.0001); + + // Second spectrum + // Test some X values + TS_ASSERT_DELTA(outWS->readX(1)[10], 0.2000, 0.0001); + TS_ASSERT_DELTA(outWS->readX(1)[19], 0.3800, 0.0001); + TS_ASSERT_DELTA(outWS->readX(1)[49], 0.9800, 0.0001); + // Test some Y values + TS_ASSERT_DELTA(outWS->readY(1)[10], 0.0274, 0.0001); + TS_ASSERT_DELTA(outWS->readY(1)[19], -0.1003, 0.0001); + TS_ASSERT_DELTA(outWS->readY(1)[49], 0.0802, 0.0001); + // Test some E values + TS_ASSERT_DELTA(outWS->readE(1)[10], 0.0054, 0.0001); + TS_ASSERT_DELTA(outWS->readE(1)[19], 0.0059, 0.0001); + TS_ASSERT_DELTA(outWS->readE(1)[49], 0.0078, 0.0001); + } + + void test_SpectrumList() { + + auto ws = createWorkspace(2, 50); + + // First, run the algorithm without specifying any spectrum + IAlgorithm_sptr alg1 = + AlgorithmManager::Instance().create("RemoveExpDecay"); + alg1->initialize(); + alg1->setChild(true); + alg1->setProperty("InputWorkspace", ws); + alg1->setPropertyValue("OutputWorkspace", outputName); + TS_ASSERT_THROWS_NOTHING(alg1->execute()); + TS_ASSERT(alg1->isExecuted()); + MatrixWorkspace_sptr out1 = alg1->getProperty("OutputWorkspace"); + + // Then run the algorithm on the second spectrum only + IAlgorithm_sptr alg2 = + AlgorithmManager::Instance().create("RemoveExpDecay"); + alg2->initialize(); + alg2->setChild(true); + alg2->setProperty("InputWorkspace", ws); + alg2->setPropertyValue("OutputWorkspace", outputName); + alg2->setPropertyValue("Spectra", "1"); + TS_ASSERT_THROWS_NOTHING(alg2->execute()); + TS_ASSERT(alg2->isExecuted()); + MatrixWorkspace_sptr out2 = alg2->getProperty("OutputWorkspace"); + + // Both output workspaces should have 2 spectra + TS_ASSERT_EQUALS(out1->getNumberHistograms(), ws->getNumberHistograms()); + TS_ASSERT_EQUALS(out2->getNumberHistograms(), ws->getNumberHistograms()); + + // Compare results, they should match for the selected spectrum + TS_ASSERT_EQUALS(out1->readX(1), out2->readX(1)); + TS_ASSERT_EQUALS(out1->readY(1), out2->readY(1)); + TS_ASSERT_EQUALS(out1->readE(1), out2->readE(1)); + + // Compare non-selected spectra, the should match the input ones + TS_ASSERT_EQUALS(ws->readX(0), out2->readX(0)); + TS_ASSERT_EQUALS(ws->readY(0), out2->readY(0)); + TS_ASSERT_EQUALS(ws->readE(0), out2->readE(0)); } void test_yUnitLabel() { - auto ws = WorkspaceCreationHelper::Create2DWorkspace(1, 1); - MuonRemoveExpDecay alg; - alg.initialize(); - alg.setChild(true); - alg.setProperty("InputWorkspace", ws); - alg.setProperty("OutputWorkspace", outputName); - alg.execute(); + auto ws = createWorkspace(4, 50); + + IAlgorithm_sptr alg = AlgorithmManager::Instance().create("RemoveExpDecay"); + alg->initialize(); + alg->setChild(true); + alg->setProperty("InputWorkspace", ws); + alg->setPropertyValue("OutputWorkspace", outputName); + TS_ASSERT_THROWS_NOTHING(alg->execute()); + TS_ASSERT(alg->isExecuted()) - MatrixWorkspace_sptr result = alg.getProperty("OutputWorkspace"); + MatrixWorkspace_sptr result = alg->getProperty("OutputWorkspace"); TS_ASSERT(result); TS_ASSERT_EQUALS(result->YUnitLabel(), "Asymmetry"); } + + MatrixWorkspace_sptr createWorkspace(size_t nspec, size_t maxt) { + + // Create a fake muon dataset + double a = 0.1; // Amplitude of the oscillations + double w = 25.; // Frequency of the oscillations + double tau = 2.2; // Muon life time + + MantidVec X; + MantidVec Y; + MantidVec E; + for (size_t s = 0; s < nspec; s++) { + for (size_t t = 0; t < maxt; t++) { + double x = static_cast<double>(t) / static_cast<double>(maxt); + double e = exp(-x / tau); + X.push_back(x); + Y.push_back(a * sin(w * x + + static_cast<double>(s) * M_PI / + static_cast<double>(nspec)) * + e + + e); + E.push_back(0.005); + } + } + + auto createWS = AlgorithmManager::Instance().create("CreateWorkspace"); + createWS->initialize(); + createWS->setChild(true); + createWS->setProperty("DataX", X); + createWS->setProperty("DataY", Y); + createWS->setProperty("DataE", E); + createWS->setProperty("NSpec", static_cast<int>(nspec)); + createWS->setPropertyValue("OutputWorkspace", "ws"); + createWS->execute(); + MatrixWorkspace_sptr ws = createWS->getProperty("OutputWorkspace"); + + return ws; + } }; #endif /*MUONREMOVEEXPDECAYTEST_H_*/ diff --git a/Framework/CurveFitting/src/ParameterEstimator.cpp b/Framework/CurveFitting/src/ParameterEstimator.cpp index 93c46fd68fbb9ae0690fbf296458a5f3bb20b7c4..db682fa12c32e3fce6170d9e4ca8c7a28725dfcd 100644 --- a/Framework/CurveFitting/src/ParameterEstimator.cpp +++ b/Framework/CurveFitting/src/ParameterEstimator.cpp @@ -7,6 +7,8 @@ #include "MantidKernel/Logger.h" +#include <Poco/Mutex.h> + #include <cmath> namespace Mantid { @@ -18,20 +20,44 @@ using namespace Functions; /// The logger. Kernel::Logger g_log("ParameterEstimator"); +namespace { +/// Mutex to prevent simultaneous access to functionMap +Poco::Mutex FUNCTION_MAP_MUTEX; +} + enum Function { None, Gaussian, Lorentzian, BackToBackExponential }; typedef std::map<std::string, std::pair<size_t, Function>> FunctionMapType; //---------------------------------------------------------------------------------------------- + +/// Initializes a FunctionMapType object +/// @param functionMapType :: the function map to initialize +void initFunctionLookup(FunctionMapType &functionMapType) { + assert(functionMapType.empty()); + + functionMapType["Gaussian"] = std::make_pair(2, Gaussian); + functionMapType["Lorentzian"] = std::make_pair(2, Lorentzian); + functionMapType["BackToBackExponential"] = + std::make_pair(4, BackToBackExponential); +} + +/// Returns a reference to the static functionMapType +/// @returns :: a const reference to the functionMapType +const FunctionMapType &getFunctionMapType() { + + Poco::Mutex::ScopedLock lock(FUNCTION_MAP_MUTEX); + + static FunctionMapType functionMapType; + + if (functionMapType.empty()) + initFunctionLookup(functionMapType); + return functionMapType; +} + /// Return a function code for a function if it needs setting values or None /// otherwise. Function whichFunction(const API::IFunction &function) { - static FunctionMapType functionMap; - if (functionMap.empty()) { - functionMap["Gaussian"] = std::make_pair(2, Gaussian); - functionMap["Lorentzian"] = std::make_pair(2, Lorentzian); - functionMap["BackToBackExponential"] = - std::make_pair(4, BackToBackExponential); - } + const FunctionMapType &functionMap = getFunctionMapType(); auto index = functionMap.find(function.name()); if (index != functionMap.end()) { if (!function.isExplicitlySet(index->second.first)) diff --git a/Framework/Geometry/inc/MantidGeometry/Crystal/HKLGenerator.h b/Framework/Geometry/inc/MantidGeometry/Crystal/HKLGenerator.h index e95bcdadc77a64621bc4906b6e030a09ac9cffd4..bbfde3fc99b3695b9b254245c192691d762ce50c 100644 --- a/Framework/Geometry/inc/MantidGeometry/Crystal/HKLGenerator.h +++ b/Framework/Geometry/inc/MantidGeometry/Crystal/HKLGenerator.h @@ -113,8 +113,7 @@ public: : public boost::iterator_facade<const_iterator, const Kernel::V3D &, boost::forward_traversal_tag> { public: - /// Default constructor, requirement from boost::iterator_facade - const_iterator() {} + const_iterator(); explicit const_iterator(const Kernel::V3D ¤t); diff --git a/Framework/Geometry/src/Crystal/HKLGenerator.cpp b/Framework/Geometry/src/Crystal/HKLGenerator.cpp index 0156cd97045b0a347af482893774907c011935c0..05a153674c612074fa06a4dd936f6285092284da 100644 --- a/Framework/Geometry/src/Crystal/HKLGenerator.cpp +++ b/Framework/Geometry/src/Crystal/HKLGenerator.cpp @@ -59,6 +59,11 @@ V3D HKLGenerator::getEndHKL() const { return V3D(m_hklMax.X() + 1, m_hklMin.Y(), m_hklMin.Z()); } +/// Default constructor, requirement from boost::iterator_facade +HKLGenerator::const_iterator::const_iterator() + : m_h(0), m_k(0), m_l(0), m_hkl(V3D(0, 0, 0)), m_hMin(0), m_hMax(0), + m_kMin(0), m_kMax(0), m_lMin(0), m_lMax(0) {} + /// Return an iterator with min = max = current. HKLGenerator::const_iterator::const_iterator(const V3D ¤t) : m_h(static_cast<int>(current.X())), m_k(static_cast<int>(current.Y())), diff --git a/MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/Indirect/ConvFit.h b/MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/Indirect/ConvFit.h index ed25cc6eed04b5788c3f2a4eb7fad4e11b2c3eeb..6ec99813345874f90ebcfe5d3f91ee85d5af963e 100644 --- a/MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/Indirect/ConvFit.h +++ b/MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/Indirect/ConvFit.h @@ -77,6 +77,9 @@ private: QStringList m_fitStrings; QString m_previousFit; QString m_baseName; + int m_runMin; + int m_runMax; + }; } // namespace IDA } // namespace CustomInterfaces diff --git a/MantidQt/CustomInterfaces/src/Indirect/ConvFit.cpp b/MantidQt/CustomInterfaces/src/Indirect/ConvFit.cpp index 8af4d002b29daed1fbcea4c0495aa2a709a07156..07fef6447c8a24678b514740f03f64a9664d855f 100644 --- a/MantidQt/CustomInterfaces/src/Indirect/ConvFit.cpp +++ b/MantidQt/CustomInterfaces/src/Indirect/ConvFit.cpp @@ -35,6 +35,8 @@ ConvFit::ConvFit(QWidget *parent) void ConvFit::setup() { // Create Property Managers m_stringManager = new QtStringPropertyManager(); + m_runMin = 0; + m_runMax = 0; // Initialise fitTypeStrings m_fitStrings = QStringList() << "" @@ -237,6 +239,8 @@ void ConvFit::run() { std::string function = std::string(func->asString()); std::string stX = m_properties["StartX"]->valueText().toStdString(); std::string enX = m_properties["EndX"]->valueText().toStdString(); + m_runMin = m_uiForm.spSpectraMin->value(); + m_runMax = m_uiForm.spSpectraMax->value(); std::string specMin = m_uiForm.spSpectraMin->text().toStdString(); std::string specMax = m_uiForm.spSpectraMax->text().toStdString(); int maxIterations = @@ -984,22 +988,23 @@ void ConvFit::updatePlot() { } // If there is a result plot then plot it - std::string groupName = m_baseName.toStdString() + "_Workspaces"; + std::string groupName = m_baseName.toStdString() + "_Workspaces"; if (AnalysisDataService::Instance().doesExist(groupName)) { WorkspaceGroup_sptr outputGroup = - AnalysisDataService::Instance().retrieveWS<WorkspaceGroup>( - groupName); - if (specNo >= static_cast<int>(outputGroup->size())) + AnalysisDataService::Instance().retrieveWS<WorkspaceGroup>(groupName); + if (specNo - m_runMin >= static_cast<int>(outputGroup->size())) return; - MatrixWorkspace_sptr ws = boost::dynamic_pointer_cast<MatrixWorkspace>( - outputGroup->getItem(specNo)); - if (ws) { - m_uiForm.ppPlot->addSpectrum("Fit", ws, 1, Qt::red); - m_uiForm.ppPlot->addSpectrum("Diff", ws, 2, Qt::blue); - if(m_uiForm.ckPlotGuess->isChecked()){ - m_uiForm.ppPlot->removeSpectrum("Guess"); - m_uiForm.ckPlotGuess->setChecked(false); - } + if ((specNo - m_runMin) >= 0) { + MatrixWorkspace_sptr ws = boost::dynamic_pointer_cast<MatrixWorkspace>( + outputGroup->getItem(specNo- m_runMin)); + if (ws) { + m_uiForm.ppPlot->addSpectrum("Fit", ws, 1, Qt::red); + m_uiForm.ppPlot->addSpectrum("Diff", ws, 2, Qt::blue); + if (m_uiForm.ckPlotGuess->isChecked()) { + m_uiForm.ppPlot->removeSpectrum("Guess"); + m_uiForm.ckPlotGuess->setChecked(false); + } + } } } } diff --git a/docs/source/algorithms/RemoveExpDecay-v1.rst b/docs/source/algorithms/RemoveExpDecay-v1.rst index 7307a59b69f6df06cd07ce3e4b48d5faa0791848..099f5988544139bcfb50a2bec4e27a834ad1fb42 100644 --- a/docs/source/algorithms/RemoveExpDecay-v1.rst +++ b/docs/source/algorithms/RemoveExpDecay-v1.rst @@ -9,8 +9,9 @@ Description ----------- -This algorithm removes the exponential time decay from a specified muon -spectra. By default, all the spectra in a workspace will be corrected. +This algorithm removes the exponential time decay from the specified muon +spectra, leaving the rest unchanged. By default, all the spectra +in a workspace will be corrected. The formula for removing the exponential decay is given by: