Skip to content

Commit

Permalink
Add form factor attribute to quantification models.
Browse files Browse the repository at this point in the history
Allows the user to specify the form factor type or turn it off without
coding a whole new model. Refs #7020
  • Loading branch information
martyngigg committed May 10, 2013
1 parent efa754b commit 1bfa698
Show file tree
Hide file tree
Showing 6 changed files with 160 additions and 40 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,14 @@

namespace Mantid
{
//----------------------------------------------------------------------------
// Forward declarations
//----------------------------------------------------------------------------
namespace PhysicalConstants
{
class MagneticFormFactorTable;
}

namespace MDAlgorithms
{
/**
Expand All @@ -48,6 +56,8 @@ namespace Mantid
ForegroundModel();
/// Constructor taking the fitted function to access the current parameter values
ForegroundModel(const API::IFunction & fittingFunction);
/// Destructor
~ForegroundModel();

/// Returns the type of model
virtual ModelType modelType() const = 0;
Expand All @@ -58,6 +68,8 @@ namespace Mantid
void setFunctionUnderMinimization(const API::IFunction & fitFunction);
/// Declares the parameters
void declareParameters();
/// Called when an attribute value is set
void setAttribute(const std::string & name, const API::IFunction::Attribute & attr);
/// Return the initial value of the parameter according to the fit by index
double getInitialParameterValue(size_t index) const;
/// Return the initial value of the parameter according to the fit by name
Expand All @@ -71,11 +83,18 @@ namespace Mantid
/// Returns a reference to the fitting function
const API::IFunction & functionUnderMinimization() const;

/// Set the default ion type for the form factor calculation
void setFormFactorIon(const std::string & ionType);
/// Returns the form factor for the given q^2 value
double formFactor(const double qsqr) const;

private:
DISABLE_COPY_AND_ASSIGN(ForegroundModel);

/// Required by the interface
void function(const Mantid::API::FunctionDomain&, Mantid::API::FunctionValues&) const {}
/// Add attributes common to all models
void addAttributes();

/// Hide these
using ParamFunction::getParameter;
Expand All @@ -84,6 +103,9 @@ namespace Mantid
const API::IFunction * m_fittingFunction;
/// An offset for the number of parameters that were declared before this one
size_t m_parOffset;

/// Owned pointer to magnetic form factor cache
PhysicalConstants::MagneticFormFactorTable *m_formFactorTable;
};

/// boost::shared_ptr typedef
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,6 @@
*/
#include "MantidMDAlgorithms/Quantification/ForegroundModel.h"

#include "MantidKernel/MagneticFormFactorTable.h"

namespace Mantid
{
namespace MDAlgorithms
Expand All @@ -36,19 +34,15 @@ namespace Mantid
*/
class DLLExport Strontium122 : public ForegroundModel
{
public:
/// Constructor
Strontium122();

private:
/// String name of the model
std::string name() const { return "Strontium122"; }
/// Declare the fitting parameters
void declareParameters();
/// Declare fixed attributes
void declareAttributes();

/// Setup the model
void init();
/// Called when an attribute is set
void setAttribute(const std::string & name, const API::IFunction::Attribute& attr);

/// Returns the type of model
ModelType modelType() const { return Broad; }
/// Calculates the intensity for the model for the current parameters.
Expand All @@ -58,8 +52,6 @@ namespace Mantid
int m_twinType;
/// MultEps attribute
bool m_multEps;
/// Magnetic form factor cache
PhysicalConstants::MagneticFormFactorTable m_formFactorTable;
};

}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,29 +3,51 @@
//
#include "MantidMDAlgorithms/Quantification/ForegroundModel.h"
#include "MantidKernel/Exception.h"
#include "MantidKernel/MagneticFormFactorTable.h"

namespace Mantid
{
namespace MDAlgorithms
{
namespace
{
/// Length of the form factor interpolation table
const int FORM_FACTOR_TABLE_LENGTH = 500;
/// Name of the form factor attribute
const char * FORM_FACTOR_ION = "FormFactorIon";
}

/**
* Default constructor only callable by the factory
*/
ForegroundModel::ForegroundModel()
: API::ParamFunction(), m_fittingFunction(NULL), m_parOffset(0)
: API::ParamFunction(), m_fittingFunction(NULL), m_parOffset(0),
m_formFactorTable(NULL)
{
addAttributes();
setFormFactorIon("0"); // Off
}

/**
* Constructor taking the fitted function to access the current parameter values
* @param fittingFunction :: A reference to the fitting function
*/
ForegroundModel::ForegroundModel(const API::IFunction & fittingFunction)
: API::ParamFunction(), m_fittingFunction(NULL), m_parOffset(0)
: API::ParamFunction(), m_fittingFunction(NULL), m_parOffset(0),
m_formFactorTable(NULL)
{
addAttributes();
setFormFactorIon("0"); // Off
setFunctionUnderMinimization(fittingFunction);
}

/**
*/
ForegroundModel::~ForegroundModel()
{
delete m_formFactorTable;
}

/**
* Set a reference to the convolved fitting function. Required as we need a default constructor for the factory
* @param fittingFunction :: This object has access to the current value of the model parameters
Expand All @@ -44,6 +66,19 @@ namespace Mantid
throw Kernel::Exception::NotImplementedError("Error: Override ForegroundModel::declareParameters() and declare model parameters");
}

/**
* Called when an attribute value is set
* @param name :: The name of the attribute
* @param attr :: The value of the attribute
*/
void ForegroundModel::setAttribute(const std::string & name, const API::IFunction::Attribute & attr)
{
if(name == FORM_FACTOR_ION)
{
setFormFactorIon(attr.asString());
}
}

/**
* Return the initial value of the parameter by index
* @param index :: An index for the parameter
Expand Down Expand Up @@ -96,5 +131,48 @@ namespace Mantid
return *m_fittingFunction;
}

/**
* Set the default ion type for the form factor calculation
* @param ionType A symbol string containing the atom and charge
*/
void ForegroundModel::setFormFactorIon(const std::string & ionType)
{
// "0" indicates off
if(ionType == "0")
{
delete m_formFactorTable;
m_formFactorTable = NULL;
}
else
{
using namespace PhysicalConstants;
m_formFactorTable = new MagneticFormFactorTable(FORM_FACTOR_TABLE_LENGTH, getMagneticIon(ionType));
}
}

/**
* Returns the form factor for the given \f$Q^2\f$ value
* @param qsr :: \f$Q^2\f$ in \f$\AA^{-2}\f$
* @returns The form factorfor the given factor
*/
double ForegroundModel::formFactor(const double qsqr) const
{
if(m_formFactorTable) return m_formFactorTable->value(qsqr);
else return 0.0;
}

//-------------------------------------------------------------------------
// Private members
//-------------------------------------------------------------------------

/**
* Add attributes common to all models
*/
void ForegroundModel::addAttributes()
{
// Ion type string for form factor. "0" = off
declareAttribute(FORM_FACTOR_ION, API::IFunction::Attribute("0"));
}

}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,6 @@

#include "MantidGeometry/Crystal/OrientedLattice.h"
#include "MantidKernel/Math/Distributions/BoseEinsteinDistribution.h"
#include "MantidKernel/MagneticIon.h"
#include "MantidKernel/PhysicalConstants.h"

#include <cmath>

Expand All @@ -14,7 +12,6 @@ namespace Mantid
{
DECLARE_FOREGROUNDMODEL(Strontium122);

using PhysicalConstants::MagneticIon;
using Kernel::Math::BoseEinsteinDistribution;

namespace // anonymous
Expand All @@ -35,49 +32,43 @@ namespace Mantid
const double TWO_PI = 2.*M_PI;
}

Strontium122::Strontium122()
: m_formFactorTable(500, PhysicalConstants::getMagneticIon("Fe", 2), /*J*/0, /*L*/0)
{
}

/**
* Declares the parameters that should participate in fitting
* Initialize the model
*/
void Strontium122::declareParameters()
void Strontium122::init()
{
// Default form factor. Can be overridden with the FormFactorIon attribute
setFormFactorIon("Fe2");

// Declare parameters that participate in fitting
for(unsigned int i = 0; i < NPARAMS; ++i)
{
declareParameter(PAR_NAMES[i], 0.0);
}
}

/**
* Declare fixed attributes
*/
void Strontium122::declareAttributes()
{
// Declare fixed attributes
for(unsigned int i = 0; i < NATTS; ++i)
{
declareAttribute(ATTR_NAMES[i], API::IFunction::Attribute(1));
}
}

/**
* Called when an attribute is set
* Called when an attribute is set from the Fit string
* @param name :: The name of the attribute
* @param attr :: The value of the attribute
*/
void Strontium122::setAttribute(const std::string & name, const API::IFunction::Attribute& attr)
{
int asInt = attr.asInt();
if(name == ATTR_NAMES[0])
{
m_multEps = (asInt > 0);
m_multEps = (attr.asInt() > 0);
}
else if(name == ATTR_NAMES[1])
{
m_twinType = asInt;
m_twinType = attr.asInt();
}
else ForegroundModel::setAttribute(name, attr); // pass it on the base
}

/**
Expand Down Expand Up @@ -143,7 +134,7 @@ namespace Mantid

const double tempInK = exptSetup.getLogAsSingleValue("temperature_log");
const double boseFactor = BoseEinsteinDistribution::np1Eps(eps,tempInK);
const double magFormFactorSqr = std::pow(m_formFactorTable.value(qsqr), 2);
const double magFormFactorSqr = std::pow(formFactor(qsqr), 2);

const double s_eff = getCurrentParameterValue(Seff);
const double sj_1a = getCurrentParameterValue(J1a);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ class ResolutionConvolvedCrossSectionTest : public CxxTest::TestSuite
const size_t startingNAttrs = crossSection.nAttributes();
crossSection.setAttributeValue("ResolutionFunction", "FakeConvolution");

TS_ASSERT_EQUALS(crossSection.nAttributes(), startingNAttrs + 4);
TS_ASSERT_EQUALS(crossSection.nAttributes(), startingNAttrs + 5);
}

void test_ResolutionConvolution_Attributes_Are_Passed_On_Correctly()
Expand Down
45 changes: 41 additions & 4 deletions Code/Mantid/Framework/MDAlgorithms/test/Strontium122Test.h
Original file line number Diff line number Diff line change
Expand Up @@ -63,16 +63,53 @@ class Strontium122Test : public CxxTest::TestSuite
TS_ASSERT_EQUALS(sr122.nParams(), 6);
}

void test_Given_ND_Point_Returns_Expected_Value_For_Test_Parameter_Values()
void test_Sr122_Has_DefaultIon_As_Fe2()
{
using Mantid::MDAlgorithms::Strontium122;
using Mantid::MDAlgorithms::ForegroundModel;
Strontium122 sr122Default;
sr122Default.initialize();
sr122Default.setAttributeValue("MultEps", 0);
sr122Default.setAttributeValue("TwinType", 0);
double valueWithDefault = calculateTestModelWeight(sr122Default);
TS_ASSERT_DELTA(0.0000062768, valueWithDefault, 1e-10); // Check the absolute value is correct

Strontium122 sr122;
sr122.initialize();
sr122.setAttributeValue("MultEps", 0);
sr122.setAttributeValue("TwinType", 0);
sr122.setAttributeValue("FormFactorIon", "Fe2");

// Same test but set the ion to check they match
double valueWithAttrSet = calculateTestModelWeight(sr122);

TS_ASSERT_DELTA(valueWithDefault, valueWithAttrSet, 1e-10);

// FakeFGModelFitFunction fakeFitFunction(sr122); // Use fit function to access current fit values

// const double qx(7.7), qy(6.5), qz(4.3), deltaE(300);
// const double qOmega[4] = {qx, qy, qz, deltaE};
// Mantid::API::ExperimentInfo experimentDescr;
// auto lattice = new Mantid::Geometry::OrientedLattice(5.51,12.298,5.57);
// Mantid::Kernel::V3D uVec(9.800000e-03,9.996000e-01,9.700000e-03),
// vVec(-3.460000e-02,-4.580000e-02,9.992000e-01);
// lattice->setUFromVectors(uVec, vVec);

// experimentDescr.mutableSample().setOrientedLattice(lattice);
// experimentDescr.mutableRun().addProperty("temperature_log", 6.0);

// double weight(-1.0);
// const ForegroundModel & sr122Function = sr122; // scatteringIntensity is private concrete model
// TS_ASSERT_THROWS_NOTHING( weight = sr122Function.scatteringIntensity(experimentDescr, std::vector<double>(qOmega, qOmega + 4)) );
// TS_ASSERT_DELTA(0.0000062768, weight, 1e-10);
}

FakeFGModelFitFunction fakeFitFunction(sr122); // Use fit function to access current fit values
private:

double calculateTestModelWeight(Mantid::MDAlgorithms::Strontium122 & model)
{
using Mantid::MDAlgorithms::ForegroundModel;
FakeFGModelFitFunction fakeFitFunction(model); // Use fit function to access current fit values

const double qx(7.7), qy(6.5), qz(4.3), deltaE(300);
const double qOmega[4] = {qx, qy, qz, deltaE};
Expand All @@ -86,9 +123,9 @@ class Strontium122Test : public CxxTest::TestSuite
experimentDescr.mutableRun().addProperty("temperature_log", 6.0);

double weight(-1.0);
const ForegroundModel & sr122Function = sr122; // scatteringIntensity is private concrete model
const ForegroundModel & sr122Function = model; // scatteringIntensity is private concrete model
TS_ASSERT_THROWS_NOTHING( weight = sr122Function.scatteringIntensity(experimentDescr, std::vector<double>(qOmega, qOmega + 4)) );
TS_ASSERT_DELTA(0.0000062768, weight, 1e-10);
return weight;
}

};
Expand Down

0 comments on commit 1bfa698

Please sign in to comment.