Mantid
Loading...
Searching...
No Matches
ParameterMap.cpp
Go to the documentation of this file.
1// Mantid Repository : https://github.com/mantidproject/mantid
2//
3// Copyright © 2018 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 +
15#include "MantidKernel/Cache.h"
16#include "MantidKernel/Logger.h"
18#include "MantidNexus/NexusFile.h"
19#include <boost/algorithm/string.hpp>
20#include <cstring>
21#include <numeric>
22
23#ifdef _WIN32
24#define strcasecmp _stricmp
25#else
26#include "strings.h"
27#endif
28
29namespace Mantid::Geometry {
30using Kernel::Quat;
31using Kernel::V3D;
32
33namespace {
34// names of common parameter types
35const std::string POS_PARAM_NAME = "pos";
36const std::string POSX_PARAM_NAME = "x";
37const std::string POSY_PARAM_NAME = "y";
38const std::string POSZ_PARAM_NAME = "z";
39
40const std::string ROT_PARAM_NAME = "rot";
41const std::string ROTX_PARAM_NAME = "rotx";
42const std::string ROTY_PARAM_NAME = "roty";
43const std::string ROTZ_PARAM_NAME = "rotz";
44
45const std::string DOUBLE_PARAM_NAME = "double";
46const std::string INT_PARAM_NAME = "int";
47const std::string BOOL_PARAM_NAME = "bool";
48const std::string STRING_PARAM_NAME = "string";
49const std::string V3D_PARAM_NAME = "V3D";
50const std::string QUAT_PARAM_NAME = "Quat";
51
52const std::string SCALE_PARAM_NAME = "sca";
53
54// static logger reference
55Kernel::Logger g_log("ParameterMap");
56
57void checkIsNotMaskingParameter(const std::string &name) {
58 if (name == std::string("masked"))
59 throw std::runtime_error("Masking data (\"masked\") cannot be stored in "
60 "ParameterMap. Use DetectorInfo instead");
61}
62} // namespace
67 : m_cacheLocMap(std::make_unique<Kernel::Cache<const ComponentID, Kernel::V3D>>()),
68 m_cacheRotMap(std::make_unique<Kernel::Cache<const ComponentID, Kernel::Quat>>()) {}
69
71 : m_parameterFileNames(other.m_parameterFileNames), m_map(other.m_map),
72 m_cacheLocMap(std::make_unique<Kernel::Cache<const ComponentID, Kernel::V3D>>(*other.m_cacheLocMap)),
73 m_cacheRotMap(std::make_unique<Kernel::Cache<const ComponentID, Kernel::Quat>>(*other.m_cacheRotMap)),
74 m_instrument(other.m_instrument) {
75 if (m_instrument)
76 std::tie(m_componentInfo, m_detectorInfo) = m_instrument->makeBeamline(*this, &other);
77}
78
79// Defined as default in source for forward declaration with std::unique_ptr.
81
85// Position
86const std::string &ParameterMap::pos() { return POS_PARAM_NAME; }
87
88const std::string &ParameterMap::posx() { return POSX_PARAM_NAME; }
89
90const std::string &ParameterMap::posy() { return POSY_PARAM_NAME; }
91
92const std::string &ParameterMap::posz() { return POSZ_PARAM_NAME; }
93
94// Rotation
95const std::string &ParameterMap::rot() { return ROT_PARAM_NAME; }
96
97const std::string &ParameterMap::rotx() { return ROTX_PARAM_NAME; }
98
99const std::string &ParameterMap::roty() { return ROTY_PARAM_NAME; }
100
101const std::string &ParameterMap::rotz() { return ROTZ_PARAM_NAME; }
102
103// Other types
104const std::string &ParameterMap::pDouble() { return DOUBLE_PARAM_NAME; }
105
106const std::string &ParameterMap::pInt() { return INT_PARAM_NAME; }
107
108const std::string &ParameterMap::pBool() { return BOOL_PARAM_NAME; }
109
110const std::string &ParameterMap::pString() { return STRING_PARAM_NAME; }
111
112const std::string &ParameterMap::pV3D() { return V3D_PARAM_NAME; }
113
114const std::string &ParameterMap::pQuat() { return QUAT_PARAM_NAME; }
115
116// Scale
117const std::string &ParameterMap::scale() { return SCALE_PARAM_NAME; }
118
125bool ParameterMap::operator!=(const ParameterMap &rhs) const { return !(this->operator==(rhs)); }
126
133bool ParameterMap::operator==(const ParameterMap &rhs) const { return diff(rhs, true, false, 0.).empty(); }
134
142const std::string ParameterMap::getDescription(const std::string &compName, const std::string &name) const {
143 pmap_cit it;
144 std::string result;
145 for (it = m_map.begin(); it != m_map.end(); ++it) {
146 if (compName == it->first->getName()) {
147 std::shared_ptr<Parameter> param = get(it->first, name);
148 if (param) {
149 result = param->getDescription();
150 if (!result.empty())
151 return result;
152 }
153 }
154 }
155 return result;
156}
164const std::string ParameterMap::getShortDescription(const std::string &compName, const std::string &name) const {
165 pmap_cit it;
166 std::string result;
167 for (it = m_map.begin(); it != m_map.end(); ++it) {
168 if (compName == it->first->getName()) {
169 std::shared_ptr<Parameter> param = get(it->first, name);
170 if (param) {
171 result = param->getShortDescription();
172 if (!result.empty())
173 return result;
174 }
175 }
176 }
177 return result;
178}
179
180//------------------------------------------------------------------------------------------------
194bool ParameterMap::relErr(double x1, double x2, double errorVal) const {
195 double num = std::fabs(x1 - x2);
196 // how to treat x1<0 and x2 > 0 ? probably this way
197 double den = 0.5 * (std::fabs(x1) + std::fabs(x2));
198 if (den < errorVal)
199 return (num > errorVal);
200
201 return (num / den > errorVal);
202}
203
218const std::string ParameterMap::diff(const ParameterMap &rhs, const bool &firstDiffOnly, const bool relative,
219 const double doubleTolerance) const {
220 if (this == &rhs)
221 return std::string(""); // True for the same object
222
223 // Quick size check
224 if (this->size() != rhs.size()) {
225 return std::string("Number of parameters does not match: ") + std::to_string(this->size()) + " not equal to " +
226 std::to_string(rhs.size());
227 }
228
229 // The map is unordered and the key is only valid at runtime. The
230 // asString method turns the ComponentIDs to full-qualified name identifiers
231 // so we will use the same approach to compare them
232
233 std::unordered_multimap<std::string, Parameter_sptr> thisMap, rhsMap;
234 for (auto &mappair : this->m_map) {
235 thisMap.emplace(mappair.first->getFullName(), mappair.second);
236 }
237 for (auto &mappair : rhs.m_map) {
238 rhsMap.emplace(mappair.first->getFullName(), mappair.second);
239 }
240
241 std::stringstream strOutput;
242 for (auto thisIt = thisMap.cbegin(); thisIt != thisMap.cend(); ++thisIt) {
243 const std::string fullName = thisIt->first;
244 const auto &param = thisIt->second;
245 bool match(false);
246 for (auto rhsIt = rhsMap.cbegin(); rhsIt != rhsMap.cend(); ++rhsIt) {
247 const std::string rhsFullName = rhsIt->first;
248 const auto &rhsParam = rhsIt->second;
249 if ((fullName == rhsFullName) && (param->name() == (rhsParam->name()))) {
250 if ((param->type() == rhsParam->type()) && (rhsParam->type() == "double")) {
251 if (relative) {
252 if (!relErr(param->value<double>(), rhsParam->value<double>(), doubleTolerance))
253 match = true;
254 } else if (std::abs(param->value<double>() - rhsParam->value<double>()) <= doubleTolerance)
255 match = true;
256 } else if (param->asString() == rhsParam->asString()) {
257 match = true;
258 }
259 if (match)
260 break;
261 }
262 }
263
264 if (!match) {
265 // output some information that helps with understanding the mismatch
266 strOutput << "Parameter mismatch LHS=RHS for LHS parameter in component "
267 "with name: "
268 << fullName << ". Parameter name is: " << (*param).name() << " and value: " << (*param).asString()
269 << '\n';
270 bool componentWithSameNameRHS = false;
271 bool parameterWithSameNameRHS = false;
272 for (auto rhsIt = rhsMap.cbegin(); rhsIt != rhsMap.cend(); ++rhsIt) {
273 const std::string rhsFullName = rhsIt->first;
274 if (fullName == rhsFullName) {
275 componentWithSameNameRHS = true;
276 if ((*param).name() == (*rhsIt->second).name()) {
277 parameterWithSameNameRHS = true;
278 strOutput << "RHS param with same name has value: " << (*rhsIt->second).asString() << '\n';
279 }
280 }
281 }
282 if (!componentWithSameNameRHS) {
283 strOutput << "No matching RHS component name\n";
284 }
285 if (componentWithSameNameRHS && !parameterWithSameNameRHS) {
286 strOutput << "Found matching RHS component name but not parameter name\n";
287 }
288 if (firstDiffOnly)
289 return strOutput.str();
290 }
291 }
292 return strOutput.str();
293}
294
300 checkIsNotMaskingParameter(name);
301 // Key is component ID so have to search through whole lot
302 for (auto itr = m_map.begin(); itr != m_map.end();) {
303 if (itr->second->name() == name) {
304 PARALLEL_CRITICAL(unsafe_erase) { itr = m_map.unsafe_erase(itr); }
305 } else {
306 ++itr;
307 }
308 }
309 // Check if the caches need invalidating
310 if (name == pos() || name == rot())
312}
313
319void ParameterMap::clearParametersByName(const std::string &name, const IComponent *comp) {
320 checkIsNotMaskingParameter(name);
321 if (!m_map.empty()) {
322 const ComponentID id = comp->getComponentID();
323 auto itrs = m_map.equal_range(id);
324 for (auto it = itrs.first; it != itrs.second;) {
325 if (it->second->name() == name) {
326 PARALLEL_CRITICAL(unsafe_erase) { it = m_map.unsafe_erase(it); }
327 } else {
328 ++it;
329 }
330 }
331
332 // Check if the caches need invalidating
333 if (name == pos() || name == rot())
335 }
336}
337
348void ParameterMap::add(const std::string &type, const IComponent *comp, const std::string &name,
349 const std::string &value, const std::string *const pDescription, const std::string &pVisible) {
350 auto param = ParameterFactory::create(type, name, pVisible);
351 param->fromString(value);
352 this->add(comp, param, pDescription);
353}
354
362void ParameterMap::add(const IComponent *comp, const std::shared_ptr<Parameter> &par,
363 const std::string *const pDescription) {
364 if (!par)
365 return;
366 checkIsNotMaskingParameter(par->name());
367 if (pDescription)
368 par->setDescription(*pDescription);
369
370 auto existing_par = positionOf(comp, par->name().c_str(), "");
371 // As this is only an add method it should really throw if it already
372 // exists.
373 // However, this is old behavior and many things rely on this actually be
374 // an
375 // add/replace-style function
376 if (existing_par != m_map.end()) {
377 std::atomic_store(&(existing_par->second), par);
378 } else {
379// When using Clang & Linux, TBB 4.4 doesn't detect C++11 features.
380// https://software.intel.com/en-us/forums/intel-threading-building-blocks/topic/641658
381#if defined(__clang__) && !defined(__APPLE__)
382#define CLANG_ON_LINUX true
383#else
384#define CLANG_ON_LINUX false
385#endif
386#if TBB_VERSION_MAJOR >= 4 && TBB_VERSION_MINOR >= 4 && !CLANG_ON_LINUX
387 m_map.emplace(comp->getComponentID(), par);
388#else
389 m_map.insert(std::make_pair(comp->getComponentID(), par));
390#endif
391 }
392}
393
408void ParameterMap::addFittingParameter(const IComponent *comp, const std::string &name,
409 const std::string &fittingFunction, const std::string &value,
410 const std::string *const pDescription, const std::string &pVisible) {
411 checkIsNotMaskingParameter(name);
412 auto param = ParameterFactory::create("fitting", name, pVisible);
413 param->fromString(value);
414 if (pDescription)
415 param->setDescription(*pDescription);
416
417 // Look for an existing fitting parameter on this component with the same name AND the same
418 // embedded function; only that one should be replaced.
419 if (!m_map.empty()) {
420 const ComponentID id = comp->getComponentID();
421 auto it_found = m_map.find(id);
422 if (it_found != m_map.end()) {
423 auto itrs = m_map.equal_range(id);
424 for (auto itr = itrs.first; itr != itrs.second; ++itr) {
425 const auto &existing = itr->second;
426 if (existing->type() == "fitting" && strcasecmp(existing->nameAsCString(), name.c_str()) == 0) {
427 try {
428 if (existing->value<FitParameter>().getFunction() == fittingFunction) {
429 g_log.debug() << "addFittingParameter: [replace] matched existing (name='" << name << "', function='"
430 << fittingFunction << "') on component '" << comp->getName() << "'; overwriting in place\n";
431 std::atomic_store(&(itr->second), param);
432 return;
433 }
434 } catch (...) {
435 // Not a FitParameter value despite the type tag
436 g_log.debug() << "addFittingParameter: [skip-match] existing 'fitting' entry (name='" << name
437 << "') on component '" << comp->getName()
438 << "' did not hold a FitParameter value; ignoring it and continuing search\n";
439 }
440 }
441 }
442 }
443 }
444
445 g_log.debug() << "addFittingParameter: [insert] no existing match for (name='" << name << "', function='"
446 << fittingFunction << "') on component '" << comp->getName() << "'; adding new entry\n";
447 m_map.insert({comp->getComponentID(), param});
448}
449
459void ParameterMap::addPositionCoordinate(const IComponent *comp, const std::string &name, const double value,
460 const std::string *const pDescription) {
461 Parameter_sptr param = get(comp, pos());
463 if (param) {
464 // so "pos" already defined
465 position = param->value<V3D>();
466 } else {
467 // so "pos" is not defined - therefore get position from component
468 position = comp->getPos();
469 }
470
471 // adjust position
472
473 if (name == posx())
475 else if (name == posy())
476 position.setY(value);
477 else if (name == posz())
478 position.setZ(value);
479 else {
480 g_log.warning() << "addPositionCoordinate() called with unrecognized "
481 "coordinate symbol: "
482 << name;
483 // set description if one is provided
484 if (pDescription) {
485 param->setDescription(*pDescription);
486 }
487 return;
488 }
489
490 // clear the position cache
492 // finally add or update "pos" parameter
493 addV3D(comp, pos(), position, pDescription);
494}
495
505void ParameterMap::addRotationParam(const IComponent *comp, const std::string &name, const double deg,
506 const std::string *const pDescription) {
507 Parameter_sptr paramRotX = get(comp, rotx());
508 Parameter_sptr paramRotY = get(comp, roty());
509 Parameter_sptr paramRotZ = get(comp, rotz());
510 double rotX, rotY, rotZ;
511
512 if (paramRotX)
513 rotX = paramRotX->value<double>();
514 else
515 rotX = 0.0;
516
517 if (paramRotY)
518 rotY = paramRotY->value<double>();
519 else
520 rotY = 0.0;
521
522 if (paramRotZ)
523 rotZ = paramRotZ->value<double>();
524 else
525 rotZ = 0.0;
526
527 // adjust rotation
528 Quat quat;
529 if (name == rotx()) {
530 addDouble(comp, rotx(), deg);
531 quat = Quat(deg, V3D(1, 0, 0)) * Quat(rotY, V3D(0, 1, 0)) * Quat(rotZ, V3D(0, 0, 1));
532 } else if (name == roty()) {
533 addDouble(comp, roty(), deg);
534 quat = Quat(rotX, V3D(1, 0, 0)) * Quat(deg, V3D(0, 1, 0)) * Quat(rotZ, V3D(0, 0, 1));
535 } else if (name == rotz()) {
536 addDouble(comp, rotz(), deg);
537 quat = Quat(rotX, V3D(1, 0, 0)) * Quat(rotY, V3D(0, 1, 0)) * Quat(deg, V3D(0, 0, 1));
538 } else {
539 g_log.warning() << "addRotationParam() called with unrecognized coordinate symbol: " << name;
540 return;
541 }
542
543 // clear the position cache
545
546 // finally add or update "pos" parameter
547 addQuat(comp, rot(), quat, pDescription);
548}
549
559void ParameterMap::addDouble(const IComponent *comp, const std::string &name, const std::string &value,
560 const std::string *const pDescription, const std::string &pVisible) {
561 add(pDouble(), comp, name, value, pDescription, pVisible);
562}
563
573void ParameterMap::addDouble(const IComponent *comp, const std::string &name, double value,
574 const std::string *const pDescription, const std::string &pVisible) {
575 add(pDouble(), comp, name, value, pDescription, pVisible);
576}
577
587void ParameterMap::addInt(const IComponent *comp, const std::string &name, const std::string &value,
588 const std::string *const pDescription, const std::string &pVisible) {
589 add(pInt(), comp, name, value, pDescription, pVisible);
590}
591
601void ParameterMap::addInt(const IComponent *comp, const std::string &name, int value,
602 const std::string *const pDescription, const std::string &pVisible) {
603 add(pInt(), comp, name, value, pDescription, pVisible);
604}
605
615void ParameterMap::addBool(const IComponent *comp, const std::string &name, const std::string &value,
616 const std::string *const pDescription, const std::string &pVisible) {
617 add(pBool(), comp, name, value, pDescription, pVisible);
618}
628void ParameterMap::addBool(const IComponent *comp, const std::string &name, bool value,
629 const std::string *const pDescription, const std::string &pVisible) {
630 add(pBool(), comp, name, value, pDescription, pVisible);
631}
632
641 const std::string name("masked");
642 auto param = create(pBool(), name);
643 auto typedParam = std::dynamic_pointer_cast<ParameterType<bool>>(param);
644 typedParam->setValue(value);
645
646// When using Clang & Linux, TBB 4.4 doesn't detect C++11 features.
647// https://software.intel.com/en-us/forums/intel-threading-building-blocks/topic/641658
648#if defined(__clang__) && !defined(__APPLE__)
649#define CLANG_ON_LINUX true
650#else
651#define CLANG_ON_LINUX false
652#endif
653#if TBB_VERSION_MAJOR >= 4 && TBB_VERSION_MINOR >= 4 && !CLANG_ON_LINUX
654 m_map.emplace(comp->getComponentID(), param);
655#else
656 m_map.insert(std::make_pair(comp->getComponentID(), param));
657#endif
658}
659
669void ParameterMap::addString(const IComponent *comp, const std::string &name, const std::string &value,
670 const std::string *const pDescription, const std::string &pVisible) {
671 add<std::string>(pString(), comp, name, value, pDescription, pVisible);
672}
673
682void ParameterMap::addV3D(const IComponent *comp, const std::string &name, const std::string &value,
683 const std::string *const pDescription) {
684 add(pV3D(), comp, name, value, pDescription);
686}
687
696void ParameterMap::addV3D(const IComponent *comp, const std::string &name, const V3D &value,
697 const std::string *const pDescription) {
698 add(pV3D(), comp, name, value, pDescription);
700}
701
710void ParameterMap::addQuat(const IComponent *comp, const std::string &name, const Quat &value,
711 const std::string *const pDescription) {
712 add(pQuat(), comp, name, value, pDescription);
714}
715
723bool ParameterMap::contains(const IComponent *comp, const std::string &name, const std::string &type) const {
724 return contains(comp, name.c_str(), type.c_str());
725}
726
735bool ParameterMap::contains(const IComponent *comp, const char *name, const char *type) const {
736 checkIsNotMaskingParameter(name);
737 if (m_map.empty())
738 return false;
739 const ComponentID id = comp->getComponentID();
740 std::pair<pmap_cit, pmap_cit> components = m_map.equal_range(id);
741 bool anytype = (strlen(type) == 0);
742 for (auto itr = components.first; itr != components.second; ++itr) {
743 const auto &param = itr->second;
744 if (strcasecmp(param->nameAsCString(), name) == 0 && (anytype || param->type() == type)) {
745 return true;
746 }
747 }
748 return false;
749}
750
756bool ParameterMap::contains(const IComponent *comp, const Parameter &parameter) const {
757 checkIsNotMaskingParameter(parameter.name());
758 if (m_map.empty() || !comp)
759 return false;
760
761 const ComponentID id = comp->getComponentID();
762 auto it_found = m_map.find(id);
763 if (it_found != m_map.end()) {
764 auto itrs = m_map.equal_range(id);
765 for (auto itr = itrs.first; itr != itrs.second; ++itr) {
766 const Parameter_sptr &param = itr->second;
767 if (*param == parameter)
768 return true;
769 }
770 return false;
771 } else
772 return false;
773}
774
781Parameter_sptr ParameterMap::get(const IComponent *comp, const std::string &name, const std::string &type) const {
782 return get(comp, name.c_str(), type.c_str());
783}
784
792std::shared_ptr<Parameter> ParameterMap::get(const IComponent *comp, const char *name, const char *type) const {
793 checkIsNotMaskingParameter(name);
794 Parameter_sptr result;
795 if (!comp)
796 return result;
797
798 auto itr = positionOf(comp, name, type);
799 if (itr != m_map.end())
800 result = std::atomic_load(&itr->second);
801 return result;
802}
803
811component_map_it ParameterMap::positionOf(const IComponent *comp, const char *name, const char *type) {
812 auto result = m_map.end();
813 if (!comp)
814 return result;
815 const bool anytype = (strlen(type) == 0);
816 if (!m_map.empty()) {
817 const ComponentID id = comp->getComponentID();
818 auto it_found = m_map.find(id);
819 if (it_found != m_map.end()) {
820 auto itrs = m_map.equal_range(id);
821 for (auto itr = itrs.first; itr != itrs.second; ++itr) {
822 const auto &param = itr->second;
823 if (strcasecmp(param->nameAsCString(), name) == 0 && (anytype || param->type() == type)) {
824 result = itr;
825 break;
826 }
827 }
828 }
829 }
830 return result;
831}
832
840component_map_cit ParameterMap::positionOf(const IComponent *comp, const char *name, const char *type) const {
841 auto result = m_map.end();
842 if (!comp)
843 return result;
844 const bool anytype = (strlen(type) == 0);
845 if (!m_map.empty()) {
846 const ComponentID id = comp->getComponentID();
847 auto it_found = m_map.find(id);
848 if (it_found != m_map.end()) {
849 auto itrs = m_map.equal_range(id);
850 for (auto itr = itrs.first; itr != itrs.second; ++itr) {
851 const auto &param = itr->second;
852 if (strcasecmp(param->nameAsCString(), name) == 0 && (anytype || param->type() == type)) {
853 result = itr;
854 break;
855 }
856 }
857 }
858 }
859 return result;
860}
861
867Parameter_sptr ParameterMap::getByType(const IComponent *comp, const std::string &type) const {
868 Parameter_sptr result;
869 if (!m_map.empty()) {
870 const ComponentID id = comp->getComponentID();
871 auto it_found = m_map.find(id);
872 if (it_found != m_map.end() && it_found->first) {
873 auto itrs = m_map.equal_range(id);
874 for (auto itr = itrs.first; itr != itrs.second; ++itr) {
875 const auto &param = itr->second;
876 if (strcasecmp(param->type().c_str(), type.c_str()) == 0) {
877 result = std::atomic_load(&param);
878 break;
879 }
880 } // found->firdst
881 } // it_found != m_map.end()
882 }
883 return result;
884}
885
892Parameter_sptr ParameterMap::getRecursiveByType(const IComponent *comp, const std::string &type) const {
893 std::shared_ptr<const IComponent> compInFocus(comp, NoDeleting());
894 while (compInFocus != nullptr) {
895 Parameter_sptr param = getByType(compInFocus.get(), type);
896 if (param) {
897 return param;
898 }
899 compInFocus = compInFocus->getParent();
900 }
901 // Nothing was found!
902 return Parameter_sptr();
903}
904
914 const std::string &type) const {
915 return getRecursive(comp, name.c_str(), type.c_str());
916}
917
926Parameter_sptr ParameterMap::getRecursive(const IComponent *comp, const char *name, const char *type) const {
927 checkIsNotMaskingParameter(name);
928 Parameter_sptr result = this->get(comp->getComponentID(), name, type);
929 if (result)
930 return result;
931
932 auto parent = comp->getParent();
933 while (parent) {
934 result = this->get(parent->getComponentID(), name, type);
935 if (result)
936 return result;
937 parent = parent->getParent();
938 }
939 return result;
940}
941
956 const std::string &fittingFunction) const {
957 checkIsNotMaskingParameter(name);
958 if (!comp || m_map.empty())
959 return Parameter_sptr();
960
961 std::shared_ptr<const IComponent> compInFocus(comp, NoDeleting());
962 while (compInFocus != nullptr) {
963 const ComponentID id = compInFocus->getComponentID();
964 auto it_found = m_map.find(id);
965 if (it_found != m_map.end()) {
966 auto itrs = m_map.equal_range(id);
967 for (auto itr = itrs.first; itr != itrs.second; ++itr) {
968 const auto &param = itr->second;
969 if (param->type() == "fitting" && strcasecmp(param->nameAsCString(), name.c_str()) == 0) {
970 try {
971 if (param->value<FitParameter>().getFunction() == fittingFunction) {
972 return std::atomic_load(&itr->second);
973 }
974 } catch (...) {
975 // Not a FitParameter value despite the type tag, keep looking.
976 }
977 }
978 }
979 }
980 compInFocus = compInFocus->getParent();
981 }
982 return Parameter_sptr();
983}
984
993std::string ParameterMap::getString(const IComponent *comp, const std::string &name, bool recursive) const {
994 Parameter_sptr param;
995 if (recursive) {
996 param = getRecursive(comp, name);
997 } else {
998 param = get(comp, name);
999 }
1000 if (!param)
1001 return "";
1002 return param->asString();
1003}
1004
1010std::set<std::string> ParameterMap::names(const IComponent *comp) const {
1011 std::set<std::string> paramNames;
1012 const ComponentID id = comp->getComponentID();
1013 auto it_found = m_map.find(id);
1014 if (it_found == m_map.end()) {
1015 return paramNames;
1016 }
1017
1018 auto itrs = m_map.equal_range(id);
1019 for (auto it = itrs.first; it != itrs.second; ++it) {
1020 paramNames.insert(it->second->name());
1021 }
1022
1023 return paramNames;
1024}
1025
1032std::string ParameterMap::asString() const {
1033 std::stringstream out;
1034 for (const auto &mappair : m_map) {
1035 const std::shared_ptr<Parameter> &p = mappair.second;
1036 if (p && mappair.first) {
1037 const auto *comp = dynamic_cast<const IComponent *>(mappair.first);
1038 const auto *det = dynamic_cast<const IDetector *>(comp);
1039 if (det) {
1040 out << "detID:" << det->getID();
1041 } else if (comp) {
1042 out << comp->getFullName(); // Use full path name to ensure unambiguous
1043 // naming
1044 }
1045 const auto paramVisible = "visible:" + std::string(p->visible() == 1 ? "true" : "false");
1046 out << ';' << p->type() << ';' << p->name() << ';' << p->asString() << ';' << paramVisible << '|';
1047 }
1048 }
1049 return out.str();
1050}
1051
1059
1063void ParameterMap::setCachedLocation(const IComponent *comp, const V3D &location) const {
1064 m_cacheLocMap->setCache(comp->getComponentID(), location);
1065}
1066
1071bool ParameterMap::getCachedLocation(const IComponent *comp, V3D &location) const {
1072 return m_cacheLocMap->getCache(comp->getComponentID(), location);
1073}
1074
1079 m_cacheRotMap->setCache(comp->getComponentID(), rotation);
1080}
1081
1087 return m_cacheRotMap->getCache(comp->getComponentID(), rotation);
1088}
1089
1098 const ParameterMap *oldPMap) {
1099
1100 auto oldParameterNames = oldPMap->names(oldComp);
1101 for (const auto &oldParameterName : oldParameterNames) {
1102 Parameter_sptr thisParameter = oldPMap->get(oldComp, oldParameterName);
1103// Insert the fetched parameter in the m_map
1104#if TBB_VERSION_MAJOR >= 4 && TBB_VERSION_MINOR >= 4 && !CLANG_ON_LINUX
1105 m_map.emplace(newComp->getComponentID(), std::move(thisParameter));
1106#else
1107 m_map.insert(std::make_pair(newComp->getComponentID(), std::move(thisParameter)));
1108#endif
1109 }
1110}
1111
1112//--------------------------------------------------------------------------------------------
1117void ParameterMap::saveNexus(Nexus::File *file, const std::string &group) const {
1118 file->makeGroup(group, "NXnote", true);
1119 file->putAttr("version", 1);
1120 file->writeData("author", "");
1121 file->writeData("date", Types::Core::DateAndTime::getCurrentTime().toISO8601String());
1122 file->writeData("description", "A string representation of the parameter "
1123 "map. The format is either: "
1124 "|detID:id-value;param-type;param-name;param-"
1125 "value| for a detector or "
1126 "|comp-name;param-type;param-name;param-value|"
1127 " for other components.");
1128 file->writeData("type", "text/plain");
1129 std::string s = this->asString();
1130 file->writeData("data", s);
1131 file->closeGroup();
1132}
1133
1137const std::vector<std::string> &ParameterMap::getParameterFilenames() const { return m_parameterFileNames; }
1139
1142void ParameterMap::addParameterFilename(const std::string &filename) { m_parameterFileNames.emplace_back(filename); }
1143
1145std::shared_ptr<Parameter> ParameterMap::create(const std::string &className, const std::string &name,
1146 const std::string &visible) const {
1147 return ParameterFactory::create(className, name, visible);
1148}
1149
1156bool ParameterMap::hasDetectorInfo(const Instrument *instrument) const {
1157 if (instrument != m_instrument)
1158 return false;
1159 return static_cast<bool>(m_detectorInfo);
1160}
1161
1165bool ParameterMap::hasComponentInfo(const Instrument *instrument) const {
1166 if (instrument != m_instrument)
1167 return false;
1168 return static_cast<bool>(m_componentInfo);
1169}
1170
1174 throw std::runtime_error("Cannot return reference to NULL DetectorInfo");
1175 return *m_detectorInfo;
1176}
1177
1181 throw std::runtime_error("Cannot return reference to NULL DetectorInfo");
1182 return *m_detectorInfo;
1183}
1184
1188 throw std::runtime_error("Cannot return reference to NULL ComponentInfo");
1189 }
1190 return *m_componentInfo;
1191}
1192
1196 throw std::runtime_error("Cannot return reference to NULL ComponentInfo");
1197 }
1198 return *m_componentInfo;
1199}
1200
1202size_t ParameterMap::detectorIndex(const detid_t detID) const { return m_instrument->detectorIndex(detID); }
1203
1204size_t ParameterMap::componentIndex(const ComponentID componentId) const {
1205 return m_componentInfo->indexOf(componentId);
1206}
1207
1210 if (instrument == m_instrument)
1211 return;
1212 if (!instrument) {
1213 m_componentInfo = nullptr;
1214 m_detectorInfo = nullptr;
1215 return;
1216 }
1217 if (m_instrument)
1218 throw std::logic_error("ParameterMap::setInstrument: Cannot change "
1219 "instrument once it has been set.");
1220 if (instrument->isParametrized())
1221 throw std::logic_error("ParameterMap::setInstrument must be called with "
1222 "base instrument, not a parametrized instrument");
1223 m_instrument = instrument;
1224 if (m_map.empty()) {
1226 } else {
1228 }
1229}
1230
1235 // m_map: tbb::concurrent_unordered_multimap<ComponentID, shared_ptr<Parameter>>
1236 // Each node: key + value + ~2 pointers for chaining and bucket slot
1237 const size_t n = m_map.size();
1238 const size_t mapMem = n * (sizeof(pmap::value_type) + 2 * sizeof(void *));
1239 // Count the heap-allocated Parameter objects the shared_ptrs point to.
1240 // ParameterMap is a friend of Parameter so private string members are accessible.
1241 size_t parameterObjectsMem = 0;
1242 for (const auto &entry : m_map) {
1243 const auto &param = entry.second;
1244 if (param) {
1245 parameterObjectsMem += sizeof(Parameter);
1246 parameterObjectsMem += param->m_name.capacity();
1247 parameterObjectsMem += param->m_type.capacity();
1248 parameterObjectsMem += param->m_str_value.capacity();
1249 parameterObjectsMem += param->m_description.capacity();
1250 }
1251 }
1252 // m_parameterFileNames: vector of strings; sizeof(*this) covers the vector object, count the heap buffer
1253 const size_t fileNamesMem = m_parameterFileNames.size() * sizeof(std::string) +
1254 std::accumulate(m_parameterFileNames.cbegin(), m_parameterFileNames.cend(), size_t{0},
1255 [](size_t acc, const auto &s) { return acc + s.capacity(); });
1256 // m_cacheLocMap and m_cacheRotMap: count the heap Cache objects; the internal std::map entries are not
1257 // counted because Kernel::Cache::size() is non-const and cannot be called here.
1258 const size_t cacheLocMem = m_cacheLocMap ? sizeof(*m_cacheLocMap) : 0;
1259 const size_t cacheRotMem = m_cacheRotMap ? sizeof(*m_cacheRotMap) : 0;
1260 // m_detectorInfo and m_componentInfo: owned by ParameterMap for parametrized instruments
1261 const size_t detectorInfoMem = m_detectorInfo ? m_detectorInfo->getMemorySize() : 0;
1262 const size_t componentInfoMem = m_componentInfo ? m_componentInfo->getMemorySize() : 0;
1263 // m_instrument is a non-owning raw pointer to the base Instrument; its memory is counted in
1264 // Instrument::getMemorySize() and excluded here to avoid double-counting.
1265 return sizeof(*this) + mapMem + parameterObjectsMem + fileNamesMem + cacheLocMem + cacheRotMem + detectorInfoMem +
1266 componentInfoMem;
1267}
1268
1269} // namespace Mantid::Geometry
std::string name
Definition Run.cpp:60
const std::vector< double > & rhs
double value
The value of the point.
Definition FitMW.cpp:51
double position
Definition GetAllEi.cpp:154
#define PARALLEL_CRITICAL(name)
Mantid::Kernel::Quat(ComponentInfo::* rotation)(const size_t) const
ComponentInfo : Provides a component centric view on to the instrument.
bool isParametrized() const override
Return true if the Component is, in fact, parametrized (that is - it has a valid parameter map)
Definition Component.cpp:75
Geometry::DetectorInfo is an intermediate step towards a DetectorInfo that is part of Instrument-2....
Store information about a fitting parameter such as its value if it is constrained or tied.
const std::string & getFunction() const
get function
base class for Geometric IComponent
Definition IComponent.h:53
virtual Kernel::V3D getPos() const =0
Get the position of the IComponent. Tree structure is traverse through the.
virtual std::shared_ptr< const IComponent > getParent() const =0
Return a pointer to the current parent.
virtual ComponentID getComponentID() const =0
Returns the ComponentID - a unique identifier of the component.
virtual std::string getName() const =0
Get the IComponent name.
Interface class for detector objects.
Definition IDetector.h:43
virtual detid_t getID() const =0
Get the detector ID.
Base Instrument Class.
Definition Instrument.h:49
std::pair< std::unique_ptr< ComponentInfo >, std::unique_ptr< DetectorInfo > > makeBeamlineNew(ParameterMap &pmap) const
Return ComponentInfo and DetectorInfo for instrument given by pmap.
std::pair< std::unique_ptr< ComponentInfo >, std::unique_ptr< DetectorInfo > > makeBeamline(ParameterMap &pmap, const ParameterMap *source=nullptr) const
Return ComponentInfo and DetectorInfo for instrument given by pmap.
size_t detectorIndex(const detid_t detID) const
Returns the index for a detector ID. Used for accessing DetectorInfo.
static std::shared_ptr< Parameter > create(const std::string &className, const std::string &name, const std::string &visible="true")
Creates an instance of a parameter.
Definition Parameter.cpp:83
component_map_it positionOf(const IComponent *comp, const char *name, const char *type)
internal function to get position of the parameter in the parameter map
bool getCachedRotation(const IComponent *comp, Kernel::Quat &rotation) const
Attempts to retrieve a rotation from the rotation cache.
const Geometry::DetectorInfo & detectorInfo() const
Only for use by ExperimentInfo. Returns a reference to the DetectorInfo.
const std::vector< std::string > & getParameterFilenames() const
Returns a list of all the parameter files loaded.
static const std::string & pQuat()
bool getCachedLocation(const IComponent *comp, Kernel::V3D &location) const
Attempts to retrieve a location from the location cache.
void clearPositionSensitiveCaches()
Clears the location, rotation & bounding box caches.
std::unique_ptr< Geometry::DetectorInfo > m_detectorInfo
Pointer to the DetectorInfo wrapper.
bool contains(const IComponent *comp, const std::string &name, const std::string &type="") const
Does the named parameter exist for the given component and type (std::string version)
void copyFromParameterMap(const IComponent *oldComp, const IComponent *newComp, const ParameterMap *oldPMap)
Copy pairs (oldComp->id,Parameter) to the m_map assigning the new newComp->id.
void addInt(const IComponent *comp, const std::string &name, const std::string &value, const std::string *const pDescription=nullptr, const std::string &pVisible="true")
Adds an int value to the parameter map.
void addPositionCoordinate(const IComponent *comp, const std::string &name, const double value, const std::string *const pDescription=nullptr)
Create or adjust "pos" parameter for a component.
std::shared_ptr< Parameter > getRecursive(const IComponent *comp, const std::string &name, const std::string &type="") const
Use get() recursively to see if can find param in all parents of comp and given type (std::string ver...
void addParameterFilename(const std::string &filename)
adds a parameter filename that has been loaded
static const std::string & scale()
std::shared_ptr< Parameter > getRecursiveByType(const IComponent *comp, const std::string &type) const
Looks recursively upwards in the component tree for the first instance of a parameter with a specifie...
static const std::string & rot()
void setCachedLocation(const IComponent *comp, const Kernel::V3D &location) const
Sets a cached location on the location cache.
const Instrument * m_instrument
Pointer to the owning instrument for translating detector IDs into detector indices when accessing th...
std::string getString(const IComponent *comp, const std::string &name, bool recursive=false) const
Return the value of a parameter as a string.
static const std::string & pBool()
void saveNexus(Nexus::File *file, const std::string &group) const
Persist a representation of the Parameter map to the open Nexus file.
void setCachedRotation(const IComponent *comp, const Kernel::Quat &rotation) const
Sets a cached rotation on the rotation cache.
void clearParametersByName(const std::string &name)
Clear any parameters with the given name.
const std::string getDescription(const std::string &compName, const std::string &name) const
Get the component description by name.
std::shared_ptr< Parameter > getByType(const IComponent *comp, const std::string &type) const
Finds the parameter in the map via the parameter type.
void setInstrument(const Instrument *instrument)
Only for use by Instrument. Sets the pointer to the owning instrument.
Geometry::ComponentInfo & mutableComponentInfo()
Only for use by ExperimentInfo. Returns a reference to the ComponentInfo.
bool operator==(const ParameterMap &rhs) const
Equality comparison operator.
std::shared_ptr< Parameter > create(const std::string &className, const std::string &name, const std::string &visible="true") const
Wrapper for ParameterFactory::create to avoid include in header.
void addString(const IComponent *comp, const std::string &name, const std::string &value, const std::string *const pDescription=nullptr, const std::string &pVisible="true")
Adds a std::string value to the parameter map.
std::set< std::string > names(const IComponent *comp) const
Returns a set with all parameter names for component.
int size() const
Return the size of the map.
std::vector< std::string > m_parameterFileNames
internal list of parameter files loaded
pmap m_map
internal parameter map instance
static const std::string & pV3D()
std::unique_ptr< Kernel::Cache< const ComponentID, Kernel::V3D > > m_cacheLocMap
internal cache map instance for cached position values
size_t getMemorySize() const
Get the footprint in memory in bytes.
void addDouble(const IComponent *comp, const std::string &name, const std::string &value, const std::string *const pDescription=nullptr, const std::string &pVisible="true")
Adds a double value to the parameter map.
static const std::string & posz()
std::unique_ptr< Kernel::Cache< const ComponentID, Kernel::Quat > > m_cacheRotMap
internal cache map instance for cached rotation values
bool relErr(double x1, double x2, double errorVal) const
calculate relative error for use in diff
const std::string diff(const ParameterMap &rhs, const bool &firstDiffOnly=false, const bool relative=false, const double doubleTolerance=Kernel::Tolerance) const
Output information that helps understanding the mismatch between two parameter maps.
static const std::string & pDouble()
static const std::string & pos()
Return string to be used in the map.
void addRotationParam(const IComponent *comp, const std::string &name, const double deg, const std::string *const pDescription=nullptr)
Create or adjust "rot" parameter for a component.
ParameterMap()
Default constructor.
std::string asString() const
Returns a string with all component names, parameter names and values.
void addFittingParameter(const IComponent *comp, const std::string &name, const std::string &fittingFunction, const std::string &value, const std::string *const pDescription=nullptr, const std::string &pVisible="true")
Add a fitting parameter.
void addQuat(const IComponent *comp, const std::string &name, const Kernel::Quat &value, const std::string *const pDescription=nullptr)
Adds a Kernel::Quat value to the parameter map.
size_t componentIndex(const Geometry::ComponentID componentId) const
void add(const std::string &type, const IComponent *comp, const std::string &name, const std::string &value, const std::string *const pDescription=nullptr, const std::string &visible="true")
Method for adding a parameter providing its value as a string.
std::shared_ptr< Parameter > getRecursiveFittingParameter(const IComponent *comp, const std::string &name, const std::string &fittingFunction) const
Look for a fitting parameter recursively, picking the one whose embedded FitParameter function name m...
static const std::string & rotz()
const std::string getShortDescription(const std::string &compName, const std::string &name) const
Get the component tooltip by name.
size_t detectorIndex(const detid_t detID) const
Only for use by Detector. Returns a detector index for a detector ID.
static const std::string & posy()
static const std::string & posx()
static const std::string & pString()
tbb::concurrent_unordered_multimap< ComponentID, std::shared_ptr< Parameter > >::const_iterator pmap_cit
Parameter map iterator typedef.
void addV3D(const IComponent *comp, const std::string &name, const std::string &value, const std::string *const pDescription=nullptr)
Adds a Kernel::V3D value to the parameter map.
static const std::string & pInt()
void addBool(const IComponent *comp, const std::string &name, const std::string &value, const std::string *const pDescription=nullptr, const std::string &pVisible="true")
Adds a bool value to the parameter map.
bool operator!=(const ParameterMap &rhs) const
Inquality comparison operator.
bool hasComponentInfo(const Instrument *instrument) const
Only for use by ExperimentInfo.
std::unique_ptr< Geometry::ComponentInfo > m_componentInfo
Pointer to the ComponentInfo wrapper.
static const std::string & rotx()
bool hasDetectorInfo(const Instrument *instrument) const
Only for use by ExperimentInfo.
std::shared_ptr< Parameter > get(const IComponent *comp, const std::string &name, const std::string &type="") const
Get a parameter with a given name and type (std::string version)
void forceUnsafeSetMasked(const IComponent *comp, bool value)
Force adding masking information.
static const std::string & roty()
const Geometry::ComponentInfo & componentInfo() const
Only for use by ExperimentInfo. Returns a reference to the ComponentInfo.
Geometry::DetectorInfo & mutableDetectorInfo()
Only for use by ExperimentInfo. Returns a reference to the DetectorInfo.
Base class for parameters of an instrument.
Definition Parameter.h:37
const std::string & name() const
Parameter name.
Definition Parameter.h:45
Cache is a generic caching storage class.
Definition Cache.h:27
void debug(const std::string &msg)
Logs at debug level.
Definition Logger.cpp:145
void warning(const std::string &msg)
Logs at warning level.
Definition Logger.cpp:117
Class for quaternions.
Definition Quat.h:39
Class for 3D vectors.
Definition V3D.h:34
void setX(const double xx) noexcept
Set is x position.
Definition V3D.h:224
This functor is used as the deleter object of a shared_ptr to effectively erase ownership Raw pointer...
Definition IComponent.h:173
tbb::concurrent_unordered_multimap< ComponentID, std::shared_ptr< Parameter > >::const_iterator component_map_cit
std::shared_ptr< Parameter > Parameter_sptr
Typedef for the shared pointer.
Definition Parameter.h:194
tbb::concurrent_unordered_multimap< ComponentID, std::shared_ptr< Parameter > >::iterator component_map_it
Parameter map iterator typedef.
Mantid::Kernel::Logger g_log("Goniometer")
int32_t detid_t
Typedef for a detector ID.
STL namespace.
std::string to_string(const wide_integer< Bits, Signed > &n)