Mantid
Loading...
Searching...
No Matches
DetermineSpinStateOrder.cpp
Go to the documentation of this file.
1// Mantid Repository : https://github.com/mantidproject/mantid
2//
3// Copyright © 2025 ISIS Rutherford Appleton Laboratory UKRI,
4// NScD Oak Ridge National Laboratory, European Spallation Source,
5// Institut Laue - Langevin & CSNS, Institute of High Energy Physics, CAS
6// SPDX - License - Identifier: GPL - 3.0 +
7
9#include "MantidAPI/Axis.h"
12#include "MantidAPI/Run.h"
15#include "MantidKernel/Logger.h"
17
18#include <algorithm>
19#include <sstream>
20
21namespace Mantid {
22namespace Algorithms {
25
26Kernel::Logger g_log("DetermineSpinStateOrder");
27
28// Register the algorithm into the AlgorithmFactory
30
31//----------------------------------------------------------------------------------------------
32
33
34const std::string DetermineSpinStateOrder::name() const { return "DetermineSpinStateOrder"; }
35
37int DetermineSpinStateOrder::version() const { return 1; }
38
40const std::string DetermineSpinStateOrder::category() const { return "SANS"; }
41
43const std::string DetermineSpinStateOrder::summary() const {
44 return "Takes a workspace group of Polarised SANS run periods and returns a string (e.g '11, 10, 01, 00') of their "
45 "corresponding spin states in Wildes notation.";
46}
47
48const std::vector<std::string> DetermineSpinStateOrder::seeAlso() const { return {"AssertSpinStateOrder"}; }
49
50//----------------------------------------------------------------------------------------------
56 "InputWorkspace", "", Direction::Input, std::make_shared<Mantid::API::PolSANSWorkspaceValidator>()),
57 "A Polarised SANS run from either LARMOR or ZOOM (group workspace with 4 periods).");
58 declareProperty("SpinFlipperLogName", std::string(""),
59 "Name of the log contained in the InputWorkspace which holds the flipper current (can be inferred if "
60 "data is from LARMOR or ZOOM).",
62 declareProperty("SpinFlipperAverageCurrent", EMPTY_DBL(),
63 "Expected average current for the spin slipper over all periods. Used to determine if a particular "
64 "period has the flipper active or not (can be inferred if data is from LARMOR or ZOOM).",
66 declareProperty("SpinStates", std::string(""),
67 "A comma-seperated string of the spin states of each of the run periods e.g '11, 10, 01, 00'",
69}
70
71void validateGroupItem(API::MatrixWorkspace_sptr const &workspace, std::map<std::string, std::string> &errorList,
72 const std::string &spinFlipperLogName = "") {
73 if (spinFlipperLogName != "" && !workspace->run().hasProperty(spinFlipperLogName)) {
74 errorList["InputWorkspace"] =
75 "All input workspaces must contain the provided spin flipper log: " + spinFlipperLogName + ".";
76 }
77}
78
79std::map<std::string, std::string> DetermineSpinStateOrder::validateInputs() {
80 std::map<std::string, std::string> helpMessages;
81 API::WorkspaceGroup_const_sptr wsGroup = getProperty("InputWorkspace");
82
83 for (const API::Workspace_sptr &ws : wsGroup->getAllItems()) {
84 const auto groupItem = std::dynamic_pointer_cast<API::MatrixWorkspace>(ws);
85 validateGroupItem(groupItem, helpMessages, getPropertyValue("SpinFlipperLogName"));
86 if (!helpMessages.empty()) {
87 return helpMessages;
88 }
89 }
90
91 if (isDefault("SpinFlipperLogName") || isDefault("SpinFlipperAverageCurrent")) {
92 const auto firstItem = std::dynamic_pointer_cast<API::MatrixWorkspace>(wsGroup->getItem(0));
93 const auto instrument = firstItem->getInstrument()->getName();
94
95 if (instrument == "LARMOR") {
97 isDefault("SpinFlipperLogName") ? "FlipperCurrent" : getPropertyValue("SpinFlipperLogName");
99 isDefault("SpinFlipperAverageCurrent") ? 4.0 : std::stod(getPropertyValue("SpinFlipperAverageCurrent"));
100 } else if (instrument == "ZOOM") {
101 m_spinFlipperLogName = isDefault("SpinFlipperLogName") ? "Spin_flipper" : getPropertyValue("SpinFlipperLogName");
103 isDefault("SpinFlipperAverageCurrent") ? 0.0 : std::stod(getPropertyValue("SpinFlipperAverageCurrent"));
104 } else {
105 helpMessages["InputWorkspace"] = "Sub workspaces must be data from either LARMOR or ZOOM when SpinFlipperLogName "
106 "or SpinFlipperAverageCurrent are not provided";
107 }
108 }
109
110 return helpMessages;
111}
112
113//----------------------------------------------------------------------------------------------
117 API::WorkspaceGroup_const_sptr wsGroup = getProperty("InputWorkspace");
118 if (!isDefault("SpinFlipperLogName") && !isDefault("SpinFlipperAverageCurrent")) {
119 m_spinFlipperLogName = getPropertyValue("SpinFlipperLogName");
120 m_rfStateCondition = std::stod(getPropertyValue("SpinFlipperAverageCurrent"));
121 }
122
123 const double averageTrans = averageTransmission(wsGroup);
124 std::vector<std::string> spinStatesOrder;
125
126 for (const API::Workspace_sptr &ws : wsGroup->getAllItems()) {
127 const auto groupItem = std::dynamic_pointer_cast<API::MatrixWorkspace>(ws);
128 const auto sfLog =
129 dynamic_cast<const Kernel::TimeSeriesProperty<double> *>(groupItem->run().getLogData(m_spinFlipperLogName));
130 if (!sfLog) {
131 throw std::runtime_error(m_spinFlipperLogName + " was not a TimeSeriesProperty.");
132 }
133 const auto sfLogValues = sfLog->filteredValuesAsVector();
134 const double rfState =
135 std::accumulate(sfLogValues.cbegin(), sfLogValues.cend(), 0.0) / static_cast<double>(sfLogValues.size());
136 const double heState = *std::max_element(groupItem->readY(0).cbegin(), groupItem->readY(0).cend()) - averageTrans;
137
138 if (rfState > m_rfStateCondition) {
139 if (heState < 0) {
140 spinStatesOrder.push_back("10");
141 } else {
142 spinStatesOrder.push_back("11");
143 }
144 } else {
145 if (heState < 0) {
146 spinStatesOrder.push_back("01");
147 } else {
148 spinStatesOrder.push_back("00");
149 }
150 }
151 }
152
153 const std::string spinStates = Kernel::Strings::join(spinStatesOrder.cbegin(), spinStatesOrder.cend(), ",");
154 std::stringstream msg;
155 msg << "Determined the following spin state order for " << wsGroup->getName() << ": " << spinStates;
156 g_log.notice(msg.str());
157 setProperty("SpinStates", spinStates);
158}
159
161 const auto workspaces = wsGroup->getAllItems();
162
163 double total =
164 std::accumulate(workspaces.cbegin(), workspaces.cend(), 0.0, [](double total, const API::Workspace_sptr ws) {
165 const auto groupItem = std::dynamic_pointer_cast<API::MatrixWorkspace>(ws);
166 return total + *std::max_element(groupItem->readY(0).cbegin(), groupItem->readY(0).cend());
167 });
168
169 return total / static_cast<double>(workspaces.size());
170}
171
172} // namespace Algorithms
173} // namespace Mantid
std::string name
Definition Run.cpp:60
#define DECLARE_ALGORITHM(classname)
Definition Algorithm.h:538
IPeaksWorkspace_sptr workspace
void declareProperty(std::unique_ptr< Kernel::Property > p, const std::string &doc="") override
Add a property to the list of managed properties.
std::string getPropertyValue(const std::string &name) const override
Get the value of a property as a string.
TypedValue getProperty(const std::string &name) const override
Get the value of a property.
Kernel::Logger & g_log
Definition Algorithm.h:422
bool isDefault(const std::string &name) const
A property class for workspaces.
DetermineSpinStateOrder : Takes a workspace group of Polarised SANS run periods and returns a string ...
double averageTransmission(Mantid::API::WorkspaceGroup_const_sptr const &wsGroup) const
std::map< std::string, std::string > validateInputs() override
Method checking errors on ALL the inputs, before execution.
const std::vector< std::string > seeAlso() const override
Function to return all of the seeAlso algorithms related to this algorithm.
const std::string summary() const override
Algorithm's summary for use in the GUI and help.
const std::string category() const override
Algorithm's category for identification.
int version() const override
Algorithm's version for identification.
void init() override
Initialize the algorithm's properties.
IPropertyManager * setProperty(const std::string &name, const T &value)
Templated method to set the value of a PropertyWithValue.
The Logger class is in charge of the publishing messages from the framework through various channels.
Definition Logger.h:51
void notice(const std::string &msg)
Logs at notice level.
Definition Logger.cpp:126
A specialised Property class for holding a series of time-value pairs.
std::shared_ptr< Workspace > Workspace_sptr
shared pointer to Mantid::API::Workspace
std::shared_ptr< const WorkspaceGroup > WorkspaceGroup_const_sptr
shared pointer to Mantid::API::WorkspaceGroup, pointer to const version
std::shared_ptr< MatrixWorkspace > MatrixWorkspace_sptr
shared pointer to the matrix workspace base class
void validateGroupItem(API::MatrixWorkspace_sptr const &workspace, std::map< std::string, std::string > &errorList, const std::string &spinFlipperLogName="")
Kernel::Logger g_log("DetermineSpinStateOrder")
DLLExport std::string join(ITERATOR_TYPE begin, ITERATOR_TYPE end, const std::string &separator, typename std::enable_if<!(std::is_same< typename std::iterator_traits< ITERATOR_TYPE >::iterator_category, std::random_access_iterator_tag >::value)>::type *=nullptr)
Join a set or vector of (something that turns into a string) together into one string,...
Definition Strings.h:84
Helper class which provides the Collimation Length for SANS instruments.
constexpr double EMPTY_DBL() noexcept
Returns what we consider an "empty" double within a property.
Definition EmptyValues.h:42
STL namespace.
Describes the direction (within an algorithm) of a Property.
Definition Property.h:50
@ Input
An input workspace.
Definition Property.h:53
@ Output
An output workspace.
Definition Property.h:54