diff --git a/CMakeLists.txt b/CMakeLists.txt index 626f4d7a97b82be3fc6d85409157a281b548a415..448bed15d4541fce5ae21fc823b36d1245089f63 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -387,7 +387,7 @@ if(ENABLE_CPACK) "sip >= 4.18," "python-six,python-ipython >= 1.1.0,python-ipython-notebook,PyYAML," "python-requests," - "scipy,python2-scikit-image," + "scipy," "hdf,hdf5,jsoncpp >= 0.7.0") if(ENABLE_MANTIDPLOT) set(CPACK_RPM_PACKAGE_REQUIRES @@ -395,7 +395,7 @@ if(ENABLE_CPACK) endif() if(ENABLE_WORKBENCH) set(CPACK_RPM_PACKAGE_REQUIRES - "${CPACK_RPM_PACKAGE_REQUIRES},qt5-qtbase,python-qt5") + "${CPACK_RPM_PACKAGE_REQUIRES},qt5-qtbase,python2-qt5") endif() if("${UNIX_CODENAME}" MATCHES "Santiago") # RHEL6 @@ -498,7 +498,6 @@ if(ENABLE_CPACK) "python3-matplotlib," "python3-qtpy," "python3-scipy," - "python3-skimage," "python3-pycifrw (>= 4.2.1)," "python3-yaml," "ipython3-qtconsole") # transitional package for bionic @@ -521,7 +520,6 @@ if(ENABLE_CPACK) "python-matplotlib," "python-qtpy," "python-scipy," - "python-skimage," "python-pycifrw (>= 4.2.1)," "python-yaml," "ipython-qtconsole") diff --git a/Framework/API/src/Algorithm.cpp b/Framework/API/src/Algorithm.cpp index 8675f9c01dd69e143a3ed3f680112443d934f569..a9c04a2d467ea94120b5e8d1862c02ecfc3e8474 100644 --- a/Framework/API/src/Algorithm.cpp +++ b/Framework/API/src/Algorithm.cpp @@ -1758,8 +1758,8 @@ void Algorithm::registerFeatureUsage() const { if (UsageService::Instance().isEnabled()) { std::ostringstream oss; oss << this->name() << ".v" << this->version(); - UsageService::Instance().registerFeatureUsage("Algorithm", oss.str(), - isChild()); + UsageService::Instance().registerFeatureUsage(FeatureType::Algorithm, + oss.str(), isChild()); } } diff --git a/Framework/Kernel/inc/MantidKernel/UsageService.h b/Framework/Kernel/inc/MantidKernel/UsageService.h index cf8282bc4ed252dba7edb5cef6c206f794e4dc7d..15feb908cf8483d830ccb1a79d0b4538730c2e68 100644 --- a/Framework/Kernel/inc/MantidKernel/UsageService.h +++ b/Framework/Kernel/inc/MantidKernel/UsageService.h @@ -22,6 +22,11 @@ namespace Mantid { namespace Kernel { +/** An enum specifying the 3 possible features types that can be logged in the + usage service +*/ +enum class FeatureType { Algorithm, Interface, Feature }; + /** UsageReporter : The Usage reporter is responsible for collating, and sending all usage data. This centralizes all the logic covering Usage Reporting including: @@ -36,15 +41,17 @@ namespace Kernel { class FeatureUsage { public: /// Constructor - FeatureUsage(const std::string &type, const std::string &name, - const bool internal); + FeatureUsage(const FeatureType &type, std::string name, const bool internal); bool operator<(const FeatureUsage &r) const; ::Json::Value asJson() const; - std::string type; + FeatureType type; std::string name; bool internal; + +protected: + std::string featureTypeToString() const; }; class MANTID_KERNEL_DLL UsageServiceImpl { @@ -57,8 +64,22 @@ public: void setInterval(const uint32_t seconds = 60); /// Registers the Startup of Mantid void registerStartup(); - /// Registers the use of a feature in mantid - void registerFeatureUsage(const std::string &type, const std::string &name, + /// registerFeatureUsage registers the use of a feature in mantid. + /// Provide three overloads: + /// Version that takes vector of strings if want to register + /// usage of a particular class/method combination + void registerFeatureUsage(const FeatureType &type, + const std::vector<std::string> &name, + const bool internal); + /// Version that takes a string if just registering usage of a class + void registerFeatureUsage(const FeatureType &type, const std::string &name, + const bool internal); + /// Version that accepts an initializer list. This is required because + /// {"abc","def"} is both a valid constructor for std::string and an + /// initializer list so without this it's not clear which overload is being + /// called + void registerFeatureUsage(const FeatureType &type, + std::initializer_list<std::string> name, const bool internal); /// Returns true if usage reporting is enabled diff --git a/Framework/Kernel/src/UsageService.cpp b/Framework/Kernel/src/UsageService.cpp index 661c390c7c1edebcd81694ed104441d7d8f13676..f6e5638d7cd5f48a242008346d6056f1808e99be 100644 --- a/Framework/Kernel/src/UsageService.cpp +++ b/Framework/Kernel/src/UsageService.cpp @@ -15,9 +15,18 @@ #include "MantidKernel/ParaViewVersion.h" #include <Poco/ActiveResult.h> +#include <Poco/String.h> +#include <algorithm> +#include <boost/algorithm/string/join.hpp> +#include <boost/algorithm/string/trim.hpp> +#include <boost/bind.hpp> #include <json/json.h> +namespace { +constexpr auto SEPARATOR = "->"; +} + namespace Mantid { namespace Kernel { @@ -27,9 +36,9 @@ Kernel::Logger g_log("UsageServiceImpl"); //---------------------------------------------------------------------------------------------- /** FeatureUsage */ -FeatureUsage::FeatureUsage(const std::string &type, const std::string &name, +FeatureUsage::FeatureUsage(const FeatureType &type, std::string name, const bool internal) - : type(type), name(name), internal(internal) {} + : type(type), name(std::move(name)), internal(internal) {} // Better brute force. bool FeatureUsage::operator<(const FeatureUsage &r) const { @@ -51,10 +60,24 @@ bool FeatureUsage::operator<(const FeatureUsage &r) const { return false; } +/// Convert the stored feature type enum to a string +std::string FeatureUsage::featureTypeToString() const { + + switch (type) { + case FeatureType::Algorithm: + return "Algorithm"; + case FeatureType::Feature: + return "Feature"; + case FeatureType::Interface: + return "Interface"; + } + return "Unknown"; +} + ::Json::Value FeatureUsage::asJson() const { ::Json::Value retVal; - retVal["type"] = type; + retVal["type"] = featureTypeToString(); retVal["name"] = name; retVal["internal"] = internal; @@ -106,15 +129,34 @@ void UsageServiceImpl::registerStartup() { /** registerFeatureUsage */ -void UsageServiceImpl::registerFeatureUsage(const std::string &type, +void UsageServiceImpl::registerFeatureUsage( + const FeatureType &type, const std::vector<std::string> &name, + const bool internal) { + if (isEnabled()) { + std::lock_guard<std::mutex> _lock(m_mutex); + + using boost::algorithm::join; + m_FeatureQueue.push(FeatureUsage(type, join(name, SEPARATOR), internal)); + } +} + +void UsageServiceImpl::registerFeatureUsage(const FeatureType &type, const std::string &name, const bool internal) { if (isEnabled()) { std::lock_guard<std::mutex> _lock(m_mutex); + m_FeatureQueue.push(FeatureUsage(type, name, internal)); } } +void UsageServiceImpl::registerFeatureUsage( + const FeatureType &type, std::initializer_list<std::string> name, + const bool internal) { + + registerFeatureUsage(type, std::vector<std::string>(name), internal); +} + bool UsageServiceImpl::isEnabled() const { return m_isEnabled; } void UsageServiceImpl::setEnabled(const bool enabled) { diff --git a/Framework/Kernel/test/UsageServiceTest.h b/Framework/Kernel/test/UsageServiceTest.h index 3a5048c87aea34291bafb5405b0be4834b2734c5..3c3b8c8e9525375bf82f82d196e7f7cd99c04e0e 100644 --- a/Framework/Kernel/test/UsageServiceTest.h +++ b/Framework/Kernel/test/UsageServiceTest.h @@ -86,12 +86,18 @@ public: TestableUsageService usageService; usageService.setInterval(10000); usageService.setEnabled(true); - usageService.registerFeatureUsage("Algorithm", "MyAlg.v1", true); - usageService.registerFeatureUsage("Interface", "MyAlg.v1", true); + usageService.registerFeatureUsage(Mantid::Kernel::FeatureType::Algorithm, + "MyAlg.v1", true); + usageService.registerFeatureUsage(Mantid::Kernel::FeatureType::Interface, + "MyAlg.v1", true); for (size_t i = 0; i < 10000; i++) { - usageService.registerFeatureUsage("Algorithm", "MyLoopAlg.v1", false); + usageService.registerFeatureUsage(Mantid::Kernel::FeatureType::Algorithm, + "MyLoopAlg.v1", false); } - usageService.registerFeatureUsage("Algorithm", "MyLoopAlg.v1", true); + usageService.registerFeatureUsage(Mantid::Kernel::FeatureType::Algorithm, + "MyLoopAlg.v1", true); + usageService.registerFeatureUsage(Mantid::Kernel::FeatureType::Algorithm, + {"MyAlg.v1", "Method1"}, true); std::string message = usageService.generateFeatureUsageMessage(); @@ -127,6 +133,9 @@ public: if (type == "Algorithm" && name == "MyLoopAlg.v1" && internal == true && count == 1) correct = true; + if (type == "Algorithm" && name == "MyAlg.v1->Method1" && + internal == true && count == 1) + correct = true; TSM_ASSERT("Usage record was not as expected", correct) } } @@ -136,7 +145,8 @@ public: usageService.setInterval(10000); usageService.setEnabled(true); for (size_t i = 0; i < 10; i++) { - usageService.registerFeatureUsage("Algorithm", "MyLoopAlg.v1", false); + usageService.registerFeatureUsage(Mantid::Kernel::FeatureType::Algorithm, + {"MyLoopAlg.v1"}, false); } // this should empty the feature usage list usageService.flush(); @@ -149,7 +159,8 @@ public: usageService.setInterval(10000); usageService.setEnabled(true); for (size_t i = 0; i < 10; i++) { - usageService.registerFeatureUsage("Algorithm", "MyLoopAlg.v1", false); + usageService.registerFeatureUsage(Mantid::Kernel::FeatureType::Algorithm, + {"MyLoopAlg.v1"}, false); } // this should empty the feature usage list usageService.shutdown(); diff --git a/Framework/PythonInterface/mantid/kernel/src/Exports/UsageService.cpp b/Framework/PythonInterface/mantid/kernel/src/Exports/UsageService.cpp index 0430447cf8b049ce296756dd2d9283fea5ca9931..1d75c6c6ba5049e6b7b89f909746a1b006002200 100644 --- a/Framework/PythonInterface/mantid/kernel/src/Exports/UsageService.cpp +++ b/Framework/PythonInterface/mantid/kernel/src/Exports/UsageService.cpp @@ -5,8 +5,10 @@ // & Institut Laue - Langevin // SPDX - License - Identifier: GPL - 3.0 + #include "MantidKernel/UsageService.h" +#include "MantidPythonInterface/core/Converters/PySequenceToVector.h" #include "MantidPythonInterface/core/GetPointer.h" #include <boost/python/class.hpp> +#include <boost/python/enum.hpp> #include <boost/python/reference_existing_object.hpp> #include <mutex> @@ -14,6 +16,8 @@ using Mantid::Kernel::UsageService; using Mantid::Kernel::UsageServiceImpl; using namespace boost::python; +using ExtractStdString = boost::python::extract<std::string>; +using Mantid::PythonInterface::Converters::PySequenceToVector; GET_POINTER_SPECIALIZATION(UsageServiceImpl) @@ -37,9 +41,27 @@ UsageServiceImpl &instance() { }); return svc; } + +/// Register feature usage from a python list +void registerFeatureUsage(UsageServiceImpl &self, + const Mantid::Kernel::FeatureType &type, + const object &paths, const bool internal) { + ExtractStdString singleString(paths); + if (singleString.check()) { + self.registerFeatureUsage(type, singleString(), internal); + } else { + self.registerFeatureUsage(type, PySequenceToVector<std::string>(paths)(), + internal); + } +} + } // namespace void export_UsageService() { + enum_<Mantid::Kernel::FeatureType>("FeatureType") + .value("Algorithm", Mantid::Kernel::FeatureType::Algorithm) + .value("Interface", Mantid::Kernel::FeatureType::Interface) + .value("Feature", Mantid::Kernel::FeatureType::Feature); class_<UsageServiceImpl, boost::noncopyable>("UsageServiceImpl", no_init) .def("flush", &UsageServiceImpl::flush, arg("self"), @@ -64,7 +86,7 @@ void export_UsageService() { arg("self"), "Gets the application name that has invoked Mantid.") .def("registerStartup", &UsageServiceImpl::registerStartup, arg("self"), "Registers the startup of Mantid.") - .def("registerFeatureUsage", &UsageServiceImpl::registerFeatureUsage, + .def("registerFeatureUsage", ®isterFeatureUsage, (arg("self"), arg("type"), arg("name"), arg("internal")), "Registers the use of a feature in Mantid.") .def("getStartTime", &UsageServiceImpl::getStartTime, (arg("self")), diff --git a/Framework/PythonInterface/plugins/algorithms/HFIRSANS2Wavelength.py b/Framework/PythonInterface/plugins/algorithms/HFIRSANS2Wavelength.py index 1e97c77719d93bb4fd613b786303c95e3364495f..08555abd701271d1e9e8f1c1dbcdd7193e61f855 100644 --- a/Framework/PythonInterface/plugins/algorithms/HFIRSANS2Wavelength.py +++ b/Framework/PythonInterface/plugins/algorithms/HFIRSANS2Wavelength.py @@ -32,6 +32,7 @@ class HFIRSANS2Wavelength(PythonAlgorithm): try: wavelength = runObj['wavelength'].getStatistics().mean wavelength_spread = runObj['wavelength_spread'].getStatistics().mean + wavelength_spread *= wavelength except: raise ValueError("Could not read wavelength and wavelength_spread logs from the workspace") progress = Progress(self, 0.0, 1.0, 4) diff --git a/Framework/PythonInterface/test/python/mantid/kernel/UsageServiceTest.py b/Framework/PythonInterface/test/python/mantid/kernel/UsageServiceTest.py index 01a57c0c759078414c4e015f3985deb3d2b28643..555f1bc3c0de43989b139f59b48cde7e9a64c751 100644 --- a/Framework/PythonInterface/test/python/mantid/kernel/UsageServiceTest.py +++ b/Framework/PythonInterface/test/python/mantid/kernel/UsageServiceTest.py @@ -8,7 +8,7 @@ from __future__ import (absolute_import, division, print_function, unicode_liter import unittest -from mantid.kernel import (UsageService, UsageServiceImpl) +from mantid.kernel import (UsageService, UsageServiceImpl, FeatureType) class UsageServiceTest(unittest.TestCase): @@ -43,7 +43,10 @@ class UsageServiceTest(unittest.TestCase): def test_registerFeatureUsage(self): UsageService.setEnabled(False) #this will do nothing as it is disabled - UsageService.registerFeatureUsage("Algorithm", "Test.v1", True) + UsageService.registerFeatureUsage(FeatureType.Algorithm, "testv1", True) + UsageService.setEnabled(True) + UsageService.registerFeatureUsage(FeatureType.Algorithm, "testv1", True) + UsageService.registerFeatureUsage(FeatureType.Algorithm, ["testv1","level2feature"], True) def test_Flush(self): diff --git a/Framework/PythonInterface/test/python/plugins/algorithms/HFIRSANS2WavelengthTest.py b/Framework/PythonInterface/test/python/plugins/algorithms/HFIRSANS2WavelengthTest.py index cd4bc1a572c4e5ab7b7ba60798d5b4033a5b4207..ae3be4f2a61ea7372218554be5cfb0d6c33f36d4 100644 --- a/Framework/PythonInterface/test/python/plugins/algorithms/HFIRSANS2WavelengthTest.py +++ b/Framework/PythonInterface/test/python/plugins/algorithms/HFIRSANS2WavelengthTest.py @@ -18,7 +18,7 @@ class HFIRSANS2WavelengthTest(unittest.TestCase): UnitX="TOF", NSpec=2) AddSampleLog(ws, LogName='wavelength', LogText='6.5', LogType='Number Series') - AddSampleLog(ws, LogName='wavelength_spread', LogText='1.0', LogType='Number Series') + AddSampleLog(ws, LogName='wavelength_spread', LogText='0.1', LogType='Number Series') def tearDown(self): mtd.clear() @@ -28,8 +28,8 @@ class HFIRSANS2WavelengthTest(unittest.TestCase): out = HFIRSANS2Wavelength(InputWorkspace="ws") self.assertTrue(out) self.assertEqual(out.blocksize(), 1) - self.assertEqual(out.readX(0)[0], 6) - self.assertEqual(out.readX(1)[1], 7) + self.assertEqual(out.readX(0)[0], 6.175) + self.assertEqual(out.readX(1)[1], 6.825) self.assertEqual(out.readY(0)[0], 24) self.assertAlmostEqual(out.readE(1)[0], 7.071067, 5) self.assertEqual(out.getAxis(0).getUnit().caption(), 'Wavelength') diff --git a/MantidPlot/src/Mantid/InstrumentWidget/InstrumentWindow.cpp b/MantidPlot/src/Mantid/InstrumentWidget/InstrumentWindow.cpp index cdc4a45b96bfd0a11f3fb687f85268e13f3d7a07..408de306a833fccfb32e4dc40eb3677a23a57570 100644 --- a/MantidPlot/src/Mantid/InstrumentWidget/InstrumentWindow.cpp +++ b/MantidPlot/src/Mantid/InstrumentWidget/InstrumentWindow.cpp @@ -41,7 +41,7 @@ InstrumentWindow::InstrumentWindow(const QString &wsName, const QString &label, connect(m_instrumentWidget, SIGNAL(clearingHandle()), this, SLOT(closeSafely())); Mantid::Kernel::UsageService::Instance().registerFeatureUsage( - "Interface", "InstrumentView", false); + Mantid::Kernel::FeatureType::Interface, "InstrumentView", false); } InstrumentWindow::~InstrumentWindow() {} diff --git a/MantidPlot/src/ProjectRecovery.cpp b/MantidPlot/src/ProjectRecovery.cpp index a16b7623277af3d724054e631c57794ac33e91ef..131eb06af79472867a6f89ca0089dbf5fc0bad97 100644 --- a/MantidPlot/src/ProjectRecovery.cpp +++ b/MantidPlot/src/ProjectRecovery.cpp @@ -309,7 +309,8 @@ ProjectRecovery::~ProjectRecovery() { void ProjectRecovery::attemptRecovery() { Mantid::Kernel::UsageService::Instance().registerFeatureUsage( - "Feature", "ProjectRecovery->AttemptRecovery", true); + Mantid::Kernel::FeatureType::Feature, + {"ProjectRecovery", "AttemptRecovery"}, true); m_recoveryGui = new ProjectRecoveryPresenter(this, m_windowPtr); bool failed = m_recoveryGui->startRecoveryView(); diff --git a/MantidPlot/src/ProjectRecoveryGUIs/ProjectRecoveryView.cpp b/MantidPlot/src/ProjectRecoveryGUIs/ProjectRecoveryView.cpp index 4e44af806e4539d7572914d56536775f56e43957..4d92f4753af7e2b25f18ed5c7c67859c4df67e75 100644 --- a/MantidPlot/src/ProjectRecoveryGUIs/ProjectRecoveryView.cpp +++ b/MantidPlot/src/ProjectRecoveryGUIs/ProjectRecoveryView.cpp @@ -21,7 +21,7 @@ ProjectRecoveryView::ProjectRecoveryView(QWidget *parent, // Set the table information addDataToTable(); Mantid::Kernel::UsageService::Instance().registerFeatureUsage( - "Interface", "ProjectRecoveryWindow", true); + Mantid::Kernel::FeatureType::Interface, "ProjectRecoveryWindow", true); } void ProjectRecoveryView::addDataToTable() { @@ -34,28 +34,32 @@ void ProjectRecoveryView::onClickLastCheckpoint() { // Recover last checkpoint m_presenter->recoverLast(); Mantid::Kernel::UsageService::Instance().registerFeatureUsage( - "Feature", "ProjectRecoveryWindow->RecoverLastCheckpoint", false); + Mantid::Kernel::FeatureType::Feature, + {"ProjectRecoveryWindow", "RecoverLastCheckpoint"}, false); } void ProjectRecoveryView::onClickOpenLastInScriptWindow() { // Open checkpoint in script window m_presenter->openLastInEditor(); Mantid::Kernel::UsageService::Instance().registerFeatureUsage( - "Feature", "ProjectRecoveryWindow->OpenInScriptWindow", false); + Mantid::Kernel::FeatureType::Feature, + {"ProjectRecoveryWindow", "OpenInScriptWindow"}, false); } void ProjectRecoveryView::onClickStartMantidNormally() { // Start save and close this, clear checkpoint that was offered for load m_presenter->startMantidNormally(); Mantid::Kernel::UsageService::Instance().registerFeatureUsage( - "Feature", "ProjectRecoveryWindow->StartMantidNormally", false); + Mantid::Kernel::FeatureType::Feature, + {"ProjectRecoveryWindow", "StartMantidNormally"}, false); } void ProjectRecoveryView::reject() { // Do the same as startMantidNormally m_presenter->startMantidNormally(); Mantid::Kernel::UsageService::Instance().registerFeatureUsage( - "Feature", "ProjectRecoveryWindow->StartMantidNormally", false); + Mantid::Kernel::FeatureType::Feature, + {"ProjectRecoveryWindow", "StartMantidNormally"}, false); } void ProjectRecoveryView::updateProgressBar(int newValue, bool err) { diff --git a/MantidPlot/src/ProjectRecoveryGUIs/RecoveryFailureView.cpp b/MantidPlot/src/ProjectRecoveryGUIs/RecoveryFailureView.cpp index a8fd18f5995ebd5297582039c6b6be773fc1627b..f6cc6b9229dc8a89f71d27e123782f9aecc052df 100644 --- a/MantidPlot/src/ProjectRecoveryGUIs/RecoveryFailureView.cpp +++ b/MantidPlot/src/ProjectRecoveryGUIs/RecoveryFailureView.cpp @@ -22,7 +22,8 @@ RecoveryFailureView::RecoveryFailureView(QWidget *parent, // Set the table information addDataToTable(); Mantid::Kernel::UsageService::Instance().registerFeatureUsage( - "Interface", "ProjectRecoveryFailureWindow", true); + Mantid::Kernel::FeatureType::Interface, "ProjectRecoveryFailureWindow", + true); } void RecoveryFailureView::addDataToTable() { @@ -41,7 +42,8 @@ void RecoveryFailureView::onClickLastCheckpoint() { // Recover last checkpoint m_presenter->recoverLast(); Mantid::Kernel::UsageService::Instance().registerFeatureUsage( - "Feature", "ProjectRecoveryFailureWindow->RecoverLastCheckpoint", false); + Mantid::Kernel::FeatureType::Feature, + {"ProjectRecoveryFailureWindow", "RecoverLastCheckpoint"}, false); } void RecoveryFailureView::onClickSelectedCheckpoint() { @@ -55,8 +57,8 @@ void RecoveryFailureView::onClickSelectedCheckpoint() { m_presenter->recoverSelectedCheckpoint(text); } Mantid::Kernel::UsageService::Instance().registerFeatureUsage( - "Feature", "ProjectRecoveryFailureWindow->RecoverSelectedCheckpoint", - false); + Mantid::Kernel::FeatureType::Feature, + {"ProjectRecoveryFailureWindow", "RecoverSelectedCheckpoint"}, false); } void RecoveryFailureView::onClickOpenSelectedInScriptWindow() { @@ -70,22 +72,24 @@ void RecoveryFailureView::onClickOpenSelectedInScriptWindow() { m_presenter->openSelectedInEditor(text); } Mantid::Kernel::UsageService::Instance().registerFeatureUsage( - "Feature", "ProjectRecoveryFailureWindow->OpenSelectedInScriptWindow", - false); + Mantid::Kernel::FeatureType::Feature, + {"ProjectRecoveryFailureWindow", "OpenSelectedInScriptWindow"}, false); } void RecoveryFailureView::onClickStartMantidNormally() { // Start save and close this, clear checkpoint that was offered for load m_presenter->startMantidNormally(); Mantid::Kernel::UsageService::Instance().registerFeatureUsage( - "Feature", "ProjectRecoveryFailureWindow->StartMantidNormally", false); + Mantid::Kernel::FeatureType::Feature, + {"ProjectRecoveryFailureWindow", "StartMantidNormally"}, false); } void RecoveryFailureView::reject() { // Do nothing just absorb request m_presenter->startMantidNormally(); Mantid::Kernel::UsageService::Instance().registerFeatureUsage( - "Feature", "ProjectRecoveryFailureWindow->StartMantidNormally", false); + Mantid::Kernel::FeatureType::Feature, + {"ProjectRecoveryFailureWindow", "StartMantidNormally"}, false); } void RecoveryFailureView::updateProgressBar(const int newValue, diff --git a/buildconfig/Jenkins/buildscript b/buildconfig/Jenkins/buildscript index 6af8bae413f127429f79d76da02ba6d5a3231cab..1178fdce29d1c0a03ac17c7265e7b1c3e91e5f90 100755 --- a/buildconfig/Jenkins/buildscript +++ b/buildconfig/Jenkins/buildscript @@ -11,18 +11,9 @@ ############################################################################### SCRIPT_DIR=$(dirname "$0") XVFB_SERVER_NUM=101 +XVFB_ERROR_LOG_PREFIX=${WORKSPACE}/mantid-xvfb-error ULIMIT_CORE_ORIG=$(ulimit -c) -if [ $(command -v xvfb-run) ]; then - X11_RUNNER="xvfb-run" - X11_RUNNER_ARGS1=--server-args="-screen 0 640x480x24" - X11_RUNNER_ARGS2=--server-num=${XVFB_SERVER_NUM} -else - X11_RUNNER="eval" - X11_RUNNER_ARGS1="" - X11_RUNNER_ARGS2="" -fi - ############################################################################### # Functions ############################################################################### @@ -34,7 +25,15 @@ function onexit { } function run_with_xvfb { - ${X11_RUNNER} "${X11_RUNNER_ARGS1}" "${X11_RUNNER_ARGS2}" $@ + if [ $(command -v xvfb-run) ]; then + # -e=--error-file. A bug in Xvfb on RHEL7 means --error-file + # produces an error: https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=337703;msg=2 + xvfb-run --server-args="-screen 0 640x480x24" \ + --server-num=${XVFB_SERVER_NUM} \ + -e ${XVFB_ERROR_LOG_PREFIX}-`date +%y-%m-%d-%H-%M`.xlog $@ + else + eval $@ + fi } @@ -49,6 +48,9 @@ if [ $(command -v xvfb-run) ]; then # Remove Xvfb X server lock files rm -f /tmp/.X${XVFB_SERVER_NUM}-lock + + # Remove any Xvfb error logs + rm -f ${XVFB_ERROR_LOG_PREFIX}*.xlog fi ############################################################################### diff --git a/buildconfig/dev-packages/deb/mantid-developer/ns-control b/buildconfig/dev-packages/deb/mantid-developer/ns-control index dcebbde10ca6a1007449230808529454b3fdffa4..de83b01b18db0e772d662d0eac20ed68bd083915 100644 --- a/buildconfig/dev-packages/deb/mantid-developer/ns-control +++ b/buildconfig/dev-packages/deb/mantid-developer/ns-control @@ -42,7 +42,6 @@ Depends: git, python-setuptools, python-numpy, python-scipy, - python-skimage, python-qt4-dev, python-qt4-dbg, pyqt5-dev, @@ -70,7 +69,6 @@ Depends: git, python3-qtpy, python3-numpy, python3-scipy, - python3-skimage, python3-sphinx, python3-sphinx-bootstrap-theme, python3-dateutil, diff --git a/buildconfig/dev-packages/rpm/mantid-developer/mantid-developer.spec b/buildconfig/dev-packages/rpm/mantid-developer/mantid-developer.spec index 1d38f40976f3c4b91ab0cf0415f511eca51a3baa..f5a9a55f41cf8dafd6a59dbe1078dd457350883f 100644 --- a/buildconfig/dev-packages/rpm/mantid-developer/mantid-developer.spec +++ b/buildconfig/dev-packages/rpm/mantid-developer/mantid-developer.spec @@ -5,7 +5,7 @@ %endif Name: mantid-developer -Version: 1.33 +Version: 1.34 Release: 1%{?dist} Summary: Meta Package to install dependencies for Mantid Development @@ -19,7 +19,8 @@ BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n) Requires: clang %{?fedora:Requires: cmake-gui} %{?rhel:Requires: cmake3-gui} -Requires: boost-devel +Requires: boost169-devel +Requires: boost169-python2-devel Requires: doxygen Requires: gperftools-devel Requires: gperftools-libs @@ -40,15 +41,15 @@ Requires: numpy Requires: OCE-devel Requires: poco-devel >= 1.4.6 Requires: PyQt4-devel -Requires: python-qt5-devel +Requires: python2-qt5-devel Requires: python-QtPy Requires: python-requests Requires: python-devel Requires: python-setuptools Requires: python-ipython >= 1.1 -Requires: python-matplotlib -%{?fedora:Requires: python2-matplotlib-qt4} -%{?el7:Requires: python-matplotlib-qt4} +Requires: python2-matplotlib +Requires: python2-matplotlib-qt4 +Requires: python2-matplotlib-qt4 Requires: python-pip %{?fedora:Requires: python2-qtconsole} Requires: python-sphinx @@ -63,7 +64,6 @@ Requires: qwtplot3d-qt4-devel Requires: redhat-lsb Requires: rpmdevtools Requires: scipy -Requires: python2-scikit-image Requires: sip-devel Requires: tbb Requires: tbb-devel @@ -91,7 +91,7 @@ Requires: graphviz Requires: python3-setuptools Requires: python3-sip-devel Requires: python3-PyQt4-devel -Requires: python-qt5-devel +Requires: python3-qt5-devel Requires: python3-QtPy Requires: python3-numpy Requires: python3-scipy @@ -111,11 +111,17 @@ Requires: boost-python3-devel %endif %if 0%{?el7} -Requires: boost-python36-devel -Requires: python36-devel -Requires: python36-h5py +Requires: python36-setuptools +Requires: python36-qt5-devel Requires: python36-numpy +Requires: python36-scipy +Requires: python36-sphinx +Requires: python36-dateutil Requires: python36-PyYAML +Requires: python36-mock +Requires: python36-psutil +Requires: python36-requests +Requires: boost169-python3-devel %endif BuildArch: noarch @@ -140,6 +146,19 @@ required for Mantid development. %changelog +* Tue Nov 5 2019 Martyn Gigg <martyn.gigg@stfc.ac.uk> +- Switch to python{2,3}-qt5-devel +- Remove python2-scikit-image +- Add remaining python36 packages that exist. + Missing: + * python36-h5py + * python36-qt4 + * python36-QtPy + * python36-sphinx-bootstrap-theme + * python36-matplotlib + * python36-ipython-gui +- Add boost169 + * Thu Jun 27 2019 Peter Peterson <petersonpf@ornl.gov> - Added python3 dependencies for framework on rhel7 diff --git a/docs/source/algorithms/HFIRSANS2Wavelength-v1.rst b/docs/source/algorithms/HFIRSANS2Wavelength-v1.rst index 610a468e39ced401197ca1d8f0469495925a54ef..9992ce066ea0f5b83bb07b60fe7f908a660e3bc2 100644 --- a/docs/source/algorithms/HFIRSANS2Wavelength-v1.rst +++ b/docs/source/algorithms/HFIRSANS2Wavelength-v1.rst @@ -41,8 +41,8 @@ Output: .. testoutput:: HFIRSANS2Wavelength 1 - 6.0 - 7.0 + 3.25 + 9.75 Wavelength .. categories:: diff --git a/qt/applications/workbench/workbench/plotting/figuremanager.py b/qt/applications/workbench/workbench/plotting/figuremanager.py index 988643e12e9a7a32ce9a1d961a1d425f83494599..09cca35cbaaade1d07af4fa142d3351bc9f2da4f 100644 --- a/qt/applications/workbench/workbench/plotting/figuremanager.py +++ b/qt/applications/workbench/workbench/plotting/figuremanager.py @@ -209,6 +209,7 @@ class FigureManagerWorkbench(FigureManagerBase, QObject): self.generate_plot_script_clipboard) self.toolbar.sig_generate_plot_script_file_triggered.connect( self.generate_plot_script_file) + self.toolbar.sig_home_clicked.connect(self.set_figure_zoom_to_display_all) self.toolbar.setFloatable(False) tbs_height = self.toolbar.sizeHint().height() else: @@ -398,6 +399,20 @@ class FigureManagerWorkbench(FigureManagerBase, QObject): if toolbar_action == action: self.toolbar.actions()[i+1].setVisible(enabled) + def set_figure_zoom_to_display_all(self): + axes = self.canvas.figure.get_axes() + if axes: + for ax in axes: + # We check for axes type below as a pseudo check for an axes being + # a colorbar. this is based on the same check in + # FigureManagerADSObserver.deleteHandle. + if type(ax) is not Axes: + if ax.lines: # Relim causes issues with colour plots, which have no lines. + ax.relim() + ax.autoscale() + + self.canvas.draw() + # ----------------------------------------------------------------------------- # Figure control diff --git a/qt/applications/workbench/workbench/plotting/figurewindow.py b/qt/applications/workbench/workbench/plotting/figurewindow.py index d87c9e8adab4e25b76baa684e430f64a36017410..ef14a45c62d105fa4af20073873bdd7cfca22ea8 100644 --- a/qt/applications/workbench/workbench/plotting/figurewindow.py +++ b/qt/applications/workbench/workbench/plotting/figurewindow.py @@ -11,7 +11,6 @@ from __future__ import absolute_import # std imports -import platform import weakref # 3rdparty imports @@ -40,13 +39,14 @@ class FigureWindow(QMainWindow, ObservingView): self.setAttribute(Qt.WA_DeleteOnClose, True) self.setWindowIcon(QIcon(':/images/MantidIcon.ico')) - # On Windows, setting the Workbench's main window as this window's - # parent always keeps this window on top, but still allows minimization. - # On Ubuntu the child is NOT kept above the parent, hence we use the - # focusWindowChanged event to bring this window back to the top when - # the main window gets focus. This does cause a slight flicker effect - # as the window is hidden and quickly brought back to the front. Using - # the parent-child method at least avoids this flicker on Windows. + # We use the focusWindowChanged event to bring this window back to the + # top when the main window gets focus. This does cause a slight flicker + # effect as the window is hidden and quickly brought back to the front. + + # Using the parent-child method was tried. This worked on windows but + # not on Ubuntu as the child is NOT kept above the parent. + # However this is not used for windows as whenever a plot was done by + # an interface it moved behind workbench. # Using the Qt.WindowStaysOnTopFlag was tried, however this caused the # window to stay on top of all other windows, including external @@ -57,11 +57,7 @@ class FigureWindow(QMainWindow, ObservingView): # Using the Qt.Tool flag, and setting the main window as this window's # parent, keeps this window on top. However it does not allow the # window to be minimized. - if platform.system() == "Windows": - from workbench.utils.windowfinder import get_main_window_widget - self.setParent(get_main_window_widget(), Qt.Window) - else: - QApplication.instance().focusWindowChanged.connect(self._on_focusWindowChanged) + QApplication.instance().focusWindowChanged.connect(self._on_focusWindowChanged) self.close_signal.connect(self._run_close) self.setAcceptDrops(True) diff --git a/qt/paraview_ext/VatesSimpleGui/ViewWidgets/src/MdViewerWidget.cpp b/qt/paraview_ext/VatesSimpleGui/ViewWidgets/src/MdViewerWidget.cpp index 78df4cc5a8c5ba3fd723accb729f58eba7ce2fd3..7bf1d23949921bbc4226c9bdff6b87b9ec1d8103 100644 --- a/qt/paraview_ext/VatesSimpleGui/ViewWidgets/src/MdViewerWidget.cpp +++ b/qt/paraview_ext/VatesSimpleGui/ViewWidgets/src/MdViewerWidget.cpp @@ -352,8 +352,8 @@ ViewBase *MdViewerWidget::createAndSetMainViewWidget(QWidget *container, view->setColorScaleLock(&m_colorScaleLock); using Mantid::Kernel::UsageService; - UsageService::Instance().registerFeatureUsage("Interface", featureName, - false); + UsageService::Instance().registerFeatureUsage( + Mantid::Kernel::FeatureType::Interface, featureName, false); return view; } diff --git a/qt/python/mantidqt/dialogs/spectraselectordialog.py b/qt/python/mantidqt/dialogs/spectraselectordialog.py index c564ec3b59b06a06bb043682a96f629f09cfa329..44369091ba3f15c9706aa569df27b047251983bc 100644 --- a/qt/python/mantidqt/dialogs/spectraselectordialog.py +++ b/qt/python/mantidqt/dialogs/spectraselectordialog.py @@ -130,6 +130,8 @@ class SpectraSelectionDialog(SpectraSelectionDialogUIBase): for sp_set in ws_spectra[1:]: plottable = plottable.intersection(sp_set) plottable = sorted(plottable) + if len(plottable) == 0: + raise Exception('Error: Workspaces have no common spectra.') spec_min, spec_max = min(plottable), max(plottable) self._ui.specNums.setPlaceholderText(PLACEHOLDER_FORMAT.format(spec_min, spec_max)) self.spec_min, self.spec_max = spec_min, spec_max diff --git a/qt/python/mantidqt/dialogs/spectraselectorutils.py b/qt/python/mantidqt/dialogs/spectraselectorutils.py index 7c3b7de71ca9f4d747b37196a11098c9dff333f2..26e66111b87cdb0ec55b0ff570b539e14d1ba18f 100644 --- a/qt/python/mantidqt/dialogs/spectraselectorutils.py +++ b/qt/python/mantidqt/dialogs/spectraselectorutils.py @@ -24,9 +24,20 @@ def get_spectra_selection(workspaces, parent_widget=None, show_colorfill_btn=Fal """ SpectraSelectionDialog.raise_error_if_workspaces_not_compatible(workspaces) single_spectra_ws = [wksp.getNumberHistograms() for wksp in workspaces if wksp.getNumberHistograms() == 1] - if len(single_spectra_ws) > 0 and len(workspaces) == 1: - # At least 1 workspace contains only a single spectrum so this is all - # that is possible to plot for all of them + + if len(workspaces) == len(single_spectra_ws): + plottable = [] + else: + ws_spectra = [{ws.getSpectrum(i).getSpectrumNo() for i in range(ws.getNumberHistograms())} for ws in workspaces] + plottable = ws_spectra[0] + # check if there are no common spectra in workspaces + if len(ws_spectra) > 1: + for sp_set in ws_spectra[1:]: + plottable = plottable.intersection(sp_set) + + if len(single_spectra_ws) == len(workspaces) or len(plottable) == 0: + # At least 1 workspace contains only a single spectrum and these are no + # common spectra selection = SpectraSelection(workspaces) selection.wksp_indices = [0] return selection diff --git a/qt/python/mantidqt/dialogs/test/test_spectraselectiondialog.py b/qt/python/mantidqt/dialogs/test/test_spectraselectiondialog.py index f3427bd24104105fcfdb57f69c7f4689d2fdd842..4c16093eb3c0918a838a3ace20ce9bf0121956e5 100644 --- a/qt/python/mantidqt/dialogs/test/test_spectraselectiondialog.py +++ b/qt/python/mantidqt/dialogs/test/test_spectraselectiondialog.py @@ -11,6 +11,7 @@ from qtpy.QtWidgets import QDialogButtonBox from mantid.api import WorkspaceFactory from mantid.py3compat import mock +from mantid.simpleapi import ExtractSpectra from mantidqt.dialogs.spectraselectordialog import parse_selection_str, SpectraSelectionDialog from mantidqt.dialogs.spectraselectorutils import get_spectra_selection from mantidqt.utils.qt.testing import start_qapplication @@ -137,6 +138,12 @@ class SpectraSelectionDialogTest(unittest.TestCase): table = WorkspaceFactory.Instance().createTable() self.assertRaises(ValueError, get_spectra_selection, [self._single_spec_ws, table]) + def test_set_placeholder_text_raises_error_if_workspaces_have_no_common_spectra(self): + spectra_1 = ExtractSpectra(InputWorkspace=self._multi_spec_ws, StartWorkspaceIndex=0, EndWorkspaceIndex=5) + spectra_2 = ExtractSpectra(InputWorkspace=self._multi_spec_ws, StartWorkspaceIndex=6, EndWorkspaceIndex=10) + workspaces = [spectra_1, spectra_2] + self.assertRaises(Exception, 'Error: Workspaces have no common spectra.', SpectraSelectionDialog, workspaces) + if __name__ == '__main__': unittest.main() diff --git a/qt/python/mantidqt/dialogs/test/test_spectraselectorutils.py b/qt/python/mantidqt/dialogs/test/test_spectraselectorutils.py index c0b04c284799355829c6a56d724c486b60a3477a..c91661ca720578581ed1ca7974e78cb38cba9dc2 100644 --- a/qt/python/mantidqt/dialogs/test/test_spectraselectorutils.py +++ b/qt/python/mantidqt/dialogs/test/test_spectraselectorutils.py @@ -11,6 +11,7 @@ import unittest from mantid.api import WorkspaceFactory from mantid.py3compat import mock +from mantid.simpleapi import ExtractSpectra from mantidqt.dialogs.spectraselectorutils import get_spectra_selection from mantidqt.utils.qt.testing import start_qapplication from qtpy.QtGui import QIcon @@ -58,3 +59,17 @@ class SpectraSelectionUtilsTest(unittest.TestCase): dialog_mock.assert_not_called() self.assertEqual([0], selection.wksp_indices) self.assertEqual([self._single_spec_ws], selection.workspaces) + + @mock.patch('mantidqt.dialogs.spectraselectorutils.SpectraSelectionDialog') + def test_get_spectra_selection_does_not_use_dialog_for_multiple__single_spectrum(self, dialog_mock): + spectra_1 = ExtractSpectra(InputWorkspace=self._multi_spec_ws, StartWorkspaceIndex=0, EndWorkspaceIndex=0) + spectra_2 = ExtractSpectra(InputWorkspace=self._multi_spec_ws, StartWorkspaceIndex=1, EndWorkspaceIndex=1) + selection = get_spectra_selection([spectra_1, spectra_2]) + + dialog_mock.assert_not_called() + self.assertEqual([0], selection.wksp_indices) + self.assertEqual([spectra_1, spectra_2], selection.workspaces) + + +if __name__ == '__main__': + unittest.main() diff --git a/qt/scientific_interfaces/DynamicPDF/DPDFBackgroundRemover.cpp b/qt/scientific_interfaces/DynamicPDF/DPDFBackgroundRemover.cpp index 2eab1e7a382b9f555aaeffa56c62d68be09ced6a..9064d38947f967af87b1056aa9a944b988eea35f 100644 --- a/qt/scientific_interfaces/DynamicPDF/DPDFBackgroundRemover.cpp +++ b/qt/scientific_interfaces/DynamicPDF/DPDFBackgroundRemover.cpp @@ -39,7 +39,8 @@ BackgroundRemover::BackgroundRemover(QWidget *parent) : UserSubWindow{parent}, m_sliceSelector(), m_inputDataControl(), m_displayControl(), m_fitControl{nullptr}, m_fourierTransform{nullptr} { Mantid::Kernel::UsageService::Instance().registerFeatureUsage( - "Interface", "DynamicPDF->BackgroundRemover", false); + Mantid::Kernel::FeatureType::Interface, + {"DynamicPDF", "BackgroundRemover"}, false); } /** diff --git a/qt/scientific_interfaces/DynamicPDF/SliceSelector.cpp b/qt/scientific_interfaces/DynamicPDF/SliceSelector.cpp index 217672043b3b2a924c77a530d45e3e2942270774..e273ee5130a05d579cc89ae643c5f89141bde4d3 100644 --- a/qt/scientific_interfaces/DynamicPDF/SliceSelector.cpp +++ b/qt/scientific_interfaces/DynamicPDF/SliceSelector.cpp @@ -71,7 +71,8 @@ SliceSelector::SliceSelector(QWidget *parent) m_loadedWorkspace(), m_selectedWorkspaceIndex{0} { this->observePreDelete(true); // Subscribe to notifications Mantid::Kernel::UsageService::Instance().registerFeatureUsage( - "Feature", "DynamicPDF->SliceSelector", false); + Mantid::Kernel::FeatureType::Feature, {"DynamicPDF", "SliceSelector"}, + false); this->initLayout(); } diff --git a/qt/scientific_interfaces/ISISReflectometry/GUI/Event/QtEventView.cpp b/qt/scientific_interfaces/ISISReflectometry/GUI/Event/QtEventView.cpp index a0b3a9d92d630dffa8013f200fda388a0a0bd844..8fd1df390db72e16a7984189f4217f75a1531465 100644 --- a/qt/scientific_interfaces/ISISReflectometry/GUI/Event/QtEventView.cpp +++ b/qt/scientific_interfaces/ISISReflectometry/GUI/Event/QtEventView.cpp @@ -194,7 +194,8 @@ void QtEventView::enableSliceTypeSelection() { void QtEventView::onToggleUniform(bool isChecked) { if (isChecked) { Mantid::Kernel::UsageService::Instance().registerFeatureUsage( - "Feature", "ISIS Reflectometry->EventTab->EnableUniformSlicing", false); + Mantid::Kernel::FeatureType::Feature, + {"ISIS Reflectometry", "EventTab", "EnableUniformSlicing"}, false); m_notifyee->notifySliceTypeChanged(SliceType::Uniform); } } @@ -202,8 +203,8 @@ void QtEventView::onToggleUniform(bool isChecked) { void QtEventView::onToggleUniformEven(bool isChecked) { if (isChecked) { Mantid::Kernel::UsageService::Instance().registerFeatureUsage( - "Feature", "ISIS Reflectometry->EventTab->EnableUniformEvenSlicing", - false); + Mantid::Kernel::FeatureType::Feature, + {"ISIS Reflectometry", "EventTab", "EnableUniformEvenSlicing"}, false); m_notifyee->notifySliceTypeChanged(SliceType::UniformEven); } } @@ -211,7 +212,8 @@ void QtEventView::onToggleUniformEven(bool isChecked) { void QtEventView::onToggleCustom(bool isChecked) { if (isChecked) { Mantid::Kernel::UsageService::Instance().registerFeatureUsage( - "Feature", "ISIS Reflectometry->EventTab->EnableCustomSlicing", false); + Mantid::Kernel::FeatureType::Feature, + {"ISIS Reflectometry", "EventTab", "EnableCustomSlicing"}, false); m_notifyee->notifySliceTypeChanged(SliceType::Custom); } } @@ -219,8 +221,8 @@ void QtEventView::onToggleCustom(bool isChecked) { void QtEventView::onToggleLogValue(bool isChecked) { if (isChecked) { Mantid::Kernel::UsageService::Instance().registerFeatureUsage( - "Feature", "ISIS Reflectometry->EventTab->EnableLogValueSlicing", - false); + Mantid::Kernel::FeatureType::Feature, + {"ISIS Reflectometry", "EventTab", "EnableLogValueSlicing"}, false); m_notifyee->notifySliceTypeChanged(SliceType::LogValue); } } @@ -228,7 +230,8 @@ void QtEventView::onToggleLogValue(bool isChecked) { void QtEventView::onToggleDisabledSlicing(bool isChecked) { if (isChecked) { Mantid::Kernel::UsageService::Instance().registerFeatureUsage( - "Feature", "ISIS Reflectometry->EventTab->DisableSlicing", false); + Mantid::Kernel::FeatureType::Feature, + {"ISIS Reflectometry", "EventTab", "DisableSlicing"}, false); m_notifyee->notifySliceTypeChanged(SliceType::None); } } diff --git a/qt/scientific_interfaces/ISISReflectometry/GUI/Experiment/QtExperimentView.cpp b/qt/scientific_interfaces/ISISReflectometry/GUI/Experiment/QtExperimentView.cpp index e51d7ed1e25907228075731575bb569cde38b543..ba882e52d94feb0b8e98e2e23524c3ea1b58bd9a 100644 --- a/qt/scientific_interfaces/ISISReflectometry/GUI/Experiment/QtExperimentView.cpp +++ b/qt/scientific_interfaces/ISISReflectometry/GUI/Experiment/QtExperimentView.cpp @@ -54,7 +54,8 @@ QtExperimentView::QtExperimentView( void QtExperimentView::onRemovePerThetaDefaultsRequested() { Mantid::Kernel::UsageService::Instance().registerFeatureUsage( - "Feature", "ISIS Reflectometry->ExperimentTab->RemovePerThetaDefaultsRow", + Mantid::Kernel::FeatureType::Feature, + {"ISIS Reflectometry", "ExperimentTab", "RemovePerThetaDefaultsRow"}, false); auto index = m_ui.optionsTable->currentIndex(); if (index.isValid()) { @@ -288,7 +289,8 @@ void QtExperimentView::disconnectExperimentSettingsWidgets() { void QtExperimentView::onRestoreDefaultsRequested() { Mantid::Kernel::UsageService::Instance().registerFeatureUsage( - "Feature", "ISIS Reflectometry->ExperimentTab->RestoreDefaults", false); + Mantid::Kernel::FeatureType::Feature, + {"ISIS Reflectometry", "ExperimentTab", "RestoreDefaults"}, false); m_notifyee->notifyRestoreDefaultsRequested(); } @@ -449,8 +451,8 @@ void QtExperimentView::onPerAngleDefaultsChanged(int row, int column) { /** Add a new row to the transmission runs table **/ void QtExperimentView::onNewPerThetaDefaultsRowRequested() { Mantid::Kernel::UsageService::Instance().registerFeatureUsage( - "Feature", "ISIS Reflectometry->ExperimentTab->AddPerThetaDefaultsRow", - false); + Mantid::Kernel::FeatureType::Feature, + {"ISIS Reflectometry", "ExperimentTab", "AddPerThetaDefaultsRow"}, false); m_notifyee->notifyNewPerAngleDefaultsRequested(); } diff --git a/qt/scientific_interfaces/ISISReflectometry/GUI/Instrument/QtInstrumentView.cpp b/qt/scientific_interfaces/ISISReflectometry/GUI/Instrument/QtInstrumentView.cpp index aafdd24556fb70d99dc72cd5eb6e7afa90ce7d87..26b2ef3383771fd470f8719fe0c8973a334eac10 100644 --- a/qt/scientific_interfaces/ISISReflectometry/GUI/Instrument/QtInstrumentView.cpp +++ b/qt/scientific_interfaces/ISISReflectometry/GUI/Instrument/QtInstrumentView.cpp @@ -112,7 +112,8 @@ void QtInstrumentView::onSettingsChanged() { void QtInstrumentView::onRestoreDefaultsRequested() { Mantid::Kernel::UsageService::Instance().registerFeatureUsage( - "Feature", "ISIS Reflectometry->InstrumentTab->RestoreDefaults", false); + Mantid::Kernel::FeatureType::Feature, + {"ISIS Reflectometry", "InstrumentTab", "RestoreDefaults"}, false); m_notifyee->notifyRestoreDefaultsRequested(); } diff --git a/qt/scientific_interfaces/ISISReflectometry/GUI/MainWindow/QtMainWindowView.cpp b/qt/scientific_interfaces/ISISReflectometry/GUI/MainWindow/QtMainWindowView.cpp index e6e9238b1c405e2d313c57bd89348af3de7d9f06..e68d8dca0e186db16a430aaab510c656e977e93d 100644 --- a/qt/scientific_interfaces/ISISReflectometry/GUI/MainWindow/QtMainWindowView.cpp +++ b/qt/scientific_interfaces/ISISReflectometry/GUI/MainWindow/QtMainWindowView.cpp @@ -109,37 +109,43 @@ void QtMainWindowView::initLayout() { void QtMainWindowView::onTabCloseRequested(int tabIndex) { Mantid::Kernel::UsageService::Instance().registerFeatureUsage( - "Feature", "ISIS Reflectometry->MainWindow->CloseBatch", false); + Mantid::Kernel::FeatureType::Feature, + {"ISIS Reflectometry", "MainWindow", "CloseBatch"}, false); m_notifyee->notifyCloseBatchRequested(tabIndex); } void QtMainWindowView::onNewBatchRequested(bool) { Mantid::Kernel::UsageService::Instance().registerFeatureUsage( - "Feature", "ISIS Reflectometry->MainWindow->NewBatch", false); + Mantid::Kernel::FeatureType::Feature, + {"ISIS Reflectometry", "MainWindow", "NewBatch"}, false); m_notifyee->notifyNewBatchRequested(); } void QtMainWindowView::onLoadBatchRequested(bool) { Mantid::Kernel::UsageService::Instance().registerFeatureUsage( - "Feature", "ISIS Reflectometry->MainWindow->LoadBatch", false); + Mantid::Kernel::FeatureType::Feature, + {"ISIS Reflectometry", "MainWindow", "LoadBatch"}, false); m_notifyee->notifyLoadBatchRequested(m_ui.mainTabs->currentIndex()); } void QtMainWindowView::onSaveBatchRequested(bool) { Mantid::Kernel::UsageService::Instance().registerFeatureUsage( - "Feature", "ISIS Reflectometry->MainWindow->SaveBatch", false); + Mantid::Kernel::FeatureType::Feature, + {"ISIS Reflectometry", "MainWindow", "SaveBatch"}, false); m_notifyee->notifySaveBatchRequested(m_ui.mainTabs->currentIndex()); } void QtMainWindowView::onShowOptionsRequested(bool) { Mantid::Kernel::UsageService::Instance().registerFeatureUsage( - "Feature", "ISIS Reflectometry->MainWindow->ShowOptions", false); + Mantid::Kernel::FeatureType::Feature, + {"ISIS Reflectometry", "MainWindow", "ShowOptions"}, false); m_notifyee->notifyShowOptionsRequested(); } void QtMainWindowView::onShowSlitCalculatorRequested(bool) { Mantid::Kernel::UsageService::Instance().registerFeatureUsage( - "Feature", "ISIS Reflectometry->MainWindow->ShowSlitCalculator", false); + Mantid::Kernel::FeatureType::Feature, + {"ISIS Reflectometry", "MainWindow", "ShowSlitCalculator"}, false); m_notifyee->notifyShowSlitCalculatorRequested(); } @@ -149,7 +155,8 @@ void QtMainWindowView::subscribe(MainWindowSubscriber *notifyee) { void QtMainWindowView::helpPressed() { Mantid::Kernel::UsageService::Instance().registerFeatureUsage( - "Feature", "ISIS Reflectometry->MainWindow->ShowHelp", false); + Mantid::Kernel::FeatureType::Feature, + {"ISIS Reflectometry", "MainWindow", "ShowHelp"}, false); m_notifyee->notifyHelpPressed(); } diff --git a/qt/scientific_interfaces/ISISReflectometry/GUI/Runs/QtRunsView.cpp b/qt/scientific_interfaces/ISISReflectometry/GUI/Runs/QtRunsView.cpp index 25245cead0492fa0635d8e9ecb2734bc125f0384..238c1109ff0da0482e6cc4255a6cece44ce6ec91 100644 --- a/qt/scientific_interfaces/ISISReflectometry/GUI/Runs/QtRunsView.cpp +++ b/qt/scientific_interfaces/ISISReflectometry/GUI/Runs/QtRunsView.cpp @@ -238,7 +238,8 @@ This slot notifies the presenter that the "search" button has been pressed */ void QtRunsView::on_actionSearch_triggered() { Mantid::Kernel::UsageService::Instance().registerFeatureUsage( - "Feature", "ISIS Reflectometry->RunsTab->Search", false); + Mantid::Kernel::FeatureType::Feature, + {"ISIS Reflectometry", "RunsTab", "Search"}, false); m_notifyee->notifySearch(); } @@ -248,7 +249,8 @@ This slot conducts a search operation before notifying the presenter that the */ void QtRunsView::on_actionAutoreduce_triggered() { Mantid::Kernel::UsageService::Instance().registerFeatureUsage( - "Feature", "ISIS Reflectometry->RunsTab->StartAutoprocessing", false); + Mantid::Kernel::FeatureType::Feature, + {"ISIS Reflectometry", "RunsTab", "StartAutoprocessing"}, false); m_notifyee->notifyResumeAutoreductionRequested(); } @@ -258,7 +260,8 @@ This slot conducts a search operation before notifying the presenter that the */ void QtRunsView::on_actionAutoreducePause_triggered() { Mantid::Kernel::UsageService::Instance().registerFeatureUsage( - "Feature", "ISIS Reflectometry->RunsTab->PauseAutoprocessing", false); + Mantid::Kernel::FeatureType::Feature, + {"ISIS Reflectometry", "RunsTab", "PauseAutoprocessing"}, false); m_notifyee->notifyPauseAutoreductionRequested(); } @@ -267,7 +270,8 @@ This slot notifies the presenter that the "transfer" button has been pressed */ void QtRunsView::on_actionTransfer_triggered() { Mantid::Kernel::UsageService::Instance().registerFeatureUsage( - "Feature", "ISIS Reflectometry->RunsTab->Transfer", false); + Mantid::Kernel::FeatureType::Feature, + {"ISIS Reflectometry", "RunsTab", "Transfer"}, false); m_notifyee->notifyTransfer(); } @@ -277,7 +281,8 @@ This slot is triggered when the user right clicks on the search results table */ void QtRunsView::onShowSearchContextMenuRequested(const QPoint &pos) { Mantid::Kernel::UsageService::Instance().registerFeatureUsage( - "Feature", "ISIS Reflectometry->RunsTab->ShowSearchContextMenu", false); + Mantid::Kernel::FeatureType::Feature, + {"ISIS Reflectometry", "RunsTab", "ShowSearchContextMenu"}, false); if (!m_ui.tableSearchResults->indexAt(pos).isValid()) return; @@ -294,7 +299,8 @@ void QtRunsView::onShowSearchContextMenuRequested(const QPoint &pos) { void QtRunsView::onInstrumentChanged(int index) { UNUSED_ARG(index); Mantid::Kernel::UsageService::Instance().registerFeatureUsage( - "Feature", "ISIS Reflectometry->RunsTab->InstrumentChanged", false); + Mantid::Kernel::FeatureType::Feature, + {"ISIS Reflectometry", "RunsTab", "InstrumentChanged"}, false); m_ui.textSearch->clear(); m_notifyee->notifyChangeInstrumentRequested(); } @@ -368,13 +374,15 @@ int QtRunsView::getLiveDataUpdateInterval() const { void QtRunsView::on_buttonMonitor_clicked() { Mantid::Kernel::UsageService::Instance().registerFeatureUsage( - "Feature", "ISIS Reflectometry->RunsTab->StartMonitor", false); + Mantid::Kernel::FeatureType::Feature, + {"ISIS Reflectometry", "RunsTab", "StartMonitor"}, false); startMonitor(); } void QtRunsView::on_buttonStopMonitor_clicked() { Mantid::Kernel::UsageService::Instance().registerFeatureUsage( - "Feature", "ISIS Reflectometry->RunsTab->StopMonitor", false); + Mantid::Kernel::FeatureType::Feature, + {"ISIS Reflectometry", "RunsTab", "StopMonitor"}, false); stopMonitor(); } diff --git a/qt/scientific_interfaces/ISISReflectometry/GUI/RunsTable/QtRunsTableView.cpp b/qt/scientific_interfaces/ISISReflectometry/GUI/RunsTable/QtRunsTableView.cpp index 1040862ffcfd30057878ab0e061dae6b9e328ff2..bf646821d4fb6a29f16f2aa9159de98a0e8d9034 100644 --- a/qt/scientific_interfaces/ISISReflectometry/GUI/RunsTable/QtRunsTableView.cpp +++ b/qt/scientific_interfaces/ISISReflectometry/GUI/RunsTable/QtRunsTableView.cpp @@ -87,7 +87,8 @@ void QtRunsTableView::onFilterChanged(QString const &filter) { void QtRunsTableView::onInstrumentChanged(int index) { UNUSED_ARG(index); Mantid::Kernel::UsageService::Instance().registerFeatureUsage( - "Feature", "ISIS Reflectometry->RunsTable->InstrumentChanged", false); + Mantid::Kernel::FeatureType::Feature, + {"ISIS Reflectometry", "RunsTable", "InstrumentChanged"}, false); m_notifyee->notifyChangeInstrumentRequested(); } @@ -243,13 +244,15 @@ void QtRunsTableView::onCollapseAllGroupsPressed(bool) { void QtRunsTableView::onProcessPressed(bool) { Mantid::Kernel::UsageService::Instance().registerFeatureUsage( - "Feature", "ISIS Reflectometry->RunsTable->StartProcessing", false); + Mantid::Kernel::FeatureType::Feature, + {"ISIS Reflectometry", "RunsTable", "StartProcessing"}, false); m_notifyee->notifyResumeReductionRequested(); } void QtRunsTableView::onPausePressed(bool) { Mantid::Kernel::UsageService::Instance().registerFeatureUsage( - "Feature", "ISIS Reflectometry->RunsTable->PauseProcessing", false); + Mantid::Kernel::FeatureType::Feature, + {"ISIS Reflectometry", "RunsTable", "PauseProcessing"}, false); m_notifyee->notifyPauseReductionRequested(); } @@ -283,13 +286,15 @@ void QtRunsTableView::onPastePressed(bool) { void QtRunsTableView::onPlotSelectedPressed(bool) { Mantid::Kernel::UsageService::Instance().registerFeatureUsage( - "Feature", "ISIS Reflectometry->RunsTable->PlotRows", false); + Mantid::Kernel::FeatureType::Feature, + {"ISIS Reflectometry", "RunsTable", "PlotRows"}, false); m_notifyee->notifyPlotSelectedPressed(); } void QtRunsTableView::onPlotSelectedStitchedOutputPressed(bool) { Mantid::Kernel::UsageService::Instance().registerFeatureUsage( - "Feature", "ISIS Reflectometry->RunsTable->PlotGroups", false); + Mantid::Kernel::FeatureType::Feature, + {"ISIS Reflectometry", "RunsTable", "PlotGroups"}, false); m_notifyee->notifyPlotSelectedStitchedOutputPressed(); } diff --git a/qt/scientific_interfaces/ISISReflectometry/GUI/Save/QtSaveView.cpp b/qt/scientific_interfaces/ISISReflectometry/GUI/Save/QtSaveView.cpp index 7852eb921c957581dc4668aa559673847d03bd06..e9a6753a54072257e143e82d28eb5b2163debc35 100644 --- a/qt/scientific_interfaces/ISISReflectometry/GUI/Save/QtSaveView.cpp +++ b/qt/scientific_interfaces/ISISReflectometry/GUI/Save/QtSaveView.cpp @@ -62,18 +62,21 @@ void QtSaveView::browseToSaveDirectory() { void QtSaveView::onSavePathChanged() { Mantid::Kernel::UsageService::Instance().registerFeatureUsage( - "Feature", "ISIS Reflectometry->SaveTab->SavePathChanged", false); + Mantid::Kernel::FeatureType::Feature, + {"ISIS Reflectometry", "SaveTab", "SavePathChanged"}, false); m_notifyee->notifySavePathChanged(); } void QtSaveView::onAutosaveChanged(int state) { if (state == Qt::CheckState::Checked) { Mantid::Kernel::UsageService::Instance().registerFeatureUsage( - "Feature", "ISIS Reflectometry->SaveTab->EnableAutosave", false); + Mantid::Kernel::FeatureType::Feature, + {"ISIS Reflectometry", "SaveTab", "EnableAutosave"}, false); m_notifyee->notifyAutosaveEnabled(); } else { Mantid::Kernel::UsageService::Instance().registerFeatureUsage( - "Feature", "ISIS Reflectometry->SaveTab->DisableAutosave", false); + Mantid::Kernel::FeatureType::Feature, + {"ISIS Reflectometry", "SaveTab", "DisableAutosave"}, false); m_notifyee->notifyAutosaveDisabled(); } } @@ -228,7 +231,8 @@ void QtSaveView::setParametersList(const std::vector<std::string> &logs) const { */ void QtSaveView::populateListOfWorkspaces() const { Mantid::Kernel::UsageService::Instance().registerFeatureUsage( - "Feature", "ISIS Reflectometry->SaveTab->PopulateWorkspaces", false); + Mantid::Kernel::FeatureType::Feature, + {"ISIS Reflectometry", "SaveTab", "PopulateWorkspaces"}, false); m_notifyee->notifyPopulateWorkspaceList(); } @@ -242,7 +246,8 @@ void QtSaveView::filterWorkspaceList() const { */ void QtSaveView::requestWorkspaceParams() const { Mantid::Kernel::UsageService::Instance().registerFeatureUsage( - "Feature", "ISIS Reflectometry->SaveTab->PopulateParameters", false); + Mantid::Kernel::FeatureType::Feature, + {"ISIS Reflectometry", "SaveTab", "PopulateParameters"}, false); m_notifyee->notifyPopulateParametersList(); } @@ -250,7 +255,8 @@ void QtSaveView::requestWorkspaceParams() const { */ void QtSaveView::saveWorkspaces() const { Mantid::Kernel::UsageService::Instance().registerFeatureUsage( - "Feature", "ISIS Reflectometry->SaveTab->SaveWorkspaces", false); + Mantid::Kernel::FeatureType::Feature, + {"ISIS Reflectometry", "SaveTab", "SaveWorkspaces"}, false); m_notifyee->notifySaveSelectedWorkspaces(); } diff --git a/qt/widgets/common/inc/MantidQtWidgets/Common/TrackedAction.h b/qt/widgets/common/inc/MantidQtWidgets/Common/TrackedAction.h index a8b7b67c0b5af92554c30b8b98022ad33f64f8bc..10995997c9ce021b7133a93b540f2ee1404b127a 100644 --- a/qt/widgets/common/inc/MantidQtWidgets/Common/TrackedAction.h +++ b/qt/widgets/common/inc/MantidQtWidgets/Common/TrackedAction.h @@ -24,20 +24,20 @@ public: TrackedAction(const QIcon &icon, const QString &text, QObject *parent); virtual ~TrackedAction() = default; - void setTrackingName(const std::string &name); - std::string getTrackingName() const; + void setTrackingName(const std::vector<std::string> &name); + std::vector<std::string> getTrackingName() const; void setIsTracking(const bool enableTracking); bool getIsTracking() const; protected: - virtual std::string generateTrackingName() const; - virtual void registerUsage(const std::string &name); + virtual std::vector<std::string> generateTrackingName() const; + virtual void registerUsage(const std::vector<std::string> &name); private: void setupTracking(); bool m_isTracking; - mutable std::string m_trackingName; + mutable std::vector<std::string> m_trackingName; public slots: void trackActivation(const bool checked); diff --git a/qt/widgets/common/src/TrackedAction.cpp b/qt/widgets/common/src/TrackedAction.cpp index 95bb9fdd5a29e6d5dd348d7fff3f867a62caa1b2..d1d4aa568f1a6b6c4bb680d8cbc68f4de97f7947 100644 --- a/qt/widgets/common/src/TrackedAction.cpp +++ b/qt/widgets/common/src/TrackedAction.cpp @@ -42,7 +42,7 @@ TrackedAction::TrackedAction(const QIcon &icon, const QString &text, /** Sets the tracking name for this action * @param name the tracking name for this action **/ -void TrackedAction::setTrackingName(const std::string &name) { +void TrackedAction::setTrackingName(const std::vector<std::string> &name) { m_trackingName = name; } @@ -51,7 +51,7 @@ void TrackedAction::setTrackingName(const std::string &name) { * generateTrackingName * @returns The tracking name for this action **/ -std::string TrackedAction::getTrackingName() const { +std::vector<std::string> TrackedAction::getTrackingName() const { if (m_trackingName.empty()) { m_trackingName = generateTrackingName(); } @@ -79,9 +79,9 @@ void TrackedAction::setupTracking() { /** Creates a tracking name from the action text * @returns A generated name using ApplicationName->ActionText **/ -std::string TrackedAction::generateTrackingName() const { - return QCoreApplication::applicationName().toStdString() + "->" + - QAction::text().remove("&").remove(" ").toStdString(); +std::vector<std::string> TrackedAction::generateTrackingName() const { + return {QCoreApplication::applicationName().toStdString(), + QAction::text().remove("&").remove(" ").toStdString()}; } /** Registers the feature usage if usage is enabled @@ -98,9 +98,10 @@ void TrackedAction::trackActivation(const bool checked) { /** Registers the feature usage with the usage service * @param name The name to use when registering usage **/ -void TrackedAction::registerUsage(const std::string &name) { - Mantid::Kernel::UsageService::Instance().registerFeatureUsage("Feature", name, - false); +void TrackedAction::registerUsage(const std::vector<std::string> &name) { + Mantid::Kernel::UsageService::Instance().registerFeatureUsage( + Mantid::Kernel::FeatureType::Feature, name, false); } + } // namespace MantidWidgets } // namespace MantidQt diff --git a/qt/widgets/common/src/UserSubWindow.cpp b/qt/widgets/common/src/UserSubWindow.cpp index a3ab7ef1cec6bb429cb9ba9a17a8f6a92ef62f07..07680a424d7bc86f6c38d43e51712c04fb9b899e 100644 --- a/qt/widgets/common/src/UserSubWindow.cpp +++ b/qt/widgets/common/src/UserSubWindow.cpp @@ -56,7 +56,7 @@ void UserSubWindow::initializeLayout() { m_bIsInitialized = true; Mantid::Kernel::UsageService::Instance().registerFeatureUsage( - "Interface", m_ifacename.toStdString(), false); + Mantid::Kernel::FeatureType::Interface, m_ifacename.toStdString(), false); } /** diff --git a/qt/widgets/common/test/TrackedActionTest.h b/qt/widgets/common/test/TrackedActionTest.h index fcafa287d85978b3ef27ad0e367979c8b50c6a9e..74206f9703e1e65fad4fef27866c98e05a45f39d 100644 --- a/qt/widgets/common/test/TrackedActionTest.h +++ b/qt/widgets/common/test/TrackedActionTest.h @@ -26,13 +26,15 @@ class TrackedActionTest : public CxxTest::TestSuite { QObject *parent) : TrackedAction(icon, text, parent), m_lastName(){}; - std::string getLastUsedName() const { return m_lastName; }; + std::vector<std::string> getLastUsedName() const { return m_lastName; }; protected: - void registerUsage(const std::string &name) override { m_lastName = name; }; + void registerUsage(const std::vector<std::string> &name) override { + m_lastName = name; + }; private: - std::string m_lastName; + std::vector<std::string> m_lastName; }; public: @@ -55,12 +57,18 @@ public: TestableTrackedAction action(QString::fromStdString("TestName"), &parent); std::string appNamePrefix = - QCoreApplication::applicationName().toStdString() + "->"; + QCoreApplication::applicationName().toStdString(); - TS_ASSERT_EQUALS(action.getTrackingName(), - appNamePrefix + "TestName"); // default state - action.setTrackingName("TestName2"); - TS_ASSERT_EQUALS(action.getTrackingName(), "TestName2"); // altered state + TS_ASSERT_EQUALS(action.getTrackingName().size(), 2); + TS_ASSERT_EQUALS(action.getTrackingName()[0], + appNamePrefix); // default state + TS_ASSERT_EQUALS(action.getTrackingName()[1], "TestName"); // default state + + action.setTrackingName({"TestName2"}); + + TS_ASSERT_EQUALS(action.getTrackingName().size(), 1); + TS_ASSERT_EQUALS(action.getTrackingName()[0], + "TestName2"); // altered state } void testTrackingCallLogic() { @@ -68,17 +76,19 @@ public: TestableTrackedAction action(QString::fromStdString("TestName"), &parent); // tracking should be on by default - TS_ASSERT_EQUALS(action.getIsTracking(), true); // default state - TS_ASSERT_EQUALS(action.getLastUsedName(), ""); // default state + TS_ASSERT_EQUALS(action.getIsTracking(), true); // default state + TS_ASSERT_EQUALS(action.getLastUsedName().empty(), true); // default state - action.setTrackingName("ShouldTrack"); + action.setTrackingName({"ShouldTrack"}); action.trigger(); - TS_ASSERT_EQUALS(action.getLastUsedName(), + TS_ASSERT_EQUALS(action.getLastUsedName().size(), 1); + TS_ASSERT_EQUALS(action.getLastUsedName()[0], "ShouldTrack"); // tracking occurred state action.setIsTracking(false); - action.setTrackingName("ShouldNotTrack"); + action.setTrackingName({"ShouldNotTrack"}); action.trigger(); - TS_ASSERT_DIFFERS(action.getLastUsedName(), + TS_ASSERT_EQUALS(action.getLastUsedName().size(), 1); + TS_ASSERT_DIFFERS(action.getLastUsedName()[0], "ShouldNotTrack"); // Should not have tracked } }; diff --git a/qt/widgets/sliceviewer/src/LineViewer.cpp b/qt/widgets/sliceviewer/src/LineViewer.cpp index 8604ae615a0790d948c0cc529945e190a8ca8f7e..e451486e9f1436de3a4637004895bc5e6f761513 100644 --- a/qt/widgets/sliceviewer/src/LineViewer.cpp +++ b/qt/widgets/sliceviewer/src/LineViewer.cpp @@ -151,7 +151,7 @@ LineViewer::LineViewer(QWidget *parent) SLOT(onToggleLogYAxis())); Mantid::Kernel::UsageService::Instance().registerFeatureUsage( - "Feature", "SliceViewer->LineViewer", false); + FeatureType::Feature, {"SliceViewer", "LineViewer"}, false); } LineViewer::~LineViewer() {} diff --git a/qt/widgets/sliceviewer/src/PeaksViewer.cpp b/qt/widgets/sliceviewer/src/PeaksViewer.cpp index eb5e92595c5a860ed6e5fca36d6fb7987969d26d..b13be892f96357e208087994c00bcedec35a4bf8 100644 --- a/qt/widgets/sliceviewer/src/PeaksViewer.cpp +++ b/qt/widgets/sliceviewer/src/PeaksViewer.cpp @@ -21,7 +21,8 @@ namespace SliceViewer { PeaksViewer::PeaksViewer(QWidget *parent) : QWidget(parent) { this->setMinimumWidth(500); Mantid::Kernel::UsageService::Instance().registerFeatureUsage( - "Feature", "SliceViewer->PeaksViewer", false); + Mantid::Kernel::FeatureType::Feature, {"SliceViewer", "PeaksViewer"}, + false); } void PeaksViewer::setPeaksWorkspaces(const SetPeaksWorkspaces & /*unused*/) {} diff --git a/qt/widgets/sliceviewer/src/SliceViewer.cpp b/qt/widgets/sliceviewer/src/SliceViewer.cpp index fc81687b3c9d72030699f0720ec09b9a58f633a9..ba4d4665f4e018f11d3124aea0e797d0df3d606f 100644 --- a/qt/widgets/sliceviewer/src/SliceViewer.cpp +++ b/qt/widgets/sliceviewer/src/SliceViewer.cpp @@ -210,7 +210,7 @@ SliceViewer::SliceViewer(QWidget *parent) m_rescaler = new QwtPlotRescaler(m_plot->canvas()); Mantid::Kernel::UsageService::Instance().registerFeatureUsage( - "Interface", "SliceViewer", false); + FeatureType::Interface, "SliceViewer", false); } void SliceViewer::updateAspectRatios() { diff --git a/qt/widgets/spectrumviewer/src/SpectrumView.cpp b/qt/widgets/spectrumviewer/src/SpectrumView.cpp index 73c51b2d81b1330ce3d59fffb781a2995565528f..861d67e922d7c6da2fc2a9f68e14671fdcf98dec 100644 --- a/qt/widgets/spectrumviewer/src/SpectrumView.cpp +++ b/qt/widgets/spectrumviewer/src/SpectrumView.cpp @@ -56,7 +56,7 @@ SpectrumView::SpectrumView(QWidget *parent) observePreDelete(); observeADSClear(); Mantid::Kernel::UsageService::Instance().registerFeatureUsage( - "Interface", "SpectrumView", false); + Mantid::Kernel::FeatureType::Interface, "SpectrumView", false); #ifdef Q_OS_MAC // Work around to ensure that floating windows remain on top of the main diff --git a/scripts/DGSPlanner/DGSPlannerGUI.py b/scripts/DGSPlanner/DGSPlannerGUI.py index 441c7822349d771515e9ac8ab8e446ad5093893f..17b1e77103e8f018314d18fa2bbcebc655330d47 100644 --- a/scripts/DGSPlanner/DGSPlannerGUI.py +++ b/scripts/DGSPlanner/DGSPlannerGUI.py @@ -129,7 +129,7 @@ class DGSPlannerGUI(QtWidgets.QWidget): self.progress_canceled = False # register startup - mantid.UsageService.registerFeatureUsage("Interface", "DGSPlanner", False) + mantid.UsageService.registerFeatureUsage(mantid.kernel.FeatureType.Interface, "DGSPlanner", False) @QtCore.Slot(mantid.geometry.OrientedLattice) def updateUB(self, ol): diff --git a/scripts/FilterEvents/eventFilterGUI.py b/scripts/FilterEvents/eventFilterGUI.py index da9a8516dc3772953ec25c3c56e38a76ed9c1260..e80159c892f4b91425ce4fc8e8e83373967865da 100644 --- a/scripts/FilterEvents/eventFilterGUI.py +++ b/scripts/FilterEvents/eventFilterGUI.py @@ -198,7 +198,7 @@ class MainWindow(QMainWindow): self._defaultdir = os.getcwd() # register startup - mantid.UsageService.registerFeatureUsage("Interface", "EventFilter", False) + mantid.UsageService.registerFeatureUsage(mantid.kernel.FeatureType.Interface, "EventFilter", False) def on_mouseDownEvent(self, event): """ Respond to pick up a value with mouse down event diff --git a/scripts/HFIR_4Circle_Reduction/reduce4circleControl.py b/scripts/HFIR_4Circle_Reduction/reduce4circleControl.py index f0910ab559c416f6ed23effd6779d66aa3522ce8..65fe4d27775875a3809d4372aec77f3f16b6b2f5 100644 --- a/scripts/HFIR_4Circle_Reduction/reduce4circleControl.py +++ b/scripts/HFIR_4Circle_Reduction/reduce4circleControl.py @@ -211,7 +211,7 @@ class CWSCDReductionControl(object): self._curr_2theta_fwhm_func = None # register startup - mantid.UsageService.registerFeatureUsage("Interface", "4-Circle Reduction", False) + mantid.UsageService.registerFeatureUsage(mantid.kernel.FeatureType.Interface, "4-Circle Reduction", False) # debug mode self._debugPrintMode = True diff --git a/scripts/Interface/reduction_gui/reduction/scripter.py b/scripts/Interface/reduction_gui/reduction/scripter.py index 3315e21995f5f3948880023d8102d4db55e1773a..394ad98de7b2723ef25c12442c1f397a257192b2 100644 --- a/scripts/Interface/reduction_gui/reduction/scripter.py +++ b/scripts/Interface/reduction_gui/reduction/scripter.py @@ -21,7 +21,7 @@ import os # Disable unused import warning # pylint: disable=W0611 try: - from mantid.kernel import ConfigService, Logger, version_str, UsageService + from mantid.kernel import ConfigService, Logger, version_str, UsageService, FeatureType HAS_MANTID = True except (ImportError, ImportWarning): @@ -413,8 +413,7 @@ class BaseReductionScripter(object): config = ConfigService.Instance() #register startup if HAS_MANTID: - UsageService.registerFeatureUsage("Interface", - "Reduction_gui:{0:.5}-{1:.10}".format(facility, name),False) + UsageService.registerFeatureUsage(FeatureType.Interface, "Reduction_gui:{0:.5}-{1:.10}".format(facility, name), False) try: head, _tail = os.path.split(config.getUserFilename()) if os.path.isdir(head): diff --git a/scripts/Interface/ui/reflectometer/refl_gui.py b/scripts/Interface/ui/reflectometer/refl_gui.py index 8c761e4c749f24d4842966564570f4c835cc4456..37dfb1981900412d87dbeaa66582d5fc6f459a5d 100644 --- a/scripts/Interface/ui/reflectometer/refl_gui.py +++ b/scripts/Interface/ui/reflectometer/refl_gui.py @@ -26,7 +26,7 @@ from isis_reflectometry import load_live_runs from isis_reflectometry.combineMulti import * import mantidqtpython from mantid.api import Workspace, WorkspaceGroup, CatalogManager, AlgorithmManager -from mantid import UsageService +from mantid import UsageService, FeatureType from mantid import logger from ui.reflectometer.ui_refl_window import Ui_windowRefl @@ -144,7 +144,7 @@ We recommend you use ISIS Reflectometry instead, If this is not possible contact del settings # register startup - UsageService.registerFeatureUsage("Interface", "ISIS Reflectomety", False) + UsageService.registerFeatureUsage(FeatureType.Interface, "ISIS Reflectomety", False) def __del__(self): """ diff --git a/scripts/Interface/ui/sans_isis/SANSSaveOtherWindow.py b/scripts/Interface/ui/sans_isis/SANSSaveOtherWindow.py index 215768b50492e879b6d909ea735eb3f1eb8721c9..dabd7d061ea1dfc655c2044eed5c3a6c3dca06c7 100644 --- a/scripts/Interface/ui/sans_isis/SANSSaveOtherWindow.py +++ b/scripts/Interface/ui/sans_isis/SANSSaveOtherWindow.py @@ -10,6 +10,7 @@ from mantidqt.utils.qt import load_ui from mantidqt.widgets.workspacewidget import workspacetreewidget from mantid import UsageService +from mantid.kernel import FeatureType from sans.common.enums import SaveType from qtpy import PYQT4 @@ -31,7 +32,7 @@ class SANSSaveOtherDialog(QtWidgets.QDialog, Ui_SaveOtherDialog): self.subscribers = [] self.setup_view() - UsageService.registerFeatureUsage("Feature", "ISIS SANS->Save Other Tab", False) + UsageService.registerFeatureUsage(FeatureType.Feature, ["ISIS SANS","Save Other Tab"], False) def setup_view(self): self.setupUi(self) diff --git a/scripts/Interface/ui/sans_isis/beam_centre.py b/scripts/Interface/ui/sans_isis/beam_centre.py index 241a15d4a05ae06624a146d7f4cbae732d107c0e..427f5063ba95ca5b36883383c5871febd2557f11 100644 --- a/scripts/Interface/ui/sans_isis/beam_centre.py +++ b/scripts/Interface/ui/sans_isis/beam_centre.py @@ -14,6 +14,7 @@ from mantidqt.utils.qt import load_ui from mantidqt.widgets import messagedisplay from mantid import UsageService +from mantid.kernel import FeatureType from sans.gui_logic.gui_common import get_detector_from_gui_selection, \ get_detector_strings_for_gui, get_string_for_gui_from_reduction_mode @@ -57,7 +58,7 @@ class BeamCentre(QtWidgets.QWidget, Ui_BeamCentre): # At the moment we only track how many times this is opened, if it's popular # we can track individual feature usage at a later date - UsageService.registerFeatureUsage("Feature", "ISIS SANS->Beam Centre Tab", False) + UsageService.registerFeatureUsage(FeatureType.Feature, ["ISIS SANS","Beam Centre Tab"], False) def _setup_log_widget(self): self.log_widget = messagedisplay.MessageDisplay(parent=self.groupBox_2) diff --git a/scripts/Interface/ui/sans_isis/sans_data_processor_gui.py b/scripts/Interface/ui/sans_isis/sans_data_processor_gui.py index da9d25bbe4b4c2d577b67aca2dfe55b647ddfdb9..7fd7aecba1fd1a93de29a81a2d26d217a6233bee 100644 --- a/scripts/Interface/ui/sans_isis/sans_data_processor_gui.py +++ b/scripts/Interface/ui/sans_isis/sans_data_processor_gui.py @@ -23,7 +23,7 @@ from mantidqt.utils.qt import load_ui from mantidqt.widgets import jobtreeview, manageuserdirectories from six import with_metaclass -from mantid.kernel import (Logger, UsageService) +from mantid.kernel import (Logger, UsageService, FeatureType) from reduction_gui.reduction.scripter import execute_script from sans.common.enums import (BinningType, ReductionDimensionality, OutputMode, SaveType, SANSInstrument, RangeStepType, ReductionMode, FitType) @@ -252,7 +252,7 @@ class SANSDataProcessorGui(QMainWindow, self._setup_add_runs_page() # At a later date we can drop new once we confirm the old GUI is not using "ISIS SANS" - UsageService.registerFeatureUsage("Interface", "ISIS SANS (new)", False) + UsageService.registerFeatureUsage(FeatureType.Interface, "ISIS SANS (new)", False) def _setup_progress_bar(self): self.batch_progress_bar.setMinimum(0) @@ -491,22 +491,22 @@ class SANSDataProcessorGui(QMainWindow, """ Process runs """ - UsageService.registerFeatureUsage("Feature", "ISIS SANS->Process Selected", False) + UsageService.registerFeatureUsage(FeatureType.Feature, ["ISIS SANS","Process Selected"], False) self._call_settings_listeners(lambda listener: listener.on_process_selected_clicked()) def _process_all_clicked(self): """ Process All button clicked """ - UsageService.registerFeatureUsage("Feature", "ISIS SANS->Process All", False) + UsageService.registerFeatureUsage(FeatureType.Feature, ["ISIS SANS","Process All"], False) self._call_settings_listeners(lambda listener: listener.on_process_all_clicked()) def _load_clicked(self): - UsageService.registerFeatureUsage("Feature", "ISIS SANS->Load", False) + UsageService.registerFeatureUsage(FeatureType.Feature, ["ISIS SANS","Load"], False) self._call_settings_listeners(lambda listener: listener.on_load_clicked()) def _export_table_clicked(self): - UsageService.registerFeatureUsage("Feature", "ISIS SANS->Export Table", False) + UsageService.registerFeatureUsage(FeatureType.Feature, ["ISIS SANS","Export Table"], False) self._call_settings_listeners(lambda listener: listener.on_export_table_clicked()) def _processing_finished(self): @@ -543,23 +543,23 @@ class SANSDataProcessorGui(QMainWindow, def _remove_rows_requested_from_button(self): rows = self.get_selected_rows() - UsageService.registerFeatureUsage("Feature", "ISIS SANS->Rows removed button", False) + UsageService.registerFeatureUsage(FeatureType.Feature, ["ISIS SANS","Rows removed button"], False) self._call_settings_listeners(lambda listener: listener.on_rows_removed(rows)) def _copy_rows_requested(self): - UsageService.registerFeatureUsage("Feature", "ISIS SANS->Copy rows button", False) + UsageService.registerFeatureUsage(FeatureType.Feature, ["ISIS SANS","Copy rows button"], False) self._call_settings_listeners(lambda listener: listener.on_copy_rows_requested()) def _erase_rows(self): - UsageService.registerFeatureUsage("Feature", "ISIS SANS->Erase rows button", False) + UsageService.registerFeatureUsage(FeatureType.Feature, ["ISIS SANS","Erase rows button"], False) self._call_settings_listeners(lambda listener: listener.on_erase_rows()) def _cut_rows(self): - UsageService.registerFeatureUsage("Feature", "ISIS SANS->Cut rows button", False) + UsageService.registerFeatureUsage(FeatureType.Feature, ["ISIS SANS","Cut rows button"], False) self._call_settings_listeners(lambda listener: listener.on_cut_rows()) def _paste_rows_requested(self): - UsageService.registerFeatureUsage("Feature", "ISIS SANS->Paste rows button", False) + UsageService.registerFeatureUsage(FeatureType.Feature, ["ISIS SANS","Paste rows button"], False) self._call_settings_listeners(lambda listener: listener.on_paste_rows_requested()) def _instrument_changed(self): @@ -596,7 +596,7 @@ class SANSDataProcessorGui(QMainWindow, def _on_save_can_clicked(self, value): self.save_can_checkBox.setChecked(value) - UsageService.registerFeatureUsage("Feature", "ISIS SANS->Save Can Toggled", False) + UsageService.registerFeatureUsage(FeatureType.Feature, ["ISIS SANS","Save Can Toggled"], False) set_setting(self.__generic_settings, self.__save_can_key, value) def _on_reduction_dimensionality_changed(self, is_1d): @@ -669,7 +669,7 @@ class SANSDataProcessorGui(QMainWindow, Load the batch file """ - UsageService.registerFeatureUsage("Feature", "ISIS SANS->Loaded Batch File", False) + UsageService.registerFeatureUsage(FeatureType.Feature, ["ISIS SANS","Loaded Batch File"], False) load_file(self.batch_line_edit, "*.*", self.__generic_settings, self.__batch_file_key, self.get_batch_file_path) self._call_settings_listeners(lambda listener: listener.on_batch_file_load()) @@ -932,12 +932,12 @@ class SANSDataProcessorGui(QMainWindow, self._call_settings_listeners(lambda listener: listener.on_mask_file_add()) def _on_multi_period_selection(self): - UsageService.registerFeatureUsage("Feature", "ISIS SANS->Multiple Period Toggled", False) + UsageService.registerFeatureUsage(FeatureType.Feature, ["ISIS SANS","Multiple Period Toggled"], False) self._call_settings_listeners( lambda listener: listener.on_multi_period_selection(self.is_multi_period_view())) def _on_sample_geometry_selection(self): - UsageService.registerFeatureUsage("Feature", "ISIS SANS->Sample Geometry Toggled", False) + UsageService.registerFeatureUsage(FeatureType.Feature, ["ISIS SANS","Sample Geometry Toggled"], False) self._call_settings_listeners(lambda listener: listener.on_sample_geometry_selection(self.is_sample_geometry())) def _on_manage_directories(self): diff --git a/scripts/Interface/ui/sans_isis/settings_diagnostic_tab.py b/scripts/Interface/ui/sans_isis/settings_diagnostic_tab.py index 6c09b538f4c688fc8c2fb0224f562cf01b2c1c06..32a2880d0e879773e143df4e0cdc0ffabba70f89 100644 --- a/scripts/Interface/ui/sans_isis/settings_diagnostic_tab.py +++ b/scripts/Interface/ui/sans_isis/settings_diagnostic_tab.py @@ -21,6 +21,7 @@ from six import with_metaclass, PY3 from mantidqt.utils.qt import load_ui from mantid import UsageService +from mantid.kernel import FeatureType from sans.gui_logic.gui_common import (GENERIC_SETTINGS, JSON_SUFFIX, load_file) if PY3: @@ -70,7 +71,7 @@ class SettingsDiagnosticTab(QtWidgets.QWidget, Ui_SettingsDiagnosticTab): self.__generic_settings = GENERIC_SETTINGS self.__save_location_path_key = "save_state_location" - UsageService.registerFeatureUsage("Feature", "ISIS SANS->Settings Diagnostics Tab", False) + UsageService.registerFeatureUsage(FeatureType.Feature, ["ISIS SANS","Settings Diagnostics Tab"], False) def add_listener(self, listener): if not isinstance(listener, SettingsDiagnosticTab.SettingsDiagnosticTabListener): diff --git a/scripts/Muon/GUI/Common/usage_report.py b/scripts/Muon/GUI/Common/usage_report.py index 1632c21a009c9cec55770f68e0b789316bd13e34..c09b33c061aabf52ca873efdaa69d3f8afb98113 100644 --- a/scripts/Muon/GUI/Common/usage_report.py +++ b/scripts/Muon/GUI/Common/usage_report.py @@ -6,9 +6,9 @@ # SPDX - License - Identifier: GPL - 3.0 + from __future__ import (absolute_import, division, unicode_literals) -from mantid.kernel import UsageService +from mantid.kernel import (UsageService, FeatureType) def report_interface_startup(name): #interface startup - UsageService.registerFeatureUsage("Interface", name, False) + UsageService.registerFeatureUsage(FeatureType.Interface, name, False) diff --git a/scripts/QECoverage.py b/scripts/QECoverage.py index aea0442ba58cf4adb6d2410cd71702ef3b9fdea0..0e001a36c521fffa1dab417b0dc8e338f3720424 100644 --- a/scripts/QECoverage.py +++ b/scripts/QECoverage.py @@ -214,7 +214,7 @@ class QECoverageGUI(QtWidgets.QWidget): self.qt_url = 'qthelp://org.sphinx.mantidproject.' + version + '/doc/interfaces/QE Coverage.html' self.external_url = 'http://docs.mantidproject.org/nightly/interfaces/QE Coverage.html' #register startup - mantid.UsageService.registerFeatureUsage("Interface","QECoverage",False) + mantid.UsageService.registerFeatureUsage(mantid.kernel.FeatureType.Interface,"QECoverage",False) def onHelp(self): show_interface_help(self.mantidplot_name, diff --git a/scripts/SANS/sans/user_file/user_file_parser.py b/scripts/SANS/sans/user_file/user_file_parser.py index 47d059c5929e2da5e9c0d5142cbe0a50f6219ac5..bce1e1da1c9edf74f30d2e85fe761e7c98c22f60 100644 --- a/scripts/SANS/sans/user_file/user_file_parser.py +++ b/scripts/SANS/sans/user_file/user_file_parser.py @@ -1391,12 +1391,16 @@ class TransParser(UserFileComponentParser): dist, monitor = int(split_vars[0]), int(split_vars[1]) - if monitor == 4: - return {TransId.spec_4_shift: dist} - elif monitor == 5: + if monitor == 5: return {TransId.spec_5_shift: dist} + elif monitor >= 0: + # Some instruments (i.e. LOQ) do not have monitor 4 on spectrum 4, as ZOOM + # is currently the only one with monitor 5 at spectrum 5 we can make it an edge case + # If a future instrument wants to use monitor 5 at a different spectrum number or + # uses monitor 4 at spectrum 5 this should be updated + return {TransId.spec_4_shift: dist} else: - raise RuntimeError("The monitor {0} cannot be shifted".format(monitor)) + raise RuntimeError("Monitor {0} cannot be shifted".format(monitor)) def _extract_trans_spec(self, line): trans_spec_string = re.sub(self._trans_spec, "", line) @@ -1418,11 +1422,14 @@ class TransParser(UserFileComponentParser): trans_spec_shift_string = re.sub(" ", "", trans_spec_shift_string) trans_spec_shift = convert_string_to_float(trans_spec_shift_string) - # Pair up the monitor and shift amount - if trans_spec == 4: - return {TransId.spec_4_shift: trans_spec_shift, TransId.spec: trans_spec} - elif trans_spec == 5: + if trans_spec == 5: return {TransId.spec_5_shift: trans_spec_shift, TransId.spec: trans_spec} + elif trans_spec >= 0: + # Some instruments (i.e. LOQ) do not have monitor 4 on spectrum 4, as ZOOM + # is currently the only one with monitor 5 at spectrum 5 we can make it an edge case + # If a future instrument wants to use monitor 5 at a different spectrum number or + # uses monitor 4 at spectrum 5 this should be updated + return {TransId.spec_4_shift: trans_spec_shift, TransId.spec: trans_spec} else: raise RuntimeError("Monitor {0} cannot be shifted".format(trans_spec)) diff --git a/scripts/TofConverter/converterGUI.py b/scripts/TofConverter/converterGUI.py index c015658cfdbea9c6fa00ba091a55e9118334cce2..68bb6209cbbf7ddab33f331fb35cd4c92f049359 100644 --- a/scripts/TofConverter/converterGUI.py +++ b/scripts/TofConverter/converterGUI.py @@ -92,7 +92,7 @@ class MainWindow(QMainWindow): try: import mantid #register startup - mantid.UsageService.registerFeatureUsage("Interface","TofConverter",False) + mantid.UsageService.registerFeatureUsage(mantid.kernel.FeatureType.Interface,"TofConverter",False) except ImportError: pass diff --git a/scripts/test/SANS/user_file/user_file_parser_test.py b/scripts/test/SANS/user_file/user_file_parser_test.py index 609b807bd81be4d7c4e8f508afe2d1d943f3bb71..5b618fddb8c7edd94dc7d47df0e4b16579d4a9b1 100644 --- a/scripts/test/SANS/user_file/user_file_parser_test.py +++ b/scripts/test/SANS/user_file/user_file_parser_test.py @@ -597,24 +597,27 @@ class TransParserTest(unittest.TestCase): "TRANS/ SHIFT=4000 5": {TransId.spec_5_shift: 4000}, "TRANS /SHIFT=4000 5": {TransId.spec_5_shift: 4000}, "TRANS/SHIFT=4000 5": {TransId.spec_5_shift: 4000}, + # An unrecognised monitor position (i.e. not 5) should be considered as 4 + # see source code for details + "TRANS/SHIFT=1000 12": {TransId.spec_4_shift: 1000}, + "TRANS/SHIFT=4000 =12": {TransId.spec_4_shift: 4000}, + "TRANS/SHIFT=4000 =1": {TransId.spec_4_shift: 4000}, + "TRANS/SHIFT4000 120": {TransId.spec_4_shift: 4000}, + "TRANS/SHIFT 4000 999": {TransId.spec_4_shift: 4000}, } - invalid_settings = {"TRANS/SHIFT=1000 12": RuntimeError, + invalid_settings = { "TRANS/SHIFT=4000 -1" : RuntimeError, "TRANS/SHIFT+4000 -1": RuntimeError, "TRANS/TRANSSHIFT=4000 -1": RuntimeError, "TRANS/SHIFTAab=4000 -1": RuntimeError, "TRANS/SHIF=4000 1": RuntimeError, "TRANS/SHIFT4000": RuntimeError, - "TRANS/SHIFT4000 1": RuntimeError, - "TRANS/SHIFT 4000 1": RuntimeError, "TRANS/SHIFT 1": RuntimeError, "TRANS/SHIFT 4000": RuntimeError, "TRANS/SHIFT=4000": RuntimeError, "TRANS/SHIFT=4000 a": RuntimeError, - "TRANS/SHIFT=4000 =12": RuntimeError, - "TRANS/SHIFT=4000 =1": RuntimeError, - } + } trans_parser = TransParser() do_test(trans_parser, valid_settings, invalid_settings, self.assertTrue, self.assertRaises) @@ -622,11 +625,11 @@ class TransParserTest(unittest.TestCase): def test_that_trans_spec_shift_is_parsed_correctly(self): valid_settings = {"TRANS/TRANSPEC=4/SHIFT=23": {TransId.spec_4_shift: 23, TransId.spec: 4}, "TRANS/TRANSPEC =4/ SHIFT = 23": {TransId.spec_4_shift: 23, TransId.spec: 4}, + "TRANS/TRANSPEC =900/ SHIFT = 23": {TransId.spec_4_shift: 23, TransId.spec: 900}, } invalid_settings = { - "TRANS/TRANSPEC =6/ SHIFT = 23": RuntimeError, "TRANS/TRANSPEC=4/SHIFT/23": RuntimeError, "TRANS/TRANSPEC=4/SHIFT 23": RuntimeError, "TRANS/TRANSPEC/SHIFT=23": RuntimeError,