Skip to content

Commit

Permalink
Merge branch '11651_plotpeakbylogvalue_minimizer_string' into 11561_c…
Browse files Browse the repository at this point in the history
…onvfit_furyfit_fabada

Refs #11561
  • Loading branch information
DanNixon committed May 7, 2015
2 parents 3a56fd5 + a3b282b commit 2431adf
Show file tree
Hide file tree
Showing 4 changed files with 153 additions and 16 deletions.
Expand Up @@ -107,6 +107,12 @@ class DLLExport PlotPeakByLogValue : public API::Algorithm {

/// Create a list of input workspace names
std::vector<InputData> makeNames() const;

/// Create a minimizer string based on template string provided
std::string getMinimizerString(const std::string &wsName,
const std::string &specIndex);

std::map<std::string, std::vector<std::string>> m_minimizerWorkspaces;
};

} // namespace CurveFitting
Expand Down
69 changes: 61 additions & 8 deletions Code/Mantid/Framework/CurveFitting/src/PlotPeakByLogValue.cpp
Expand Up @@ -9,8 +9,10 @@
#include <algorithm>
#include <Poco/StringTokenizer.h>
#include <boost/lexical_cast.hpp>
#include <boost/algorithm/string/replace.hpp>

#include "MantidCurveFitting/PlotPeakByLogValue.h"
#include "MantidAPI/IFuncMinimizer.h"
#include "MantidAPI/AlgorithmManager.h"
#include "MantidAPI/FuncMinimizerFactory.h"
#include "MantidAPI/CostFunctionFactory.h"
Expand All @@ -27,6 +29,10 @@
#include "MantidKernel/ListValidator.h"
#include "MantidKernel/MandatoryValidator.h"

namespace {
Mantid::Kernel::Logger g_log("PlotPeakByLogValue");
}

