Mantid
Loading...
Searching...
No Matches
Component.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 +
17
18#include <Poco/SAX/AttributesImpl.h>
19#include <Poco/XML/XMLWriter.h>
20
21#include <utility>
22
23namespace Mantid::Geometry {
24
25using Kernel::Quat;
26using Kernel::V2D;
27using Kernel::V3D;
28
34 : m_parent(nullptr), m_base(dynamic_cast<const Component *>(base)), m_map(map) {
35 if (!m_base) {
36 throw std::invalid_argument("Component::Component() - Cannot construct a "
37 "parameterized component from an invalid base component.");
38 }
39}
40
44Component::Component() : m_parent(nullptr), m_base(nullptr), m_map(nullptr), m_name(), m_pos(), m_rot() {}
45
51 : m_parent(parent), m_base(nullptr), m_map(nullptr), m_name(std::move(name)), m_pos(), m_rot() {}
52
59Component::Component(std::string name, const V3D &position, IComponent *parent)
60 : m_parent(parent), m_base(nullptr), m_map(nullptr), m_name(std::move(name)), m_pos(position), m_rot() {}
61
68Component::Component(std::string name, const V3D &position, const Quat &rotation, IComponent *parent)
69 : m_parent(parent), m_base(nullptr), m_map(nullptr), m_name(std::move(name)), m_pos(position), m_rot(rotation) {}
70
71//------------------------------------------------------------------------------------------------
75bool Component::isParametrized() const { return (m_map != nullptr); }
76
82 // TODO : overload to copy the new pmap
83 // Create a new one with pmap parameter
85 return new Component(*this);
86}
87
92 if (m_map)
93 return ComponentID(const_cast<Component *>(m_base));
94 else
95 return ComponentID(const_cast<Component *>(this));
96}
97
99 if (m_map)
100 return const_cast<const Component *>(m_base);
101 else
102 return const_cast<const Component *>(this);
103}
104
105//-------------------------------------------------------------------------------
110
111//--------------------------------------------------------------------------------------------
115std::shared_ptr<const IComponent> Component::getParent() const {
116 if (this->m_map) {
117 std::shared_ptr<const IComponent> parent = m_base->getParent();
118 return ParComponentFactory::create(parent, m_map);
119 } else
120 return std::shared_ptr<const IComponent>(m_parent, NoDeleting());
121}
122
123//--------------------------------------------------------------------------------------------
131bool Component::isParentNamed(const std::string &expectedName, int maxDepth) const {
132 int depth = 0;
133 const IComponent *parent = m_parent;
134 while (parent && (depth < maxDepth || maxDepth < 0)) {
135 // Correct name? stop searching
136 if (parent->getName() == expectedName)
137 return true;
138 parent = parent->getBareParent();
139 depth++;
140 }
141 return false;
142}
143
144//--------------------------------------------------------------------------------------------
149std::vector<std::shared_ptr<const IComponent>> Component::getAncestors() const {
150 std::vector<std::shared_ptr<const IComponent>> ancs;
151
152 std::shared_ptr<const IComponent> current = this->getParent();
153 while (current) {
154 ancs.emplace_back(current);
155 current = current->getParent();
156 }
157 return ancs;
158}
159
160//--------------------------------------------------------------------------------------------
164void Component::setName(const std::string &s) {
165 if (!m_map)
166 this->m_name = s;
167 else
168 throw Kernel::Exception::NotImplementedError("Component::setName (for Parametrized Component)");
169}
170
171//--------------------------------------------------------------------------------------------
175std::string Component::getName() const {
176 if (m_map)
177 return m_base->getName();
178 else
179 return m_name;
180}
181
185std::string Component::getFullName() const {
186 std::vector<std::shared_ptr<const IComponent>> ancestors = this->getAncestors();
187 if (ancestors.empty()) {
188 return this->getName();
189 } else {
190 std::ostringstream oss;
191 std::vector<std::shared_ptr<const IComponent>>::reverse_iterator rit;
192 for (rit = ancestors.rbegin(); rit < ancestors.rend(); ++rit) {
193 oss << (*rit)->getName() << "/";
194 }
195 oss << this->getName();
196 return oss.str();
197 }
198}
199
206void Component::setPos(double x, double y, double z) {
207 if (!m_map)
208 m_pos = V3D(x, y, z);
209 else
210 throw Kernel::Exception::NotImplementedError("Component::setPos (for Parametrized Component)");
211}
212
217void Component::setPos(const V3D &v) {
218 if (!m_map)
219 m_pos = v;
220 else
221 throw Kernel::Exception::NotImplementedError("Component::setPos (for Parametrized Component)");
222}
223
225
230void Component::setRot(const Quat &q) {
231 if (!m_map)
232 m_rot = q;
233 else
234 throw Kernel::Exception::NotImplementedError("Component::setRot (for Parametrized Component)");
235}
236
242void Component::translate(double x, double y, double z) {
243 if (!m_map) {
244 m_pos[0] += x;
245 m_pos[1] += y;
246 m_pos[2] += z;
247 } else
248 throw Kernel::Exception::NotImplementedError("Component::translate (for Parametrized Component)");
249}
250
254void Component::translate(const V3D &v) {
255 if (!m_map)
256 m_pos += v;
257 else
258 throw Kernel::Exception::NotImplementedError("Component::translate (for Parametrized Component)");
259}
260
264void Component::rotate(const Quat &r) {
265 if (!m_map)
266 m_rot = m_rot * r;
267 else
268 throw Kernel::Exception::NotImplementedError("Component::rotate (for Parametrized Component)");
269}
270
275void Component::rotate(double angle, const V3D &axis) {
276 (void)angle; // Avoid compiler warning
277 (void)axis; // Avoid compiler warning
278 throw Kernel::Exception::NotImplementedError("Rotate(double angle, const V3D& axis) has not been implemented");
279}
280
287 if (m_map) {
288 if (hasComponentInfo()) {
290 } else {
292 if (par) {
293 return par->value<V3D>();
294 }
295 }
296 }
297 return V3D(1, 1, 1);
298}
299
301size_t Component::index() const { return m_map->componentIndex(this->getComponentID()); }
302
304 const IComponent *root = m_base;
305 while (auto parent = root->getBareParent())
306 root = parent;
307 auto instrument = dynamic_cast<const Instrument *>(root);
308 return m_map->hasComponentInfo(instrument);
309}
310
313 if (m_map) {
314
315 if (hasComponentInfo()) {
317 } else {
318 if (m_map->contains(m_base, "pos")) {
319 return m_map->get(m_base, "pos")->value<V3D>();
320 } else
321 return m_base->m_pos;
322 }
323 } else {
324 return m_pos;
325 }
326}
327
330 if (m_map) {
331 if (hasComponentInfo()) {
332 return m_map->componentInfo().position(index());
333 } else {
334 // We currently have to treat detectors in a different way because
335 // InfoComponentVisitor functionality is incomplete w.r.t DetectorInfo
336
337 // Avoid instantiation of the parent's parameterized object if possible
338 const IComponent *baseParent = m_base->m_parent;
339 if (!baseParent) {
340 return this->getRelativePos();
341 } else {
342 // Avoid instantiation of parent shared pointer if we can
343 V3D absPos = this->getRelativePos();
344 // get the parent rotation, try to get it from the cache first to avoid
345 // instantiaing the class
346
347 Quat parentRot;
348 V3D parentPos;
349 if (!(m_map->getCachedLocation(baseParent, parentPos) && m_map->getCachedRotation(baseParent, parentRot))) {
350 // Couldn't get them from the cache, so I have to instantiate the
351 // class
352 std::shared_ptr<const IComponent> parParent = getParent();
353 if (parParent) {
354 parentRot = parParent->getRotation();
355 parentPos = parParent->getPos();
356 }
357 }
358 parentRot.rotate(absPos);
359 absPos += parentPos;
360 return absPos;
361 }
362 }
363 } else {
364 if (!m_parent) {
365 return m_pos;
366 } else {
367 V3D absPos(m_pos);
368 m_parent->getRotation().rotate(absPos);
369 return absPos + m_parent->getPos();
370 }
371 }
372}
373
375std::optional<Kernel::V2D> Component::getSideBySideViewPos() const {
376 if (m_map) {
378 } else if (!m_parent) {
379 return m_sidebysideviewpos;
380 } else {
382 return std::nullopt;
383 else {
384 V2D absPos = m_sidebysideviewpos ? *m_sidebysideviewpos : V2D{0., 0.};
385 V2D parentPos = m_parent->getSideBySideViewPos() ? *m_parent->getSideBySideViewPos() : V2D{0., 0.};
386 return absPos + parentPos;
387 }
388 }
389}
390
393 if (m_map) {
394 if (hasComponentInfo()) {
396 } else {
397 if (m_map->contains(m_base, "rot")) {
398 return m_map->get(m_base, "rot")->value<Quat>();
399 }
400 return m_base->m_rot;
401 }
402 } else {
403 return m_rot;
404 }
405}
406
409 if (m_map) {
410 if (hasComponentInfo()) {
411 return m_map->componentInfo().rotation(index());
412 } else {
413 // Avoid instantiation of the parent's parameterized object if possible
414 const IComponent *baseParent = m_base->m_parent;
415 if (!baseParent) {
416 return getRelativeRot();
417 } else {
418 Quat parentRot;
419 if (!m_map->getCachedRotation(baseParent, parentRot)) {
420 // Get the parent's rotation
421 std::shared_ptr<const IComponent> parParent = getParent();
422 if (parParent) {
423 parentRot = parParent->getRotation();
424 }
425 }
426 return parentRot * getRelativeRot();
427 }
428 }
429 } else {
430 // Not parametrized
431 if (!m_parent)
432 return m_rot;
433 else
434 return m_parent->getRotation() * m_rot;
435 }
436}
437
442double Component::getDistance(const IComponent &comp) const { return getPos().distance(comp.getPos()); }
443
449void Component::getBoundingBox(BoundingBox &boundingBox) const { boundingBox = BoundingBox(); }
450
457std::set<std::string> Component::getParameterNames(bool recursive) const {
458 if (!m_map)
459 return std::set<std::string>();
460
461 std::set<std::string> names = m_map->names(this);
462 if (recursive) {
463 // Walk up the tree and find the parameters attached to the parent
464 // components
465 std::shared_ptr<const IComponent> parent = getParent();
466 if (parent) {
467 std::set<std::string> parentNames = parent->getParameterNames(true);
468 names.insert(parentNames.begin(), parentNames.end());
469 }
470 }
471 return names;
472}
473
480std::map<std::string, ComponentID> Component::getParameterNamesByComponent() const {
481 auto retVal = std::map<std::string, ComponentID>();
482 if (!m_map)
483 return retVal;
484
485 auto names = m_map->names(this);
486 for (const auto &name : names) {
487 retVal.insert(std::pair<std::string, ComponentID>(name, this->getComponentID()));
488 }
489
490 // Walk up the tree and find the parameters attached to the parent components
491 std::shared_ptr<const IComponent> parent = getParent();
492 if (parent) {
493 auto parentNames = parent->getParameterNamesByComponent();
494 // this should discard duplicates
495 retVal.insert(parentNames.begin(), parentNames.end());
496 }
497 return retVal;
498}
499
507bool Component::hasParameter(const std::string &name, bool recursive) const {
508 if (!m_map)
509 return false;
510
511 bool match_found(false);
512 if (m_map->contains(this, name)) {
513 match_found = true;
514 } else if (recursive) {
515 std::shared_ptr<const IComponent> parent = getParent();
516 if (parent) {
517 match_found = parent->hasParameter(name, true);
518 } else {
519 match_found = false;
520 }
521 } else {
522 match_found = false;
523 }
524 return match_found;
525}
526
530void Component::printSelf(std::ostream &os) const {
531 std::shared_ptr<const IComponent> parent = getParent();
532 os << "Name : " << getName() << '\n';
533 os << "Type: " << this->type() << '\n';
534 if (parent)
535 os << "Parent: " << parent->getName() << '\n';
536 else
537 os << "Parent: None\n";
538
539 os << "Position : " << getPos() << '\n';
540 os << "Orientation :" << getRelativeRot() << '\n';
541}
542
548std::ostream &operator<<(std::ostream &os, const Component &comp) {
549 comp.printSelf(os);
550 return os;
551}
552
553//------------------------------------------------------------------------------------------------
556void Component::readXMLAttributes(const Poco::XML::Attributes &attr) {
557 UNUSED_ARG(attr);
558 // std::string pos = attr.getValue("", "pos");
559 // m_pos.fromString(pos);
560 // std::string rot = attr.getValue("", "rot");
561 // m_rot.fromString(rot);
562}
563
564void Component::writeXML(Poco::XML::XMLWriter &writer) const {
565 Poco::XML::AttributesImpl attr;
566 attr.addAttribute("", "pos", "", "", m_pos.toString());
567 writer.startElement("", "Component", "", attr);
568 writer.endElement("", "Component", "");
569}
570
571//------------------------------------------------------------------------------------------------
574void Component::appendXML(std::ostream &xmlStream) const {
575 xmlStream << "<pos>";
576 m_pos.write(xmlStream);
577 xmlStream << "</pos>\n";
578 xmlStream << "<rot>" << m_rot << "</rot>\n";
579}
580
581//--------------------------------------------------------------------------
582// Private methods
583//--------------------------------------------------------------------------
584
591void Component::swap(const Component *base, const ParameterMap *pmap) {
592 m_base = base;
593 m_map = pmap;
594}
606std::string Component::getParamDescription(const std::string &pname, bool recursive) const {
607 if (!m_map) { // no description for non-parameterized components
608 return std::string("");
609 }
610 Parameter_sptr param;
611 if (recursive) {
612 param = m_map->getRecursive(this, pname);
613 } else {
614 param = m_map->get(this, pname);
615 }
616 if (param)
617 return param->getDescription();
618 else
619 return std::string("");
620}
622std::string Component::getDescription() const {
623 auto name = this->getName();
624 return this->getParamDescription(name, false);
625}
626
637std::string Component::getParamShortDescription(const std::string &pname, bool recursive) const {
638 if (!m_map) { // no tooltips for non-parameterized components
639 return std::string("");
640 }
641 Parameter_sptr param;
642 if (recursive) {
643 param = m_map->getRecursive(this, pname);
644 } else {
645 param = m_map->get(this, pname);
646 }
647 if (param)
648 return param->getShortDescription();
649 else
650 return std::string("");
651}
652
656 auto name = this->getName();
657 return this->getParamShortDescription(name, false);
658}
662void Component::setDescription(const std::string &descr) {
663 if (m_map) {
664 std::string name = this->getName();
665 auto param = m_map->getRecursive(this, name);
666 if (param) {
667 param->setDescription(descr);
668 } else {
669 // I see no reason why component's parameter map should be constant.
670 // But as I do not understand why it is constant, let's HACK!
671 (const_cast<ParameterMap *>(m_map))->addString(this, name, "", &descr);
672 }
673 } else
674 throw Kernel::Exception::NotImplementedError("Component::setDescription "
675 "not implemented for "
676 "non-Parametrized Component)");
677}
678
679size_t Component::registerContents(class ComponentVisitor &componentVisitor) const {
680 return componentVisitor.registerGenericComponent(*this);
681}
682
690double Component::getFittingParameter(const std::string &pname, double xvalue) const {
691 if (m_map) {
692 Parameter_sptr parameter = m_map->getRecursive(this, pname, "fitting");
693 if (!parameter) {
694 throw std::runtime_error("Fitting parameter=" + pname +
695 " could not be extracted from component=" + this->getName());
696 }
697
698 try {
699 const auto &fitParam = parameter->value<FitParameter>();
700 return fitParam.getValue(xvalue);
701 } catch (...) {
702 throw std::runtime_error("Unable to get lookup table for parameter=" + pname +
703 " from component=" + this->getName());
704 }
705 } else {
706 throw std::runtime_error("Parameter map is not available in component=" + this->getName());
707 }
708}
709
710} // namespace Mantid::Geometry
std::string name
Definition Run.cpp:60
double position
Definition GetAllEi.cpp:154
Mantid::Kernel::Quat(ComponentInfo::* rotation)(const size_t) const
#define UNUSED_ARG(x)
Function arguments are sometimes unused in certain implmentations but are required for documentation ...
Definition System.h:48
A simple structure that defines an axis-aligned cuboid shaped bounding box for a geometrical object.
Definition BoundingBox.h:33
Kernel::Quat rotation(const size_t componentIndex) const
Kernel::V3D position(const size_t componentIndex) const
Kernel::V3D relativePosition(const size_t componentIndex) const
Kernel::Quat relativeRotation(const size_t componentIndex) const
Kernel::V3D scaleFactor(const size_t componentIndex) const
ComponentVisitor : Visitor for IComponents.
virtual size_t registerGenericComponent(const IComponent &component)=0
Component is a wrapper for a Component which can modify some of its parameters, e....
Definition Component.h:42
const ParameterMap * m_map
A pointer to const ParameterMap containing the parameters.
Definition Component.h:316
void setSideBySideViewPos(const Kernel::V2D &) override
Set the IComponent position in the side by side instrument view.
virtual void writeXML(Poco::XML::XMLWriter &writer) const
std::map< std::string, ComponentID > getParameterNamesByComponent() const override
return the parameter names and the component they are from
std::string getParamDescription(const std::string &pname, bool recursive=true) const
Get description of a parameter attached to this component
void setRot(const Kernel::Quat &) override
Set the orientation Kernel::Quaternion relative to parent (if present)
std::string getParamShortDescription(const std::string &pname, bool recursive=true) const
Get a component's parameter short description.
std::optional< Kernel::V2D > m_sidebysideviewpos
Position of component in instrument viewer side by side view.
Definition Component.h:325
double getFittingParameter(const std::string &pname, double xvalue) const
Get fitting parameter.
virtual void readXMLAttributes(const Poco::XML::Attributes &attr)
Reads the XML attributes from Poco XML parser.
size_t index() const
Helper for legacy access mode. Returns the index of the component.
void setParent(IComponent *) override
Assign a parent IComponent. Previous parent link is lost.
std::string m_name
Name of the component.
Definition Component.h:319
Kernel::Quat getRelativeRot() const override
Get the relative Orientation.
void printSelf(std::ostream &) const override
Prints a text representation of itself.
Component()
Create Empty Component at Origin, with no orientation and null parent.
Definition Component.cpp:44
Kernel::V3D m_pos
Position w.
Definition Component.h:321
Kernel::V3D getRelativePos() const override
Get the position relative to the parent IComponent (absolute if no parent)
IComponent * clone() const override
Clone method Make a copy of the Component.
Definition Component.cpp:81
void setName(const std::string &) override
Set the IComponent name.
virtual void appendXML(std::ostream &xmlStream) const
Append to an open XML string.
void rotate(const Kernel::Quat &) override
Rotate the IComponent. This is relative to parent.
void getBoundingBox(BoundingBox &boundingBox) const override
Get the bounding box for this component and store it in the given argument.
const IComponent * base() const
Returns the address of the base component.
Definition Component.h:289
std::set< std::string > getParameterNames(bool recursive=true) const override
Return the parameter names.
virtual size_t registerContents(class ComponentVisitor &componentVisitor) const override
Kernel::V3D getScaleFactor() const override
Returns the ScaleFactor.
Kernel::V3D getPos() const override
Get the position of the IComponent. Tree structure is traverse through the.
std::shared_ptr< const IComponent > getParent() const override
Return a pointer to the current parent. as shared pointer.
std::optional< Kernel::V2D > getSideBySideViewPos() const override
Return the position of the component required on the instrument side by side view.
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
const IComponent * m_parent
Parent component in the tree.
Definition Component.h:309
void swap(const Component *base, const ParameterMap *pmap)
Swap the current references to the un-parameterized component and parameter map for new ones.
Kernel::Quat m_rot
Orientation.
Definition Component.h:323
std::string getFullName() const override
Get the full pathname.
IComponent const * getBaseComponent() const override
Returns const pointer to base component if this component is parametrized.
Definition Component.cpp:98
double getDistance(const IComponent &) const override
Get the distance to another IComponent.
std::string getName() const override
Get the IComponent name.
const Component * m_base
The base component - this is the unmodified component (without the parameters).
Definition Component.h:314
bool isParentNamed(const std::string &expectedName, int maxDepth=-1) const
Return true if one of the parents of this component is named something.
Kernel::Quat getRotation() const override
Get the absolute orientation of the IComponent.
std::vector< std::shared_ptr< const IComponent > > getAncestors() const override
Return an array of all ancestors.
void setDescription(const std::string &descr)
Set components description.
void setPos(double, double, double) override
Set the IComponent position, x, y, z respective to parent (if present)
std::string getDescription() const
Get this component parameter's description – no recursive search within children.
bool hasParameter(const std::string &name, bool recursive=true) const override
Returns a boolean indicating if the component has the named parameter.
void translate(const Kernel::V3D &) override
Translate the IComponent (vector form). This is relative to parent if.
ComponentID getComponentID() const override
Returns the ComponentID - a unique identifier of the component.
Definition Component.cpp:91
std::string getShortDescription() const
Get a components's short description.
Store information about a fitting parameter such as its value if it is constrained or tied.
double getValue(const double &at) const
get paramter value
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::string type() const
Returns a string representation of the IComponent type.
Definition IComponent.h:56
virtual std::optional< Kernel::V2D > getSideBySideViewPos() const =0
Get the position of the IComponent for display on the side by side instrument view.
virtual Kernel::Quat getRotation() const =0
Get the absolute orientation of the IComponent.
virtual const IComponent * getBareParent() const =0
Returns the bare pointer to the IComponent parent.
virtual std::string getName() const =0
Get the IComponent name.
Base Instrument Class.
Definition Instrument.h:47
Void deleter for shared pointers.
static std::shared_ptr< IComponent > create(const std::shared_ptr< const IComponent > &base, const ParameterMap *map)
Create a parameterized component from the given base component and ParameterMap.
bool getCachedRotation(const IComponent *comp, Kernel::Quat &rotation) const
Attempts to retrieve a rotation from the rotation cache.
bool getCachedLocation(const IComponent *comp, Kernel::V3D &location) const
Attempts to retrieve a location from the location cache.
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)
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...
static const std::string & scale()
std::set< std::string > names(const IComponent *comp) const
Returns a set with all parameter names for component.
size_t componentIndex(const Geometry::ComponentID componentId) const
bool hasComponentInfo(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)
const Geometry::ComponentInfo & componentInfo() const
Only for use by ExperimentInfo. Returns a reference to the ComponentInfo.
Marks code as not implemented yet.
Definition Exception.h:138
Class for quaternions.
Definition Quat.h:39
void rotate(V3D &) const
Rotate a vector.
Definition Quat.cpp:397
std::vector< double > getRotation(bool check_normalisation=false, bool throw_on_errors=false) const
returns the rotation matrix defined by this quaternion as an 9-point
Definition Quat.cpp:453
Implements a 2-dimensional vector embedded in a 3D space, i.e.
Definition V2D.h:29
Class for 3D vectors.
Definition V3D.h:34
double distance(const V3D &v) const noexcept
Calculates the distance between two vectors.
Definition V3D.h:293
std::string toString() const
Definition V3D.cpp:332
void write(std::ostream &) const
Write out the point values.
Definition V3D.cpp:322
std::shared_ptr< Parameter > Parameter_sptr
Typedef for the shared pointer.
Definition Parameter.h:194
MANTID_GEOMETRY_DLL std::ostream & operator<<(std::ostream &stream, const PointGroup &self)
Returns a streamed representation of the PointGroup object.
IComponent * ComponentID
Define a type for a unique component identifier.
Definition IComponent.h:35
Generate a tableworkspace to store the calibration results.
STL namespace.