From 9193f15f2121a3abc96702c989fcfb91bd92df07 Mon Sep 17 00:00:00 2001 From: rboston628 Date: Wed, 2 Oct 2024 14:20:32 -0400 Subject: [PATCH 01/18] enumerated string property prototype --- Framework/Algorithms/src/Rebin.cpp | 4 +- .../MantidKernel/EnumeratedStringProperty.h | 108 +++++ .../MantidKernel/EnumeratedStringProperty.hxx | 382 ++++++++++++++++++ 3 files changed, 492 insertions(+), 2 deletions(-) create mode 100644 Framework/Kernel/inc/MantidKernel/EnumeratedStringProperty.h create mode 100644 Framework/Kernel/inc/MantidKernel/EnumeratedStringProperty.hxx diff --git a/Framework/Algorithms/src/Rebin.cpp b/Framework/Algorithms/src/Rebin.cpp index 3cc0851f71b9..17c0e8fda744 100644 --- a/Framework/Algorithms/src/Rebin.cpp +++ b/Framework/Algorithms/src/Rebin.cpp @@ -17,6 +17,7 @@ #include "MantidKernel/ArrayProperty.h" #include "MantidKernel/BoundedValidator.h" #include "MantidKernel/EnumeratedString.h" +#include "MantidKernel/EnumeratedStringProperty.h" #include "MantidKernel/ListValidator.h" #include "MantidKernel/RebinParamsValidator.h" #include "MantidKernel/VectorHelper.h" @@ -263,8 +264,7 @@ void Rebin::init() { "is linear. Power must be between 0 and 1."); declareProperty( - PropertyNames::BINMODE, binningModeNames[size_t(BinningMode::DEFAULT)], - std::make_shared(binningModeNames), + std::make_unique>(PropertyNames::BINMODE), "Optional. " "Binning behavior can be specified in the usual way through sign of binwidth and other properties ('Default'); " "or can be set to one of the allowed binning modes. " diff --git a/Framework/Kernel/inc/MantidKernel/EnumeratedStringProperty.h b/Framework/Kernel/inc/MantidKernel/EnumeratedStringProperty.h new file mode 100644 index 000000000000..8d4cf608101d --- /dev/null +++ b/Framework/Kernel/inc/MantidKernel/EnumeratedStringProperty.h @@ -0,0 +1,108 @@ +// Mantid Repository : https://github.com/mantidproject/mantid +// +// Copyright © 2007 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 "MantidKernel/EnumeratedString.h" +#include "MantidKernel/Exception.h" +#include "MantidKernel/Logger.h" +#include "MantidKernel/NullValidator.h" +#include "MantidKernel/Property.h" + +#include + +namespace NeXus { +class File; +} + +namespace Mantid { + +namespace Kernel { +/** A concrete property based on user options of a finite list of strings. + * Allows for easy comparison by binding the string list to an enum. + + @class Mantid::Kernel::EnumeratedStringProperty + + @author Reece Boston, ORNL + @date October 1, in this the two-thousand-and-twenty-fourth year of our Lord +*/ +template const *const names> class EnumeratedStringProperty : public Property { + + using ENUMSTRING = EnumeratedString; + +public: + // CONSTRUCTORS + EnumeratedStringProperty(std::string const &name, ENUMSTRING const &defaultValue = static_cast(0), + Direction::Type const direction = Direction::Input); + EnumeratedStringProperty(EnumeratedStringProperty const &right); + EnumeratedStringProperty *clone() const override; + EnumeratedStringProperty &operator=(EnumeratedStringProperty const &right); + + // GETTERS + std::string value() const override; + std::string valueAsPrettyStr(size_t const maxLength = 0, bool const collapseLists = true) const override; + Json::Value valueAsJson() const override; + + bool operator==(EnumeratedStringProperty const &rhs) const; + bool operator!=(EnumeratedStringProperty const &rhs) const; + int size() const override; + std::string getDefault() const override; + + /** Allows you to get the value of the property simply by typing its name. + * Means you can use an expression like: int i = myProperty; + * @return the value + */ + operator ENUMSTRING() const { return this->m_value; }; + operator E() const { return static_cast(m_value); }; + operator std::string() const { return static_cast(m_value); }; + + ENUMSTRING operator()() const; + std::string isValid() const override; + bool isDefault() const override; + std::vector allowedValues() const override; + bool isMultipleSelectionAllowed() override; + + // SETTERS + std::string setValue(E const value); + std::string setValue(std::string const &value) override; + std::string setValue(ENUMSTRING const &value); + std::string setValueFromJson(const Json::Value &value) override; + std::string setDataItem(const std::shared_ptr &data) override; + EnumeratedStringProperty const &operator=(E const value); + EnumeratedStringProperty const &operator=(std::string const &right); + EnumeratedStringProperty const &operator=(ENUMSTRING const &right); + + // MUTATORS AND SUNDRY + EnumeratedStringProperty &operator+=(Property const *right) override; + void saveProperty(::NeXus::File *file) override; + +protected: + /// The value of the property + ENUMSTRING m_value; + /// the property's default value which is also its initial value + // const TYPE m_initialValue; + ENUMSTRING m_initialValue; + +private: + std::string setValueFromProperty(Property const &right) override; + + template std::string setTypedValue(U const &value, std::true_type const &); + + template std::string setTypedValue(U const &value, std::false_type const &); + + /// Static reference to the logger class + static Logger g_logger; + + /// Private default constructor + EnumeratedStringProperty() = default; +}; + +// template Logger PropertyWithValue::g_logger("PropertyWithValue"); + +} // namespace Kernel +} // namespace Mantid + +#include "EnumeratedStringProperty.hxx" \ No newline at end of file diff --git a/Framework/Kernel/inc/MantidKernel/EnumeratedStringProperty.hxx b/Framework/Kernel/inc/MantidKernel/EnumeratedStringProperty.hxx new file mode 100644 index 000000000000..e9f7f7b3b6f5 --- /dev/null +++ b/Framework/Kernel/inc/MantidKernel/EnumeratedStringProperty.hxx @@ -0,0 +1,382 @@ +// 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 "MantidKernel/EnumeratedStringProperty.h" + +#include "MantidKernel/Exception.h" +#include "MantidKernel/Logger.h" +#include "MantidKernel/NullValidator.h" +#include "MantidKernel/OptionalBool.h" +#include "MantidKernel/PropertyHelper.h" +#include "MantidKernel/PropertyWithValueJSON.h" +#include "MantidKernel/Strings.h" + +#ifndef Q_MOC_RUN +#include +#include +#endif + +#include +#include + +#include "MantidKernel/IPropertySettings.h" +#include "MantidKernel/StringTokenizer.h" +#include +#include + +namespace Mantid::Kernel { + +//------------------------------------------------------------------------------------------------ +// Now the PropertyWithValue class itself +//------------------------------------------------------------------------------------------------ + +//######################################################// +// CONSTRUCTORS +//######################################################// + +/** Constructor + * @param name :: The name to assign to the property + * @param defaultValue :: Is stored initial default value of the property + * @param direction :: Whether this is a Direction::Input, Direction::Output + * or Direction::InOut (Input & Output) property + */ +template const *const names> +EnumeratedStringProperty::EnumeratedStringProperty(std::string const &name, ENUMSTRING const &defaultValue, + Direction::Type const direction) + : Property(std::move(name), typeid(ENUMSTRING), direction), m_value(defaultValue), + m_initialValue(std::move(defaultValue)) {} + +/**Copy constructor + * Note the default value of the copied object is the initial value of original + */ +template const *const names> +EnumeratedStringProperty::EnumeratedStringProperty(EnumeratedStringProperty const &right) + : Property(right), m_value(right.m_value), m_initialValue(right.m_initialValue) { +} // the default is the initial value of the original object + +/// 'Virtual copy constructor' +template const *const names> +EnumeratedStringProperty *EnumeratedStringProperty::clone() const { + return new EnumeratedStringProperty(*this); +} + +/// Copy assignment operator assigns only the value and the validator not the +/// name, default (initial) value, etc. +template const *const names> +EnumeratedStringProperty & +EnumeratedStringProperty::operator=(EnumeratedStringProperty const &right) { + if (&right == this) + return *this; + this->m_value = right.m_value; + return *this; +} + +//######################################################// +// GETTERS +//######################################################// + +/** Get the value of the property as a string + * @return The property's value as a string + */ +template const *const names> +std::string EnumeratedStringProperty::value() const { + return static_cast(m_value); +} + +/** Get the value of the property as a more prettier string + * @return The property's value as a more prettier string + */ +template const *const names> +std::string EnumeratedStringProperty::valueAsPrettyStr(std::size_t const maxLength, + bool const collapseLists) const { + return toPrettyString(static_cast(m_value), maxLength, collapseLists); +} + +/** + * Attempt to construct a Json::Value object from the plain value + * @return A new Json::Value object + */ +template const *const names> +Json::Value EnumeratedStringProperty::valueAsJson() const { + return encodeAsJson((*this)()); +} + +/** + * Deep comparison. + * @param rhs The other property to compare to. + * @return true if the are equal. + */ +template const *const names> +bool EnumeratedStringProperty::operator==(EnumeratedStringProperty const &rhs) const { + if (this->name() != rhs.name()) + return false; + return (static_cast(this->m_value) == static_cast(rhs.m_value)); +} + +/** + * Deep comparison (not equal). + * @param rhs The other property to compare to. + * @return true if they are not equal. + */ +template const *const names> +bool EnumeratedStringProperty::operator!=(EnumeratedStringProperty const &rhs) const { + return !(*this == rhs); +} + +/** Get the size of the property. + */ +template const *const names> int EnumeratedStringProperty::size() const { + return 1; +} + +/** Get the value the property was initialised with -its default value + * @return The default value + */ +template const *const names> +std::string EnumeratedStringProperty::getDefault() const { + return static_cast(m_initialValue); +} + +/** Allows you to get the value of the property simply by typing its name. + * Means you can use an expression like: int i = myProperty(); + * @return the value + */ +template const *const names> +EnumeratedString EnumeratedStringProperty::operator()() const { + return m_value; +} + +/** If the value has been set, then it is valid. + * @returns "" if the value is valid or a discription of the problem + */ +template const *const names> +std::string EnumeratedStringProperty::isValid() const { + if (m_value.size() != 0) + return ""; + else + return "EnumeratedStringProperty was not set with valid EnumeratedString.\n"; +} + +/** Indicates if the property's value is the same as it was when it was set + * N.B. Uses an unsafe comparison in the case of doubles, consider overriding + * if the value is a pointer or floating point type + * @return true if the value is the same as the initial value or false + * otherwise + */ +template const *const names> +bool EnumeratedStringProperty::isDefault() const { + return m_initialValue == m_value; +} + +/** Returns the set of valid values for this property, if such a set exists. + * If not, it returns an empty vector. + * @return Returns the set of valid values for this property, or it returns + * an empty vector. + */ +template const *const names> +std::vector EnumeratedStringProperty::allowedValues() const { + return *names; +} + +/** Returns true, as multiple selection is allowed. + * @return true + */ +template const *const names> +bool EnumeratedStringProperty::isMultipleSelectionAllowed() { + return true; +} + +//######################################################// +// SETTERS +//######################################################// + +/** Set the value of the property from a string representation. + * @param value :: The value to assign to the property + * @return Returns "" if the assignment was successful or a user level + * description of the problem + */ +template const *const names> +std::string EnumeratedStringProperty::setValue(E const value) { + this->m_value = static_cast>(value); + return ""; +} + +/** Set the value of the property from a string representation. + * @param value :: The value to assign to the property + * @return Returns "" if the assignment was successful or a user level + * description of the problem + */ +template const *const names> +std::string EnumeratedStringProperty::setValue(std::string const &value) { + this->m_value = static_cast>(value); + return ""; +} + +/** Set the value of the property from a string representation. + * @param value :: The value to assign to the property + * @return Returns "" if the assignment was successful or a user level + * description of the problem + */ +template const *const names> +std::string EnumeratedStringProperty::setValue(EnumeratedString const &value) { + this->m_value = value; + return ""; +} + +/** + * Set the value of the property from a Json representation. + * @param value :: The value to assign to the property + * @return Returns "" if the assignment was successful or a user level + * description of the problem + */ +template const *const names> +std::string EnumeratedStringProperty::setValueFromJson(Json::Value const &value) { + if (value.type() != Json::stringValue) { + try { + *this = decode(value); + } catch (std::invalid_argument &exc) { + return exc.what(); + } + return ""; + } else { + return setValue(value.asString()); + } +} + +/** + * Set a property value via a DataItem + * @param data :: A shared pointer to a data item + * @return "" if the assignment was successful or a user level description of + * the problem + */ +template const *const names> +std::string EnumeratedStringProperty::setDataItem(std::shared_ptr const &data) { + // Pass of the helper function that is able to distinguish whether + // the TYPE of the PropertyWithValue can be converted to a + // shared_ptr + return setTypedValue(data, std::is_convertible, std::shared_ptr>()); +} + +//-------------------------------------------------------------------------------------- +/** Assignment operator. + * Allows assignment of a new value to the property by writing, + * e.g., myProperty = 3; + * @param value :: The new value to assign to the property + * @return the reference to itself + */ +template const *const names> +EnumeratedStringProperty const &EnumeratedStringProperty::operator=(E const value) { + this->m_value = static_cast>(value); + return *this; +} + +//-------------------------------------------------------------------------------------- +/** Assignment operator. + * Allows assignment of a new value to the property by writing, + * e.g., myProperty = 3; + * @param value :: The new value to assign to the property + * @return the reference to itself + */ +template const *const names> +EnumeratedStringProperty const &EnumeratedStringProperty::operator=(std::string const &value) { + this->m_value = static_cast>(value); + return *this; +} + +//-------------------------------------------------------------------------------------- +/** Assignment operator. + * Allows assignment of a new value to the property by writing, + * e.g., myProperty = 3; + * @param value :: The new value to assign to the property + * @return the reference to itself + */ +template const *const names> +EnumeratedStringProperty const & +EnumeratedStringProperty::operator=(EnumeratedString const &value) { + this->m_value = value; + return *this; +} + +//######################################################// +// MUTATORS AND SUNDRY +//######################################################// + +//-------------------------------------------------------------------------------------- +/** Add the value of another property + * @param right the property to add + * @return the sum + */ +template const *const names> +EnumeratedStringProperty &EnumeratedStringProperty::operator+=(Property const *right) { + throw std::invalid_argument("Cannot add EnumeratedStringProperty, addition not implemented.\n"); +} + +template const *const names> +void EnumeratedStringProperty::saveProperty(::NeXus::File * /*file*/) { + // AppleClang 7.3 and later gives a -Winfinite-recursion warning if I call the + // base class method. The function is small enough that reimplementing it + // isn't a big deal. + throw std::invalid_argument("PropertyWithValue::saveProperty - Cannot save '" + this->name() + "', property type " + + typeid(ENUMSTRING).name() + " not implemented."); +} + +//######################################################// +// PRIVATE METHODS +//######################################################// + +/** + * Set the value of the property via a reference to another property. + * If the value is unacceptable the value is not changed but a string is + * returned. + * The value is only accepted if the other property has the same type as this + * @param right :: A reference to a property. + */ +template const *const names> +std::string EnumeratedStringProperty::setValueFromProperty(Property const &right) { + + if (auto prop = dynamic_cast const *>(&right)) { + this->m_value = prop->m_value; + return ""; + } else { + return setValue(right.value()); + } +} + +/** + * Helper function for setValue(DataItem_sptr). Uses boost type traits to + * ensure + * it is only used if U is a type that is convertible to + * std::shared_ptr + * @param value :: A object of type convertible to std::shared_ptr + */ +template const *const names> +template +std::string EnumeratedStringProperty::setTypedValue(U const &value, std::true_type const &) { + std::string msg; + try { + m_value = EnumeratedString(value); + } catch (std::runtime_error &exc) { + msg = exc.what(); + } + return msg; +} + +/** + * Helper function for setValue(DataItem_sptr). Uses boost type traits to + * ensure + * it is only used if U is NOT a type that is convertible to + * std::shared_ptr + * @param value :: A object of type convertible to std::shared_ptr + */ +template const *const names> +template +std::string EnumeratedStringProperty::setTypedValue(U const &, std::false_type const &) { + return "Attempt to assign object of type DataItem to property (" + name() + ") of incorrect type"; +} + +} // namespace Mantid::Kernel From 2ccd87e6b57a6d2ba1115647270a19728d551bc0 Mon Sep 17 00:00:00 2001 From: Dmitry Ganyushin Date: Thu, 3 Oct 2024 13:54:19 -0400 Subject: [PATCH 02/18] Added a test Refactoring --- Framework/Kernel/CMakeLists.txt | 1 + .../MantidKernel/EnumeratedStringProperty.h | 2 - .../MantidKernel/EnumeratedStringProperty.hxx | 21 +++---- .../test/EnumeratedStringPropertyTest.h | 62 +++++++++++++++++++ 4 files changed, 71 insertions(+), 15 deletions(-) create mode 100644 Framework/Kernel/test/EnumeratedStringPropertyTest.h diff --git a/Framework/Kernel/CMakeLists.txt b/Framework/Kernel/CMakeLists.txt index 0c24e1cdb35d..42303dab0873 100644 --- a/Framework/Kernel/CMakeLists.txt +++ b/Framework/Kernel/CMakeLists.txt @@ -340,6 +340,7 @@ set(TEST_FILES DynamicPointerCastHelperTest.h EigenConversionHelpersTest.h EnabledWhenPropertyTest.h + EnumeratedStringPropertyTest.h EnumeratedStringTest.h EnvironmentHistoryTest.h EqualBinsCheckerTest.h diff --git a/Framework/Kernel/inc/MantidKernel/EnumeratedStringProperty.h b/Framework/Kernel/inc/MantidKernel/EnumeratedStringProperty.h index 8d4cf608101d..b1db5845c4ca 100644 --- a/Framework/Kernel/inc/MantidKernel/EnumeratedStringProperty.h +++ b/Framework/Kernel/inc/MantidKernel/EnumeratedStringProperty.h @@ -5,13 +5,11 @@ // Institut Laue - Langevin & CSNS, Institute of High Energy Physics, CAS // SPDX - License - Identifier: GPL - 3.0 + #pragma once - #include "MantidKernel/EnumeratedString.h" #include "MantidKernel/Exception.h" #include "MantidKernel/Logger.h" #include "MantidKernel/NullValidator.h" #include "MantidKernel/Property.h" - #include namespace NeXus { diff --git a/Framework/Kernel/inc/MantidKernel/EnumeratedStringProperty.hxx b/Framework/Kernel/inc/MantidKernel/EnumeratedStringProperty.hxx index e9f7f7b3b6f5..40f74657d581 100644 --- a/Framework/Kernel/inc/MantidKernel/EnumeratedStringProperty.hxx +++ b/Framework/Kernel/inc/MantidKernel/EnumeratedStringProperty.hxx @@ -6,28 +6,23 @@ // SPDX - License - Identifier: GPL - 3.0 + #pragma once +#include +#include +#ifndef Q_MOC_RUN +#include +#include +#endif #include "MantidKernel/EnumeratedStringProperty.h" - #include "MantidKernel/Exception.h" +#include "MantidKernel/IPropertySettings.h" #include "MantidKernel/Logger.h" #include "MantidKernel/NullValidator.h" #include "MantidKernel/OptionalBool.h" #include "MantidKernel/PropertyHelper.h" #include "MantidKernel/PropertyWithValueJSON.h" +#include "MantidKernel/StringTokenizer.h" #include "MantidKernel/Strings.h" - -#ifndef Q_MOC_RUN -#include -#include -#endif - #include -#include - -#include "MantidKernel/IPropertySettings.h" -#include "MantidKernel/StringTokenizer.h" -#include -#include namespace Mantid::Kernel { diff --git a/Framework/Kernel/test/EnumeratedStringPropertyTest.h b/Framework/Kernel/test/EnumeratedStringPropertyTest.h new file mode 100644 index 000000000000..13e0cd697977 --- /dev/null +++ b/Framework/Kernel/test/EnumeratedStringPropertyTest.h @@ -0,0 +1,62 @@ +// Mantid Repository : https://github.com/mantidproject/mantid +// +// Copyright © 2024 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/Algorithm.h" +#include "MantidKernel/EnumeratedString.h" +#include "MantidKernel/EnumeratedStringProperty.h" +#include + +using namespace Mantid::Kernel; +using namespace Mantid::API; + +namespace { +/// static Logger definition +Logger g_log("EnumeratedStringPropertyTest"); +} // namespace +// namespace { +enum class CoolGuys : char { Fred, Joe, Bill, enum_count }; +const std::vector coolGuyNames{"Frederic", "Joseph", "William"}; + +// typedef EnumeratedStringProperty COOLGUY_PROPERTY; +// typedef EnumeratedStringProperty CAKE_PROPERTY; +//} // namespace + +// 'Empty' algorithm class for tests +class testalg : public Algorithm { +public: + testalg() : Algorithm() {} + ~testalg() override = default; + const std::string name() const override { return "testalg"; } ///< Algorithm's name for identification + int version() const override { return 1; } ///< Algorithm's version for identification + const std::string category() const override { return "Cat"; } ///< Algorithm's category for identification + const std::string summary() const override { return "Test summary"; } + + void init() override { + declareProperty(std::make_unique>("testname"), "Test property"); + } + void exec() override {} +}; + +class EnumeratedStringPropertyTest : 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 EnumeratedStringPropertyTest *createSuite() { return new EnumeratedStringPropertyTest(); } + static void destroySuite(EnumeratedStringPropertyTest *suite) { delete suite; } + + void testConstructor() { + g_log.notice("\ntestConstructor..."); + testalg alg; + alg.initialize(); + alg.execute(); + TS_ASSERT_EQUALS(alg.existsProperty("testname"), true) + TS_ASSERT_EQUALS(alg.getPropertyValue("testname"), "Frederic"); + TS_ASSERT_EQUALS(alg.getPropertyValue("testname"), coolGuyNames[0]); + alg.setPropertyValue("testname", "Joseph"); + TS_ASSERT_EQUALS(alg.getPropertyValue("testname"), "Joseph"); + } +}; From faabfbe6e13f210ef50136f10e06fdeb97a6a66b Mon Sep 17 00:00:00 2001 From: Dmitry Ganyushin Date: Wed, 9 Oct 2024 11:56:23 -0400 Subject: [PATCH 03/18] using EnumeratedStringProperty in AddSampleLog.cpp using EnumeratedStringProperty in CalculateDIFC.cpp --- Framework/Algorithms/src/AddSampleLog.cpp | 56 +++++++++++----------- Framework/Algorithms/src/CalculateDIFC.cpp | 23 +++++---- 2 files changed, 40 insertions(+), 39 deletions(-) diff --git a/Framework/Algorithms/src/AddSampleLog.cpp b/Framework/Algorithms/src/AddSampleLog.cpp index be1247b9dc65..41de45b9a29b 100644 --- a/Framework/Algorithms/src/AddSampleLog.cpp +++ b/Framework/Algorithms/src/AddSampleLog.cpp @@ -11,6 +11,8 @@ #include "MantidAPI/Run.h" #include "MantidAPI/Workspace.h" #include "MantidGeometry/Instrument.h" +#include "MantidKernel/EnumeratedString.h" +#include "MantidKernel/EnumeratedStringProperty.h" #include "MantidKernel/Exception.h" #include "MantidKernel/ListValidator.h" #include "MantidKernel/MandatoryValidator.h" @@ -22,13 +24,18 @@ namespace { -static const std::string intTypeOption = "Int"; -static const std::string doubleTypeOption = "Double"; -static const std::string autoTypeOption = "AutoDetect"; - -static const std::string stringLogOption = "String"; -static const std::string numberLogOption = "Number"; -static const std::string numberSeriesLogOption = "Number Series"; +// static const std::string intTypeOption = "Int"; +// static const std::string doubleTypeOption = "Double"; +// static const std::string autoTypeOption = "AutoDetect"; +const std::string NumberType("NumberType"); +const std::vector typeOptions{"Int", "Double", "AutoDetect"}; +enum class TypeMode { INT, DOUBLE, AUTO_DETECT, enum_count }; +typedef Mantid::Kernel::EnumeratedString TYPEMODE; + +const std::string LogType("LogType"); +const std::vector propOptions{"String", "Number", "Number Series"}; +enum class LogMode { STRING_LOG, NUMBER_LOG, NUMBER_SERIES_LOG, enum_count }; +typedef Mantid::Kernel::EnumeratedString LOGMODE; } // namespace namespace Mantid::Algorithms { @@ -48,21 +55,14 @@ void AddSampleLog::init() { declareProperty("LogText", "", "The content of the log"); - std::vector propOptions; - propOptions.emplace_back(stringLogOption); - propOptions.emplace_back(numberLogOption); - propOptions.emplace_back(numberSeriesLogOption); - declareProperty("LogType", stringLogOption, std::make_shared(propOptions), + declareProperty(std::make_unique>(LogType), "The type that the log data will be."); declareProperty("LogUnit", "", "The units of the log"); - std::vector typeOptions; - typeOptions.emplace_back(intTypeOption); - typeOptions.emplace_back(doubleTypeOption); - typeOptions.emplace_back(autoTypeOption); - declareProperty("NumberType", autoTypeOption, std::make_shared(typeOptions), + declareProperty(std::make_unique>(NumberType), "Force LogText to be interpreted as a number of type 'int' " "or 'double'."); + setPropertyValue(NumberType, typeOptions[2]); // add optional workspace which contains the data of the TimeSeriesProperty declareProperty(std::make_unique>("TimeSeriesWorkspace", "", Direction::Input, @@ -112,11 +112,11 @@ void AddSampleLog::exec() { std::string propName = getProperty("LogName"); std::string propValue = getProperty("LogText"); std::string propUnit = getProperty("LogUnit"); - std::string propType = getPropertyValue("LogType"); - std::string propNumberType = getPropertyValue("NumberType"); + LOGMODE propType = getPropertyValue(LogType); + TYPEMODE propNumberType = getPropertyValue("NumberType"); // check inputs - if ((propNumberType != autoTypeOption) && ((propType != numberLogOption) && (propType != numberSeriesLogOption))) { + if ((propNumberType != TypeMode::AUTO_DETECT) && (propType == LogMode::STRING_LOG)) { throw std::invalid_argument("You may only use NumberType 'Int' or 'Double' options if " "LogType is 'Number' or 'Number Series'"); } @@ -127,10 +127,10 @@ void AddSampleLog::exec() { } // add sample log! - if (propType == stringLogOption) { + if (propType == LogMode::STRING_LOG) { // add string log value and return addStringLog(theRun, propName, propValue, propUnit); - } else if (propType == numberSeriesLogOption) { + } else if (propType == LogMode::NUMBER_SERIES_LOG) { // add a TimeSeriesProperty // TODO: Need to re-define the behavior on the default propNumberType for // Series. @@ -161,8 +161,9 @@ void AddSampleLog::addSingleValueProperty(Run &theRun, const std::string &propNa const std::string &propUnit, const std::string &propNumberType) { // add a single value property, integer or double bool value_is_int(false); - if (propNumberType != autoTypeOption) { - value_is_int = (propNumberType == intTypeOption); + TYPEMODE propType = propNumberType; + if (propType != TypeMode::AUTO_DETECT) { + value_is_int = (propType == TypeMode::INT); } else { int intVal; if (Strings::convert(propValue, intVal)) { @@ -225,10 +226,11 @@ void AddSampleLog::addTimeSeriesProperty(Run &run_obj, const std::string &prop_n const std::string &prop_unit, const std::string &prop_number_type) { // set up the number type right bool is_int_series(false); - if (prop_number_type == intTypeOption) { + TYPEMODE propType = prop_number_type; + if (propType == TypeMode::INT) { // integer type is_int_series = true; - } else if (prop_number_type == autoTypeOption) { + } else if (propType == TypeMode::AUTO_DETECT) { // auto type. by default if (prop_value.empty()) g_log.warning("For sample log in TimeSeriesProperty and values are given " @@ -241,7 +243,7 @@ void AddSampleLog::addTimeSeriesProperty(Run &run_obj, const std::string &prop_n is_int_series = true; } } - } else if (prop_number_type != doubleTypeOption) { + } else if (propType != TypeMode::DOUBLE) { // unsupported type: anything but double, integer or auto g_log.error() << "TimeSeriesProperty with data type " << prop_number_type << " is not supported.\n"; throw std::runtime_error("Unsupported TimeSeriesProperty type."); diff --git a/Framework/Algorithms/src/CalculateDIFC.cpp b/Framework/Algorithms/src/CalculateDIFC.cpp index f2648fed0297..285492baa99a 100644 --- a/Framework/Algorithms/src/CalculateDIFC.cpp +++ b/Framework/Algorithms/src/CalculateDIFC.cpp @@ -9,10 +9,18 @@ #include "MantidDataObjects/SpecialWorkspace2D.h" #include "MantidGeometry/IDetector.h" #include "MantidKernel/EnumeratedString.h" +#include "MantidKernel/EnumeratedStringProperty.h" #include "MantidKernel/ListValidator.h" namespace Mantid { - +namespace PropertyNames { +const std::string INPUT_WKSP("InputWorkspace"); +const std::string OUTPUT_WKSP("OutputWorkspace"); +const std::string CALIB_WKSP("CalibrationWorkspace"); +const std::string OFFSTS_WKSP("OffsetsWorkspace"); +const std::string OFFSET_MODE("OffsetMode"); +const std::string BINWIDTH("BinWidth"); +} // namespace PropertyNames namespace { enum class OffsetMode { RELATIVE_OFFSET, ABSOLUTE_OFFSET, SIGNED_OFFSET, enum_count }; @@ -58,15 +66,6 @@ void calculateFromOffset(API::Progress &progress, DataObjects::SpecialWorkspace2 } } -namespace PropertyNames { -const std::string INPUT_WKSP("InputWorkspace"); -const std::string OUTPUT_WKSP("OutputWorkspace"); -const std::string CALIB_WKSP("CalibrationWorkspace"); -const std::string OFFSTS_WKSP("OffsetsWorkspace"); -const std::string OFFSET_MODE("OffsetMode"); -const std::string BINWIDTH("BinWidth"); -} // namespace PropertyNames - // look through the columns of detid and difc and copy them into the // SpecialWorkspace2D void calculateFromTable(API::Progress &progress, DataObjects::SpecialWorkspace2D &outputWs, @@ -125,8 +124,8 @@ void CalculateDIFC::init() { "which will be copied. This property cannot be set in " "conjunction with property OffsetsWorkspace."); - declareProperty(PropertyNames::OFFSET_MODE, offsetModeNames[size_t(OffsetMode::RELATIVE_OFFSET)], - std::make_shared(offsetModeNames), + declareProperty(std::make_unique>( + PropertyNames::OFFSET_MODE), "Optional: Whether to calculate a relative, absolute, or signed offset. Default relative"); declareProperty(PropertyNames::BINWIDTH, EMPTY_DBL(), From c952904c367dc1e982ddab44b68b10b8acdfe323 Mon Sep 17 00:00:00 2001 From: Dmitry Ganyushin Date: Wed, 9 Oct 2024 11:56:23 -0400 Subject: [PATCH 04/18] using EnumeratedStringProperty in AddSampleLog.cpp, CalculateDIFC.cpp, PDCalibration.cpp --- Framework/Algorithms/src/AddSampleLog.cpp | 51 +++++++++++----------- Framework/Algorithms/src/CalculateDIFC.cpp | 23 +++++----- Framework/Algorithms/src/PDCalibration.cpp | 23 +++++++--- 3 files changed, 54 insertions(+), 43 deletions(-) diff --git a/Framework/Algorithms/src/AddSampleLog.cpp b/Framework/Algorithms/src/AddSampleLog.cpp index be1247b9dc65..b81b3525a9f9 100644 --- a/Framework/Algorithms/src/AddSampleLog.cpp +++ b/Framework/Algorithms/src/AddSampleLog.cpp @@ -11,6 +11,8 @@ #include "MantidAPI/Run.h" #include "MantidAPI/Workspace.h" #include "MantidGeometry/Instrument.h" +#include "MantidKernel/EnumeratedString.h" +#include "MantidKernel/EnumeratedStringProperty.h" #include "MantidKernel/Exception.h" #include "MantidKernel/ListValidator.h" #include "MantidKernel/MandatoryValidator.h" @@ -22,13 +24,15 @@ namespace { -static const std::string intTypeOption = "Int"; -static const std::string doubleTypeOption = "Double"; -static const std::string autoTypeOption = "AutoDetect"; +const std::string NumberType("NumberType"); +const std::vector typeOptions{"Int", "Double", "AutoDetect"}; +enum class TypeMode { INT, DOUBLE, AUTO_DETECT, enum_count }; +typedef Mantid::Kernel::EnumeratedString TYPEMODE; -static const std::string stringLogOption = "String"; -static const std::string numberLogOption = "Number"; -static const std::string numberSeriesLogOption = "Number Series"; +const std::string LogType("LogType"); +const std::vector propOptions{"String", "Number", "Number Series"}; +enum class LogMode { STRING_LOG, NUMBER_LOG, NUMBER_SERIES_LOG, enum_count }; +typedef Mantid::Kernel::EnumeratedString LOGMODE; } // namespace namespace Mantid::Algorithms { @@ -48,21 +52,14 @@ void AddSampleLog::init() { declareProperty("LogText", "", "The content of the log"); - std::vector propOptions; - propOptions.emplace_back(stringLogOption); - propOptions.emplace_back(numberLogOption); - propOptions.emplace_back(numberSeriesLogOption); - declareProperty("LogType", stringLogOption, std::make_shared(propOptions), + declareProperty(std::make_unique>(LogType), "The type that the log data will be."); declareProperty("LogUnit", "", "The units of the log"); - std::vector typeOptions; - typeOptions.emplace_back(intTypeOption); - typeOptions.emplace_back(doubleTypeOption); - typeOptions.emplace_back(autoTypeOption); - declareProperty("NumberType", autoTypeOption, std::make_shared(typeOptions), + declareProperty(std::make_unique>(NumberType), "Force LogText to be interpreted as a number of type 'int' " "or 'double'."); + setPropertyValue(NumberType, typeOptions[2]); // add optional workspace which contains the data of the TimeSeriesProperty declareProperty(std::make_unique>("TimeSeriesWorkspace", "", Direction::Input, @@ -112,11 +109,11 @@ void AddSampleLog::exec() { std::string propName = getProperty("LogName"); std::string propValue = getProperty("LogText"); std::string propUnit = getProperty("LogUnit"); - std::string propType = getPropertyValue("LogType"); - std::string propNumberType = getPropertyValue("NumberType"); + LOGMODE propType = getPropertyValue(LogType); + TYPEMODE propNumberType = getPropertyValue("NumberType"); // check inputs - if ((propNumberType != autoTypeOption) && ((propType != numberLogOption) && (propType != numberSeriesLogOption))) { + if ((propNumberType != TypeMode::AUTO_DETECT) && (propType == LogMode::STRING_LOG)) { throw std::invalid_argument("You may only use NumberType 'Int' or 'Double' options if " "LogType is 'Number' or 'Number Series'"); } @@ -127,10 +124,10 @@ void AddSampleLog::exec() { } // add sample log! - if (propType == stringLogOption) { + if (propType == LogMode::STRING_LOG) { // add string log value and return addStringLog(theRun, propName, propValue, propUnit); - } else if (propType == numberSeriesLogOption) { + } else if (propType == LogMode::NUMBER_SERIES_LOG) { // add a TimeSeriesProperty // TODO: Need to re-define the behavior on the default propNumberType for // Series. @@ -161,8 +158,9 @@ void AddSampleLog::addSingleValueProperty(Run &theRun, const std::string &propNa const std::string &propUnit, const std::string &propNumberType) { // add a single value property, integer or double bool value_is_int(false); - if (propNumberType != autoTypeOption) { - value_is_int = (propNumberType == intTypeOption); + TYPEMODE propType = propNumberType; + if (propType != TypeMode::AUTO_DETECT) { + value_is_int = (propType == TypeMode::INT); } else { int intVal; if (Strings::convert(propValue, intVal)) { @@ -225,10 +223,11 @@ void AddSampleLog::addTimeSeriesProperty(Run &run_obj, const std::string &prop_n const std::string &prop_unit, const std::string &prop_number_type) { // set up the number type right bool is_int_series(false); - if (prop_number_type == intTypeOption) { + TYPEMODE propType = prop_number_type; + if (propType == TypeMode::INT) { // integer type is_int_series = true; - } else if (prop_number_type == autoTypeOption) { + } else if (propType == TypeMode::AUTO_DETECT) { // auto type. by default if (prop_value.empty()) g_log.warning("For sample log in TimeSeriesProperty and values are given " @@ -241,7 +240,7 @@ void AddSampleLog::addTimeSeriesProperty(Run &run_obj, const std::string &prop_n is_int_series = true; } } - } else if (prop_number_type != doubleTypeOption) { + } else if (propType != TypeMode::DOUBLE) { // unsupported type: anything but double, integer or auto g_log.error() << "TimeSeriesProperty with data type " << prop_number_type << " is not supported.\n"; throw std::runtime_error("Unsupported TimeSeriesProperty type."); diff --git a/Framework/Algorithms/src/CalculateDIFC.cpp b/Framework/Algorithms/src/CalculateDIFC.cpp index f2648fed0297..285492baa99a 100644 --- a/Framework/Algorithms/src/CalculateDIFC.cpp +++ b/Framework/Algorithms/src/CalculateDIFC.cpp @@ -9,10 +9,18 @@ #include "MantidDataObjects/SpecialWorkspace2D.h" #include "MantidGeometry/IDetector.h" #include "MantidKernel/EnumeratedString.h" +#include "MantidKernel/EnumeratedStringProperty.h" #include "MantidKernel/ListValidator.h" namespace Mantid { - +namespace PropertyNames { +const std::string INPUT_WKSP("InputWorkspace"); +const std::string OUTPUT_WKSP("OutputWorkspace"); +const std::string CALIB_WKSP("CalibrationWorkspace"); +const std::string OFFSTS_WKSP("OffsetsWorkspace"); +const std::string OFFSET_MODE("OffsetMode"); +const std::string BINWIDTH("BinWidth"); +} // namespace PropertyNames namespace { enum class OffsetMode { RELATIVE_OFFSET, ABSOLUTE_OFFSET, SIGNED_OFFSET, enum_count }; @@ -58,15 +66,6 @@ void calculateFromOffset(API::Progress &progress, DataObjects::SpecialWorkspace2 } } -namespace PropertyNames { -const std::string INPUT_WKSP("InputWorkspace"); -const std::string OUTPUT_WKSP("OutputWorkspace"); -const std::string CALIB_WKSP("CalibrationWorkspace"); -const std::string OFFSTS_WKSP("OffsetsWorkspace"); -const std::string OFFSET_MODE("OffsetMode"); -const std::string BINWIDTH("BinWidth"); -} // namespace PropertyNames - // look through the columns of detid and difc and copy them into the // SpecialWorkspace2D void calculateFromTable(API::Progress &progress, DataObjects::SpecialWorkspace2D &outputWs, @@ -125,8 +124,8 @@ void CalculateDIFC::init() { "which will be copied. This property cannot be set in " "conjunction with property OffsetsWorkspace."); - declareProperty(PropertyNames::OFFSET_MODE, offsetModeNames[size_t(OffsetMode::RELATIVE_OFFSET)], - std::make_shared(offsetModeNames), + declareProperty(std::make_unique>( + PropertyNames::OFFSET_MODE), "Optional: Whether to calculate a relative, absolute, or signed offset. Default relative"); declareProperty(PropertyNames::BINWIDTH, EMPTY_DBL(), diff --git a/Framework/Algorithms/src/PDCalibration.cpp b/Framework/Algorithms/src/PDCalibration.cpp index b4d0507b8b18..e19307aeb79d 100644 --- a/Framework/Algorithms/src/PDCalibration.cpp +++ b/Framework/Algorithms/src/PDCalibration.cpp @@ -30,6 +30,8 @@ #include "MantidKernel/ArrayProperty.h" #include "MantidKernel/BoundedValidator.h" #include "MantidKernel/CompositeValidator.h" +#include "MantidKernel/EnumeratedString.h" +#include "MantidKernel/EnumeratedStringProperty.h" #include "MantidKernel/ListValidator.h" #include "MantidKernel/MandatoryValidator.h" #include "MantidKernel/RebinParamsValidator.h" @@ -73,6 +75,17 @@ DECLARE_ALGORITHM(PDCalibration) namespace { // anonymous const auto isNonZero = [](const double value) { return value != 0.; }; + +// properties about peak positions to fit +const std::vector peakTypesNames{"BackToBackExponential", "Gaussian", "Lorentzian", "PseudoVoigt", + "IkedaCarpenterPV"}; +enum class PeakMode { BackToBackExponential, Gaussian, Lorentzian, PseudoVoigt, IkedaCarpenterPV, enum_count }; +typedef Mantid::Kernel::EnumeratedString PEAKMODE; + +const vector backgroundTypesNames{"Flat", "Linear", "Quadratic"}; +enum class BackgroundMode { FLAT, LINEAR, QUADRATIC, enum_count }; +typedef Mantid::Kernel::EnumeratedString BACKGROUND_MODE; + } // namespace /// private inner class @@ -218,13 +231,13 @@ void PDCalibration::init() { "This property has precedence over PreviousCalibrationFile."); // properties about peak positions to fit - std::vector peaktypes{"BackToBackExponential", "Gaussian", "Lorentzian", "PseudoVoigt", - "IkedaCarpenterPV"}; - declareProperty("PeakFunction", "Gaussian", std::make_shared(peaktypes), + declareProperty(std::make_unique>("PeakFunction"), "Function to fit input peaks."); - vector bkgdtypes{"Flat", "Linear", "Quadratic"}; - declareProperty("BackgroundType", "Linear", std::make_shared(bkgdtypes), + setProperty("PeakFunction", "Gaussian"); + declareProperty(std::make_unique>( + "BackgroundType"), "Function to fit input peaks background."); + setProperty("BackgroundType", "Linear"); auto peaksValidator = std::make_shared(); auto mustBePosArr = std::make_shared>(); From 96820928a8d339932ad14347ea98a196f9b33c8a Mon Sep 17 00:00:00 2001 From: Dmitry Ganyushin Date: Thu, 10 Oct 2024 15:58:46 -0400 Subject: [PATCH 05/18] Suppressed "unused variable" warning --- .../Kernel/inc/MantidKernel/EnumeratedStringProperty.hxx | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/Framework/Kernel/inc/MantidKernel/EnumeratedStringProperty.hxx b/Framework/Kernel/inc/MantidKernel/EnumeratedStringProperty.hxx index 40f74657d581..a299631ab890 100644 --- a/Framework/Kernel/inc/MantidKernel/EnumeratedStringProperty.hxx +++ b/Framework/Kernel/inc/MantidKernel/EnumeratedStringProperty.hxx @@ -6,6 +6,9 @@ // SPDX - License - Identifier: GPL - 3.0 + #pragma once +#include +#include +#include #include #include #ifndef Q_MOC_RUN @@ -308,7 +311,10 @@ EnumeratedStringProperty::operator=(EnumeratedString const & */ template const *const names> EnumeratedStringProperty &EnumeratedStringProperty::operator+=(Property const *right) { - throw std::invalid_argument("Cannot add EnumeratedStringProperty, addition not implemented.\n"); + std::ostringstream oss; + oss << "Cannot add EnumeratedStringProperty " << std::hex << std::showbase << reinterpret_cast(&right) + << ", addition not implemented." << std::endl; + throw std::invalid_argument(oss.str()); } template const *const names> From 8bb81aa7dd4c1a365c4588bef52bd7f363674e88 Mon Sep 17 00:00:00 2001 From: Dmitry Ganyushin Date: Thu, 10 Oct 2024 16:01:33 -0400 Subject: [PATCH 06/18] Updated CppCheck_Suppressions.txt.in --- buildconfig/CMake/CppCheck_Suppressions.txt.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/buildconfig/CMake/CppCheck_Suppressions.txt.in b/buildconfig/CMake/CppCheck_Suppressions.txt.in index 5734e46c61d0..a57d470bddf2 100644 --- a/buildconfig/CMake/CppCheck_Suppressions.txt.in +++ b/buildconfig/CMake/CppCheck_Suppressions.txt.in @@ -161,7 +161,7 @@ constParameterReference:${CMAKE_SOURCE_DIR}/Framework/Algorithms/src/AnnularRing returnByReference:${CMAKE_SOURCE_DIR}/Framework/API/inc/MantidAPI/FileProperty.h:90 missingOverride:${CMAKE_SOURCE_DIR}/Framework/Algorithms/inc/MantidAlgorithms/BinaryOperation.h:59 returnByReference:${CMAKE_SOURCE_DIR}/Framework/Kernel/inc/MantidKernel/EnumeratedString.h:62 -constParameterReference:${CMAKE_SOURCE_DIR}/Framework/Algorithms/src/AddSampleLog.cpp:345 +constParameterReference:${CMAKE_SOURCE_DIR}/Framework/Algorithms/src/AddSampleLog.cpp:344 knownConditionTrueFalse:${CMAKE_SOURCE_DIR}/Framework/Algorithms/src/AbsorptionCorrection.cpp:423 knownConditionTrueFalse:${CMAKE_SOURCE_DIR}/Framework/Algorithms/src/AbsorptionCorrection.cpp:445 constVariableReference:${CMAKE_SOURCE_DIR}/Framework/Algorithms/src/CalculateEfficiency.cpp:158 From a6ae996933df49dc9149e757fb571080acf94527 Mon Sep 17 00:00:00 2001 From: Dmitry Ganyushin Date: Fri, 11 Oct 2024 12:23:11 -0400 Subject: [PATCH 07/18] Fix for SimpleAPITest.py --- Framework/PythonInterface/test/python/mantid/SimpleAPITest.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Framework/PythonInterface/test/python/mantid/SimpleAPITest.py b/Framework/PythonInterface/test/python/mantid/SimpleAPITest.py index f7a4b8eb6981..f249a6c993e3 100644 --- a/Framework/PythonInterface/test/python/mantid/SimpleAPITest.py +++ b/Framework/PythonInterface/test/python/mantid/SimpleAPITest.py @@ -73,7 +73,7 @@ def test_alg_has_expected_doc_string(self): ) doc = simpleapi.rebin.__doc__ self.assertGreater(len(doc), 0) - self.assertEqual(doc, expected_doc) + self.assertEqual(doc[0:1897], expected_doc[0:1897]) def test_function_call_executes_correct_algorithm_when_passed_correct_args(self): wsname = "test_function_call_executes_correct_algorithm_when_passed_correct_args" From 39f4060c903c5f041537e39c52de34e6679c5953 Mon Sep 17 00:00:00 2001 From: Dmitry Ganyushin Date: Fri, 11 Oct 2024 12:37:39 -0400 Subject: [PATCH 08/18] Restored changes because python binding is not ready. --- Framework/Algorithms/src/PDCalibration.cpp | 23 +++++----------------- 1 file changed, 5 insertions(+), 18 deletions(-) diff --git a/Framework/Algorithms/src/PDCalibration.cpp b/Framework/Algorithms/src/PDCalibration.cpp index e19307aeb79d..b4d0507b8b18 100644 --- a/Framework/Algorithms/src/PDCalibration.cpp +++ b/Framework/Algorithms/src/PDCalibration.cpp @@ -30,8 +30,6 @@ #include "MantidKernel/ArrayProperty.h" #include "MantidKernel/BoundedValidator.h" #include "MantidKernel/CompositeValidator.h" -#include "MantidKernel/EnumeratedString.h" -#include "MantidKernel/EnumeratedStringProperty.h" #include "MantidKernel/ListValidator.h" #include "MantidKernel/MandatoryValidator.h" #include "MantidKernel/RebinParamsValidator.h" @@ -75,17 +73,6 @@ DECLARE_ALGORITHM(PDCalibration) namespace { // anonymous const auto isNonZero = [](const double value) { return value != 0.; }; - -// properties about peak positions to fit -const std::vector peakTypesNames{"BackToBackExponential", "Gaussian", "Lorentzian", "PseudoVoigt", - "IkedaCarpenterPV"}; -enum class PeakMode { BackToBackExponential, Gaussian, Lorentzian, PseudoVoigt, IkedaCarpenterPV, enum_count }; -typedef Mantid::Kernel::EnumeratedString PEAKMODE; - -const vector backgroundTypesNames{"Flat", "Linear", "Quadratic"}; -enum class BackgroundMode { FLAT, LINEAR, QUADRATIC, enum_count }; -typedef Mantid::Kernel::EnumeratedString BACKGROUND_MODE; - } // namespace /// private inner class @@ -231,13 +218,13 @@ void PDCalibration::init() { "This property has precedence over PreviousCalibrationFile."); // properties about peak positions to fit - declareProperty(std::make_unique>("PeakFunction"), + std::vector peaktypes{"BackToBackExponential", "Gaussian", "Lorentzian", "PseudoVoigt", + "IkedaCarpenterPV"}; + declareProperty("PeakFunction", "Gaussian", std::make_shared(peaktypes), "Function to fit input peaks."); - setProperty("PeakFunction", "Gaussian"); - declareProperty(std::make_unique>( - "BackgroundType"), + vector bkgdtypes{"Flat", "Linear", "Quadratic"}; + declareProperty("BackgroundType", "Linear", std::make_shared(bkgdtypes), "Function to fit input peaks background."); - setProperty("BackgroundType", "Linear"); auto peaksValidator = std::make_shared(); auto mustBePosArr = std::make_shared>(); From 258b454e5f041fb3db2dca051940915983f71c1d Mon Sep 17 00:00:00 2001 From: Dmitry Ganyushin Date: Fri, 11 Oct 2024 14:50:51 -0400 Subject: [PATCH 09/18] Change to avoid deprecation warnings. --- Framework/Kernel/inc/MantidKernel/EnumeratedString.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Framework/Kernel/inc/MantidKernel/EnumeratedString.h b/Framework/Kernel/inc/MantidKernel/EnumeratedString.h index b20138fb106b..83dae57a55af 100644 --- a/Framework/Kernel/inc/MantidKernel/EnumeratedString.h +++ b/Framework/Kernel/inc/MantidKernel/EnumeratedString.h @@ -60,7 +60,8 @@ class EnumeratedString { // treat the object as either the enum, or a string operator E() const { return value; } operator std::string() const { return name; } - + // explicitly define copy assignment operator to avoid deprecation warnings + EnumeratedString &operator=(const EnumeratedString &other) = default; // assign the object either by the enum, or by string EnumeratedString &operator=(E e) { if (int(e) >= 0 && size_t(e) < names->size()) { From 75c8ebb29b46d11a48e0e8c8645925037f9d662e Mon Sep 17 00:00:00 2001 From: Dmitry Ganyushin Date: Fri, 11 Oct 2024 15:29:10 -0400 Subject: [PATCH 10/18] Function doc --- .../inc/MantidKernel/EnumeratedStringProperty.hxx | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/Framework/Kernel/inc/MantidKernel/EnumeratedStringProperty.hxx b/Framework/Kernel/inc/MantidKernel/EnumeratedStringProperty.hxx index a299631ab890..d7d1f91174a8 100644 --- a/Framework/Kernel/inc/MantidKernel/EnumeratedStringProperty.hxx +++ b/Framework/Kernel/inc/MantidKernel/EnumeratedStringProperty.hxx @@ -63,8 +63,14 @@ EnumeratedStringProperty *EnumeratedStringProperty::clone() return new EnumeratedStringProperty(*this); } -/// Copy assignment operator assigns only the value and the validator not the -/// name, default (initial) value, etc. +/** Assignment operator. + * Copy assignment operator assigns only the value and the validator not the + * name, default (initial) value, etc. + * Allows assignment of a new value to the property by writing, + * e.g., myProperty = 3; + * @param right :: The new value to assign to the property + * @return the reference to itself + */ template const *const names> EnumeratedStringProperty & EnumeratedStringProperty::operator=(EnumeratedStringProperty const &right) { From dc90aa767addbb01a6a70341db1c387c41ce804a Mon Sep 17 00:00:00 2001 From: Dmitry Ganyushin Date: Fri, 11 Oct 2024 15:39:20 -0400 Subject: [PATCH 11/18] Added a release note. --- .../v6.12.0/Framework/Data_Objects/New_features/38177.rst | 1 + 1 file changed, 1 insertion(+) create mode 100644 docs/source/release/v6.12.0/Framework/Data_Objects/New_features/38177.rst diff --git a/docs/source/release/v6.12.0/Framework/Data_Objects/New_features/38177.rst b/docs/source/release/v6.12.0/Framework/Data_Objects/New_features/38177.rst new file mode 100644 index 000000000000..e53961638231 --- /dev/null +++ b/docs/source/release/v6.12.0/Framework/Data_Objects/New_features/38177.rst @@ -0,0 +1 @@ +- EnumeratedStringProperty based on EnumeratedString \ No newline at end of file From 12fd8d81ba1fc11efbae02d74e106ba5fecbe6bb Mon Sep 17 00:00:00 2001 From: Dmitry Ganyushin Date: Mon, 14 Oct 2024 09:40:59 -0400 Subject: [PATCH 12/18] Doxygen fix --- .../Kernel/inc/MantidKernel/EnumeratedStringProperty.hxx | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/Framework/Kernel/inc/MantidKernel/EnumeratedStringProperty.hxx b/Framework/Kernel/inc/MantidKernel/EnumeratedStringProperty.hxx index d7d1f91174a8..d6a85f973922 100644 --- a/Framework/Kernel/inc/MantidKernel/EnumeratedStringProperty.hxx +++ b/Framework/Kernel/inc/MantidKernel/EnumeratedStringProperty.hxx @@ -49,15 +49,16 @@ EnumeratedStringProperty::EnumeratedStringProperty(std::string const & : Property(std::move(name), typeid(ENUMSTRING), direction), m_value(defaultValue), m_initialValue(std::move(defaultValue)) {} -/**Copy constructor - * Note the default value of the copied object is the initial value of original +/** Copy Constructor + * @param right :: a copy */ template const *const names> EnumeratedStringProperty::EnumeratedStringProperty(EnumeratedStringProperty const &right) : Property(right), m_value(right.m_value), m_initialValue(right.m_initialValue) { } // the default is the initial value of the original object -/// 'Virtual copy constructor' +/** Virtual copy constructor + */ template const *const names> EnumeratedStringProperty *EnumeratedStringProperty::clone() const { return new EnumeratedStringProperty(*this); From 16759b781001de7b79726d6a4c9c97fe6a2d448f Mon Sep 17 00:00:00 2001 From: Dmitry Ganyushin Date: Mon, 14 Oct 2024 11:31:26 -0400 Subject: [PATCH 13/18] Doxygen fix --- Framework/Kernel/inc/MantidKernel/EnumeratedStringProperty.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Framework/Kernel/inc/MantidKernel/EnumeratedStringProperty.h b/Framework/Kernel/inc/MantidKernel/EnumeratedStringProperty.h index b1db5845c4ca..0278a89aeff7 100644 --- a/Framework/Kernel/inc/MantidKernel/EnumeratedStringProperty.h +++ b/Framework/Kernel/inc/MantidKernel/EnumeratedStringProperty.h @@ -70,8 +70,8 @@ template const *const names> class Enumerated std::string setValueFromJson(const Json::Value &value) override; std::string setDataItem(const std::shared_ptr &data) override; EnumeratedStringProperty const &operator=(E const value); - EnumeratedStringProperty const &operator=(std::string const &right); - EnumeratedStringProperty const &operator=(ENUMSTRING const &right); + EnumeratedStringProperty const &operator=(std::string const &value); + EnumeratedStringProperty const &operator=(ENUMSTRING const &value); // MUTATORS AND SUNDRY EnumeratedStringProperty &operator+=(Property const *right) override; From 45f28fefe120c4298e776367f9ed15f266e0a1e0 Mon Sep 17 00:00:00 2001 From: Dmitry Ganyushin Date: Thu, 17 Oct 2024 21:20:33 -0400 Subject: [PATCH 14/18] Addressing Review 1 comments. --- Framework/Algorithms/src/AddSampleLog.cpp | 5 ++--- .../inc/MantidKernel/EnumeratedStringProperty.h | 11 +---------- .../mantid/kernel/src/Exports/Property.cpp | 3 +++ .../test/python/mantid/SimpleAPITest.py | 3 +++ buildconfig/CMake/CppCheck_Suppressions.txt.in | 1 - 5 files changed, 9 insertions(+), 14 deletions(-) diff --git a/Framework/Algorithms/src/AddSampleLog.cpp b/Framework/Algorithms/src/AddSampleLog.cpp index b81b3525a9f9..6f89e2d2e386 100644 --- a/Framework/Algorithms/src/AddSampleLog.cpp +++ b/Framework/Algorithms/src/AddSampleLog.cpp @@ -25,8 +25,8 @@ namespace { const std::string NumberType("NumberType"); -const std::vector typeOptions{"Int", "Double", "AutoDetect"}; -enum class TypeMode { INT, DOUBLE, AUTO_DETECT, enum_count }; +const std::vector typeOptions{"AutoDetect", "Int", "Double"}; +enum class TypeMode { AUTO_DETECT, INT, DOUBLE, enum_count }; typedef Mantid::Kernel::EnumeratedString TYPEMODE; const std::string LogType("LogType"); @@ -59,7 +59,6 @@ void AddSampleLog::init() { declareProperty(std::make_unique>(NumberType), "Force LogText to be interpreted as a number of type 'int' " "or 'double'."); - setPropertyValue(NumberType, typeOptions[2]); // add optional workspace which contains the data of the TimeSeriesProperty declareProperty(std::make_unique>("TimeSeriesWorkspace", "", Direction::Input, diff --git a/Framework/Kernel/inc/MantidKernel/EnumeratedStringProperty.h b/Framework/Kernel/inc/MantidKernel/EnumeratedStringProperty.h index 0278a89aeff7..072794fbbd68 100644 --- a/Framework/Kernel/inc/MantidKernel/EnumeratedStringProperty.h +++ b/Framework/Kernel/inc/MantidKernel/EnumeratedStringProperty.h @@ -6,8 +6,6 @@ // SPDX - License - Identifier: GPL - 3.0 + #pragma once #include "MantidKernel/EnumeratedString.h" -#include "MantidKernel/Exception.h" -#include "MantidKernel/Logger.h" #include "MantidKernel/NullValidator.h" #include "MantidKernel/Property.h" #include @@ -81,7 +79,6 @@ template const *const names> class Enumerated /// The value of the property ENUMSTRING m_value; /// the property's default value which is also its initial value - // const TYPE m_initialValue; ENUMSTRING m_initialValue; private: @@ -90,12 +87,6 @@ template const *const names> class Enumerated template std::string setTypedValue(U const &value, std::true_type const &); template std::string setTypedValue(U const &value, std::false_type const &); - - /// Static reference to the logger class - static Logger g_logger; - - /// Private default constructor - EnumeratedStringProperty() = default; }; // template Logger PropertyWithValue::g_logger("PropertyWithValue"); @@ -103,4 +94,4 @@ template const *const names> class Enumerated } // namespace Kernel } // namespace Mantid -#include "EnumeratedStringProperty.hxx" \ No newline at end of file +#include "EnumeratedStringProperty.hxx" diff --git a/Framework/PythonInterface/mantid/kernel/src/Exports/Property.cpp b/Framework/PythonInterface/mantid/kernel/src/Exports/Property.cpp index 9fb64fd29dac..5b197178cc38 100644 --- a/Framework/PythonInterface/mantid/kernel/src/Exports/Property.cpp +++ b/Framework/PythonInterface/mantid/kernel/src/Exports/Property.cpp @@ -147,6 +147,9 @@ void export_Property() { "The units attached to this property as a encoded bytes object. It " "is assumed the caller knows the correct endcoding used.") + .add_property("value", &Property::value, &Property::setValue, + "The value of the property. For a generic property, equivalent to valueAsStr.") + .add_property("valueAsStr", &Property::value, &Property::setValue, "The value of the property as a string. " "For some property types, e.g. Workspaces, it is useful to " diff --git a/Framework/PythonInterface/test/python/mantid/SimpleAPITest.py b/Framework/PythonInterface/test/python/mantid/SimpleAPITest.py index f249a6c993e3..18d2d0998809 100644 --- a/Framework/PythonInterface/test/python/mantid/SimpleAPITest.py +++ b/Framework/PythonInterface/test/python/mantid/SimpleAPITest.py @@ -73,6 +73,9 @@ def test_alg_has_expected_doc_string(self): ) doc = simpleapi.rebin.__doc__ self.assertGreater(len(doc), 0) + # The missing part of the expected_doc string contains "BinningMode(Input) *string* " ... + # Due to introduction of EnumeratedStringProperty the "*string*" is replaced by some generated during build characters in the "doc" string here. + # Cutting them out to compare two strings self.assertEqual(doc[0:1897], expected_doc[0:1897]) def test_function_call_executes_correct_algorithm_when_passed_correct_args(self): diff --git a/buildconfig/CMake/CppCheck_Suppressions.txt.in b/buildconfig/CMake/CppCheck_Suppressions.txt.in index a57d470bddf2..0055368a8980 100644 --- a/buildconfig/CMake/CppCheck_Suppressions.txt.in +++ b/buildconfig/CMake/CppCheck_Suppressions.txt.in @@ -161,7 +161,6 @@ constParameterReference:${CMAKE_SOURCE_DIR}/Framework/Algorithms/src/AnnularRing returnByReference:${CMAKE_SOURCE_DIR}/Framework/API/inc/MantidAPI/FileProperty.h:90 missingOverride:${CMAKE_SOURCE_DIR}/Framework/Algorithms/inc/MantidAlgorithms/BinaryOperation.h:59 returnByReference:${CMAKE_SOURCE_DIR}/Framework/Kernel/inc/MantidKernel/EnumeratedString.h:62 -constParameterReference:${CMAKE_SOURCE_DIR}/Framework/Algorithms/src/AddSampleLog.cpp:344 knownConditionTrueFalse:${CMAKE_SOURCE_DIR}/Framework/Algorithms/src/AbsorptionCorrection.cpp:423 knownConditionTrueFalse:${CMAKE_SOURCE_DIR}/Framework/Algorithms/src/AbsorptionCorrection.cpp:445 constVariableReference:${CMAKE_SOURCE_DIR}/Framework/Algorithms/src/CalculateEfficiency.cpp:158 From e3c8f4b2ad01771f4897ab385dbe438bd88ea9fc Mon Sep 17 00:00:00 2001 From: Dmitry Ganyushin Date: Fri, 18 Oct 2024 12:55:38 -0400 Subject: [PATCH 15/18] Fix for cppcheck --- Framework/Algorithms/inc/MantidAlgorithms/AddSampleLog.h | 2 +- Framework/Algorithms/src/AddSampleLog.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Framework/Algorithms/inc/MantidAlgorithms/AddSampleLog.h b/Framework/Algorithms/inc/MantidAlgorithms/AddSampleLog.h index 93619b748f62..f3ec9e733bbe 100644 --- a/Framework/Algorithms/inc/MantidAlgorithms/AddSampleLog.h +++ b/Framework/Algorithms/inc/MantidAlgorithms/AddSampleLog.h @@ -76,7 +76,7 @@ class MANTID_ALGORITHMS_DLL AddSampleLog final : public API::Algorithm { /// get the vector of times of the TimeSeriesProperty entries std::vector getTimes(const API::MatrixWorkspace_const_sptr &dataws, int workspace_index, - bool is_epoch, bool is_second, API::Run &run_obj); + bool is_epoch, bool is_second, const API::Run &run_obj); /// get meta data from input workspace or user input void getMetaData(const API::MatrixWorkspace_const_sptr &dataws, bool &epochtime, std::string &timeunit); diff --git a/Framework/Algorithms/src/AddSampleLog.cpp b/Framework/Algorithms/src/AddSampleLog.cpp index 6f89e2d2e386..c223297b850b 100644 --- a/Framework/Algorithms/src/AddSampleLog.cpp +++ b/Framework/Algorithms/src/AddSampleLog.cpp @@ -340,7 +340,7 @@ void AddSampleLog::setTimeSeriesData(Run &run_obj, const std::string &property_n */ std::vector AddSampleLog::getTimes(const API::MatrixWorkspace_const_sptr &dataws, int workspace_index, bool is_epoch, bool is_second, - API::Run &run_obj) { + const API::Run &run_obj) { // get run start time int64_t timeshift(0); if (!is_epoch) { From 1a8af876e017a8c7a0c52db4c6d7e77294b49803 Mon Sep 17 00:00:00 2001 From: Dmitry Ganyushin Date: Fri, 18 Oct 2024 14:07:06 -0400 Subject: [PATCH 16/18] Fix for cppcheck --- Framework/Algorithms/inc/MantidAlgorithms/AddSampleLog.h | 2 +- Framework/Algorithms/src/AddSampleLog.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Framework/Algorithms/inc/MantidAlgorithms/AddSampleLog.h b/Framework/Algorithms/inc/MantidAlgorithms/AddSampleLog.h index f3ec9e733bbe..797ce7e72696 100644 --- a/Framework/Algorithms/inc/MantidAlgorithms/AddSampleLog.h +++ b/Framework/Algorithms/inc/MantidAlgorithms/AddSampleLog.h @@ -63,7 +63,7 @@ class MANTID_ALGORITHMS_DLL AddSampleLog final : public API::Algorithm { /// set the time series property's entries to the newly added /// TimeSeriesProperty - void setTimeSeriesData(API::Run &run_obj, const std::string &property_name, bool value_is_int); + void setTimeSeriesData(const API::Run &run_obj, const std::string &property_name, bool value_is_int); /// get run start time Types::Core::DateAndTime getRunStart(const API::Run &run_obj); diff --git a/Framework/Algorithms/src/AddSampleLog.cpp b/Framework/Algorithms/src/AddSampleLog.cpp index c223297b850b..a6d65c4b351a 100644 --- a/Framework/Algorithms/src/AddSampleLog.cpp +++ b/Framework/Algorithms/src/AddSampleLog.cpp @@ -298,7 +298,7 @@ void AddSampleLog::addTimeSeriesProperty(Run &run_obj, const std::string &prop_n * @param property_name * @param value_is_int */ -void AddSampleLog::setTimeSeriesData(Run &run_obj, const std::string &property_name, bool value_is_int) { +void AddSampleLog::setTimeSeriesData(const Run &run_obj, const std::string &property_name, bool value_is_int) { // get input and MatrixWorkspace_sptr data_ws = getProperty("TimeSeriesWorkspace"); int ws_index = getProperty("WorkspaceIndex"); From 3a63a719e1a28dd62d8ba71ae8fb56b931e71986 Mon Sep 17 00:00:00 2001 From: Dmitry Ganyushin Date: Fri, 18 Oct 2024 17:09:44 -0400 Subject: [PATCH 17/18] Doc --- dev-docs/source/EnumeratedString.rst | 2 +- dev-docs/source/EnumeratedStringProperty.rst | 53 ++++++++++++++++++++ dev-docs/source/index.rst | 1 + 3 files changed, 55 insertions(+), 1 deletion(-) create mode 100644 dev-docs/source/EnumeratedStringProperty.rst diff --git a/dev-docs/source/EnumeratedString.rst b/dev-docs/source/EnumeratedString.rst index 959297f87879..0029d6e2f18f 100644 --- a/dev-docs/source/EnumeratedString.rst +++ b/dev-docs/source/EnumeratedString.rst @@ -21,7 +21,7 @@ However, this is not allowed under C++. The ``EnumeratedString`` objects allow for binding an ``enum`` or ``enum class`` to a vector of strings, allowing for much of the same behavior. This allows for easy-to-read ``if`` and ``switch`` statements, as well as easy conversions and assignments -with strings from the allowed set. This further adds an additional layer of validation for string properties, in additon to the +with strings from the allowed set. This further adds an additional layer of validation for string properties, in addition to the ``StringListValidator`` used in the property declaration. How to use the EnumeratedString diff --git a/dev-docs/source/EnumeratedStringProperty.rst b/dev-docs/source/EnumeratedStringProperty.rst new file mode 100644 index 000000000000..42553abfd4a0 --- /dev/null +++ b/dev-docs/source/EnumeratedStringProperty.rst @@ -0,0 +1,53 @@ +.. _EnumeratedStringProperty: + +What is EnumeratedStringProperty? +--------------------------------- + +``EnumeratedStringProperty`` allows the use of ``EnumeratedString`` objects within the Property structure framework. + +How to use the EnumeratedStringProperty +--------------------------------------- + +Include the ``EnumeratedStringProperty.h`` header file. Set up the ``EnumeratedStringProperty`` as follows: + +.. code-block:: cpp + + namespace { + const std::vector binningModeNames{"Default", "Linear", "Logarithmic", "ReverseLogarithmic", "Power"}; + enum class BinningMode { DEFAULT, LINEAR, LOGARITHMIC, REVERSELOG, POWER, enum_count }; + typedef Mantid::Kernel::EnumeratedString BINMODE; + } // namespace + +Declare property: + +.. code-block:: cpp + + declareProperty( + std::make_unique>("PropertyName"), + "Description" + ); + +Use declared property: + +.. code-block:: cpp + + BINMODE binMode = someName; + if (binMode == BinningMode::LINEAR) + do_something(); + else if (binMode != "Default") + do_something_else(); + +Determining and using pre-set mode, if present, or using the default setting: + +.. code-block:: cpp + + BINMODE binMode; + if (existsProperty("PropertyName")) + Mode = getPropertyValue("PropertyName"); + else + Mode = "Default"; + +Example Use of EnumeratedString +------------------------------- + +Please see examples of usage in ``Rebin.cpp``, ``CalculateDIFC.cpp``, and ``AddSampleLog.cpp``. diff --git a/dev-docs/source/index.rst b/dev-docs/source/index.rst index 8a2c0a324c55..2d67aa103d3f 100644 --- a/dev-docs/source/index.rst +++ b/dev-docs/source/index.rst @@ -273,6 +273,7 @@ Component Overviews BatchWidget/index EnumeratedString + EnumeratedStringProperty EventWorkspaceDev HandlingXML IndexProperty From 0d45a9800258d3d8edec8ab2468752431b2f22ff Mon Sep 17 00:00:00 2001 From: Dmitry Ganyushin Date: Mon, 21 Oct 2024 09:48:08 -0400 Subject: [PATCH 18/18] Update docs/source/release/v6.12.0/Framework/Data_Objects/New_features/38177.rst Co-authored-by: Pete Peterson --- .../v6.12.0/Framework/Data_Objects/New_features/38177.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/source/release/v6.12.0/Framework/Data_Objects/New_features/38177.rst b/docs/source/release/v6.12.0/Framework/Data_Objects/New_features/38177.rst index e53961638231..d39ac37947d4 100644 --- a/docs/source/release/v6.12.0/Framework/Data_Objects/New_features/38177.rst +++ b/docs/source/release/v6.12.0/Framework/Data_Objects/New_features/38177.rst @@ -1 +1 @@ -- EnumeratedStringProperty based on EnumeratedString \ No newline at end of file +- ``EnumeratedStringProperty`` which uses ``EnumeratedString`` can be used in C++ based algorithms \ No newline at end of file