namespace Mantid {
namespace CurveFitting {

Expand Down Expand Up @@ -93,15 +99,11 @@ void PlotPeakByLogValue::init() {
"functions that"
"have attribute WorkspaceIndex.");

std::vector<std::string> minimizerOptions =
FuncMinimizerFactory::Instance().getKeys();
declareProperty("Minimizer", "Levenberg-Marquardt",
boost::make_shared<StringListValidator>(minimizerOptions),
"Minimizer to use for fitting. Minimizers available are "
"'Levenberg-Marquardt', 'Simplex', \n"
"'Levenberg-Marquardt', 'Simplex', 'FABADA',\n"
"'Conjugate gradient (Fletcher-Reeves imp.)', 'Conjugate "
"gradient (Polak-Ribiere imp.)' and 'BFGS'",
Direction::InOut);
"gradient (Polak-Ribiere imp.)' and 'BFGS'");

std::vector<std::string> costFuncOptions =
CostFunctionFactory::Instance().getKeys();
Expand All @@ -111,6 +113,10 @@ void PlotPeakByLogValue::init() {
"are 'Least squares' and 'Ignore positive peaks'",
Direction::InOut);

declareProperty("MaxIterations", 500,
"Stop after this number of iterations if a good fit is not "
"found");

declareProperty("CreateOutput", false, "Set to true to create output "
"workspaces with the results of the "
"fit(default is false).");
Expand Down Expand Up @@ -244,7 +250,7 @@ void PlotPeakByLogValue::exec() {
<< " with " << std::endl;
g_log.debug() << ifun->asString() << std::endl;

std::string spectrum_index = boost::lexical_cast<std::string>(j);
const std::string spectrum_index = boost::lexical_cast<std::string>(j);
std::string wsBaseName = "";

if (createFitOutput)
Expand All @@ -259,8 +265,11 @@ void PlotPeakByLogValue::exec() {
fit->setProperty("WorkspaceIndex", j);
fit->setPropertyValue("StartX", getPropertyValue("StartX"));
fit->setPropertyValue("EndX", getPropertyValue("EndX"));
fit->setPropertyValue("Minimizer", getPropertyValue("Minimizer"));
fit->setPropertyValue(
"Minimizer", getMinimizerString(wsNames[i].name, spectrum_index));
fit->setPropertyValue("CostFunction", getPropertyValue("CostFunction"));
fit->setPropertyValue("MaxIterations",
getPropertyValue("MaxIterations"));
fit->setProperty("CalcErrors", true);
fit->setProperty("CreateOutput", createFitOutput);
fit->setProperty("OutputCompositeMembers", outputCompositeMembers);
Expand Down Expand Up @@ -339,6 +348,17 @@ void PlotPeakByLogValue::exec() {
groupAlg->setProperty("OutputWorkspace", baseName + "_Workspaces");
groupAlg->execute();
}

for (auto it = m_minimizerWorkspaces.begin();
it != m_minimizerWorkspaces.end(); ++it) {
const std::string paramName = (*it).first;
API::IAlgorithm_sptr groupAlg =
AlgorithmManager::Instance().createUnmanaged("GroupWorkspaces");
groupAlg->initialize();
groupAlg->setProperty("InputWorkspaces", (*it).second);
groupAlg->setProperty("OutputWorkspace", baseName + "_" + paramName);
groupAlg->execute();
}
}

/** Get a workspace identified by an InputData structure.
Expand Down Expand Up @@ -553,5 +573,38 @@ PlotPeakByLogValue::makeNames() const {
return nameList;
}

/**
* Formats the minimizer string for a given spectrum from a given workspace.
*
* @param wsName Name of workspace being fitted
* @param specIndex Index of spectrum being fitted
* @return Formatted minimizer string
*/
std::string
PlotPeakByLogValue::getMinimizerString(const std::string &wsName,
const std::string &specIndex) {
std::string format = getPropertyValue("Minimizer");
std::string wsBaseName = wsName + "_" + specIndex;
boost::replace_all(format, "$wsname", wsName);
boost::replace_all(format, "$wsindex", specIndex);
boost::replace_all(format, "$basename", wsBaseName);

auto minimizer = FuncMinimizerFactory::Instance().createMinimizer(format);
auto minimizerProps = minimizer->getProperties();
for (auto it = minimizerProps.begin(); it != minimizerProps.end(); ++it) {
Mantid::API::WorkspaceProperty<> *wsProp =
dynamic_cast<Mantid::API::WorkspaceProperty<> *>(*it);
if (wsProp) {
std::string wsPropValue = (*it)->value();
if (wsPropValue != "") {
std::string wsPropName = (*it)->name();
m_minimizerWorkspaces[wsPropName].push_back(wsPropValue);
}
}
}

return format;
}

} // namespace CurveFitting
} // namespace Mantid
67 changes: 63 additions & 4 deletions Code/Mantid/Framework/CurveFitting/test/PlotPeakByLogValueTest.h
Expand Up @@ -57,6 +57,21 @@ namespace
};

DECLARE_FUNCTION(PLOTPEAKBYLOGVALUETEST_Fun)

class PropertyNameIs
{
public:
PropertyNameIs(std::string name) : m_name(name) {};

bool operator()(Mantid::Kernel::PropertyHistory_sptr p)
{
return p->name() == m_name;
}

private:
std::string m_name;
};

}

class PlotPeak_Expression
Expand Down Expand Up @@ -205,9 +220,9 @@ class PlotPeakByLogValueTest : public CxxTest::TestSuite

deleteData();
WorkspaceCreationHelper::removeWS("PlotPeakResult");

}


void testWorkspaceList_plotting_against_ws_names()
{
createData();
Expand Down Expand Up @@ -363,7 +378,7 @@ class PlotPeakByLogValueTest : public CxxTest::TestSuite
void test_createOutputOptionMultipleWorkspaces()
{
createData();

PlotPeakByLogValue alg;
alg.initialize();
alg.setPropertyValue("Input","PlotPeakGroup_0;PlotPeakGroup_1;PlotPeakGroup_2");
Expand Down Expand Up @@ -432,11 +447,55 @@ class PlotPeakByLogValueTest : public CxxTest::TestSuite
auto fit = AnalysisDataService::Instance().retrieveWS<const MatrixWorkspace>(wsNames[i]);
TS_ASSERT( fit );
TS_ASSERT( fit->getNumberHistograms() == 5);
}
}

AnalysisDataService::Instance().clear();
}


