Mantid
Loading...
Searching...
No Matches
TableWorkspace.cpp
Go to the documentation of this file.
1// Mantid Repository : https://github.com/mantidproject/mantid
2//
3// Copyright © 2018 ISIS Rutherford Appleton Laboratory UKRI,
4// NScD Oak Ridge National Laboratory, European Spallation Source,
5// Institut Laue - Langevin & CSNS, Institute of High Energy Physics, CAS
6// SPDX - License - Identifier: GPL - 3.0 +
10#include "MantidKernel/Logger.h"
11
12#include <queue>
13
14namespace Mantid::DataObjects {
15namespace {
17Kernel::Logger g_log("TableWorkspace");
18
19// struct to keep record on what rows to sort and according to which criteria
20struct SortIterationRecord {
21 SortIterationRecord(size_t ki, size_t is, size_t ie) : keyIndex(ki), iStart(is), iEnd(ie) {}
22 size_t keyIndex; // index in criteria vector
23 size_t iStart; // start row to sort
24 size_t iEnd; // end row to sort (one past last)
25};
26} // namespace
27
28DECLARE_WORKSPACE(TableWorkspace)
29
30
31TableWorkspace::TableWorkspace(size_t nrows) : ITableWorkspace(), m_rowCount(0), m_LogManager(new API::LogManager) {
32 setRowCount(nrows);
33}
34
36 : ITableWorkspace(other), m_rowCount(0), m_LogManager(new API::LogManager) {
37 setRowCount(other.m_rowCount);
38
39 auto it = other.m_columns.cbegin();
40 while (it != other.m_columns.cend()) {
41 addColumn(std::shared_ptr<API::Column>((*it)->clone()));
42 ++it;
43 }
44 // copy logs/properties.
45 m_LogManager = std::make_shared<API::LogManager>(*(other.m_LogManager));
46}
47
49 size_t data_size = std::accumulate(m_columns.cbegin(), m_columns.cend(), static_cast<size_t>(0),
50 [](size_t sum, const auto &column) { return sum = column->sizeOfData(); });
51 data_size += m_LogManager->getMemorySize();
52 return data_size;
53}
54
59API::Column_sptr TableWorkspace::addColumn(const std::string &type, const std::string &name) {
61 if (type.empty()) {
62 throw std::invalid_argument("Empty string passed as type argument of addColumn.");
63 }
64 if (name.empty()) {
65 throw std::invalid_argument("Empty string passed as name argument of addColumn.");
66 }
67 // Check that there is no column with the same name.
68 auto ci = std::find_if(m_columns.begin(), m_columns.end(), FindName(name));
69 if (ci != m_columns.end()) {
70 std::stringstream ss;
71 ss << "Column with name " << name << " already exists.\n";
72 throw std::invalid_argument(ss.str());
73 }
74 try {
75 c = API::ColumnFactory::Instance().create(type);
76 m_columns.emplace_back(c);
77 c->setName(name);
78 resizeColumn(c.get(), rowCount());
80 std::stringstream ss;
81 ss << "Column of type " << type << " and name " << name << " has not been added.\n";
82 ss << e.what() << '\n';
83 throw std::invalid_argument(ss.str());
84 }
85 modified();
86 return c;
87}
88
95 if (count == rowCount())
96 return;
97 for (auto &column : m_columns)
98 resizeColumn(column.get(), count);
100}
101
104 auto ci = std::find_if(m_columns.begin(), m_columns.end(), FindName(name));
105 if (ci == m_columns.end()) {
106 std::string str = "Column " + name + " does not exist.\n";
107 throw std::runtime_error(str);
108 }
109 return *ci;
110}
112API::Column_const_sptr TableWorkspace::getColumn(const std::string &name) const {
113 const auto found = std::find_if(m_columns.cbegin(), m_columns.cend(),
114 [&name](const auto &column) { return column->name() == name; });
115 if (found == m_columns.cend()) {
116 throw std::runtime_error("Column " + name + " does not exist.");
117 }
118 return *found;
119}
120
123 if (index >= columnCount()) {
124 std::stringstream ss;
125 ss << "Column index is out of range: " << index << "(" << columnCount() << ")\n";
126 throw std::range_error(ss.str());
127 }
128 return m_columns[index];
129}
130
133 if (index >= columnCount()) {
134 std::stringstream ss;
135 ss << "Column index is out of range: " << index << "(" << columnCount() << ")\n";
136 throw std::range_error(ss.str());
137 }
138 return m_columns[index];
139}
140
141void TableWorkspace::removeColumn(const std::string &name) {
142 auto ci = std::find_if(m_columns.begin(), m_columns.end(), FindName(name));
143 if (ci != m_columns.end()) {
144 if (!ci->unique()) {
145 g_log.error() << "Deleting column in use (" << name << ").\n";
146 }
147 m_columns.erase(ci);
148 }
149 modified();
150}
151
156 if (index >= rowCount())
157 index = rowCount();
158 for (auto &column : m_columns)
159 insertInColumn(column.get(), index);
160 ++m_rowCount;
161 modified();
162 return index;
163}
164
168 if (index >= rowCount()) {
169 std::stringstream ss;
170 ss << "Attempt to delete a non-existing row (" << index << ")\n";
171 throw std::range_error(ss.str());
172 }
173 for (auto &column : m_columns)
174 removeFromColumn(column.get(), index);
175 --m_rowCount;
176 modified();
177}
178
179std::vector<std::string> TableWorkspace::getColumnNames() const {
180 std::vector<std::string> nameList;
181 nameList.reserve(m_columns.size());
182 std::transform(m_columns.cbegin(), m_columns.cend(), std::back_inserter(nameList),
183 [](const auto &column) { return column->name(); });
184 return nameList;
185}
186
187void TableWorkspace::addColumn(const std::shared_ptr<API::Column> &column) {
188 auto ci = std::find_if(m_columns.begin(), m_columns.end(), FindName(column->name()));
189 if (ci != m_columns.end()) {
190 std::stringstream ss;
191 ss << "Column with name " << column->name() << " already exists.\n";
192 throw std::invalid_argument(ss.str());
193 } else {
194 modified();
195 m_columns.emplace_back(column);
196 }
197}
198
204void TableWorkspace::sort(std::vector<std::pair<std::string, bool>> &criteria) {
205 if (criteria.empty())
206 return;
207
208 if (criteria.size() > columnCount()) {
209 throw std::runtime_error("Too many column names given.");
210 }
211
212 const size_t nRows = rowCount();
213 if (nRows == 0)
214 return;
215
216 // first sort an array of indices according to criteria then put the rows
217 // in order of the sorted indices
218
219 std::vector<size_t> indexVec(nRows);
220 // initialize the index vector with consecutive numbers
221 for (auto i = indexVec.begin() + 1; i != indexVec.end(); ++i) {
222 *i = *(i - 1) + 1;
223 }
224
225 // dynamically populate and use a queue of records for iteratively sort all
226 // rows
227 std::queue<SortIterationRecord> sortRecords;
228 // start with first pair in criteria and sort all rows
229 sortRecords.push(SortIterationRecord(0, 0, nRows));
230
231 // maximum possible number of calls to Column::sortIndex (I think)
232 const size_t maxNLoops = criteria.size() * nRows / 2;
233 // loop over sortRecords and sort indexVec
234 for (size_t counter = 0; counter < maxNLoops; ++counter) {
235 // get the record from the front of the queue
236 SortIterationRecord record = sortRecords.front();
237 sortRecords.pop();
238 // define the arguments for Column::sortIndex
239 auto &crt = criteria[record.keyIndex];
240 const std::string columnName = crt.first;
241 const bool ascending = crt.second;
242 auto &column = *getColumn(columnName);
243 std::vector<std::pair<size_t, size_t>> equalRanges;
244
245 // sort indexVec
246 column.sortIndex(ascending, record.iStart, record.iEnd, indexVec, equalRanges);
247
248 // if column had 1 or more ranges of equal values and there is next item in
249 // criteria
250 // add more records to the back of the queue
251 if (record.keyIndex < criteria.size() - 1) {
252 size_t keyIndex = record.keyIndex + 1;
253 for (auto &equalRange : equalRanges) {
254 sortRecords.push(SortIterationRecord(keyIndex, equalRange.first, equalRange.second));
255 }
256 }
257
258 if (sortRecords.empty()) {
259 // there is nothing to do
260 break;
261 }
262 }
263
264 // finally sort the rows
265 const size_t nCols = columnCount();
266 for (size_t i = 0; i < nCols; ++i) {
267 getColumn(i)->sortValues(indexVec);
268 }
269 modified();
270}
271
274TableWorkspace *TableWorkspace::doCloneColumns(const std::vector<std::string> &colNames) const {
275 if (colNames.empty()) {
276 return new TableWorkspace(*this);
277 }
278 auto ws = new TableWorkspace();
279 ws->setRowCount(rowCount());
280 auto it = m_columns.cbegin();
281 while (it != m_columns.cend()) {
282 if (colNames.end() != std::find(colNames.begin(), colNames.end(), (**it).name())) {
283 ws->addColumn(std::shared_ptr<API::Column>((*it)->clone()));
284 }
285 ++it;
286 }
287 // copy logs/properties.
288 ws->m_LogManager = std::make_shared<API::LogManager>(*(m_LogManager));
289 return ws;
290}
291
292// template<>
293// boost::tuples::null_type TableWorkspace::make_TupleRef<
294// boost::tuples::null_type >(size_t j,const std::vector<std::string>&
295// names,size_t i)
296// {return boost::tuples::null_type();}
297
298} // namespace Mantid::DataObjects
299
301namespace Mantid::Kernel {
302template <>
304IPropertyManager::getValue<DataObjects::TableWorkspace_sptr>(const std::string &name) const {
305 auto *prop = dynamic_cast<PropertyWithValue<DataObjects::TableWorkspace_sptr> *>(getPointerToProperty(name));
306 if (prop) {
307 return *prop;
308 } else {
309 std::string message =
310 "Attempt to assign property " + name + " to incorrect type. Expected shared_ptr<TableWorkspace>.";
311 throw std::runtime_error(message);
312 }
313}
314
315template <>
317IPropertyManager::getValue<DataObjects::TableWorkspace_const_sptr>(const std::string &name) const {
318 auto *prop = dynamic_cast<PropertyWithValue<DataObjects::TableWorkspace_sptr> *>(getPointerToProperty(name));
319 if (prop) {
320 return prop->operator()();
321 } else {
322 std::string message =
323 "Attempt to assign property " + name + " to incorrect type. Expected const shared_ptr<TableWorkspace>.";
324 throw std::runtime_error(message);
325 }
326}
327
328} // namespace Mantid::Kernel
329
std::map< DeltaEMode::Type, std::string > index
Definition: DeltaEMode.cpp:19
int count
counter
Definition: Matrix.cpp:37
#define DLLExport
Definitions of the DLLImport compiler directives for MSVC.
Definition: System.h:53
size_t iEnd
size_t keyIndex
size_t iStart
#define DECLARE_WORKSPACE(classname)
ITableWorkspace is an implementation of Workspace in which the data are organised in columns of same ...
void removeFromColumn(Column *c, size_t index)
Remove an element from a column.
void modified()
If the workspace is the AnalysisDataService sends AfterReplaceNotification.
void insertInColumn(Column *c, size_t index)
Insert a new element into a column.
void resizeColumn(Column *c, size_t size)
Resize a column.
This class contains the information about the log entries.
Definition: LogManager.h:44
Used in std::find_if algorithm to find a Column with name name.
TableWorkspace is an implementation of Workspace in which the data are organised in columns of same s...
size_t columnCount() const override
Number of columns in the workspace.
std::vector< std::string > getColumnNames() const override
Returns a vector of all column names.
API::LogManager_sptr m_LogManager
shared pointer to the logManager, responsible for the workspace properties.
size_t insertRow(size_t index) override
Inserts a row before row pointed to by index and fills it with default vales.
size_t rowCount() const override
Number of rows in the workspace.
void setRowCount(size_t count) override
Resizes the workspace.
API::Column_sptr addColumn(const std::string &type, const std::string &name) override
Creates a new column.
TableWorkspace * doCloneColumns(const std::vector< std::string > &colNames) const override
Clone the workspace keeping only selected columns.
size_t getMemorySize() const override
Get the footprint in memory in KB.
void removeColumn(const std::string &name) override
Removes a column.
void removeRow(size_t index) override
Delets a row if it exists.
TableWorkspace(size_t nrows=0)
Constructor.
API::Column_sptr getColumn(const std::string &name) override
Gets the shared pointer to a column.
std::vector< std::shared_ptr< API::Column > > m_columns
Shared pointers to the columns.
void sort(std::vector< std::pair< std::string, bool > > &criteria) override
Sort this table.
Exception for when an item is not found in a collection.
Definition: Exception.h:145
const char * what() const noexcept override
Writes out the range and limits.
Definition: Exception.cpp:105
void error(const std::string &msg)
Logs at error level.
Definition: Logger.cpp:77
The concrete, templated class for properties.
static T & Instance()
Return a reference to the Singleton instance, creating it if it does not already exist Creation is do...
std::shared_ptr< Column > Column_sptr
Definition: Column.h:228
Kernel::Logger g_log("ExperimentInfo")
static logger object
std::shared_ptr< const Column > Column_const_sptr
Definition: Column.h:229
std::shared_ptr< TableWorkspace > TableWorkspace_sptr
shared pointer to Mantid::DataObjects::TableWorkspace
std::shared_ptr< const TableWorkspace > TableWorkspace_const_sptr
shared pointer to Mantid::DataObjects::TableWorkspace (const version)