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(const double x, const double y, const 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 V3D absPos = this->getRelativePos();
343 Quat parentRot;
344 V3D parentPos;
345 std::shared_ptr<const IComponent> parParent = getParent();
346 if (parParent) {
347 parentRot = parParent->getRotation();
348 parentPos = parParent->getPos();
349 }
350 parentRot.rotate(absPos);
351 absPos += parentPos;
352 return absPos;
353 }
354 }
355 } else {
356 if (!m_parent) {
357 return m_pos;
358 } else {
359 V3D absPos(m_pos);
360 m_parent->getRotation().rotate(absPos);
361 return absPos + m_parent->getPos();
362 }
363 }
364}
365
367std::optional<Kernel::V2D> Component::getSideBySideViewPos() const {
368 if (m_map) {
370 } else if (!m_parent) {
371 return m_sidebysideviewpos;
372 } else {
374 return std::nullopt;
375 else {
376 V2D absPos = m_sidebysideviewpos ? *m_sidebysideviewpos : V2D{0., 0.};
377 V2D parentPos = m_parent->getSideBySideViewPos() ? *m_parent->getSideBySideViewPos() : V2D{0., 0.};
378 return absPos + parentPos;
379 }
380 }
381}
382
385 if (m_map) {
386 if (hasComponentInfo()) {
388 } else {
389 if (m_map->contains(m_base, "rot")) {
390 return m_map->get(m_base, "rot")->value<Quat>();
391 }
392 return m_base->m_rot;
393 }
394 } else {
395 return m_rot;
396 }
397}
398
401 if (m_map) {
402 if (hasComponentInfo()) {
403 return m_map->componentInfo().rotation(index());
404 } else {
405 // Avoid instantiation of the parent's parameterized object if possible
406 const IComponent *baseParent = m_base->m_parent;
407 if (!baseParent) {
408 return getRelativeRot();
409 } else {
410 Quat parentRot;
411 std::shared_ptr<const IComponent> parParent = getParent();
412 if (parParent) {
413 parentRot = parParent->getRotation();
414 }
415 return parentRot * getRelativeRot();
416 }
417 }
418 } else {
419 // Not parametrized
420 if (!m_parent)
421 return m_rot;
422 else
423 return m_parent->getRotation() * m_rot;
424 }
425}
426
431double Component::getDistance(const IComponent &comp) const { return getPos().distance(comp.getPos()); }
432
438void Component::getBoundingBox(BoundingBox &boundingBox) const { boundingBox = BoundingBox(); }
439
446std::set<std::string> Component::getParameterNames(bool recursive) const {
447 if (!m_map)
448 return std::set<std::string>();
449
450 std::set<std::string> names = m_map->names(this);
451 if (recursive) {
452 // Walk up the tree and find the parameters attached to the parent
453 // components
454 std::shared_ptr<const IComponent> parent = getParent();
455 if (parent) {
456 std::set<std::string> parentNames = parent->getParameterNames(true);
457 names.insert(parentNames.begin(), parentNames.end());
458 }
459 }
460 return names;
461}
462
470bool Component::hasParameter(const std::string &name, bool recursive) const {
471 if (!m_map)
472 return false;
473
474 bool match_found(false);
475 if (m_map->contains(this, name)) {
476 match_found = true;
477 } else if (recursive) {
478 std::shared_ptr<const IComponent> parent = getParent();
479 if (parent) {
480 match_found = parent->hasParameter(name, true);
481 } else {
482 match_found = false;
483 }
484 } else {
485 match_found = false;
486 }
487 return match_found;
488}
489
493void Component::printSelf(std::ostream &os) const {
494 std::shared_ptr<const IComponent> parent = getParent();
495 os << "Name : " << getName() << '\n';
496 os << "Type: " << this->type() << '\n';
497 if (parent)
498 os << "Parent: " << parent->getName() << '\n';
499 else
500 os << "Parent: None\n";
501
502 os << "Position : " << getPos() << '\n';
503 os << "Orientation :" << getRelativeRot() << '\n';
504}
505
511std::ostream &operator<<(std::ostream &os, const Component &comp) {
512 comp.printSelf(os);
513 return os;
514}
515
516//------------------------------------------------------------------------------------------------
519void Component::readXMLAttributes(const Poco::XML::Attributes &attr) {
520 UNUSED_ARG(attr);
521 // std::string pos = attr.getValue("", "pos");
522 // m_pos.fromString(pos);
523 // std::string rot = attr.getValue("", "rot");
524 // m_rot.fromString(rot);
525}
526
527void Component::writeXML(Poco::XML::XMLWriter &writer) const {
528 Poco::XML::AttributesImpl attr;
529 attr.addAttribute("", "pos", "", "", m_pos.toString());
530 writer.startElement("", "Component", "", attr);
531 writer.endElement("", "Component", "");
532}
533
534//------------------------------------------------------------------------------------------------
537void Component::appendXML(std::ostream &xmlStream) const {
538 xmlStream << "<pos>";
539 m_pos.write(xmlStream);
540 xmlStream << "</pos>\n";
541 xmlStream << "<rot>" << m_rot << "</rot>\n";
542}
543
544//--------------------------------------------------------------------------
545// Private methods
546//--------------------------------------------------------------------------
547
554void Component::swap(const Component *base, const ParameterMap *pmap) {
555 m_base = base;
556 m_map = pmap;
557}
569std::string Component::getParamDescription(const std::string &pname, bool recursive) const {
570 if (!m_map) { // no description for non-parameterized components
571 return std::string("");
572 }
573 Parameter_sptr param;
574 if (recursive) {
575 param = m_map->getRecursive(this, pname);
576 } else {
577 param = m_map->get(this, pname);
578 }
579 if (param)
580 return param->getDescription();
581 else
582 return std::string("");
583}
585std::string Component::getDescription() const {
586 auto name = this->getName();
587 return this->getParamDescription(name, false);
588}
589
600std::string Component::getParamShortDescription(const std::string &pname, bool recursive) const {
601 if (!m_map) { // no tooltips for non-parameterized components
602 return std::string("");
603 }
604 Parameter_sptr param;
605 if (recursive) {
606 param = m_map->getRecursive(this, pname);
607 } else {
608 param = m_map->get(this, pname);
609 }
610 if (param)
611 return param->getShortDescription();
612 else
613 return std::string("");
614}
615
619 auto name = this->getName();
620 return this->getParamShortDescription(name, false);
621}
625void Component::setDescription(const std::string &descr) {
626 if (m_map) {
627 std::string name = this->getName();
628 auto param = m_map->getRecursive(this, name);
629 if (param) {
630 param->setDescription(descr);
631 } else {
632 // I see no reason why component's parameter map should be constant.
633 // But as I do not understand why it is constant, let's HACK!
634 (const_cast<ParameterMap *>(m_map))->addString(this, name, "", &descr);
635 }
636 } else
637 throw Kernel::Exception::NotImplementedError("Component::setDescription "
638 "not implemented for "
639 "non-Parametrized Component)");
640}
641
642size_t Component::registerContents(class ComponentVisitor &componentVisitor) const {
643 return componentVisitor.registerGenericComponent(*this);
644}
645
653double Component::getFittingParameter(const std::string &pname, double xvalue) const {
654 if (m_map) {
655 Parameter_sptr parameter = m_map->getRecursive(this, pname, "fitting");
656 if (!parameter) {
657 throw std::runtime_error("Fitting parameter=" + pname +
658 " could not be extracted from component=" + this->getName());
659 }
660
661 try {
662 const auto &fitParam = parameter->value<FitParameter>();
663 return fitParam.getValue(xvalue);
664 } catch (...) {
665 throw std::runtime_error("Unable to get lookup table for parameter=" + pname +
666 " from component=" + this->getName());
667 }
668 } else {
669 throw std::runtime_error("Parameter map is not available in component=" + this->getName());
670 }
671}
672
673} // 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:44
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:318
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::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:327
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:321
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:323
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:291
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:311
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:325
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:316
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:50
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.
Parameter map iterator typedef.
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:38
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:35
double distance(const V3D &v) const noexcept
Calculates the distance between two vectors.
Definition V3D.h:294
std::string toString() const
Definition V3D.cpp:332
void write(std::ostream &) const
Write out the point values.
Definition V3D.cpp:322
This functor is used as the deleter object of a shared_ptr to effectively erase ownership Raw pointer...
Definition IComponent.h:171
std::shared_ptr< Parameter > Parameter_sptr
Typedef for the shared pointer.
Definition Parameter.h:203
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.