diff --git a/Framework/Algorithms/test/ConvertTableToMatrixWorkspaceTest.h b/Framework/Algorithms/test/ConvertTableToMatrixWorkspaceTest.h index 788bf97cdf846ccfd28c3ff392a0bc2c73037aba..97371f0a2e976c9c9b44cdc57e22086b31ffe93e 100644 --- a/Framework/Algorithms/test/ConvertTableToMatrixWorkspaceTest.h +++ b/Framework/Algorithms/test/ConvertTableToMatrixWorkspaceTest.h @@ -71,7 +71,7 @@ public: int x; double y, e; row >> x >> y >> e; - TS_ASSERT_EQUALS(double(x), X[i]); + TS_ASSERT_EQUALS(static_cast<double>(x), X[i]); TS_ASSERT_EQUALS(y, Y[i]); TS_ASSERT_EQUALS(e, E[i]); } @@ -89,7 +89,7 @@ public: size_t n = 10; for (size_t i = 0; i < n; ++i) { TableRow row = tws->appendRow(); - double x = double(i); + double x = static_cast<double>(i); double y = x * 1.1; row << x << y; } @@ -139,6 +139,88 @@ public: TS_ASSERT_THROWS_NOTHING(m_converter->setPropertyValue("ColumnX", "A")); TS_ASSERT_THROWS_NOTHING(m_converter->setPropertyValue("ColumnY", "B")); } + // test if it can convert a string to a double, if the string is numeric + void testStringToDouble() { + + auto tws = WorkspaceFactory::Instance().createTable(); + tws->addColumn("str", "A"); + tws->addColumn("double", "B"); + tws->addColumn("double", "C"); + + size_t n = 10; + for (size_t i = 0; i < n; ++i) { + TableRow row = tws->appendRow(); + std::string x = "1"; + double y = static_cast<double>(i) * 1.1; + double e = sqrt(y); + row << x << y << e; + } + + TS_ASSERT_THROWS_NOTHING(m_converter->setProperty("InputWorkspace", tws)); + TS_ASSERT_THROWS_NOTHING( + m_converter->setPropertyValue("OutputWorkspace", "out")); + TS_ASSERT_THROWS_NOTHING(m_converter->setPropertyValue("ColumnX", "A")); + TS_ASSERT_THROWS_NOTHING(m_converter->setPropertyValue("ColumnY", "B")); + TS_ASSERT_THROWS_NOTHING(m_converter->setPropertyValue("ColumnE", "C")); + + TS_ASSERT(m_converter->execute()); + + MatrixWorkspace_sptr mws = boost::dynamic_pointer_cast<MatrixWorkspace>( + API::AnalysisDataService::Instance().retrieve("out")); + + TS_ASSERT(mws); + TS_ASSERT_EQUALS(mws->getNumberHistograms(), 1); + TS_ASSERT(!mws->isHistogramData()); + TS_ASSERT_EQUALS(mws->blocksize(), tws->rowCount()); + + auto &X = mws->x(0); + auto &Y = mws->y(0); + auto &E = mws->e(0); + + for (size_t i = 0; i < tws->rowCount(); ++i) { + TableRow row = tws->getRow(i); + std::string x; + double y, e; + row >> x >> y >> e; + TS_ASSERT_EQUALS(std::stod(x), X[i]); + TS_ASSERT_EQUALS(y, Y[i]); + TS_ASSERT_EQUALS(e, E[i]); + } + + auto label = + boost::dynamic_pointer_cast<Units::Label>(mws->getAxis(0)->unit()); + TS_ASSERT(label); + TS_ASSERT_EQUALS(label->caption(), "A"); + TS_ASSERT_EQUALS(mws->YUnitLabel(), "B"); + API::AnalysisDataService::Instance().remove("out"); + } + // test that an error is thrown when a non-numeric string is used + void testNotANumber() { + + ITableWorkspace_sptr tws = WorkspaceFactory::Instance().createTable(); + tws->addColumn("str", "A"); + tws->addColumn("double", "B"); + tws->addColumn("double", "C"); + + size_t n = 10; + for (size_t i = 0; i < n; ++i) { + TableRow row = tws->appendRow(); + std::string x = "not a number"; + double y = static_cast<double>(i) * 1.1; + double e = sqrt(y); + row << x << y << e; + } + + TS_ASSERT_THROWS_NOTHING(m_converter->setProperty("InputWorkspace", tws)); + TS_ASSERT_THROWS_NOTHING( + m_converter->setPropertyValue("OutputWorkspace", "out")); + TS_ASSERT_THROWS_NOTHING(m_converter->setPropertyValue("ColumnX", "A")); + TS_ASSERT_THROWS_NOTHING(m_converter->setPropertyValue("ColumnY", "B")); + TS_ASSERT_THROWS_NOTHING(m_converter->setPropertyValue("ColumnE", "C")); + + TS_ASSERT_THROWS(m_converter->execute(), std::invalid_argument); + API::AnalysisDataService::Instance().remove("out"); + } private: IAlgorithm_sptr m_converter; diff --git a/Framework/DataObjects/inc/MantidDataObjects/TableColumn.h b/Framework/DataObjects/inc/MantidDataObjects/TableColumn.h index 6213255557bc595e9c0248e44c6cd58386bd3e83..4f4d4fbdc826cb4482ec5b3d746f409d14aa8be7 100644 --- a/Framework/DataObjects/inc/MantidDataObjects/TableColumn.h +++ b/Framework/DataObjects/inc/MantidDataObjects/TableColumn.h @@ -13,8 +13,6 @@ #include <stdexcept> #include <boost/shared_ptr.hpp> #include <limits> -#include <boost/lexical_cast.hpp> -#include <boost/mpl/if.hpp> #include <boost/type_traits.hpp> #include <boost/numeric/conversion/cast.hpp> @@ -155,14 +153,30 @@ public: * is throw. In case of an overflow boost::numeric::positive_overflow or * boost::numeric::negative_overflow * is throw. - * @param i :: The index to an element. + * @param value :: The value of the element. */ - double toDouble(size_t i) const override { + template <typename T> double convertToDouble(const T &value) const { typedef - typename boost::mpl::if_c<boost::is_convertible<double, Type>::value, - Type, InconvertibleToDoubleType>::type - DoubleType; - return boost::numeric_cast<double, DoubleType>(m_data[i]); + typename std::conditional<std::is_convertible<double, T>::value, T, + InconvertibleToDoubleType>::type DoubleType; + return boost::numeric_cast<double, DoubleType>(value); + } + + /** + * Cast an string to double if possible. If it's impossible + * std::invalid_argument + * is throw. In case of an overflow boost::numeric::positive_overflow or + * boost::numeric::negative_overflow + * is throw. + * @param value :: The value of the element. + */ + + double convertToDouble(const std::string &value) const { + return std::stod(value); + } + + double toDouble(size_t i) const override { + return convertToDouble(m_data[i]); } /** @@ -175,10 +189,9 @@ public: * @param value: cast this value */ void fromDouble(size_t i, double value) override { - typedef - typename boost::mpl::if_c<boost::is_convertible<double, Type>::value, - Type, InconvertibleToDoubleType>::type - DoubleType; + typedef typename std::conditional<std::is_convertible<double, Type>::value, + Type, InconvertibleToDoubleType>::type + DoubleType; m_data[i] = static_cast<Type>(boost::numeric_cast<DoubleType, double>(value)); } @@ -194,7 +207,7 @@ public: /// that the casting is possible double operator[](size_t i) const override { try { - return boost::lexical_cast<double>(m_data[i]); + return convertToDouble(m_data[i]); } catch (...) { return std::numeric_limits<double>::quiet_NaN(); } diff --git a/Framework/DataObjects/test/TableWorkspaceTest.h b/Framework/DataObjects/test/TableWorkspaceTest.h index 4975ed28dd971914198d01b47010e0372729053f..7e50d4b2ffe639a06dd0490d3edd5ff1a6e544b8 100644 --- a/Framework/DataObjects/test/TableWorkspaceTest.h +++ b/Framework/DataObjects/test/TableWorkspaceTest.h @@ -360,7 +360,7 @@ public: TS_ASSERT_EQUALS(d, 0.0); TS_ASSERT_THROWS_NOTHING(d = tw.getColumn("T")->toDouble(0)); TS_ASSERT_EQUALS(d, 1.0); - TS_ASSERT_THROWS(d = tw.getColumn("S")->toDouble(0), std::runtime_error); + TS_ASSERT_THROWS(d = tw.getColumn("S")->toDouble(0), std::invalid_argument); } void testGetVectorSetVectorValues() {