Mantid
Loading...
Searching...
No Matches
MDHistoDimension.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 +
10#include <memory>
11#include <sstream>
12#include <stdexcept>
13
14#include <boost/algorithm/string.hpp>
15#include <boost/format.hpp>
16
17#include <Poco/DOM/Attr.h>
18#include <Poco/DOM/AutoPtr.h>
19#include <Poco/DOM/DOMParser.h>
20#include <Poco/DOM/DOMWriter.h>
21#include <Poco/DOM/Document.h>
22#include <Poco/DOM/Element.h>
23#include <Poco/DOM/Text.h>
24
25namespace Mantid::Geometry {
26
28 // Build a replacement unit that preserves the frame's Q-ness. The workspace's
29 // special coordinate system is derived from the unit's isQUnit() (see
30 // MDFramesToSpecialCoordinateSystem), so a Q frame must keep a Q unit. Discriminate
31 // on the frame itself, not the current unit's isQUnit(): a general frame may already
32 // carry a Q-like label (e.g. "A^-1") yet must still accept arbitrary relabelling.
33 std::unique_ptr<Kernel::MDUnit> newUnit;
34 if (m_frame->isQ()) {
35 newUnit = std::make_unique<Kernel::ReciprocalLatticeUnit>(units);
36 } else {
37 newUnit = std::make_unique<Kernel::LabelUnit>(units);
38 }
39
40 // Snapshot the current unit so we can roll back if the new label is not honoured.
41 std::unique_ptr<Kernel::MDUnit> previousUnit(m_frame->getMDUnit().clone());
42
43 if (!m_frame->setMDUnit(*newUnit)) {
44 throw std::invalid_argument("Cannot set units on dimension '" + m_name + "': its '" + m_frame->name() +
45 "' frame has a fixed unit and does not support relabelling. Use the SetMDFrame "
46 "algorithm to change the frame instead.");
47 }
48
49 // Some frames (e.g. HKL) silently revert a label they do not accept; reject rather
50 // than leave the dimension showing an unexpected label.
51 if (m_frame->getUnitLabel().ascii() != units.ascii()) {
52 m_frame->setMDUnit(*previousUnit); // roll back so the dimension is unchanged
53 throw std::invalid_argument(
54 "Cannot set units to '" + units.ascii() + "' on dimension '" + m_name +
55 "': an HKL (reciprocal-lattice) dimension only accepts 'r.l.u.' or an inverse-Angstrom-style label of the "
56 "form 'in <value> A^-1' (e.g. 'in 2.5 A^-1'), used for non-orthogonal projections. Use the SetMDFrame "
57 "algorithm to assign an arbitrary unit label.");
58 }
59}
60
61std::string MDHistoDimension::toXMLString() const {
62 using namespace Poco::XML;
63
64 // Create the root element for this fragment.
65 AutoPtr<Document> pDoc = new Document;
66 AutoPtr<Element> pDimensionElement = pDoc->createElement("Dimension");
67 pDoc->appendChild(pDimensionElement);
68
69 // Set the id.
70 AutoPtr<Attr> idAttribute = pDoc->createAttribute("ID");
71 idAttribute->setNodeValue(this->getDimensionId());
72 pDimensionElement->setAttributeNode(idAttribute);
73
74 // Set the name.
75 AutoPtr<Element> nameElement = pDoc->createElement("Name");
76 AutoPtr<Text> nameText = pDoc->createTextNode(this->getName());
77 nameElement->appendChild(nameText);
78 pDimensionElement->appendChild(nameElement);
79
80 // Set the units.
81 AutoPtr<Element> unitsElement = pDoc->createElement("Units");
82 AutoPtr<Text> unitsText = pDoc->createTextNode(this->getUnits());
83 unitsElement->appendChild(unitsText);
84 pDimensionElement->appendChild(unitsElement);
85
86 // Set the frame.
87 AutoPtr<Element> frameElement = pDoc->createElement("Frame");
88 AutoPtr<Text> frameText = pDoc->createTextNode(this->getMDFrame().name());
89 frameElement->appendChild(frameText);
90 pDimensionElement->appendChild(frameElement);
91
92 // Set the upper bounds
93 AutoPtr<Element> upperBoundsElement = pDoc->createElement("UpperBounds");
94 AutoPtr<Text> upperBoundsText = pDoc->createTextNode(boost::str(boost::format("%.4f") % this->getMaximum()));
95 upperBoundsElement->appendChild(upperBoundsText);
96 pDimensionElement->appendChild(upperBoundsElement);
97
98 // Set the lower bounds
99 AutoPtr<Element> lowerBoundsElement = pDoc->createElement("LowerBounds");
100 AutoPtr<Text> lowerBoundsText = pDoc->createTextNode(boost::str(boost::format("%.4f") % this->getMinimum()));
101 lowerBoundsElement->appendChild(lowerBoundsText);
102 pDimensionElement->appendChild(lowerBoundsElement);
103
104 // Set the number of bins
105 AutoPtr<Element> numberOfBinsElement = pDoc->createElement("NumberOfBins");
106 AutoPtr<Text> numberOfBinsText = pDoc->createTextNode(boost::str(boost::format("%.4d") % this->getNBins()));
107 numberOfBinsElement->appendChild(numberOfBinsText);
108 pDimensionElement->appendChild(numberOfBinsElement);
109
110 // Provide upper and lower limits for integrated dimensions.
111 if (this->getIsIntegrated()) {
112 AutoPtr<Element> integratedElement = pDoc->createElement("Integrated");
113 // Set the upper limit
114 AutoPtr<Element> upperLimitElement = pDoc->createElement("UpperLimit");
115 AutoPtr<Text> upperLimitText =
116 pDoc->createTextNode(boost::str(boost::format("%.4f") % this->getMaximum())); // Dimension does not yet
117 // provide integration
118 // ranges.
119 upperLimitElement->appendChild(upperLimitText);
120 integratedElement->appendChild(upperLimitElement);
121
122 // Set the lower limit
123 AutoPtr<Element> lowerLimitElement = pDoc->createElement("LowerLimit");
124 AutoPtr<Text> lowerLimitText =
125 pDoc->createTextNode(boost::str(boost::format("%.4f") % this->getMinimum())); // Dimension does not yet
126 // provide integration
127 // ranges.
128 lowerLimitElement->appendChild(lowerLimitText);
129 integratedElement->appendChild(lowerLimitElement);
130
131 pDimensionElement->appendChild(integratedElement);
132 }
133
134 // Create a string representation of the DOM tree.
135 std::stringstream xmlstream;
136 DOMWriter writer;
137 writer.writeNode(xmlstream, pDoc);
138
139 return xmlstream.str();
140}
141} // namespace Mantid::Geometry
std::string name
Definition Run.cpp:60
virtual bool getIsIntegrated() const
coord_t getMaximum() const override
Returns the maximum extent of this dimension.
void setUnits(const Kernel::UnitLabel &units)
Set the units of the dimension by relabelling its frame's unit.
coord_t getMinimum() const override
Returns the minimum extent of this dimension.
Geometry::MDFrame_uptr m_frame
Multidimensional frame.
std::string toXMLString() const override
Dimensions must be xml serializable.
const MDFrame & getMDFrame() const override
Return the md frame.
const Kernel::UnitLabel getUnits() const override
Return the units of the dimension as a string.
std::string getName() const override
Return the name of the dimension as can be displayed along the axis.
const std::string & getDimensionId() const override
Short name which identify the dimension among other dimension.
size_t getNBins() const override
number of bins dimension have (an integrated has one).
A base-class for the a class that is able to return unit labels in different representations.
Definition UnitLabel.h:20
const AsciiString & ascii() const
Return an ascii label for unit.