diff --git a/Framework/DataObjects/CMakeLists.txt b/Framework/DataObjects/CMakeLists.txt index 45c84d1d3a99b1400cb426c26a27371a71db490a..aa8f3ad56e5d7cbc622227fc60da59d079a3ce36 100644 --- a/Framework/DataObjects/CMakeLists.txt +++ b/Framework/DataObjects/CMakeLists.txt @@ -31,7 +31,6 @@ set(SRC_FILES src/LeanElasticPeak.cpp src/BasePeak.cpp src/PeakColumn.cpp - src/LeanElasticPeakColumn.cpp src/PeakNoShapeFactory.cpp src/PeakShapeBase.cpp src/PeakShapeEllipsoid.cpp @@ -115,7 +114,6 @@ set(INC_FILES inc/MantidDataObjects/LeanElasticPeak.h inc/MantidDataObjects/BasePeak.h inc/MantidDataObjects/PeakColumn.h - inc/MantidDataObjects/LeanElasticPeakColumn.h inc/MantidDataObjects/PeakNoShapeFactory.h inc/MantidDataObjects/PeakShapeBase.h inc/MantidDataObjects/PeakShapeEllipsoid.h @@ -177,7 +175,6 @@ set(TEST_FILES NoShapeTest.h OffsetsWorkspaceTest.h PeakColumnTest.h - LeanElasticPeakColumnTest.h PeakNoShapeFactoryTest.h PeakShapeEllipsoidFactoryTest.h PeakShapeEllipsoidTest.h diff --git a/Framework/DataObjects/inc/MantidDataObjects/BasePeak.h b/Framework/DataObjects/inc/MantidDataObjects/BasePeak.h index 0f5df6a8820091aeb95c5da1d8eaec3abaf7018f..ac3aa85b097a8832cc116c206f7f462209cc0fd1 100644 --- a/Framework/DataObjects/inc/MantidDataObjects/BasePeak.h +++ b/Framework/DataObjects/inc/MantidDataObjects/BasePeak.h @@ -32,9 +32,6 @@ namespace DataObjects { */ class DLLExport BasePeak : public Geometry::IPeak { public: - /// Allow PeakColumn class to directly access members. - friend class PeakColumn; - BasePeak(); BasePeak(const Mantid::Kernel::Matrix<double> &goniometer); /// Copy constructor diff --git a/Framework/DataObjects/inc/MantidDataObjects/LeanElasticPeak.h b/Framework/DataObjects/inc/MantidDataObjects/LeanElasticPeak.h index 527e3c52c4634d80dc0003d4c13c4f375cc815a3..67a3b7e49c0e13a4a3a999bd2b497d80d062ebab 100644 --- a/Framework/DataObjects/inc/MantidDataObjects/LeanElasticPeak.h +++ b/Framework/DataObjects/inc/MantidDataObjects/LeanElasticPeak.h @@ -30,8 +30,6 @@ namespace DataObjects { */ class DLLExport LeanElasticPeak : public BasePeak { public: - /// Allow PeakColumn class to directly access members. - friend class PeakColumn; LeanElasticPeak(); LeanElasticPeak(const Mantid::Kernel::V3D &QSampleFrame); diff --git a/Framework/DataObjects/inc/MantidDataObjects/LeanElasticPeakColumn.h b/Framework/DataObjects/inc/MantidDataObjects/LeanElasticPeakColumn.h deleted file mode 100644 index eca3415d85bccad3465bcb40fe8d13798af0e8f6..0000000000000000000000000000000000000000 --- a/Framework/DataObjects/inc/MantidDataObjects/LeanElasticPeakColumn.h +++ /dev/null @@ -1,107 +0,0 @@ -// Mantid Repository : https://github.com/mantidproject/mantid -// -// Copyright © 2018 ISIS Rutherford Appleton Laboratory UKRI, -// NScD Oak Ridge National Laboratory, European Spallation Source, -// Institut Laue - Langevin & CSNS, Institute of High Energy Physics, CAS -// SPDX - License - Identifier: GPL - 3.0 + -#pragma once - -#include "MantidAPI/Column.h" -#include "MantidDataObjects/LeanElasticPeak.h" - -#include <boost/variant.hpp> -#include <list> - -namespace Mantid { -namespace DataObjects { - -/** PeakColumn : a Column sub-class used to display - * peak information as a TableWorkspace. - * - * The column holds a reference to a vector of Peak objects. - * Values in the column are taken directly from those Peak objects. - * - * @author Janik Zikovsky - * @date 2011-04-25 18:06:32.952258 - */ -class DLLExport LeanElasticPeakColumn : public Mantid::API::Column { - -public: - /// Construct a column with a reference to the peaks list, a name & type - LeanElasticPeakColumn(std::vector<LeanElasticPeak> &peaks, - const std::string &name); - - /// Number of individual elements in the column. - size_t size() const override { return m_peaks.size(); } - - /// Returns typeid for the data in the column - const std::type_info &get_type_info() const override; - - /// Returns typeid for the pointer type to the data element in the column - const std::type_info &get_pointer_type_info() const override; - - bool getReadOnly() const override; - - /// Prints - void print(size_t index, std::ostream &s) const override; - - void read(size_t index, const std::string &text) override; - - /// Sets item from a stream - void read(const size_t index, std::istringstream &in) override; - - /// Specialized type check - bool isBool() const override; - - bool isNumber() const override; - - /// Must return overall memory size taken by the column. - long int sizeOfData() const override; - - /// Clone. - LeanElasticPeakColumn *clone() const override; - - /// Cast to double - double toDouble(size_t i) const override; - - /// Assign from double - void fromDouble(size_t i, double value) override; - - /// Reference to the data. - const std::vector<LeanElasticPeak> &data() const { return m_peaks; } - - bool equals(const Column &otherColumn, double tolerance) const override { - (void)otherColumn; - (void)tolerance; - throw std::runtime_error( - "equals not implemented, to compare use CompareWorkspace"); - } - -protected: - /// Sets the new column size. - void resize(size_t count) override; - /// Inserts an item. - void insert(size_t index) override; - /// Removes an item. - void remove(size_t index) override; - /// Pointer to a data element - void *void_pointer(size_t index) override; - /// Pointer to a data element - const void *void_pointer(size_t index) const override; - -private: - /// Reference to the peaks object saved in the PeaksWorkspace. - std::vector<LeanElasticPeak> &m_peaks; - /// Precision of hkl in table workspace - int m_hklPrec; - - /// Type of the row cache value - using CacheValueType = boost::variant<double, int, std::string, Kernel::V3D>; - /// - mutable std::list<CacheValueType> m_oldRows; - /// Sets the correct value in the referenced peak. - void setPeakHKLOrRunNumber(const size_t index, const double val); -}; - -} // namespace DataObjects -} // namespace Mantid diff --git a/Framework/DataObjects/inc/MantidDataObjects/LeanElasticPeaksWorkspace.h b/Framework/DataObjects/inc/MantidDataObjects/LeanElasticPeaksWorkspace.h index e2f671536441855ac5b736951b55b650e8b889df..0d5783a5bafcd99c523ad7b7c8a105a363a0beb6 100644 --- a/Framework/DataObjects/inc/MantidDataObjects/LeanElasticPeaksWorkspace.h +++ b/Framework/DataObjects/inc/MantidDataObjects/LeanElasticPeaksWorkspace.h @@ -10,7 +10,7 @@ #include "MantidAPI/ITableWorkspace.h" #include "MantidDataObjects/DllConfig.h" #include "MantidDataObjects/LeanElasticPeak.h" -#include "MantidDataObjects/LeanElasticPeakColumn.h" +#include "MantidDataObjects/PeakColumn.h" #include "MantidGeometry/Crystal/IPeak.h" #include "MantidKernel/SpecialCoordinateSystem.h" #include "MantidKernel/V3D.h" @@ -277,7 +277,7 @@ private: std::vector<LeanElasticPeak> peaks; /** Column shared pointers. */ - std::vector<std::shared_ptr<Mantid::DataObjects::LeanElasticPeakColumn>> + std::vector<std::shared_ptr<Mantid::DataObjects::PeakColumn<LeanElasticPeak>>> columns; /** Column names */ diff --git a/Framework/DataObjects/inc/MantidDataObjects/Peak.h b/Framework/DataObjects/inc/MantidDataObjects/Peak.h index c8572fc9f1fd39a3168a0b5c4a8d47f6b23dbd62..11ee02932b37662bb7b031966e4b394fdf81e712 100644 --- a/Framework/DataObjects/inc/MantidDataObjects/Peak.h +++ b/Framework/DataObjects/inc/MantidDataObjects/Peak.h @@ -34,9 +34,6 @@ namespace DataObjects { */ class DLLExport Peak : public BasePeak { public: - /// Allow PeakColumn class to directly access members. - friend class PeakColumn; - Peak(); Peak(const Geometry::Instrument_const_sptr &m_inst, const Mantid::Kernel::V3D &QLabFrame, diff --git a/Framework/DataObjects/inc/MantidDataObjects/PeakColumn.h b/Framework/DataObjects/inc/MantidDataObjects/PeakColumn.h index c9e4024f8b9b90527ebc35926faba7db73bd2eb0..9e09910ac30c49ea6dc32f2c0e980ac87c9fa292 100644 --- a/Framework/DataObjects/inc/MantidDataObjects/PeakColumn.h +++ b/Framework/DataObjects/inc/MantidDataObjects/PeakColumn.h @@ -7,6 +7,7 @@ #pragma once #include "MantidAPI/Column.h" +#include "MantidDataObjects/LeanElasticPeak.h" #include "MantidDataObjects/Peak.h" #include <boost/variant.hpp> @@ -24,11 +25,11 @@ namespace DataObjects { * @author Janik Zikovsky * @date 2011-04-25 18:06:32.952258 */ -class DLLExport PeakColumn : public Mantid::API::Column { +template <class T> class DLLExport PeakColumn : public Mantid::API::Column { public: /// Construct a column with a reference to the peaks list, a name & type - PeakColumn(std::vector<Peak> &peaks, const std::string &name); + PeakColumn(std::vector<T> &peaks, const std::string &name); /// Number of individual elements in the column. size_t size() const override { return m_peaks.size(); } @@ -67,7 +68,7 @@ public: void fromDouble(size_t i, double value) override; /// Reference to the data. - const std::vector<Peak> &data() const { return m_peaks; } + const std::vector<T> &data() const { return m_peaks; } bool equals(const Column &otherColumn, double tolerance) const override { (void)otherColumn; @@ -90,7 +91,7 @@ protected: private: /// Reference to the peaks object saved in the PeaksWorkspace. - std::vector<Peak> &m_peaks; + std::vector<T> &m_peaks; /// Precision of hkl in table workspace int m_hklPrec; diff --git a/Framework/DataObjects/inc/MantidDataObjects/PeaksWorkspace.h b/Framework/DataObjects/inc/MantidDataObjects/PeaksWorkspace.h index a06284d2fa48a48ce246529ea963f17572be103f..4f64f09323eea36a270ff0e0af09188744dfcc6f 100644 --- a/Framework/DataObjects/inc/MantidDataObjects/PeaksWorkspace.h +++ b/Framework/DataObjects/inc/MantidDataObjects/PeaksWorkspace.h @@ -269,7 +269,7 @@ private: std::vector<Peak> peaks; /** Column shared pointers. */ - std::vector<std::shared_ptr<Mantid::DataObjects::PeakColumn>> columns; + std::vector<std::shared_ptr<Mantid::DataObjects::PeakColumn<Peak>>> columns; /** Column names */ std::vector<std::string> columnNames; diff --git a/Framework/DataObjects/src/LeanElasticPeakColumn.cpp b/Framework/DataObjects/src/LeanElasticPeakColumn.cpp deleted file mode 100644 index 48ae42a5b999984a5e5a990d85e1376b980d40c1..0000000000000000000000000000000000000000 --- a/Framework/DataObjects/src/LeanElasticPeakColumn.cpp +++ /dev/null @@ -1,369 +0,0 @@ -// Mantid Repository : https://github.com/mantidproject/mantid -// -// Copyright © 2018 ISIS Rutherford Appleton Laboratory UKRI, -// NScD Oak Ridge National Laboratory, European Spallation Source, -// Institut Laue - Langevin & CSNS, Institute of High Energy Physics, CAS -// SPDX - License - Identifier: GPL - 3.0 + -#include "MantidDataObjects/LeanElasticPeakColumn.h" -#include "MantidKernel/ConfigService.h" -#include "MantidKernel/Exception.h" -#include "MantidKernel/MultiThreaded.h" -#include "MantidKernel/Strings.h" -#include "MantidKernel/System.h" - -#include <boost/variant/get.hpp> - -using namespace Mantid::Kernel; - -namespace Mantid { -namespace DataObjects { -namespace { -/// static logger -Kernel::Logger g_log("LeanElasticPeakColumn"); - -/// Number of items to keep around in the cell cache (see void_pointer()) -size_t NCELL_ITEM_CACHED = 100; - -/** - * Private implementation to wrap a map such that it can be - * initialized in a thread-safe manner with a local static - */ -class ColumnNameToType { -public: - ColumnNameToType() { - // Assume double if not in this map - m_type_index.emplace("DetID", "int"); - m_type_index.emplace("RunNumber", "int"); - m_type_index.emplace("h", "double"); - m_type_index.emplace("k", "double"); - m_type_index.emplace("l", "double"); - m_type_index.emplace("Wavelength", "double"); - m_type_index.emplace("Energy", "double"); - m_type_index.emplace("TOF", "double"); - m_type_index.emplace("DSpacing", "double"); - m_type_index.emplace("Intens", "double"); - m_type_index.emplace("SigInt", "double"); - m_type_index.emplace("Intens/SigInt", "double"); - m_type_index.emplace("BinCount", "double"); - m_type_index.emplace("BankName", "str"); - m_type_index.emplace("Row", "double"); - m_type_index.emplace("Col", "double"); - m_type_index.emplace("QLab", "V3D"); - m_type_index.emplace("QSample", "V3D"); - m_type_index.emplace("PeakNumber", "int"); - m_type_index.emplace("TBar", "double"); - } - - inline const auto &data() const { return m_type_index; } - -private: - std::unordered_map<std::string, std::string> m_type_index; -}; - -/** - * Returns a string type identifier from the given name - * @param name :: The name of the column - * @returns A string identifier for the column type - */ -const std::string typeFromName(const std::string &name) { - static ColumnNameToType typeIndex; - auto iter = typeIndex.data().find(name); - if (iter != typeIndex.data().end()) { - return iter->second; - } else { - throw std::runtime_error("LeanElasticPeakColumn - Unknown column name: \"" + - name + - "\"" - "Peak column names/types must be explicitly " - "marked in LeanElasticPeakColumn.cpp"); - } -} -} // namespace - -//---------------------------------------------------------------------------------------------- -/** Constructor - * @param peaks :: vector of peaks - * @param name :: name for the column - */ -LeanElasticPeakColumn::LeanElasticPeakColumn( - std::vector<LeanElasticPeak> &peaks, const std::string &name) - : m_peaks(peaks), m_oldRows() { - this->m_name = name; - this->m_type = typeFromName(name); // Throws if the name is unknown - const std::string key = "PeakColumn.hklPrec"; - auto hklPrec = ConfigService::Instance().getValue<int>(key); - this->m_hklPrec = hklPrec.get_value_or(2); - if (!hklPrec.is_initialized()) { - g_log.information() - << "In LeanElasticPeakColumn constructor, did not find any value for '" - << key - << "' from the Config Service. Using default: " << this->m_hklPrec - << "\n"; - } -} - -/// Returns typeid for the data in the column -const std::type_info &LeanElasticPeakColumn::get_type_info() const { - // This is horrible copy-and-paste with the method below. The whole thing - // around columns could be much better implemented using templates & traits to - // avoid this - // type of thing! - - if (type() == "double") { - return typeid(double); - } else if (type() == "int") { - return typeid(int); - } else if (type() == "str") { - return typeid(std::string); - } else if (type() == "V3D") { - return typeid(V3D); - } else { - throw std::runtime_error( - "LeanElasticPeakColumn::get_type_info() - Unknown column type: " + - m_name); - } -} - -/// Returns typeid for the pointer type to the data element in the column -const std::type_info &LeanElasticPeakColumn::get_pointer_type_info() const { - if (type() == "double") { - return typeid(double *); - } else if (type() == "int") { - return typeid(int *); - } else if (type() == "str") { - return typeid(std::string *); - } else if (type() == "V3D") { - return typeid(V3D *); - } else { - throw std::runtime_error( - "LeanElasticPeakColumn::get_pointer_type_info() -: " + m_name); - } -} - -//------------------------------------------------------------------------------------- -/** Prints out the column string at the given row index. - * - * @param s :: stream to output - * @param index :: row index - */ -void LeanElasticPeakColumn::print(size_t index, std::ostream &s) const { - LeanElasticPeak &peak = m_peaks[index]; - s.imbue(std::locale("C")); - std::ios::fmtflags fflags(s.flags()); - if (m_name == "RunNumber") - s << peak.getRunNumber(); - else if (m_name == "DetID") - s << peak.getDetectorID(); - else if (m_name == "BankName") - s << peak.getBankName(); - else if (m_name == "QLab") - s << peak.getQLabFrame(); - else if (m_name == "QSample") - s << peak.getQSampleFrame(); - else if (m_name == "h") { - s << std::fixed << std::setprecision(m_hklPrec) << peak.getH(); - } else if (m_name == "k") { - s << std::fixed << std::setprecision(m_hklPrec) << peak.getK(); - } else if (m_name == "l") { - s << std::fixed << std::setprecision(m_hklPrec) << peak.getL(); - } else if (m_name == "PeakNumber") { - s << peak.getPeakNumber(); - } else - s << peak.getValueByColName(m_name); - s.flags(fflags); -} - -//------------------------------------------------------------------------------------- -/** Read in some text and convert to a number in the PeaksWorkspace - * - * @param text :: string to read - * @param index :: index of the peak to modify - */ -void LeanElasticPeakColumn::read(size_t index, const std::string &text) { - // Don't modify read-only ones - if (this->getReadOnly() || index >= m_peaks.size()) - return; - - // Convert to a double - double val = 0; - int success = Strings::convert(text, val); - - if (success == 0) { - g_log.error() << "Could not convert string '" << text << "' to a number.\n"; - return; - } - setPeakHKLOrRunNumber(index, val); -} - -/** Read in from stream and convert to a number in the PeaksWorkspace - * - * @param index :: index of the peak to modify - * @param in :: input stream - */ -void LeanElasticPeakColumn::read(const size_t index, std::istringstream &in) { - if (this->getReadOnly() || index >= m_peaks.size()) - return; - - double val; - try { - in >> val; - } catch (std::exception &e) { - g_log.error() << "Could not convert input to a number. " << e.what() - << '\n'; - return; - } - - setPeakHKLOrRunNumber(index, val); -} - -//------------------------------------------------------------------------------------- -/** @return true if the column is read-only */ -bool LeanElasticPeakColumn::getReadOnly() const { - return !((m_name == "h") || (m_name == "k") || (m_name == "l") || - (m_name == "RunNumber")); -} - -//------------------------------------------------------------------------------------- -/// Specialized type check -bool LeanElasticPeakColumn::isBool() const { return false; } - -bool LeanElasticPeakColumn::isNumber() const { return false; } - -/// @returns overall memory size taken by the column. -long int LeanElasticPeakColumn::sizeOfData() const { - return sizeof(double) * static_cast<long int>(m_peaks.size()); -} - -/** - * Sets a new size for the column. Not implemented as this is controlled - * by the PeaksWorkspace - * @param count :: Count of new column size (unused) - * @throw Exception::NotImplementedError - */ -void LeanElasticPeakColumn::resize(size_t count) { - UNUSED_ARG(count); - throw Exception::NotImplementedError( - "LeanElasticPeakColumn::resize - Peaks must be " - "added through the PeaksWorkspace " - "interface."); -} - -/** - * Inserts an item into the column. Not implemented as this is controlled by the - * PeaksWorkspace - * @param index :: The new index position (unused) - * @throw Exception::NotImplementedError - */ -void LeanElasticPeakColumn::insert(size_t index) { - UNUSED_ARG(index); - throw Exception::NotImplementedError( - "LeanElasticPeakColumn::insert - Peaks must be " - "inserted through the PeaksWorkspace " - "interface."); -} - -/** - * Removes an item from the column. Not implemented as this is controlled by the - * PeaksWorkspace - * @param index :: The index position removed(unused) - * @throw Exception::NotImplementedError - */ -void LeanElasticPeakColumn::remove(size_t index) { - UNUSED_ARG(index); - throw Exception::NotImplementedError( - "LeanElasticPeakColumn::remove - Peaks must be " - "remove through the PeaksWorkspace " - "interface."); -} - -/** - * Pointer to a data element in the PeaksWorkspace (non-const version) - * @param index :: A row index pointing to the PeaksWorkspace - * @returns A pointer to the data element at that index from this column - */ -void *LeanElasticPeakColumn::void_pointer(size_t index) { - const auto *constThis = const_cast<const LeanElasticPeakColumn *>(this); - return const_cast<void *>(constThis->void_pointer(index)); -} - -/** - * Pointer to a data element in the PeaksWorkspace (const version) - * @param index :: A row index pointing to the PeaksWorkspace - * @returns A pointer to the data element at that index from this column - */ -const void *LeanElasticPeakColumn::void_pointer(size_t index) const { - const LeanElasticPeak &peak = m_peaks[index]; - - // The cell() api requires that the value exist somewhere in memory, however, - // some of the values from a Peak are calculated on the fly so a reference - // cannot be returned. Instead we cache a value for the last NCELL_ITEM_CACHED - // accesses and return a reference to this - - m_oldRows.push_front(CacheValueType()); - if (m_oldRows.size() > NCELL_ITEM_CACHED) { - m_oldRows.pop_back(); - } - auto &value = m_oldRows.front(); // A reference to the actual stored variant - - if (type() == "double") { - value = peak.getValueByColName(m_name); // Assign the value to the store - return boost::get<double>( - &value); // Given a pointer it will return a pointer - } else if (m_name == "RunNumber") { - value = peak.getRunNumber(); - return boost::get<int>(&value); - } else if (m_name == "PeakNumber") { - value = peak.getPeakNumber(); - return boost::get<int>(&value); - } else if (m_name == "DetID") { - value = peak.getDetectorID(); - return boost::get<int>(&value); - } else if (m_name == "BankName") { - value = peak.getBankName(); - return boost::get<std::string>(&value); - } else if (m_name == "QLab") { - value = peak.getQLabFrame(); - return boost::get<Kernel::V3D>(&value); - } else if (m_name == "QSample") { - value = peak.getQSampleFrame(); - return boost::get<Kernel::V3D>(&value); - } else { - throw std::runtime_error( - "void_pointer() - Unknown peak column name or type: " + m_name); - } -} - -LeanElasticPeakColumn *LeanElasticPeakColumn::clone() const { - auto temp = new LeanElasticPeakColumn(this->m_peaks, this->m_name); - return temp; -} - -double LeanElasticPeakColumn::toDouble(size_t /*index*/) const { - throw std::runtime_error("LeanElasticPeakColumn::toDouble() not implemented, " - "LeanElasticPeakColumn " - "is has no general write access"); -} - -void LeanElasticPeakColumn::fromDouble(size_t /*index*/, double /*value*/) { - throw std::runtime_error( - "fromDouble() not implemented, LeanElasticPeakColumn is has no " - "general write access"); -} - -void LeanElasticPeakColumn::setPeakHKLOrRunNumber(const size_t index, - const double val) { - LeanElasticPeak &peak = m_peaks[index]; - if (m_name == "h") - peak.setH(val); - else if (m_name == "k") - peak.setK(val); - else if (m_name == "l") - peak.setL(val); - else if (m_name == "RunNumber") - peak.setRunNumber(static_cast<int>(val)); - else - throw std::runtime_error("Unexpected column " + m_name + " being set."); -} - -} // namespace DataObjects -} // namespace Mantid diff --git a/Framework/DataObjects/src/LeanElasticPeaksWorkspace.cpp b/Framework/DataObjects/src/LeanElasticPeaksWorkspace.cpp index ab003c988b13ce4099e52fd8ec286cdbfeb2e70a..ce6b293de873bc083f7a3a5b52e0c673ab87b8c8 100644 --- a/Framework/DataObjects/src/LeanElasticPeaksWorkspace.cpp +++ b/Framework/DataObjects/src/LeanElasticPeaksWorkspace.cpp @@ -426,7 +426,8 @@ void LeanElasticPeaksWorkspace::initColumns() { void LeanElasticPeaksWorkspace::addPeakColumn(const std::string &name) { // Create the PeakColumn. columns.emplace_back( - std::make_shared<DataObjects::LeanElasticPeakColumn>(this->peaks, name)); + std::make_shared<DataObjects::PeakColumn<LeanElasticPeak>>(this->peaks, + name)); // Cache the names columnNames.emplace_back(name); } diff --git a/Framework/DataObjects/src/PeakColumn.cpp b/Framework/DataObjects/src/PeakColumn.cpp index a46a79b4ad99ee6927c98cf09103da8728836733..9b55ed13ed06991ce6eeb34c267002adcd56ca5d 100644 --- a/Framework/DataObjects/src/PeakColumn.cpp +++ b/Framework/DataObjects/src/PeakColumn.cpp @@ -84,7 +84,8 @@ const std::string typeFromName(const std::string &name) { * @param peaks :: vector of peaks * @param name :: name for the column */ -PeakColumn::PeakColumn(std::vector<Peak> &peaks, const std::string &name) +template <class T> +PeakColumn<T>::PeakColumn(std::vector<T> &peaks, const std::string &name) : m_peaks(peaks), m_oldRows() { this->m_name = name; this->m_type = typeFromName(name); // Throws if the name is unknown @@ -100,7 +101,7 @@ PeakColumn::PeakColumn(std::vector<Peak> &peaks, const std::string &name) } /// Returns typeid for the data in the column -const std::type_info &PeakColumn::get_type_info() const { +template <class T> const std::type_info &PeakColumn<T>::get_type_info() const { // This is horrible copy-and-paste with the method below. The whole thing // around columns could be much better implemented using templates & traits to // avoid this @@ -121,7 +122,8 @@ const std::type_info &PeakColumn::get_type_info() const { } /// Returns typeid for the pointer type to the data element in the column -const std::type_info &PeakColumn::get_pointer_type_info() const { +template <class T> +const std::type_info &PeakColumn<T>::get_pointer_type_info() const { if (type() == "double") { return typeid(double *); } else if (type() == "int") { @@ -142,8 +144,9 @@ const std::type_info &PeakColumn::get_pointer_type_info() const { * @param s :: stream to output * @param index :: row index */ -void PeakColumn::print(size_t index, std::ostream &s) const { - Peak &peak = m_peaks[index]; +template <class T> +void PeakColumn<T>::print(size_t index, std::ostream &s) const { + T &peak = m_peaks[index]; s.imbue(std::locale("C")); std::ios::fmtflags fflags(s.flags()); if (m_name == "RunNumber") @@ -175,7 +178,8 @@ void PeakColumn::print(size_t index, std::ostream &s) const { * @param text :: string to read * @param index :: index of the peak to modify */ -void PeakColumn::read(size_t index, const std::string &text) { +template <class T> +void PeakColumn<T>::read(size_t index, const std::string &text) { // Don't modify read-only ones if (this->getReadOnly() || index >= m_peaks.size()) return; @@ -196,7 +200,8 @@ void PeakColumn::read(size_t index, const std::string &text) { * @param index :: index of the peak to modify * @param in :: input stream */ -void PeakColumn::read(const size_t index, std::istringstream &in) { +template <class T> +void PeakColumn<T>::read(const size_t index, std::istringstream &in) { if (this->getReadOnly() || index >= m_peaks.size()) return; @@ -214,19 +219,19 @@ void PeakColumn::read(const size_t index, std::istringstream &in) { //------------------------------------------------------------------------------------- /** @return true if the column is read-only */ -bool PeakColumn::getReadOnly() const { +template <class T> bool PeakColumn<T>::getReadOnly() const { return !((m_name == "h") || (m_name == "k") || (m_name == "l") || (m_name == "RunNumber")); } //------------------------------------------------------------------------------------- /// Specialized type check -bool PeakColumn::isBool() const { return false; } +template <class T> bool PeakColumn<T>::isBool() const { return false; } -bool PeakColumn::isNumber() const { return false; } +template <class T> bool PeakColumn<T>::isNumber() const { return false; } /// @returns overall memory size taken by the column. -long int PeakColumn::sizeOfData() const { +template <class T> long int PeakColumn<T>::sizeOfData() const { return sizeof(double) * static_cast<long int>(m_peaks.size()); } @@ -236,7 +241,7 @@ long int PeakColumn::sizeOfData() const { * @param count :: Count of new column size (unused) * @throw Exception::NotImplementedError */ -void PeakColumn::resize(size_t count) { +template <class T> void PeakColumn<T>::resize(size_t count) { UNUSED_ARG(count); throw Exception::NotImplementedError("PeakColumn::resize - Peaks must be " "added through the PeaksWorkspace " @@ -249,7 +254,7 @@ void PeakColumn::resize(size_t count) { * @param index :: The new index position (unused) * @throw Exception::NotImplementedError */ -void PeakColumn::insert(size_t index) { +template <class T> void PeakColumn<T>::insert(size_t index) { UNUSED_ARG(index); throw Exception::NotImplementedError("PeakColumn::insert - Peaks must be " "inserted through the PeaksWorkspace " @@ -262,7 +267,7 @@ void PeakColumn::insert(size_t index) { * @param index :: The index position removed(unused) * @throw Exception::NotImplementedError */ -void PeakColumn::remove(size_t index) { +template <class T> void PeakColumn<T>::remove(size_t index) { UNUSED_ARG(index); throw Exception::NotImplementedError("PeakColumn::remove - Peaks must be " "remove through the PeaksWorkspace " @@ -274,7 +279,7 @@ void PeakColumn::remove(size_t index) { * @param index :: A row index pointing to the PeaksWorkspace * @returns A pointer to the data element at that index from this column */ -void *PeakColumn::void_pointer(size_t index) { +template <class T> void *PeakColumn<T>::void_pointer(size_t index) { const auto *constThis = const_cast<const PeakColumn *>(this); return const_cast<void *>(constThis->void_pointer(index)); } @@ -284,8 +289,8 @@ void *PeakColumn::void_pointer(size_t index) { * @param index :: A row index pointing to the PeaksWorkspace * @returns A pointer to the data element at that index from this column */ -const void *PeakColumn::void_pointer(size_t index) const { - const Peak &peak = m_peaks[index]; +template <class T> const void *PeakColumn<T>::void_pointer(size_t index) const { + const T &peak = m_peaks[index]; // The cell() api requires that the value exist somewhere in memory, however, // some of the values from a Peak are calculated on the fly so a reference @@ -326,23 +331,26 @@ const void *PeakColumn::void_pointer(size_t index) const { } } -PeakColumn *PeakColumn::clone() const { - auto temp = new PeakColumn(this->m_peaks, this->m_name); +template <class T> PeakColumn<T> *PeakColumn<T>::clone() const { + auto temp = new PeakColumn<T>(this->m_peaks, this->m_name); return temp; } -double PeakColumn::toDouble(size_t /*index*/) const { +template <class T> double PeakColumn<T>::toDouble(size_t /*index*/) const { throw std::runtime_error("PeakColumn::toDouble() not implemented, PeakColumn " "is has no general write access"); } -void PeakColumn::fromDouble(size_t /*index*/, double /*value*/) { +template <class T> +void PeakColumn<T>::fromDouble(size_t /*index*/, double /*value*/) { throw std::runtime_error("fromDouble() not implemented, PeakColumn is has no " "general write access"); } -void PeakColumn::setPeakHKLOrRunNumber(const size_t index, const double val) { - Peak &peak = m_peaks[index]; +template <class T> +void PeakColumn<T>::setPeakHKLOrRunNumber(const size_t index, + const double val) { + T &peak = m_peaks[index]; if (m_name == "h") peak.setH(val); else if (m_name == "k") @@ -355,5 +363,8 @@ void PeakColumn::setPeakHKLOrRunNumber(const size_t index, const double val) { throw std::runtime_error("Unexpected column " + m_name + " being set."); } +template class PeakColumn<Peak>; +template class PeakColumn<LeanElasticPeak>; + } // namespace DataObjects } // namespace Mantid diff --git a/Framework/DataObjects/src/PeaksWorkspace.cpp b/Framework/DataObjects/src/PeaksWorkspace.cpp index 52f7be186a9bd892b9d076122e6fb2e120da1b33..74094529b3713d1bd72f766b133555adc8a3fcd7 100644 --- a/Framework/DataObjects/src/PeaksWorkspace.cpp +++ b/Framework/DataObjects/src/PeaksWorkspace.cpp @@ -659,7 +659,7 @@ void PeaksWorkspace::initColumns() { void PeaksWorkspace::addPeakColumn(const std::string &name) { // Create the PeakColumn. columns.emplace_back( - std::make_shared<DataObjects::PeakColumn>(this->peaks, name)); + std::make_shared<DataObjects::PeakColumn<Peak>>(this->peaks, name)); // Cache the names columnNames.emplace_back(name); } diff --git a/Framework/DataObjects/test/LeanElasticPeakColumnTest.h b/Framework/DataObjects/test/LeanElasticPeakColumnTest.h deleted file mode 100644 index 1e1d70ed591f3e837cc93823d302a9594ab7aff5..0000000000000000000000000000000000000000 --- a/Framework/DataObjects/test/LeanElasticPeakColumnTest.h +++ /dev/null @@ -1,182 +0,0 @@ -// Mantid Repository : https://github.com/mantidproject/mantid -// -// Copyright © 2018 ISIS Rutherford Appleton Laboratory UKRI, -// NScD Oak Ridge National Laboratory, European Spallation Source, -// Institut Laue - Langevin & CSNS, Institute of High Energy Physics, CAS -// SPDX - License - Identifier: GPL - 3.0 + -#pragma once - -#include "MantidDataObjects/LeanElasticPeak.h" -#include "MantidDataObjects/LeanElasticPeakColumn.h" -#include "MantidKernel/Exception.h" -#include <cxxtest/TestSuite.h> - -#include "MantidTestHelpers/ComponentCreationHelper.h" - -#include <locale> -#include <memory> - -using namespace Mantid::DataObjects; - -// Allow testing of protected methods -class LeanElasticPeakColumnTestHelper : public LeanElasticPeakColumn { -public: - LeanElasticPeakColumnTestHelper(std::vector<LeanElasticPeak> &peaks, - const std::string &name) - : LeanElasticPeakColumn(peaks, name) {} - - using LeanElasticPeakColumn::insert; - using LeanElasticPeakColumn::remove; - using LeanElasticPeakColumn::resize; -}; - -class LeanElasticPeakColumnTest : public CxxTest::TestSuite { -public: - // This pair of boilerplate methods prevent the suite being created statically - // This means the constructor isn't called when running other tests - static LeanElasticPeakColumnTest *createSuite() { - return new LeanElasticPeakColumnTest(); - } - static void destroySuite(LeanElasticPeakColumnTest *suite) { delete suite; } - - LeanElasticPeakColumnTest() : m_peaks(2) { - m_peaks[0] = LeanElasticPeak(Mantid::Kernel::V3D(1, 1, 1), 4.0); - m_peaks[1] = LeanElasticPeak(Mantid::Kernel::V3D(1, 1, 0), 4.1); - } - - void test_constructor_create_valid_object_when_given_valid_name() { - LeanElasticPeakColumn pc(m_peaks, "h"); - TS_ASSERT_EQUALS(pc.name(), "h"); - TS_ASSERT_EQUALS(pc.size(), 2); - } - - void test_constructor_throws_given_unknown_name() { - TS_ASSERT_THROWS(LeanElasticPeakColumn(m_peaks, "NotLeanElasticPeakColumn"), - const std::runtime_error &); - } - - void test_clone() { - LeanElasticPeakColumn pc(m_peaks, "h"); - LeanElasticPeakColumn *cloned = pc.clone(); - - TS_ASSERT_EQUALS(pc.name(), cloned->name()); - TS_ASSERT_EQUALS(2, cloned->size()); - - delete cloned; - } - - void test_type_info_is_expected_type_based_on_string_type() { - LeanElasticPeakColumnTestHelper pcInt(m_peaks, "DetID"); - TS_ASSERT(pcInt.get_type_info() == typeid(int)); - TS_ASSERT(pcInt.get_pointer_type_info() == typeid(int *)); - - LeanElasticPeakColumnTestHelper pcDouble(m_peaks, "h"); - TS_ASSERT(pcDouble.get_type_info() == typeid(double)); - TS_ASSERT(pcDouble.get_pointer_type_info() == typeid(double *)); - - LeanElasticPeakColumnTestHelper pcStr(m_peaks, "BankName"); - TS_ASSERT(pcStr.get_type_info() == typeid(std::string)); - TS_ASSERT(pcStr.get_pointer_type_info() == typeid(std::string *)); - - LeanElasticPeakColumnTestHelper pcV3D(m_peaks, "QLab"); - TS_ASSERT(pcV3D.get_type_info() == typeid(Mantid::Kernel::V3D)); - TS_ASSERT(pcV3D.get_pointer_type_info() == typeid(Mantid::Kernel::V3D *)); - } - - void test_LeanElasticPeakColumn_Cannot_Be_Resized() { - LeanElasticPeakColumnTestHelper pc(m_peaks, "DetID"); - TS_ASSERT_THROWS(pc.resize(10), - const Mantid::Kernel::Exception::NotImplementedError &); - } - - void test_Row_Cannot_Be_Inserted_Into_LeanElasticPeakColumn() { - LeanElasticPeakColumnTestHelper pc(m_peaks, "DetID"); - TS_ASSERT_THROWS(pc.insert(0), - const Mantid::Kernel::Exception::NotImplementedError &); - } - - void test_Row_Cannot_Be_Removed_From_LeanElasticPeakColumn() { - LeanElasticPeakColumnTestHelper pc(m_peaks, "DetID"); - TS_ASSERT_THROWS(pc.remove(0), - const Mantid::Kernel::Exception::NotImplementedError &); - } - - void test_cell_returns_correct_value_from_LeanElasticPeakColumn() { - LeanElasticPeakColumn pc1(m_peaks, "DetID"); - int detId = pc1.cell<int>(0); - TS_ASSERT_EQUALS(-1, detId); - detId = pc1.cell<int>(1); - TS_ASSERT_EQUALS(-1, detId); - - LeanElasticPeakColumn pc2(m_peaks, "QLab"); - const Mantid::Kernel::V3D &qlab0 = pc2.cell<Mantid::Kernel::V3D>(0); - TS_ASSERT_EQUALS(qlab0, m_peaks[0].getQLabFrame()); - const Mantid::Kernel::V3D &qlab1 = pc2.cell<Mantid::Kernel::V3D>(1); - TS_ASSERT_EQUALS(qlab1, m_peaks[1].getQLabFrame()); - } - - void test_get_read_only_returns_correct_value() { - LeanElasticPeakColumn pc1(m_peaks, "h"); - auto readOnly = pc1.getReadOnly(); - TS_ASSERT(!readOnly); - - LeanElasticPeakColumn pc2(m_peaks, "DetID"); - readOnly = pc2.getReadOnly(); - TS_ASSERT(readOnly); - } - - void test_read_locale_awerness() { - const std::vector<std::string> columnNames{"h", "k", "l", "RunNumber"}; - const std::vector<double> columnValues{-2.0, 5.0, 12.0, 143290.0}; - TestingNumpunctFacet numpunct; - const std::locale testLocale(std::locale::classic(), &numpunct); - for (size_t i = 0; i < columnNames.size(); ++i) { - LeanElasticPeakColumn pc(m_peaks, columnNames[i]); - // Use a fake punctuation facet for numeric formatting. - std::ostringstream out; - out.imbue(testLocale); - // Force some decimals to the numbers. - out << std::fixed; - out << std::setprecision(2); - out << columnValues[i]; - std::istringstream in(out.str()); - in.imbue(testLocale); - pc.read(0, in); - switch (i) { - case 0: - TS_ASSERT_EQUALS(m_peaks[0].getH(), columnValues[i]) - break; - case 1: - TS_ASSERT_EQUALS(m_peaks[0].getK(), columnValues[i]) - break; - case 2: - TS_ASSERT_EQUALS(m_peaks[0].getL(), columnValues[i]) - break; - case 3: - TS_ASSERT_EQUALS(m_peaks[0].getRunNumber(), columnValues[i]) - break; - } - } - } - - void test_cannot_be_converted_to_double() { - LeanElasticPeakColumn col(m_peaks, "DetID"); - TS_ASSERT(!col.isNumber()); - } - -private: - /// A locale facet mocking non-english numerical punctuation. - class TestingNumpunctFacet : public std::numpunct<char> { - public: - /// Informs locales not to delete this facet. - TestingNumpunctFacet() : std::numpunct<char>(1) {} - - private: - char_type do_decimal_point() const override { return '%'; } - char_type do_thousands_sep() const override { return '@'; } - string_type do_grouping() const override { return "\03"; } - }; - - Mantid::Geometry::Instrument_sptr m_inst; - std::vector<LeanElasticPeak> m_peaks; -}; diff --git a/Framework/DataObjects/test/PeakColumnTest.h b/Framework/DataObjects/test/PeakColumnTest.h index 3a240bdbe1e91fc68c68881cb53ca471869d000b..6540dcac693b4d3a0eafed44dc2785702ef5f09f 100644 --- a/Framework/DataObjects/test/PeakColumnTest.h +++ b/Framework/DataObjects/test/PeakColumnTest.h @@ -19,10 +19,10 @@ using namespace Mantid::DataObjects; // Allow testing of protected methods -class PeakColumnTestHelper : public PeakColumn { +class PeakColumnTestHelper : public PeakColumn<Peak> { public: PeakColumnTestHelper(std::vector<Peak> &peaks, const std::string &name) - : PeakColumn(peaks, name) {} + : PeakColumn<Peak>(peaks, name) {} using PeakColumn::insert; using PeakColumn::remove; @@ -43,19 +43,19 @@ public: } void test_constructor_create_valid_object_when_given_valid_name() { - PeakColumn pc(m_peaks, "h"); + PeakColumn<Peak> pc(m_peaks, "h"); TS_ASSERT_EQUALS(pc.name(), "h"); TS_ASSERT_EQUALS(pc.size(), 2); } void test_constructor_throws_given_unknown_name() { - TS_ASSERT_THROWS(PeakColumn(m_peaks, "NotPeakColumn"), + TS_ASSERT_THROWS(PeakColumn<Peak>(m_peaks, "NotPeakColumn"), const std::runtime_error &); } void test_clone() { - PeakColumn pc(m_peaks, "h"); - PeakColumn *cloned = pc.clone(); + PeakColumn<Peak> pc(m_peaks, "h"); + PeakColumn<Peak> *cloned = pc.clone(); TS_ASSERT_EQUALS(pc.name(), cloned->name()); TS_ASSERT_EQUALS(2, cloned->size()); @@ -100,13 +100,13 @@ public: } void test_cell_returns_correct_value_from_PeakColumn() { - PeakColumn pc1(m_peaks, "DetID"); + PeakColumn<Peak> pc1(m_peaks, "DetID"); int detId = pc1.cell<int>(0); TS_ASSERT_EQUALS(1, detId); detId = pc1.cell<int>(1); TS_ASSERT_EQUALS(2, detId); - PeakColumn pc2(m_peaks, "QLab"); + PeakColumn<Peak> pc2(m_peaks, "QLab"); const Mantid::Kernel::V3D &qlab0 = pc2.cell<Mantid::Kernel::V3D>(0); TS_ASSERT_EQUALS(qlab0, m_peaks[0].getQLabFrame()); const Mantid::Kernel::V3D &qlab1 = pc2.cell<Mantid::Kernel::V3D>(1); @@ -114,11 +114,11 @@ public: } void test_get_read_only_returns_correct_value() { - PeakColumn pc1(m_peaks, "h"); + PeakColumn<Peak> pc1(m_peaks, "h"); auto readOnly = pc1.getReadOnly(); TS_ASSERT(!readOnly); - PeakColumn pc2(m_peaks, "DetID"); + PeakColumn<Peak> pc2(m_peaks, "DetID"); readOnly = pc2.getReadOnly(); TS_ASSERT(readOnly); } @@ -129,7 +129,7 @@ public: TestingNumpunctFacet numpunct; const std::locale testLocale(std::locale::classic(), &numpunct); for (size_t i = 0; i < columnNames.size(); ++i) { - PeakColumn pc(m_peaks, columnNames[i]); + PeakColumn<Peak> pc(m_peaks, columnNames[i]); // Use a fake punctuation facet for numeric formatting. std::ostringstream out; out.imbue(testLocale); @@ -158,7 +158,7 @@ public: } void test_cannot_be_converted_to_double() { - PeakColumn col(m_peaks, "DetID"); + PeakColumn<Peak> col(m_peaks, "DetID"); TS_ASSERT(!col.isNumber()); }