Mantid
Loading...
Searching...
No Matches
ParameterInfo.cpp
Go to the documentation of this file.
1// Mantid Repository : https://github.com/mantidproject/mantid
2//
3// Copyright © 2026 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 +
10
11#include <numeric>
12
13namespace Mantid::Geometry {
14
15namespace {
18ParameterInfo::ComponentParameters const &emptyParameters() {
19 static ParameterInfo::ComponentParameters const empty;
20 return empty;
21}
22
30bool matchesNamedType(Parameter const &parameter, std::string const &type) {
31 return type.empty() || parameter.type() == type;
32}
33
37bool matchesType(Parameter const &parameter, std::string const &type) {
38 Kernel::CaseInsensitiveStringComparator const less;
39 return !less(parameter.type(), type) && !less(type, parameter.type());
40}
41} // namespace
42
43void ParameterInfo::add(size_t const componentIndex, std::shared_ptr<Parameter> const &parameter) {
44 if (!parameter) {
45 return;
46 }
47 auto &componentParameters = m_store[componentIndex];
48 // Add-or-replace, matching legacy ParameterMap::add(). The name comparison is the
49 // multimap's own case-insensitive comparator, so "Alpha" replaces an existing "alpha".
50 auto const existing = componentParameters.find(parameter->name());
51 if (existing != componentParameters.end()) {
52 existing->second = parameter;
53 } else {
54 componentParameters.emplace(parameter->name(), parameter);
55 }
56}
57
58bool ParameterInfo::addFittingParameter(size_t const componentIndex, std::shared_ptr<Parameter> const &parameter,
59 std::string const &fittingFunction) {
60 if (!parameter) {
61 return false;
62 }
63 auto &componentParameters = m_store[componentIndex];
64 // Deduplicate by (name, function) rather than by name alone, so that two functions on the
65 // same component may each declare a parameter of the same short name.
66 auto const range = componentParameters.equal_range(parameter->name());
67 for (auto it = range.first; it != range.second; ++it) {
68 if (it->second->type() != "fitting") {
69 continue;
70 }
71 try {
72 if (it->second->value<FitParameter>().getFunction() == fittingFunction) {
73 it->second = parameter;
74 return true;
75 }
76 } catch (...) {
77 // Tagged "fitting" but the value is not a FitParameter; not a match, keep looking.
78 }
79 }
80 componentParameters.emplace(parameter->name(), parameter);
81 return false;
82}
83
84void ParameterInfo::insert(size_t const componentIndex, std::shared_ptr<Parameter> const &parameter) {
85 if (!parameter) {
86 return;
87 }
88 m_store[componentIndex].emplace(parameter->name(), parameter);
89}
90
91bool ParameterInfo::contains(size_t const componentIndex, std::string const &name, std::string const &type) const {
92 return static_cast<bool>(get(componentIndex, name, type));
93}
94
95std::shared_ptr<Parameter> ParameterInfo::get(size_t const componentIndex, std::string const &name,
96 std::string const &type) const {
97 std::shared_ptr<Parameter> result;
98 auto const component = m_store.find(componentIndex);
99 if (component != m_store.end()) {
100 auto const range = component->second.equal_range(name);
101 for (auto it = range.first; it != range.second; ++it) {
102 if (matchesNamedType(*it->second, type)) {
103 result = it->second;
104 break;
105 }
106 }
107 }
108 return result;
109}
110
111std::shared_ptr<Parameter> ParameterInfo::getByType(size_t const componentIndex, std::string const &type) const {
112 std::shared_ptr<Parameter> result;
113 auto const component = m_store.find(componentIndex);
114 if (component != m_store.end()) {
115 for (auto const &[name, parameter] : component->second) {
116 static_cast<void>(name);
117 if (matchesType(*parameter, type)) {
118 result = parameter;
119 break;
120 }
121 }
122 }
123 return result;
124}
125
126std::shared_ptr<Parameter> ParameterInfo::getRecursive(ComponentInfo const &componentInfo, size_t const componentIndex,
127 std::string const &name, std::string const &type) const {
128 std::shared_ptr<Parameter> result;
129 for (size_t index = componentIndex;;) {
130 result = get(index, name, type);
131 if (result || !componentInfo.hasParent(index)) {
132 break;
133 }
134 index = componentInfo.parent(index);
135 }
136 return result;
137}
138
139std::shared_ptr<Parameter> ParameterInfo::getRecursiveByType(ComponentInfo const &componentInfo,
140 size_t const componentIndex,
141 std::string const &type) const {
142 std::shared_ptr<Parameter> result;
143 for (size_t index = componentIndex;;) {
144 result = getByType(index, type);
145 if (result || !componentInfo.hasParent(index)) {
146 break;
147 }
148 index = componentInfo.parent(index);
149 }
150 return result;
151}
152
153std::shared_ptr<Parameter> ParameterInfo::getRecursiveFittingParameter(ComponentInfo const &componentInfo,
154 size_t const componentIndex,
155 std::string const &name,
156 std::string const &fittingFunction) const {
157 std::shared_ptr<Parameter> result;
158 for (size_t index = componentIndex;;) {
159 auto const component = m_store.find(index);
160 if (component != m_store.end()) {
161 auto const range = component->second.equal_range(name);
162 for (auto it = range.first; it != range.second; ++it) {
163 if (it->second->type() != "fitting") {
164 continue;
165 }
166 try {
167 if (it->second->value<FitParameter>().getFunction() == fittingFunction) {
168 result = it->second;
169 break;
170 }
171 } catch (...) {
172 // Tagged "fitting" but the value is not a FitParameter; keep looking.
173 }
174 }
175 }
176 if (result || !componentInfo.hasParent(index)) {
177 break;
178 }
179 index = componentInfo.parent(index);
180 }
181 return result;
182}
183
184std::set<std::string> ParameterInfo::names(size_t const componentIndex) const {
185 std::set<std::string> result;
186 auto const component = m_store.find(componentIndex);
187 if (component != m_store.end()) {
188 for (auto const &[name, parameter] : component->second) {
189 static_cast<void>(parameter);
190 result.insert(name);
191 }
192 }
193 return result;
194}
195
196ParameterInfo::ComponentParameters const &ParameterInfo::parameters(size_t const componentIndex) const {
197 auto const component = m_store.find(componentIndex);
198 return component == m_store.end() ? emptyParameters() : component->second;
199}
200
201namespace {
210bool eraseExactName(ParameterInfo::ComponentParameters &parameters, std::string const &name) {
211 bool erased = false;
212 auto const range = parameters.equal_range(name);
213 for (auto it = range.first; it != range.second;) {
214 if (it->second && it->second->name() == name) {
215 it = parameters.erase(it);
216 erased = true;
217 } else {
218 ++it;
219 }
220 }
221 return erased;
222}
223} // namespace
224
226 for (auto component = m_store.begin(); component != m_store.end();) {
227 eraseExactName(component->second, name);
228 // Drop components that no longer carry anything, so the store stays sparse.
229 if (component->second.empty()) {
230 component = m_store.erase(component);
231 } else {
232 ++component;
233 }
234 }
235}
236
237void ParameterInfo::clearParametersByName(size_t const componentIndex, std::string const &name) {
238 auto const component = m_store.find(componentIndex);
239 if (component != m_store.end()) {
240 eraseExactName(component->second, name);
241 if (component->second.empty()) {
242 m_store.erase(component);
243 }
244 }
245}
246
247void ParameterInfo::clear() { m_store.clear(); }
248
249bool ParameterInfo::empty() const { return m_store.empty(); }
250
251size_t ParameterInfo::size() const {
252 return std::accumulate(m_store.cbegin(), m_store.cend(), size_t{0},
253 [](size_t acc, auto const &component) { return acc + component.second.size(); });
254}
255
257 size_t storeMem = 0;
258 size_t parameterObjectsMem = 0;
259 for (auto const &[componentIndex, componentParameters] : m_store) {
260 static_cast<void>(componentIndex);
261 // Outer std::map node: key + value + colour bit + 3 pointers.
262 storeMem += sizeof(decltype(m_store)::value_type) + 4 * sizeof(void *);
263 for (auto const &[name, parameter] : componentParameters) {
264 // Inner std::multimap node: same shape.
265 storeMem += sizeof(ComponentParameters::value_type) + 4 * sizeof(void *) + name.capacity();
266 if (parameter) {
267 parameterObjectsMem += sizeof(Parameter) + parameter->m_name.capacity() + parameter->m_type.capacity() +
268 parameter->m_str_value.capacity() + parameter->m_description.capacity();
269 }
270 }
271 }
272 return sizeof(*this) + storeMem + parameterObjectsMem;
273}
274
275} // namespace Mantid::Geometry
std::string name
Definition Run.cpp:60
std::map< DeltaEMode::Type, std::string > index
ComponentInfo : Provides a component centric view on to the instrument.
bool hasParent(const size_t componentIndex) const
size_t parent(const size_t componentIndex) const
Store information about a fitting parameter such as its value if it is constrained or tied.
const std::string & getFunction() const
get function
void insert(size_t const componentIndex, std::shared_ptr< Parameter > const &parameter)
Insert a parameter without add()'s add-or-replace deduplication.
size_t size() const
The total number of parameters across all components.
std::shared_ptr< Parameter > getByType(size_t const componentIndex, std::string const &type) const
The first parameter of this type on this component, or a null shared pointer.
std::set< std::string > names(size_t const componentIndex) const
The names of the parameters on this component.
bool addFittingParameter(size_t const componentIndex, std::shared_ptr< Parameter > const &parameter, std::string const &fittingFunction)
Add a fitting parameter, deduplicating by (name, function) rather than by name alone so that two func...
ComponentParameters const & parameters(size_t const componentIndex) const
All parameters on one component, non-recursive, ordered by name.
std::shared_ptr< Parameter > get(size_t const componentIndex, std::string const &name, std::string const &type="") const
The named parameter on this component, or a null shared pointer if there is none.
void clearParametersByName(std::string const &name)
Remove every parameter of this name from every component.
void clear()
Remove all parameters.
bool contains(size_t const componentIndex, std::string const &name, std::string const &type="") const
Does a parameter of this name (and optionally this type) exist on this component?
void add(size_t const componentIndex, std::shared_ptr< Parameter > const &parameter)
Add a parameter, replacing any existing parameter of the same name on the same component.
std::shared_ptr< Parameter > getRecursiveFittingParameter(ComponentInfo const &componentInfo, size_t const componentIndex, std::string const &name, std::string const &fittingFunction) const
Find a fitting parameter by (short name, function) walking up the component hierarchy.
std::multimap< std::string, std::shared_ptr< Parameter >, Kernel::CaseInsensitiveStringComparator > ComponentParameters
Parameters of a single component, ordered by name.
std::shared_ptr< Parameter > getRecursive(ComponentInfo const &componentInfo, size_t const componentIndex, std::string const &name, std::string const &type="") const
As get(), but walking up the component hierarchy until a match is found.
std::map< size_t, ComponentParameters > m_store
std::shared_ptr< Parameter > getRecursiveByType(ComponentInfo const &componentInfo, size_t const componentIndex, std::string const &type) const
As getByType(), but walking up the component hierarchy until a match is found.
Base class for parameters of an instrument.
Definition Parameter.h:38