void testMinimizer()
{
createData();

PlotPeakByLogValue alg;
alg.initialize();
alg.setPropertyValue("Input","PlotPeakGroup_0");
alg.setPropertyValue("OutputWorkspace","PlotPeakResult");
alg.setProperty("CreateOutput", true);
alg.setPropertyValue("WorkspaceIndex","1");
alg.setPropertyValue("Function","name=LinearBackground,A0=1,A1=0.3;name=Gaussian,PeakCentre=5,Height=2,Sigma=0.1");
alg.setPropertyValue("MaxIterations", "50");
// This is a stupid use case but will at least demonstrate the functionality
alg.setPropertyValue("Minimizer", "Levenberg-Marquardt,AbsError=0.01,RelError=$wsindex");

alg.execute();
TS_ASSERT(alg.isExecuted());

auto fits = AnalysisDataService::Instance().retrieveWS<const WorkspaceGroup>("PlotPeakResult_Workspaces");
TS_ASSERT(fits);

if (fits->size() > 0)
{
// Get the Fit algorithm history
auto fit = fits->getItem(0);
const auto & wsHistory = fit->getHistory();
const auto & child = wsHistory.getAlgorithmHistory(0);
TS_ASSERT_EQUALS(child->name(), "Fit");
const auto & properties = child->getProperties();

// Check max iterations property
PropertyNameIs maxIterationsCheck("MaxIterations");
auto prop = std::find_if(properties.begin(), properties.end(), maxIterationsCheck);
TS_ASSERT_EQUALS((*prop)->value(), "50");

// Check minimizer property
PropertyNameIs minimizerCheck("Minimizer");
prop = std::find_if(properties.begin(), properties.end(), minimizerCheck);
TS_ASSERT_EQUALS((*prop)->value(), "Levenberg-Marquardt,AbsError=0.01,RelError=1");
}
}


private:

WorkspaceGroup_sptr m_wsg;
Expand Down Expand Up @@ -487,7 +546,7 @@ class PlotPeakByLogValueTest : public CxxTest::TestSuite

}
xdata.access()[i] = xValue;
}
}
testWS->setX(0, xdata);
testWS->setX(1, xdata);
return testWS;
Expand Down
27 changes: 23 additions & 4 deletions Code/Mantid/docs/source/algorithms/PlotPeakByLogValue-v1.rst
Expand Up @@ -53,7 +53,7 @@ Output workspace format
:alt: PlotPeakByLogValue_Output.png

PlotPeakByLogValue\_Output.png

In this example a group of three Matrix workspaces were fitted with a
:ref:`Gaussian <func-Gaussian>` on a linear background.

Expand All @@ -64,19 +64,38 @@ columns with parameter values and fitting errors. If a parameter was
fixed or tied the error will be zero. Here is an example of the output
workspace:

Minimizer setup
###############

It is possible to supply a fully configured minimizer via the Minimizer
property, this can also include several flags that are used to indicate the
workspace name and spectrum index that has been fitted (useful for fitting using
a minimizer that output workspaces (i.e. FABADA)).

The possible flags are:

:code:`$wsname`
The name of the workspace being fitted

:code:`$wsindex`
The index of the spectrum being fitted

:code:`$basename`
A convinience flag for :code:`$wsname_$wsindex` (the same format the fit
result and parameter output takes)

Usage
-----

**Example - fitting a single spectrum of in a workspace:**
**Example - fitting a single spectrum of in a workspace:**

.. testcode:: ExPlotPeakByLogValueSimple

ws = CreateSampleWorkspace()
function = "name=Gaussian,Height=10.0041,PeakCentre=10098.6,Sigma=48.8581;name=FlatBackground,A0=0.3"
peaks = PlotPeakByLogValue(ws, function, Spectrum=1)

**Example - sequentially fitting a workspace:**
**Example - sequentially fitting a workspace:**

.. testcode:: ExPlotPeakByLogValueSeq

Expand All @@ -101,7 +120,7 @@ Usage
Output:

.. testoutput:: ExPlotPeakByLogValueSeq

True

.. categories::

0 comments on commit 2431adf

Please sign in to comment.