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 "MantidDataObjects/DllConfig.h"
11#include "MantidKernel/Logger.h"
12
13#include <queue>
14
15namespace Mantid::DataObjects {
16namespace {
18Kernel::Logger g_log("TableWorkspace");
19
20// struct to keep record on what rows to sort and according to which criteria
21struct SortIterationRecord {
22 SortIterationRecord(size_t ki, size_t is, size_t ie) : keyIndex(ki), iStart(is), iEnd(ie) {}
23 size_t keyIndex; // index in criteria vector
24 size_t iStart; // start row to sort
25 size_t iEnd; // end row to sort (one past last)
26};
27} // namespace
28
29DECLARE_WORKSPACE(TableWorkspace)
30
31
32TableWorkspace::TableWorkspace(size_t nrows) : ITableWorkspace(), m_rowCount(0), m_LogManager(new API::LogManager) {
33 setRowCount(nrows);
34}
35
37 : ITableWorkspace(other), m_rowCount(0), m_LogManager(new API::LogManager) {
38 setRowCount(other.m_rowCount);
39
40 auto it = other.m_columns.cbegin();
41 while (it != other.m_columns.cend()) {
42 addColumn(std::shared_ptr<API::Column>((*it)->clone()));
43 ++it;
44 }
45 // copy logs/properties.
46 m_LogManager = std::make_shared<API::LogManager>(*(other.m_LogManager));
47}
48
50 size_t data_size = std::accumulate(m_columns.cbegin(), m_columns.cend(), static_cast<size_t>(0),
51 [](size_t sum, const auto &column) { return sum + column->sizeOfData(); });
52 data_size += m_LogManager->getMemorySize();
53 return data_size;
54}
55
60API::Column_sptr TableWorkspace::addColumn(const std::string &type, const std::string &name) {
62 if (type.empty()) {
63 throw std::invalid_argument("Empty string passed as type argument of addColumn.");
64 }
65 if (name.empty()) {
66 throw std::invalid_argument("Empty string passed as name argument of addColumn.");
67 }
68 // Check that there is no column with the same name.
69 auto ci = std::find_if(m_columns.begin(), m_columns.end(), FindName(name));
70 if (ci != m_columns.end()) {
71 std::stringstream ss;
72 ss << "Column with name " << name << " already exists.\n";
73 throw std::invalid_argument(ss.str());
74 }
75 try {
76 c = API::ColumnFactory::Instance().create(type);
77 m_columns.emplace_back(c);
78 c->setName(name);
79 resizeColumn(c.get(), rowCount());
81 std::stringstream ss;
82 ss << "Column of type " << type << " and name " << name << " has not been added.\n";
83 ss << e.what() << '\n';
84 throw std::invalid_argument(ss.str());
85 }
86 modified();
87 return c;
88}
89
96 if (count == rowCount())
97 return;
98 for (auto &column : m_columns)
99 resizeColumn(column.get(), count);
101}
102
105 auto ci = std::find_if(m_columns.begin(), m_columns.end(), FindName(name));
106 if (ci == m_columns.end()) {
107 std::string str = "Column " + name + " does not exist.\n";
108 throw std::runtime_error(str);
109 }
110 return *ci;
111}
114 const auto found = std::find_if(m_columns.cbegin(), m_columns.cend(),
115 [&name](const auto &column) { return column->name() == name; });
116 if (found == m_columns.cend()) {
117 throw std::runtime_error("Column " + name + " does not exist.");
118 }
119 return *found;
120}
121
124 if (index >= columnCount()) {
125 std::stringstream ss;
126 ss << "Column index is out of range: " << index << "(" << columnCount() << ")\n";
127 throw std::range_error(ss.str());
128 }
129 return m_columns[index];
130}
131
134 if (index >= columnCount()) {
135 std::stringstream ss;
136 ss << "Column index is out of range: " << index << "(" << columnCount() << ")\n";
137 throw std::range_error(ss.str());
138 }
139 return m_columns[index];
140}
141
142void TableWorkspace::removeColumn(const std::string &name) {
143 auto ci = std::find_if(m_columns.begin(), m_columns.end(), FindName(name));
144 if (ci != m_columns.end()) {
145 if (ci->use_count() > 1) {
146 g_log.error() << "Deleting column in use (" << name << ").\n";
147 }
148 m_columns.erase(ci);
149 }
150 modified();
151}
152
157 if (index >= rowCount())
158 index = rowCount();
159 for (auto &column : m_columns)
160 insertInColumn(column.get(), index);
161 ++m_rowCount;
162 modified();
163 return index;
164}
165
169 if (index >= rowCount()) {
170 std::stringstream ss;
171 ss << "Attempt to delete a non-existing row (" << index << ")\n";
172 throw std::range_error(ss.str());
173 }
174 for (auto &column : m_columns)
175 removeFromColumn(column.get(), index);
176 --m_rowCount;
177 modified();
178}
179
180std::vector<std::string> TableWorkspace::getColumnNames() const {
181 std::vector<std::string> nameList;
182 nameList.reserve(m_columns.size());
183 std::transform(m_columns.cbegin(), m_columns.cend(), std::back_inserter(nameList),
184 [](const auto &column) { return column->name(); });
185 return nameList;
186}
187
188void TableWorkspace::addColumn(const std::shared_ptr<API::Column> &column) {
189 auto ci = std::find_if(m_columns.begin(), m_columns.end(), FindName(column->name()));
190 if (ci != m_columns.end()) {
191 std::stringstream ss;
192 ss << "Column with name " << column->name() << " already exists.\n";
193 throw std::invalid_argument(ss.str());
194 } else {
195 modified();
196 m_columns.emplace_back(column);
197 }
198}
199
205void TableWorkspace::sort(std::vector<std::pair<std::string, bool>> &criteria) {
206 if (criteria.empty())
207 return;
208
209 if (criteria.size() > columnCount()) {
210 throw std::runtime_error("Too many column names given.");
211 }
212
213 const size_t nRows = rowCount();
214 if (nRows == 0)
215 return;
216
217 // first sort an array of indices according to criteria then put the rows
218 // in order of the sorted indices
219
220 std::vector<size_t> indexVec(nRows);
221 // initialize the index vector with consecutive numbers
222 for (auto i = indexVec.begin() + 1; i != indexVec.end(); ++i) {
223 *i = *(i - 1) + 1;
224 }
225
226 // dynamically populate and use a queue of records for iteratively sort all
227 // rows
228 std::queue<SortIterationRecord> sortRecords;
229 // start with first pair in criteria and sort all rows
230 sortRecords.push(SortIterationRecord(0, 0, nRows));
231
232 // maximum possible number of calls to Column::sortIndex (I think)
233 const size_t maxNLoops = criteria.size() * nRows / 2;
234 // loop over sortRecords and sort indexVec
235 for (size_t counter = 0; counter < maxNLoops; ++counter) {
236 // get the record from the front of the queue
237 SortIterationRecord record = sortRecords.front();
238 sortRecords.pop();
239 // define the arguments for Column::sortIndex
240 auto &crt = criteria[record.keyIndex];
241 const std::string columnName = crt.first;
242 const bool ascending = crt.second;
243 auto &column = *getColumn(columnName);
244 std::vector<std::pair<size_t, size_t>> equalRanges;
245
246 // sort indexVec
247 column.sortIndex(ascending, record.iStart, record.iEnd, indexVec, equalRanges);
248
249 // if column had 1 or more ranges of equal values and there is next item in
250 // criteria
251 // add more records to the back of the queue
252 if (record.keyIndex < criteria.size() - 1) {
253 size_t keyIndex = record.keyIndex + 1;
254 for (auto const &equalRange : equalRanges) {
255 sortRecords.push(SortIterationRecord(keyIndex, equalRange.first, equalRange.second));
256 }
257 }
258
259 if (sortRecords.empty()) {
260 // there is nothing to do
261 break;
262 }
263 }
264
265 // finally sort the rows
266 const size_t nCols = columnCount();
267 for (size_t i = 0; i < nCols; ++i) {
268 getColumn(i)->sortValues(indexVec);
269 }
270 modified();
271}
272
275TableWorkspace *TableWorkspace::doCloneColumns(const std::vector<std::string> &colNames) const {
276 if (colNames.empty()) {
277 return new TableWorkspace(*this);
278 }
279 auto ws = new TableWorkspace();
280 ws->setRowCount(rowCount());
281 auto it = m_columns.cbegin();
282 while (it != m_columns.cend()) {
283 if (colNames.end() != std::find(colNames.begin(), colNames.end(), (**it).name())) {
284 ws->addColumn(std::shared_ptr<API::Column>((*it)->clone()));
285 }
286 ++it;
287 }
288 // copy logs/properties.
289 ws->m_LogManager = std::make_shared<API::LogManager>(*(m_LogManager));
290 return ws;
291}
292
293// template<>
294// boost::tuples::null_type TableWorkspace::make_TupleRef<
295// boost::tuples::null_type >(size_t j,const std::vector<std::string>&
296// names,size_t i)
297// {return boost::tuples::null_type();}
298
299} // namespace Mantid::DataObjects
300
302namespace Mantid::Kernel {
303template <>
304MANTID_DATAOBJECTS_DLL DataObjects::TableWorkspace_sptr
305IPropertyManager::getValue<DataObjects::TableWorkspace_sptr>(const std::string &name) const {
306 auto *prop = dynamic_cast<PropertyWithValue<DataObjects::TableWorkspace_sptr> *>(getPointerToProperty(name));
307 if (prop) {
308 return *prop;
309 } else {
310 std::string message =
311 "Attempt to assign property " + name + " to incorrect type. Expected shared_ptr<TableWorkspace>.";
312 throw std::runtime_error(message);
313 }
314}
315
316template <>
317MANTID_DATAOBJECTS_DLL DataObjects::TableWorkspace_const_sptr
318IPropertyManager::getValue<DataObjects::TableWorkspace_const_sptr>(const std::string &name) const {
319 auto const *prop = dynamic_cast<PropertyWithValue<DataObjects::TableWorkspace_sptr> *>(getPointerToProperty(name));
320 if (prop) {
321 return prop->operator()();
322 } else {
323 std::string message =
324 "Attempt to assign property " + name + " to incorrect type. Expected const shared_ptr<TableWorkspace>.";
325 throw std::runtime_error(message);
326 }
327}
328
329} // namespace Mantid::Kernel
330
std::string name
Definition Run.cpp:60
std::map< DeltaEMode::Type, std::string > index
int count
counter
Definition Matrix.cpp:37
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:43
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.
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 setRowCount(size_t count) final
Resizes the workspace.
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.
void error(const std::string &msg)
Logs at error level.
Definition Logger.cpp:108
The concrete, templated class for properties.
std::shared_ptr< Column > Column_sptr
Definition Column.h:229
Kernel::Logger g_log("ExperimentInfo")
static logger object
std::shared_ptr< const Column > Column_const_sptr
Definition Column.h:230
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)