Commit 2fae76f2 authored by Roman Tolchenov's avatar Roman Tolchenov
Browse files

Re #15699. TableWorkspace clones selected columns.

parent 041fa9f8
......@@ -3,8 +3,8 @@
#include "MantidAPI/DllConfig.h"
#include "MantidAPI/IFunction.h"
#include "MantidAPI/FunctionDomainGeneral.h"
#include "MantidAPI/IFunction.h"
#include "MantidKernel/Logger.h"
namespace Mantid {
......@@ -17,7 +17,7 @@ namespace API {
The domain and the values object can have different sizes.
In particular the domain can be empty.
Copyright © 2016 ISIS Rutherford Appleton Laboratory, NScD Oak Ridge
National Laboratory & European Spallation Source
......@@ -51,7 +51,7 @@ public:
/// Provide a concrete function in an implementation that operates on a
/// FunctionDomainGeneral.
virtual void functionGeneral(const FunctionDomainGeneral &domain,
FunctionValues &values) const = 0;
FunctionValues &values) const = 0;
/// Get number of columns that the domain must have.
/// If consider the collection of these columns as a table
......@@ -61,11 +61,12 @@ public:
/// Get number of values per argument in the domain.
virtual size_t getNumberValuesPerArgument() const = 0;
/// Get the default size of an output FunctionValues object.
/// It is a number of values the function will produce if it is
/// given an empty domain.
/// Get the default size of a domain.
/// If a function is given an empty domain then it must output
/// a values object of the size:
/// getDefaultDomainSize() * getNumberValuesPerArgument()
/// The default size must not be infinite (max of size_t).
virtual size_t getDefaultValuesSize() const;
virtual size_t getDefaultDomainSize() const;
protected:
static Kernel::Logger g_log;
......
......@@ -122,7 +122,8 @@ public:
ITableWorkspace() {}
/// Returns a clone of the workspace
ITableWorkspace_uptr clone() const { return ITableWorkspace_uptr(doClone()); }
ITableWorkspace_uptr clone(const std::vector<std::string> &colNames =
std::vector<std::string>()) const;
ITableWorkspace &operator=(const ITableWorkspace &) = delete;
/// Return the workspace typeID
......@@ -328,7 +329,8 @@ protected:
void removeFromColumn(Column *c, size_t index) { c->remove(index); }
private:
ITableWorkspace *doClone() const override = 0;
ITableWorkspace *doClone() const override {return doCloneColumns(std::vector<std::string>());}
virtual ITableWorkspace *doCloneColumns(const std::vector<std::string> &colNames) const = 0;
};
// =====================================================================================
......
......@@ -26,12 +26,12 @@ void IFunctionGeneral::functionDeriv(const FunctionDomain &domain,
size_t IFunctionGeneral::getValuesSize(const FunctionDomain &domain) const {
if (domain.size() == 0 || getNumberDomainColumns() == 0) {
return getDefaultValuesSize() * getNumberValuesPerArgument();
return getDefaultDomainSize() * getNumberValuesPerArgument();
}
return domain.size() * getNumberValuesPerArgument();
}
size_t IFunctionGeneral::getDefaultValuesSize() const { return 0; }
size_t IFunctionGeneral::getDefaultDomainSize() const { return 0; }
} // namespace API
} // namespace Mantid
......@@ -5,8 +5,14 @@
namespace Mantid {
namespace API {
/**
*/
/// Returns a clone of the workspace
/// @param colNames :: Names of the column to clone. If empty clone
/// all columns.
ITableWorkspace_uptr
ITableWorkspace::clone(const std::vector<std::string> &colNames) const {
return ITableWorkspace_uptr(doCloneColumns(colNames));
}
const std::string ITableWorkspace::toString() const {
std::ostringstream os;
os << id() << "\n";
......
......@@ -10,6 +10,7 @@ namespace Mantid {
namespace API {
class IFunctionGeneral;
class Column;
class ITableWorkspace;
}
namespace CurveFitting {
......@@ -61,6 +62,8 @@ public:
void declareDatasetProperties(const std::string &suffix = "",
bool addProp = true) override;
private:
/// Retrive the input workspace from the property manager.
boost::shared_ptr<API::ITableWorkspace> getInputWorkspace();
// Names of additional properties
/// Property names for columns in a TableWorkspace to be passed to
/// the domain.
......
#include "MantidCurveFitting/GeneralDomainCreator.h"
#include "MantidAPI/FunctionDomainGeneral.h"
#include "MantidAPI/IFunctionGeneral.h"
#include "MantidAPI/ITableWorkspace.h"
#include "MantidAPI/Workspace.h"
#include "MantidAPI/ITableWorkspace.h"
#include "MantidAPI/WorkspaceProperty.h"
#include "MantidAPI/WorkspaceFactory.h"
#include "MantidAPI/WorkspaceProperty.h"
#include "MantidCurveFitting/GeneralDomainCreator.h"
#include "MantidKernel/PropertyWithValue.h"
#include <boost/lexical_cast.hpp>
......@@ -27,12 +28,12 @@ GeneralDomainCreator::GeneralDomainCreator(
: IDomainCreator(&manager,
std::vector<std::string>(1, workspacePropertyName)) {
m_defaultValuesSize = fun.getDefaultValuesSize();
m_defaultValuesSize = fun.getDefaultDomainSize();
auto nDomainColumns = fun.getNumberDomainColumns();
if (nDomainColumns > 0) {
m_domainColumnNames.push_back("ArgumentColumn");
for(size_t i = 1; i < nDomainColumns; ++i) {
for (size_t i = 1; i < nDomainColumns; ++i) {
m_domainColumnNames.push_back(m_domainColumnNames.front() + "_" +
boost::lexical_cast<std::string>(i));
}
......@@ -42,7 +43,7 @@ GeneralDomainCreator::GeneralDomainCreator(
if (nDataColumns > 0) {
m_dataColumnNames.push_back("DataColumn");
m_weightsColumnNames.push_back("WeightsColumn");
for(size_t i = 1; i < nDataColumns; ++i) {
for (size_t i = 1; i < nDataColumns; ++i) {
auto si = "_" + boost::lexical_cast<std::string>(i);
m_dataColumnNames.push_back(m_dataColumnNames.front() + si);
m_weightsColumnNames.push_back(m_weightsColumnNames.front() + si);
......@@ -57,20 +58,32 @@ GeneralDomainCreator::GeneralDomainCreator(
/// other stuff if needed
void GeneralDomainCreator::declareDatasetProperties(const std::string &suffix,
bool addProp) {
for(auto &propName : m_domainColumnNames) {
for (auto &propName : m_domainColumnNames) {
declareProperty(new Kernel::PropertyWithValue<std::string>(propName, ""),
"A name of a domain column.");
}
for(auto &propName : m_dataColumnNames) {
for (auto &propName : m_dataColumnNames) {
declareProperty(new Kernel::PropertyWithValue<std::string>(propName, ""),
"A name of a fitting data column.");
}
for(auto &propName : m_weightsColumnNames) {
for (auto &propName : m_weightsColumnNames) {
declareProperty(new Kernel::PropertyWithValue<std::string>(propName, ""),
"A name of a fitting weights column.");
}
}
/// Retrive the input workspace from the property manager.
boost::shared_ptr<API::ITableWorkspace> GeneralDomainCreator::getInputWorkspace() {
auto workspacePropertyName = m_workspacePropertyNames.front();
API::Workspace_sptr ws = m_manager->getProperty(workspacePropertyName);
auto tableWorkspace = boost::dynamic_pointer_cast<API::ITableWorkspace>(ws);
if (!tableWorkspace) {
throw std::invalid_argument("InputWorkspace must be a TableWorkspace.");
}
return tableWorkspace;
}
/**
* Creates a domain corresponding to the assigned MatrixWorkspace
*
......@@ -83,19 +96,14 @@ void GeneralDomainCreator::createDomain(
boost::shared_ptr<FunctionValues> &values, size_t i0) {
// get the workspace
auto workspacePropertyName = m_workspacePropertyNames.front();
API::Workspace_sptr ws = m_manager->getProperty(workspacePropertyName);
auto tableWorkspace = boost::dynamic_pointer_cast<API::ITableWorkspace>(ws);
if (!tableWorkspace) {
throw std::invalid_argument("InputWorkspace must be a TableWorkspace.");
}
auto tableWorkspace = getInputWorkspace();
size_t domainSize = 0;
domain.reset(new FunctionDomainGeneral);
// Create the domain
if (!m_domainColumnNames.empty()) {
auto &generalDomain = *static_cast<FunctionDomainGeneral*>(domain.get());
for(auto &propName : m_domainColumnNames) {
auto &generalDomain = *static_cast<FunctionDomainGeneral *>(domain.get());
for (auto &propName : m_domainColumnNames) {
std::string columnName = m_manager->getPropertyValue(propName);
auto column = tableWorkspace->getColumn(columnName);
generalDomain.addColumn(column);
......@@ -110,13 +118,14 @@ void GeneralDomainCreator::createDomain(
values.reset(new FunctionValues);
}
auto nDataColumns = m_dataColumnNames.size();
for(size_t i = 0; i < nDataColumns; ++i) {
// Append each column to values' fitting data
for (size_t i = 0; i < nDataColumns; ++i) {
std::string columnName = m_manager->getPropertyValue(m_dataColumnNames[i]);
auto dataColumn = tableWorkspace->getColumn(columnName);
columnName = m_manager->getPropertyValue(m_weightsColumnNames[i]);
auto weightsColumn = tableWorkspace->getColumn(columnName);
values->expand(i0 + domainSize);
for(size_t j = 0; j < domainSize; ++j) {
for (size_t j = 0; j < domainSize; ++j) {
values->setFitData(i0 + j, dataColumn->toDouble(j));
values->setFitWeight(i0 + j, weightsColumn->toDouble(j));
}
......@@ -141,10 +150,26 @@ Workspace_sptr GeneralDomainCreator::createOutputWorkspace(
boost::shared_ptr<FunctionDomain> domain,
boost::shared_ptr<FunctionValues> values,
const std::string &outputWorkspacePropertyName) {
// don't need values, since the values need to be calculated spectrum by
// spectrum (see loop below).
UNUSED_ARG(values);
return Workspace_sptr();
if (function->getValuesSize(*domain) != values->size()) {
throw std::runtime_error("Failed to create output workspace: domain and "
"values object don't match.");
}
auto inputWorkspace = getInputWorkspace();
ITableWorkspace_sptr outputWorkspace = WorkspaceFactory::Instance().createTable();
size_t rowCount = domain->size();
if (rowCount == 0) {
auto &generalFunction = dynamic_cast<IFunctionGeneral&>(*function);
rowCount = generalFunction.getDefaultDomainSize();
}
outputWorkspace->setRowCount(rowCount);
auto &generalDomain = *static_cast<FunctionDomainGeneral *>(domain.get());
for(size_t col = 0; col < generalDomain.columnCount(); ++col) {
auto column = generalDomain.getColumn(col);
auto outColumn = outputWorkspace->addColumn(column->type(), column->name());
for(size_t row = 0; row < rowCount; ++row) {
}
}
return outputWorkspace;
}
/**
......@@ -152,9 +177,7 @@ Workspace_sptr GeneralDomainCreator::createOutputWorkspace(
*
* @return Total domain size.
*/
size_t GeneralDomainCreator::getDomainSize() const {
return 0;
}
size_t GeneralDomainCreator::getDomainSize() const { return 0; }
} // namespace CurveFitting
} // namespace Mantid
......@@ -55,10 +55,10 @@ public:
std::string name() const override {return "TestFunction2";}
size_t getNumberDomainColumns() const override {return 0;}
size_t getNumberValuesPerArgument() const override {return 2;}
size_t getDefaultValuesSize() const override {return 5;}
size_t getDefaultDomainSize() const override {return 5;}
void functionGeneral(const FunctionDomainGeneral &generalDomain, FunctionValues &values) const override {
double a = getParameter(0);
auto n = getDefaultValuesSize();
auto n = getDefaultDomainSize();
for(size_t i = 0; i < n; ++i) {
values.setCalculated(i, a * double(i));
values.setCalculated(i + n, a * (10.0 - double(i)));
......@@ -290,6 +290,11 @@ public:
TS_ASSERT_DELTA(fun->getParameter(0), 1.0, 1e-9);
}
void test_create_output() {
TableWorkspace_sptr ws = makeData2();
auto copy = ws->clone();
}
private:
TableWorkspace_sptr makeData1(double wgt3col = 0.0) {
......
......@@ -185,6 +185,7 @@ protected:
private:
PeaksWorkspace *doClone() const override { return new PeaksWorkspace(*this); }
ITableWorkspace *doCloneColumns(const std::vector<std::string> &colNames) const override;
/// Initialize the table structure
void initColumns();
......
......@@ -80,10 +80,7 @@ class MANTID_DATAOBJECTS_DLL TableWorkspace : public API::ITableWorkspace {
public:
/// Constructor.
TableWorkspace(size_t nrows = 0);
/// Returns a clone of the workspace
std::unique_ptr<TableWorkspace> clone() const {
return std::unique_ptr<TableWorkspace>(doClone());
}
TableWorkspace &operator=(const TableWorkspace &other) = delete;
/// Return the workspace typeID
const std::string id() const override { return "TableWorkspace"; }
......@@ -296,7 +293,8 @@ protected:
TableWorkspace(const TableWorkspace &other);
private:
TableWorkspace *doClone() const override { return new TableWorkspace(*this); }
//TableWorkspace *doClone() const override { return new TableWorkspace(*this); }
ITableWorkspace *doCloneColumns(const std::vector<std::string> &colNames) const override;
/// template method to find a given value in a table.
template <typename Type>
......
......@@ -842,6 +842,11 @@ API::LogManager_sptr PeaksWorkspace::logs() {
m_logCash = API::LogManager_sptr(&(this->mutableRun()), NullDeleter());
return m_logCash;
}
ITableWorkspace *PeaksWorkspace::doCloneColumns(const std::vector<std::string> &colNames) const {
throw Kernel::Exception::NotImplementedError("PeaksWorkspace cannot clone columns.");
}
}
}
......
......@@ -272,6 +272,26 @@ void TableWorkspace::sort(std::vector<std::pair<std::string, bool>> &criteria) {
}
}
/// Clone the workspace keeping only selected columns.
/// @param colNames :: Names of columns to clone.
API::ITableWorkspace *TableWorkspace::doCloneColumns(const std::vector<std::string> &colNames) const {
if (colNames.empty()) {
return new TableWorkspace(*this);
}
auto ws = new TableWorkspace();
ws->setRowCount(rowCount());
auto it = m_columns.cbegin();
while (it != m_columns.cend()) {
if (colNames.end() != std::find(colNames.begin(), colNames.end(), (**it).name())) {
ws->addColumn(boost::shared_ptr<API::Column>((*it)->clone()));
}
++it;
}
// copy logs/properties.
ws->m_LogManager = boost::make_shared<API::LogManager>(*(m_LogManager));
return ws;
}
// template<>
// boost::tuples::null_type TableWorkspace::make_TupleRef<
// boost::tuples::null_type >(size_t j,const std::vector<std::string>&
......
......@@ -305,7 +305,7 @@ public:
tw.getColumn(1)->cell<std::string>(0) = "b";
tw.getColumn(2)->cell<std::string>(0) = "c";
boost::scoped_ptr<TableWorkspace> cloned(tw.clone().release());
boost::scoped_ptr<ITableWorkspace> cloned(tw.clone().release());
// Check clone is same as original.
TS_ASSERT_EQUALS(tw.columnCount(), cloned->columnCount());
......@@ -315,6 +315,27 @@ public:
TS_ASSERT_EQUALS("c", cloned->getColumn(2)->cell<std::string>(0));
}
void testCloneColumns() {
TableWorkspace tw(1);
tw.addColumn("str", "X");
tw.addColumn("str", "Y");
tw.addColumn("str", "Z");
tw.getColumn(0)->cell<std::string>(0) = "a";
tw.getColumn(1)->cell<std::string>(0) = "b";
tw.getColumn(2)->cell<std::string>(0) = "c";
std::vector<std::string> colNames{"X", "Z"};
boost::scoped_ptr<ITableWorkspace> cloned(tw.clone(colNames).release());
// Check clone is same as original.
TS_ASSERT_EQUALS(colNames.size(), cloned->columnCount());
TS_ASSERT_EQUALS(tw.rowCount(), cloned->rowCount());
TS_ASSERT_EQUALS("a", cloned->getColumn(0)->cell<std::string>(0));
TS_ASSERT_EQUALS("c", cloned->getColumn(1)->cell<std::string>(0));
}
void test_toDouble() {
TableWorkspace tw(1);
tw.addColumn("int", "X");
......
......@@ -242,6 +242,10 @@ private:
throw std::runtime_error(
"Cloning of TableWorkspaceTester is not implemented.");
}
ITableWorkspace *doCloneColumns(const std::vector<std::string> &colNames) const override {
throw std::runtime_error(
"Cloning of TableWorkspaceTester is not implemented.");
}
};
//===================================================================================================================
......
Markdown is supported
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