Mantid
Loading...
Searching...
No Matches
SpinStateValidator.cpp
Go to the documentation of this file.
1// Mantid Repository : https://github.com/mantidproject/mantid
2//
3// Copyright © 2024 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
11#include <boost/algorithm/string.hpp>
12#include <sstream>
13
14namespace Mantid::Kernel {
15
16SpinStateValidator::SpinStateValidator(std::unordered_set<int> allowedNumbersOfSpins, const bool acceptSingleStates,
17 const std::string &paraIndicator, const std::string &antiIndicator,
18 const bool optional, const std::string &extraIndicator)
19 : TypedValidator<std::string>(), m_allowedNumbersOfSpins(std::move(allowedNumbersOfSpins)),
20 m_acceptSingleStates(acceptSingleStates), m_para(paraIndicator), m_anti(antiIndicator), m_optional(optional),
21 m_extra(extraIndicator) {}
22
24 return std::make_shared<SpinStateValidator>(m_allowedNumbersOfSpins, m_acceptSingleStates);
25}
26
27std::string SpinStateValidator::checkValidity(const std::string &input) const {
28 if (input.empty()) {
29 if (m_optional) {
30 return "";
31 }
32 std::ostringstream msg;
33 msg << "Enter a spin state string, it should be a comma-separated list, e.g. ";
34 msg << m_para << m_anti << "," << m_para << m_para << "," << m_anti << m_para << ',' << m_anti << m_anti << ".";
35 return msg.str();
36 }
37
38 const auto &allowedPairs = getAllowedPairStates();
39 const auto &allowedSingles = getAllowedSingleStates();
40
41 auto spinStates = SpinStateHelpers::splitSpinStateString(input);
42
43 int numberSpinStates = static_cast<int>(spinStates.size());
44 if (m_allowedNumbersOfSpins.find(numberSpinStates) == m_allowedNumbersOfSpins.cend())
45 return "The number of spin states specified is not an allowed value";
46
47 // First check that the spin states are valid entries
48 if (std::any_of(spinStates.cbegin(), spinStates.cend(), [&](const std::string &spinState) {
49 const bool isPair = setContains(allowedPairs, spinState);
50 const bool isSingle = m_acceptSingleStates && setContains(allowedSingles, spinState);
51 return !isPair && !isSingle;
52 })) {
53 std::ostringstream msg;
54 msg << "The format for the spin states is invalid, every comma separated value should contain ";
55 msg << (m_acceptSingleStates ? "either one or two spin states " : "two spin states ") << "from the set " << m_para
56 << "," << m_anti << (!m_extra.empty() ? "," + m_extra : "") << ".";
57
58 return msg.str();
59 }
60
61 // Single digits can't mix with pairs
63 bool containsAnySingles = SpinStateValidator::anyOfIsInSet(spinStates, allowedSingles);
64
65 bool containsAnyPairs = SpinStateValidator::anyOfIsInSet(spinStates, allowedPairs);
66 if (!(containsAnyPairs ^ containsAnySingles)) {
67 return "Single and paired spin states cannot be mixed";
68 }
69 }
70
71 // Check that each spin state only appears once
72 std::sort(spinStates.begin(), spinStates.end());
73 auto it = std::unique(spinStates.begin(), spinStates.end());
74 auto numberOfUniqueStates = static_cast<int>(std::distance(spinStates.begin(), it));
75 if (numberOfUniqueStates < numberSpinStates)
76 return "Each spin state must only appear once";
77
78 return "";
79}
80
81bool SpinStateValidator::anyOfIsInSet(const std::vector<std::string> &anyOf,
82 const std::unordered_set<std::string> &set) {
83 return std::any_of(anyOf.cbegin(), anyOf.cend(),
84 [&set](const std::string &stringPair) { return setContains(set, stringPair); });
85}
86
87const std::unordered_set<std::string> SpinStateValidator::getAllowedPairStates() const {
88 std::unordered_set<std::string> allowedPairs = {m_para + m_para, m_para + m_anti, m_anti + m_para, m_anti + m_anti};
89 if (!m_extra.empty()) {
90 allowedPairs.insert(
92 }
93 return allowedPairs;
94}
95
96const std::unordered_set<std::string> SpinStateValidator::getAllowedSingleStates() const {
97 std::unordered_set<std::string> allowedSinglePairs = {m_para, m_anti};
98 if (!m_extra.empty()) {
99 allowedSinglePairs.emplace(m_extra);
100 }
101 return allowedSinglePairs;
102}
103
104} // namespace Mantid::Kernel
static bool anyOfIsInSet(const std::vector< std::string > &anyOf, const std::unordered_set< std::string > &set)
std::unordered_set< int > m_allowedNumbersOfSpins
const std::unordered_set< std::string > getAllowedSingleStates() const
SpinStateValidator(std::unordered_set< int > allowedNumbersOfSpins, const bool acceptSingleStates=false, const std::string &paraIndicator="0", const std::string &antiIndicator="1", const bool optional=false, const std::string &extraIndicator="")
std::string checkValidity(const std::string &input) const override
const std::unordered_set< std::string > getAllowedPairStates() const
Kernel::IValidator_sptr clone() const override
MANTID_KERNEL_DLL std::vector< std::string > splitSpinStateString(const std::string &spinStates)
std::shared_ptr< IValidator > IValidator_sptr
A shared_ptr to an IValidator.
Definition IValidator.h:26
STL namespace.