Commit cfd14ad4 authored by Roman Tolchenov's avatar Roman Tolchenov
Browse files

Re #14642. Added X and Y attributes to TabulatedFunction.

parent f375af18
......@@ -14,6 +14,8 @@ typedef Poco::StringTokenizer tokenizer;
const std::string DEFAULT_OPS_STR[] = {";", ",", "=", "== != > < <= >=",
"&& || ^^", "+ -", "* /", "^"};
const std::string EMPTY_EXPRESSION_NAME = "EMPTY";
Expression::Expression() {
m_operators.reset(new Operators());
......@@ -392,8 +394,10 @@ void Expression::setFunct(const std::string &name) {
m_funct = name;
trim(m_funct);
if (m_funct.empty()) {
throw std::runtime_error("Expression: Syntax error");
m_funct = EMPTY_EXPRESSION_NAME;
return;
}
// Check if the function has arguments
......@@ -428,7 +432,7 @@ void Expression::setFunct(const std::string &name) {
std::string f = name.substr(0, i);
Expression tmp(this);
tmp.parse(args);
if (!tmp.isFunct() || tmp.name() != ",") {
if (tmp.name() != EMPTY_EXPRESSION_NAME && (!tmp.isFunct() || tmp.name() != ",")) {
m_terms.push_back(tmp);
} else {
std::string my_op = m_op;
......@@ -436,6 +440,9 @@ void Expression::setFunct(const std::string &name) {
m_op = my_op;
}
m_funct = f;
if (m_funct.empty() && m_terms.empty()) {
m_funct = EMPTY_EXPRESSION_NAME;
}
}
}
}
......
......@@ -568,7 +568,7 @@ protected:
}
/// Apply if vector
void apply(std::vector<double> &v) const {
if (m_value.empty()) {
if (m_value.empty() || m_value == "EMPTY") {
v.clear();
return;
}
......@@ -1007,7 +1007,7 @@ void IFunction::setAttributeValue(const std::string &attName,
/// Returns a list of attribute names
std::vector<std::string> IFunction::getAttributeNames() const {
std::vector<std::string> names(nAttributes(), "");
std::vector<std::string> names(m_attrs.size(), "");
size_t index(0);
for (auto iter = m_attrs.begin(); iter != m_attrs.end(); ++iter) {
names[index] = iter->first;
......
......@@ -367,6 +367,30 @@ public:
e.toList();
TS_ASSERT_EQUALS(e.name(), ",");
}
void testEmptyString() {
Expression e;
e.parse("");
TS_ASSERT_EQUALS(e.name(), "EMPTY");
}
void testEmptyStringInBrackets() {
{
Expression e;
e.parse("()");
TS_ASSERT_EQUALS(e.name(), "EMPTY");
}
{
Expression e;
e.parse(" ( ) ");
TS_ASSERT_EQUALS(e.name(), "EMPTY");
}
{
Expression e;
e.parse(" (( ) ) ");
TS_ASSERT_EQUALS(e.name(), "EMPTY");
}
}
};
#endif /*EXPRESSIONTEST_H_*/
......@@ -82,9 +82,17 @@ public:
void functionDeriv1D(API::Jacobian *out, const double *xValues,
const size_t nData);
/// Returns the number of attributes associated with the function
size_t nAttributes() const;
/// Returns a list of attribute names
std::vector<std::string> getAttributeNames() const;
/// Return a value of attribute attName
Attribute getAttribute(const std::string &attName) const;
/// Set a value to attribute attName
void setAttribute(const std::string &attName,
const IFunction::Attribute &value);
/// Check if attribute attName exists
bool hasAttribute(const std::string &attName) const;
private:
/// Call the appropriate load function
......
......@@ -74,15 +74,15 @@ void TabulatedFunction::eval(double scaling, double xshift, double xscale,
}
size_t j = 0;
for (; i < nData; i++) {
if (j >= size() - 1) {
double xi = xValues[i];
while (j < size() - 1 && xi > xData[j])
j++;
if (j > size() - 1) {
out[i] = 0;
} else {
double xi = xValues[i];
while (j < size() - 1 && xi > xData[j])
j++;
if (xi == xData[j]) {
out[i] = m_yData[j] * scaling;
} else if (j == size() - 1) {
} else if (xi > xData[j]) {
out[i] = 0;
} else if (j > 0) {
double x0 = xData[j - 1];
......@@ -181,19 +181,72 @@ void TabulatedFunction::setAttribute(const std::string &attName,
throw Kernel::Exception::FileError(error, fileName);
}
load(fileName);
m_setupFinished = false;
} else if (attName == "Workspace") {
std::string wsName = value.asString();
if (!wsName.empty()) {
storeAttributeValue(attName, value);
storeAttributeValue("FileName", Attribute("", true));
loadWorkspace(wsName);
m_setupFinished = false;
}
} else if (attName == "X") {
m_xData = value.asVector();
if (m_xData.empty()) {
return;
}
storeAttributeValue("FileName", Attribute("", true));
storeAttributeValue("Workspace", Attribute(""));
m_setupFinished = true;
} else if (attName == "Y") {
m_yData = value.asVector();
if (m_yData.empty()) {
return;
}
storeAttributeValue("FileName", Attribute("", true));
storeAttributeValue("Workspace", Attribute(""));
m_setupFinished = true;
} else {
IFunction::setAttribute(attName, value);
m_setupFinished = false;
}
}
/// Returns the number of attributes associated with the function
size_t TabulatedFunction::nAttributes() const{
// additional X and Y attributes
return IFunction::nAttributes() + 2;
}
/// Returns a list of attribute names
std::vector<std::string> TabulatedFunction::getAttributeNames() const{
std::vector<std::string> attNames = IFunction::getAttributeNames();
attNames.push_back("X");
attNames.push_back("Y");
return attNames;
}
/// Return a value of attribute attName
/// @param attName :: The attribute name
IFunction::Attribute TabulatedFunction::getAttribute(const std::string &attName) const{
if (attName == "X") {
return Attribute(m_xData);
} else if (attName == "Y") {
return Attribute(m_yData);
}
return IFunction::getAttribute(attName);
}
/// Check if attribute attName exists
/// @param attName :: The attribute name
bool TabulatedFunction::hasAttribute(const std::string &attName) const{
if (attName == "X" || attName == "Y") {
return true;
}
return IFunction::hasAttribute(attName);
}
/**
* Load input file as a Nexus file.
* @param fname :: The file name
......@@ -244,6 +297,9 @@ void TabulatedFunction::loadWorkspace(
*/
void TabulatedFunction::setupData() const {
if (m_setupFinished) {
if (m_xData.size() != m_yData.size()) {
throw std::runtime_error(this->name() + ": X and Y vectors have different sizes.");
}
g_log.debug() << "Re-setting isn't required.";
return;
}
......
......@@ -140,6 +140,16 @@ public:
TS_ASSERT_EQUALS(fun.getAttribute("Workspace").asString(),
"TABULATEDFUNCTIONTEST_WS");
TS_ASSERT_EQUALS(fun.getAttribute("FileName").asUnquotedString(), "");
auto X = fun.getAttribute("X").asVector();
TS_ASSERT_EQUALS(X.size(), ws->blocksize());
TS_ASSERT_EQUALS(X[0], ws->readX(0)[0]);
TS_ASSERT_EQUALS(X[1], ws->readX(0)[1]);
TS_ASSERT_EQUALS(X[2], ws->readX(0)[2]);
auto Y = fun.getAttribute("Y").asVector();
TS_ASSERT_EQUALS(Y.size(), ws->blocksize());
TS_ASSERT_EQUALS(Y[0], ws->readY(0)[0]);
TS_ASSERT_EQUALS(Y[1], ws->readY(0)[1]);
TS_ASSERT_EQUALS(Y[2], ws->readY(0)[2]);
AnalysisDataService::Instance().clear();
}
......@@ -219,13 +229,17 @@ public:
void test_Attributes() {
TabulatedFunction fun;
auto names = fun.getAttributeNames();
TS_ASSERT_EQUALS(names.size(), 3);
TS_ASSERT_EQUALS(names.size(), 5);
TS_ASSERT_EQUALS(names[0], "FileName");
TS_ASSERT_EQUALS(names[1], "Workspace");
TS_ASSERT_EQUALS(names[2], "WorkspaceIndex");
TS_ASSERT_EQUALS(names[3], "X");
TS_ASSERT_EQUALS(names[4], "Y");
TS_ASSERT(fun.hasAttribute("FileName"));
TS_ASSERT(fun.hasAttribute("Workspace"));
TS_ASSERT(fun.hasAttribute("WorkspaceIndex"));
TS_ASSERT(fun.hasAttribute("X"));
TS_ASSERT(fun.hasAttribute("Y"));
}
void test_factory_create_from_file() {
......@@ -263,6 +277,65 @@ public:
AnalysisDataService::Instance().clear();
}
void test_set_X_Y_attributes() {
TabulatedFunction fun;
const size_t n = 10;
std::vector<double> X(n);
std::vector<double> Y(n);
for(size_t i = 0; i < n; ++i) {
X[i] = double(i);
Y[i] = X[i] * X[i];
}
fun.setAttributeValue("X", X);
fun.setAttributeValue("Y", Y);
FunctionDomain1DVector x(0.0, 9.0, 33);
FunctionValues y(x);
fun.function(x, y);
for(size_t i = 0; i < x.size(); ++i) {
double xx = x[i];
TS_ASSERT_DELTA(y[i], xx*xx, 0.5);
}
}
void test_set_X_Y_attributes_different_sizes() {
TabulatedFunction fun;
const size_t n = 10;
std::vector<double> X(n);
std::vector<double> Y(n-1);
fun.setAttributeValue("X", X);
fun.setAttributeValue("Y", Y);
FunctionDomain1DVector x(0.0, 9.0, 33);
FunctionValues y(x);
TS_ASSERT_THROWS(fun.function(x, y), std::runtime_error);
}
void test_set_X_Y_attributes_string() {
std::string inif = "name=TabulatedFunction,X=(1,2,3),Y=(4,5,6)";
auto fun = FunctionFactory::Instance().createInitialized(inif);
TS_ASSERT(fun);
auto x = fun->getAttribute("X").asVector();
TS_ASSERT_EQUALS(x.size(), 3);
TS_ASSERT_EQUALS(x[0], 1);
TS_ASSERT_EQUALS(x[1], 2);
TS_ASSERT_EQUALS(x[2], 3);
auto y = fun->getAttribute("Y").asVector();
TS_ASSERT_EQUALS(y.size(), 3);
TS_ASSERT_EQUALS(y[0], 4);
TS_ASSERT_EQUALS(y[1], 5);
TS_ASSERT_EQUALS(y[2], 6);
}
void test_set_X_Y_attributes_string_empty() {
std::string inif = "name=TabulatedFunction,X=(),Y=()";
auto fun = FunctionFactory::Instance().createInitialized(inif);
TS_ASSERT(fun);
}
private:
const std::string m_asciiFileName;
const std::string m_nexusFileName;
......
......@@ -73,7 +73,7 @@ if platform.system() == "Windows":
# Test values of probability
prob_y = probability.dataY(0)
self.assertEquals(round(probability.dataY(0)[0], 1), -65487.5)
self.assertEquals(round(probability.dataY(1)[0], 3), -375.124)
self.assertEquals(round(probability.dataY(1)[0], 3), -375.123)
self.assertEquals(round(probability.dataY(2)[0], 6), 0)
# Test values of group
......@@ -124,16 +124,16 @@ if platform.system() == "Windows":
# Test values of result
result_y = result.dataY(0)
self.assertEquals(round(result.dataY(0)[0], 5), 8.28044)
self.assertEquals(round(result.dataY(1)[0], 7), 0.0335993)
self.assertEquals(round(result.dataY(2)[0], 5), 0.77844)
self.assertEquals(round(result.dataY(0)[0], 5), 8.2741)
self.assertEquals(round(result.dataY(1)[0], 7), 0.0335946)
self.assertEquals(round(result.dataY(2)[0], 5), 0.77801)
# Test values of group
sub_ws = group.getItem(0)
sub_y = sub_ws.dataY(0)
self.assertEquals(round(sub_ws.dataY(0)[0], 5), 0.02540)
self.assertEquals(round(sub_ws.dataY(1)[0], 5), 0.01656)
self.assertEquals(round(sub_ws.dataY(2)[0], 5), -0.00884)
self.assertEquals(round(sub_ws.dataY(1)[0], 5), 0.01648)
self.assertEquals(round(sub_ws.dataY(2)[0], 5), -0.00893)
def test_QLr_Run(self):
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment