Mantid
Loading...
Searching...
No Matches
PeakColumn.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 +
12#include "MantidKernel/System.h"
13
14#include <boost/variant/get.hpp>
15
16using namespace Mantid::Kernel;
17
18namespace Mantid::DataObjects {
19namespace {
21Kernel::Logger g_log("PeakColumn");
22
24size_t NCELL_ITEM_CACHED = 100;
25
30class ColumnNameToType {
31public:
32 ColumnNameToType() {
33 // Assume double if not in this map
34 m_type_index.emplace("DetID", "int");
35 m_type_index.emplace("RunNumber", "int");
36 m_type_index.emplace("h", "double");
37 m_type_index.emplace("k", "double");
38 m_type_index.emplace("l", "double");
39 m_type_index.emplace("Wavelength", "double");
40 m_type_index.emplace("Energy", "double");
41 m_type_index.emplace("TOF", "double");
42 m_type_index.emplace("DSpacing", "double");
43 m_type_index.emplace("Intens", "double");
44 m_type_index.emplace("SigInt", "double");
45 m_type_index.emplace("Intens/SigInt", "double");
46 m_type_index.emplace("BinCount", "double");
47 m_type_index.emplace("BankName", "str");
48 m_type_index.emplace("Row", "double");
49 m_type_index.emplace("Col", "double");
50 m_type_index.emplace("QLab", "V3D");
51 m_type_index.emplace("QSample", "V3D");
52 m_type_index.emplace("PeakNumber", "int");
53 m_type_index.emplace("TBar", "double");
54 }
55
56 inline const auto &data() const { return m_type_index; }
57
58private:
59 std::unordered_map<std::string, std::string> m_type_index;
60};
61
67const std::string typeFromName(const std::string &name) {
68 static ColumnNameToType typeIndex;
69 auto iter = typeIndex.data().find(name);
70 if (iter != typeIndex.data().end()) {
71 return iter->second;
72 } else {
73 throw std::runtime_error("PeakColumn - Unknown column name: \"" + name +
74 "\""
75 "Peak column names/types must be explicitly marked in PeakColumn.cpp");
76 }
77}
78} // namespace
79
80//----------------------------------------------------------------------------------------------
85template <class T>
86PeakColumn<T>::PeakColumn(std::vector<T> &peaks, const std::string &name) : m_peaks(peaks), m_oldRows() {
87 this->m_name = name;
88 this->m_type = typeFromName(name); // Throws if the name is unknown
89 const std::string key = "PeakColumn.hklPrec";
90 auto hklPrec = ConfigService::Instance().getValue<int>(key);
91 this->m_hklPrec = hklPrec.get_value_or(2);
92 if (!hklPrec.is_initialized()) {
93 g_log.information() << "In PeakColumn constructor, did not find any value for '" << key
94 << "' from the Config Service. Using default: " << this->m_hklPrec << "\n";
95 }
96}
97
99template <class T> const std::type_info &PeakColumn<T>::get_type_info() const {
100 // This is horrible copy-and-paste with the method below. The whole thing
101 // around columns could be much better implemented using templates & traits to
102 // avoid this
103 // type of thing!
104
105 if (type() == "double") {
106 return typeid(double);
107 } else if (type() == "int") {
108 return typeid(int);
109 } else if (type() == "str") {
110 return typeid(std::string);
111 } else if (type() == "V3D") {
112 return typeid(V3D);
113 } else {
114 throw std::runtime_error("PeakColumn::get_type_info() - Unknown column type: " + m_name);
115 }
116}
117
119template <class T> const std::type_info &PeakColumn<T>::get_pointer_type_info() const {
120 if (type() == "double") {
121 return typeid(double *);
122 } else if (type() == "int") {
123 return typeid(int *);
124 } else if (type() == "str") {
125 return typeid(std::string *);
126 } else if (type() == "V3D") {
127 return typeid(V3D *);
128 } else {
129 throw std::runtime_error("PeakColumn::get_pointer_type_info() -: " + m_name);
130 }
131}
132
133//-------------------------------------------------------------------------------------
139template <class T> void PeakColumn<T>::print(size_t index, std::ostream &s) const {
140 T &peak = m_peaks[index];
141 auto fullPeak = dynamic_cast<Peak *>(&peak); // additional printout for class Peak
142
143 s.imbue(std::locale("C"));
144 std::ios::fmtflags fflags(s.flags());
145 if (m_name == "RunNumber")
146 s << peak.getRunNumber();
147 else if (m_name == "DetID" && fullPeak) {
148 s << fullPeak->getDetectorID();
149 } else if (m_name == "BankName" && fullPeak)
150 s << fullPeak->getBankName();
151 else if (m_name == "QLab")
152 s << peak.getQLabFrame();
153 else if (m_name == "QSample")
154 s << peak.getQSampleFrame();
155 else if (m_name == "h") {
156 s << std::fixed << std::setprecision(m_hklPrec) << peak.getH();
157 } else if (m_name == "k") {
158 s << std::fixed << std::setprecision(m_hklPrec) << peak.getK();
159 } else if (m_name == "l") {
160 s << std::fixed << std::setprecision(m_hklPrec) << peak.getL();
161 } else if (m_name == "PeakNumber") {
162 s << peak.getPeakNumber();
163 } else
164 s << peak.getValueByColName(m_name);
165 s.flags(fflags);
166}
167
168//-------------------------------------------------------------------------------------
174template <class T> void PeakColumn<T>::read(size_t index, const std::string &text) {
175 // Don't modify read-only ones
176 if (this->getReadOnly() || index >= m_peaks.size())
177 return;
178
179 // Convert to a double
180 double val = 0;
181 int success = Strings::convert(text, val);
182
183 if (success == 0) {
184 g_log.error() << "Could not convert string '" << text << "' to a number.\n";
185 return;
186 }
187 setPeakHKLOrRunNumber(index, val);
188}
189
195template <class T> void PeakColumn<T>::read(const size_t index, std::istringstream &in) {
196 if (this->getReadOnly() || index >= m_peaks.size())
197 return;
198
199 double val;
200 try {
201 in >> val;
202 } catch (std::exception &e) {
203 g_log.error() << "Could not convert input to a number. " << e.what() << '\n';
204 return;
205 }
206
207 setPeakHKLOrRunNumber(index, val);
208}
209
210//-------------------------------------------------------------------------------------
212template <class T> bool PeakColumn<T>::getReadOnly() const {
213 return !((m_name == "h") || (m_name == "k") || (m_name == "l") || (m_name == "RunNumber"));
214}
215
216//-------------------------------------------------------------------------------------
218template <class T> bool PeakColumn<T>::isBool() const { return false; }
219
220template <class T> bool PeakColumn<T>::isNumber() const { return false; }
221
223template <class T> long int PeakColumn<T>::sizeOfData() const {
224 return sizeof(double) * static_cast<long int>(m_peaks.size());
225}
226
233template <class T> void PeakColumn<T>::resize(size_t count) {
235 throw Exception::NotImplementedError("PeakColumn::resize - Peaks must be "
236 "added through the PeaksWorkspace "
237 "interface.");
238}
239
246template <class T> void PeakColumn<T>::insert(size_t index) {
248 throw Exception::NotImplementedError("PeakColumn::insert - Peaks must be "
249 "inserted through the PeaksWorkspace "
250 "interface.");
251}
252
259template <class T> void PeakColumn<T>::remove(size_t index) {
261 throw Exception::NotImplementedError("PeakColumn::remove - Peaks must be "
262 "remove through the PeaksWorkspace "
263 "interface.");
264}
265
271template <class T> void *PeakColumn<T>::void_pointer(size_t index) {
272 const auto *constThis = const_cast<const PeakColumn *>(this);
273 return const_cast<void *>(constThis->void_pointer(index));
274}
275
281template <class T> const void *PeakColumn<T>::void_pointer(size_t index) const {
282 const T &peak = m_peaks[index];
283 auto fullPeak = dynamic_cast<const DataObjects::Peak *>(&peak); // additional methods available in class Peak
284
285 // The cell() api requires that the value exist somewhere in memory, however,
286 // some of the values from a Peak are calculated on the fly so a reference
287 // cannot be returned. Instead we cache a value for the last NCELL_ITEM_CACHED
288 // accesses and return a reference to this
289
290 m_oldRows.push_front(CacheValueType());
291 if (m_oldRows.size() > NCELL_ITEM_CACHED) {
292 m_oldRows.pop_back();
293 }
294 auto &value = m_oldRows.front(); // A reference to the actual stored variant
295
296 if (type() == "double") {
297 value = peak.getValueByColName(m_name); // Assign the value to the store
298 return boost::get<double>(&value); // Given a pointer it will return a pointer
299 } else if (m_name == "RunNumber") {
300 value = peak.getRunNumber();
301 return boost::get<int>(&value);
302 } else if (m_name == "PeakNumber") {
303 value = peak.getPeakNumber();
304 return boost::get<int>(&value);
305 } else if (m_name == "DetID" && fullPeak) {
306 value = fullPeak->getDetectorID();
307 return boost::get<int>(&value);
308 } else if (m_name == "BankName" && fullPeak) {
309 value = fullPeak->getBankName();
310 return boost::get<std::string>(&value);
311 } else if (m_name == "QLab") {
312 value = peak.getQLabFrame();
313 return boost::get<Kernel::V3D>(&value);
314 } else if (m_name == "QSample") {
315 value = peak.getQSampleFrame();
316 return boost::get<Kernel::V3D>(&value);
317 } else {
318 throw std::runtime_error("void_pointer() - Unknown peak column name or type: " + m_name);
319 }
320}
321
322template <class T> PeakColumn<T> *PeakColumn<T>::clone() const {
323 auto temp = new PeakColumn<T>(this->m_peaks, this->m_name);
324 return temp;
325}
326
327template <class T> double PeakColumn<T>::toDouble(size_t /*index*/) const {
328 throw std::runtime_error("PeakColumn::toDouble() not implemented, PeakColumn "
329 "is has no general write access");
330}
331
332template <class T> void PeakColumn<T>::fromDouble(size_t /*index*/, double /*value*/) {
333 throw std::runtime_error("fromDouble() not implemented, PeakColumn is has no "
334 "general write access");
335}
336
337template <class T> void PeakColumn<T>::setPeakHKLOrRunNumber(const size_t index, const double val) {
338 T &peak = m_peaks[index];
339 if (m_name == "h")
340 peak.setH(val);
341 else if (m_name == "k")
342 peak.setK(val);
343 else if (m_name == "l")
344 peak.setL(val);
345 else if (m_name == "RunNumber")
346 peak.setRunNumber(static_cast<int>(val));
347 else
348 throw std::runtime_error("Unexpected column " + m_name + " being set.");
349}
350
351template class PeakColumn<Peak>;
352template class PeakColumn<LeanElasticPeak>;
353
354} // namespace Mantid::DataObjects
double value
The value of the point.
Definition: FitMW.cpp:51
std::map< DeltaEMode::Type, std::string > index
Definition: DeltaEMode.cpp:19
int count
counter
Definition: Matrix.cpp:37
std::unordered_map< std::string, std::string > m_type_index
Definition: PeakColumn.cpp:59
#define UNUSED_ARG(x)
Function arguments are sometimes unused in certain implmentations but are required for documentation ...
Definition: System.h:64
std::string m_type
type
Definition: Column.h:186
const std::string & name() const
Name (caption) of the column.
Definition: Column.h:43
std::string m_name
name
Definition: Column.h:185
PeakColumn : a Column sub-class used to display peak information as a TableWorkspace.
Definition: PeakColumn.h:28
void fromDouble(size_t i, double value) override
Assign from double.
Definition: PeakColumn.cpp:332
const std::type_info & get_type_info() const override
Returns typeid for the data in the column.
Definition: PeakColumn.cpp:99
void * void_pointer(size_t index) override
Pointer to a data element.
Definition: PeakColumn.cpp:271
void remove(size_t index) override
Removes an item.
Definition: PeakColumn.cpp:259
bool isBool() const override
Specialized type check.
Definition: PeakColumn.cpp:218
void insert(size_t index) override
Inserts an item.
Definition: PeakColumn.cpp:246
bool getReadOnly() const override
Definition: PeakColumn.cpp:212
PeakColumn(std::vector< T > &peaks, const std::string &name)
Construct a column with a reference to the peaks list, a name & type.
Definition: PeakColumn.cpp:86
void setPeakHKLOrRunNumber(const size_t index, const double val)
Sets the correct value in the referenced peak.
Definition: PeakColumn.cpp:337
const std::type_info & get_pointer_type_info() const override
Returns typeid for the pointer type to the data element in the column.
Definition: PeakColumn.cpp:119
int m_hklPrec
Precision of hkl in table workspace.
Definition: PeakColumn.h:95
bool isNumber() const override
Are elements of the column interpretable as a number?
Definition: PeakColumn.cpp:220
void read(size_t index, const std::string &text) override
Read in some text and convert to a number in the PeaksWorkspace.
Definition: PeakColumn.cpp:174
double toDouble(size_t i) const override
Cast to double.
Definition: PeakColumn.cpp:327
void resize(size_t count) override
Sets the new column size.
Definition: PeakColumn.cpp:233
boost::variant< double, int, std::string, Kernel::V3D > CacheValueType
Type of the row cache value.
Definition: PeakColumn.h:98
long int sizeOfData() const override
Must return overall memory size taken by the column.
Definition: PeakColumn.cpp:223
PeakColumn * clone() const override
Clone.
Definition: PeakColumn.cpp:322
void print(size_t index, std::ostream &s) const override
Prints.
Definition: PeakColumn.cpp:139
Structure describing a single-crystal peak.
Definition: Peak.h:34
Marks code as not implemented yet.
Definition: Exception.h:138
The Logger class is in charge of the publishing messages from the framework through various channels.
Definition: Logger.h:52
void error(const std::string &msg)
Logs at error level.
Definition: Logger.cpp:77
void information(const std::string &msg)
Logs at information level.
Definition: Logger.cpp:105
static T & Instance()
Return a reference to the Singleton instance, creating it if it does not already exist Creation is do...
Class for 3D vectors.
Definition: V3D.h:34
Kernel::Logger g_log("ExperimentInfo")
static logger object
int convert(const std::string &A, T &out)
Convert a string into a number.
Definition: Strings.cpp:665