Skip to content

Commit

Permalink
Added option to ignore invalid data in Fit. Re #7182.
Browse files Browse the repository at this point in the history
  • Loading branch information
mantid-roman committed May 23, 2013
1 parent 9d34d73 commit 0cca0b9
Show file tree
Hide file tree
Showing 5 changed files with 103 additions and 7 deletions.
7 changes: 6 additions & 1 deletion Code/Mantid/Framework/API/inc/MantidAPI/IDomainCreator.h
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ namespace Mantid
const std::vector<std::string>& workspacePropertyNames,
DomainType domainType = Simple);
/// Virtual destructor
virtual ~IDomainCreator() {};
virtual ~IDomainCreator() {}
/// Initialize
virtual void initialize(Kernel::IPropertyManager* , const std::string&, DomainType) {}

Expand Down Expand Up @@ -103,6 +103,9 @@ namespace Mantid
/// Return the size of the domain to be created.
virtual size_t getDomainSize() const = 0;

/// Set to ignore invalid data
void ignoreInvalidData( bool yes ) {m_ignoreInvalidData = yes;}

protected:
/// Declare a property to the algorithm
void declareProperty(Kernel::Property* prop,const std::string& doc);
Expand All @@ -114,6 +117,8 @@ namespace Mantid
DomainType m_domainType;
/// Output separate composite function values
bool m_outputCompositeMembers;
/// Flag to ignore nans, infinities and zero errors.
bool m_ignoreInvalidData;
};

/// Typedef for a shared pointer to IDomainCreator.
Expand Down
2 changes: 1 addition & 1 deletion Code/Mantid/Framework/API/src/IDomainCreator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ namespace API
DomainType domainType):
m_manager( manager ),
m_workspacePropertyNames( workspacePropertyNames ),
m_domainType( domainType ), m_outputCompositeMembers(false)
m_domainType( domainType ), m_outputCompositeMembers( false ), m_ignoreInvalidData( false )
{}

/**
Expand Down
2 changes: 2 additions & 0 deletions Code/Mantid/Framework/CurveFitting/src/Fit.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -448,6 +448,7 @@ namespace CurveFitting
mustBePositive->setLower(0);
declareProperty("MaxIterations", 500, mustBePositive->clone(),
"Stop after this number of iterations if a good fit is not found" );
declareProperty("IgnoreInvalidData",false,"Flag to ignore infinities, NaNs and data with zero errors.");
declareProperty("OutputStatus","", Kernel::Direction::Output);
getPointerToProperty("OutputStatus")->setDocumentation( "Whether the fit was successful" );
declareProperty("OutputChi2overDoF",0.0, "Returns the goodness of the fit", Kernel::Direction::Output);
Expand Down Expand Up @@ -517,6 +518,7 @@ namespace CurveFitting

API::FunctionDomain_sptr domain;
API::IFunctionValues_sptr values;
m_domainCreator->ignoreInvalidData(getProperty("IgnoreInvalidData"));
m_domainCreator->createDomain(domain,values);

// do something with the function which may depend on workspace
Expand Down
23 changes: 18 additions & 5 deletions Code/Mantid/Framework/CurveFitting/src/FitMW.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
#include "MantidKernel/BoundedValidator.h"
#include "MantidKernel/EmptyValues.h"

#include <boost/math/special_functions/fpclassify.hpp>
#include <algorithm>

namespace Mantid
Expand Down Expand Up @@ -244,14 +245,26 @@ namespace
for(size_t i = m_startIndex; i < ito; ++i)
{
size_t j = i - m_startIndex + i0;
values->setFitData( j, Y[i] );
double y = Y[i];
double error = E[i];
if (error <= 0)
double weight = 0.0;

if ( ! boost::math::isfinite(y) )
{
if ( !m_ignoreInvalidData ) throw std::runtime_error("Infinte number or NaN found in input data.");
y = 0.0; // leaving inf or nan would break the fit
}
else if ( error <= 0 )
{
error = 1.0;
//foundZeroOrNegativeError = true;
if ( !m_ignoreInvalidData ) weight = 1.0;
}
values->setFitWeight( j, 1.0 / error );
else
{
weight = 1.0 / error;
}

values->setFitData( j, y );
values->setFitWeight( j, weight );
}

}
Expand Down
76 changes: 76 additions & 0 deletions Code/Mantid/Framework/CurveFitting/test/FitMWTest.h
Original file line number Diff line number Diff line change
Expand Up @@ -361,6 +361,82 @@ class FitMWTest : public CxxTest::TestSuite

}

void test_ignore_invalid_data()
{
auto ws = createTestWorkspace(false);
const double zero = 0.0;
const double one = 1.0;
ws->dataY(0)[3] = 1.0 / zero;
ws->dataY(0)[5] = log(-one);
ws->dataE(0)[7] = 0;

FunctionDomain_sptr domain;
IFunctionValues_sptr values;

// Requires a property manager to make a workspce
auto propManager = boost::make_shared<Mantid::Kernel::PropertyManager>();
const std::string wsPropName = "TestWorkspaceInput";
propManager->declareProperty(new WorkspaceProperty<Workspace>(wsPropName, "", Mantid::Kernel::Direction::Input));
propManager->setProperty<Workspace_sptr>(wsPropName, ws);

FitMW fitmw(propManager.get(), wsPropName);
fitmw.declareDatasetProperties("", true);
fitmw.ignoreInvalidData(true);
fitmw.createDomain(domain, values);

FunctionValues *val = dynamic_cast<FunctionValues*>(values.get());
for(size_t i = 0; i < val->size(); ++i)
{
if ( i == 3 || i == 5 || i == 7 )
{
TS_ASSERT_EQUALS( val->getFitWeight(i), 0.0 );
}
else
{
TS_ASSERT_DIFFERS( val->getFitWeight(i), 0.0 );
}
}

API::IFunction_sptr fun(new ExpDecay);
fun->setParameter("Height",1.);
fun->setParameter("Lifetime",1.0);

Fit fit;
fit.initialize();

fit.setProperty("Function",fun);
fit.setProperty("InputWorkspace",ws);
fit.setProperty("WorkspaceIndex",0);

fit.execute();
TS_ASSERT(! fit.isExecuted());

fit.setProperty("IgnoreInvalidData",true);
fit.setProperty("Minimizer","Levenberg-Marquardt");
fit.execute();
TS_ASSERT(fit.isExecuted());

TS_ASSERT_DELTA( fun->getParameter("Height"), 10.0, 1e-3);
TS_ASSERT_DELTA( fun->getParameter("Lifetime"), 0.5, 1e-4);

// check Levenberg-MarquardtMD minimizer
fun->setParameter("Height",1.);
fun->setParameter("Lifetime",1.0);
Fit fit1;
fit1.initialize();
fit1.setProperty("Function",fun);
fit1.setProperty("InputWorkspace",ws);
fit1.setProperty("WorkspaceIndex",0);
fit1.setProperty("IgnoreInvalidData",true);
fit1.setProperty("Minimizer","Levenberg-MarquardtMD");
fit1.execute();
TS_ASSERT(fit1.isExecuted());

TS_ASSERT_DELTA( fun->getParameter("Height"), 10.0, 1e-3);
TS_ASSERT_DELTA( fun->getParameter("Lifetime"), 0.5, 1e-4);

}


private:

Expand Down

0 comments on commit 0cca0b9

Please sign in to comment.