26#include "MantidTypes/Core/DateAndTime.h"
27#include "MantidTypes/Core/DateAndTimeHelpers.h"
29#include <Poco/DOM/DOMParser.h>
30#include <Poco/DOM/DOMWriter.h>
31#include <Poco/DOM/Document.h>
32#include <Poco/DOM/Element.h>
33#include <Poco/DOM/NodeFilter.h>
34#include <Poco/DOM/NodeIterator.h>
35#include <Poco/DOM/NodeList.h>
37#include <Poco/SAX/AttributesImpl.h>
38#include <Poco/String.h>
39#include <Poco/XML/XMLWriter.h>
41#include <boost/regex.hpp>
43#include <unordered_set>
49using Poco::XML::Document;
50using Poco::XML::DOMParser;
51using Poco::XML::Element;
53using Poco::XML::NodeFilter;
54using Poco::XML::NodeIterator;
55using Poco::XML::NodeList;
67 m_hasParameterElement_beenSet(false), m_haveDefaultFacing(false), m_deltaOffsets(false), m_angleConvertConst(1.0),
68 m_indirectPositions(false), m_cachingOption(NoneApplied) {
79 const std::string &xmlText)
81 m_hasParameterElement_beenSet(false), m_haveDefaultFacing(false), m_deltaOffsets(false), m_angleConvertConst(1.0),
82 m_indirectPositions(false), m_cachingOption(NoneApplied) {
96 const std::string &instName,
const std::string &xmlText)
98 m_hasParameterElement_beenSet(false), m_haveDefaultFacing(false), m_deltaOffsets(false), m_angleConvertConst(1.0),
99 m_indirectPositions(false), m_cachingOption(NoneApplied) {
100 initialise(xmlFile->getFileFullPathStr(), instName, xmlText, expectedCacheFile->getFileFullPathStr());
115 const std::string &xmlText,
const std::string &vtpFilename) {
134 if (vtpFilename.empty()) {
137 m_cacheFile = std::make_shared<const IDFObject>(vtpFilename);
157 if (!(xml.empty())) {
176 throw std::invalid_argument(
"Instrument XML string is empty");
182 }
catch (Poco::Exception &exc) {
183 throw std::invalid_argument(exc.displayText() +
". Unable to parse XML");
185 throw std::invalid_argument(
"Unable to parse XML");
198 const std::string &typeName)
const {
202 .append(
"contains more than one type element named ")
205 std::string(
"XML instrument file contains more than one type element named ")
222 Poco::XML::Element *pRootElem = pDoc->documentElement();
224 if (!pRootElem->hasChildNodes()) {
225 g_log.
error(
"Instrument XML contains no root element.");
233 const std::string filename =
m_xmlFile->getFileFullPathStr();
235 std::vector<Element *> typeElems;
236 std::vector<Element *> compElems;
239 if (typeElems.empty()) {
240 g_log.
error(
"XML file: " + filename +
"contains no type elements.");
292 const std::vector<Element *> &typeElems,
294 const size_t numberOfTypes = typeElems.size();
295 for (
size_t iType = 0; iType < numberOfTypes; ++iType) {
296 Element *pTypeElem = typeElems[iType];
297 std::string typeName = pTypeElem->getAttribute(
"name");
301 Poco::AutoPtr<NodeList> pNL_type_combine_into_one_shape =
302 pTypeElem->getElementsByTagName(
"combine-components-into-one-shape");
303 if (pNL_type_combine_into_one_shape->length() > 0) {
323 const std::string &filename,
324 const std::vector<Element *> &compElems) {
325 if (progressReporter)
328 for (
auto pElem : compElems) {
329 if (progressReporter)
330 progressReporter->
report(
"Loading instrument Definition");
341 for (Node *pNode = pElem->firstChild(); pNode !=
nullptr; pNode = pNode->nextSibling()) {
342 auto pChildElem =
dynamic_cast<Element *
>(pNode);
345 if (pChildElem->tagName() ==
"location") {
348 if (
isAssembly(pElem->getAttribute(
"type"))) {
353 }
else if (pChildElem->tagName() ==
"locations") {
373 const std::string &filename)
const {
374 Poco::AutoPtr<NodeList> pNL_location = pElem->getElementsByTagName(
"location");
375 Poco::AutoPtr<NodeList> pNL_locations = pElem->getElementsByTagName(
"locations");
377 if (pNL_location->length() == 0 && pNL_locations->length() == 0) {
378 g_log.
error(std::string(
"A component element must contain at least one "
379 "<location> or <locations> element") +
380 " even if it is just an empty location element of the form "
383 "<location> or <locations> element") +
384 " even if it is just an empty location element of the form "
399 const std::string &filename)
const {
400 if (idList.
counted !=
static_cast<int>(idList.
vec.size())) {
401 std::stringstream ss1, ss2;
402 ss1 << idList.
vec.size();
404 if (!pElem->hasAttribute(
"idlist")) {
405 g_log.
error(
"No detector ID list found for detectors of type " + pElem->getAttribute(
"type"));
406 }
else if (idList.
vec.empty()) {
407 g_log.
error(
"No detector IDs found for detectors in list " + pElem->getAttribute(
"idlist") +
408 "for detectors of type" + pElem->getAttribute(
"type"));
410 g_log.
error(
"The number of detector IDs listed in idlist named " + pElem->getAttribute(
"idlist") +
411 " is larger than the number of detectors listed in type = " + pElem->getAttribute(
"type"));
414 "Number of IDs listed in idlist (=" + ss1.str() +
") is larger than the number of detectors listed in type = " +
415 pElem->getAttribute(
"type") +
" (=" + ss2.str() +
").",
426 Poco::AutoPtr<NodeList> pNL_parameter = pRootElem->getElementsByTagName(
"parameter");
427 unsigned long numParameter = pNL_parameter->length();
433 NodeIterator it(pRootElem, NodeFilter::SHOW_ELEMENT);
434 Node *pNode = it.nextNode();
436 if (pNode->nodeName() ==
"parameter") {
437 auto pParameterElem =
dynamic_cast<Element *
>(pNode);
440 pNode = it.nextNode();
456 const std::string &filename,
457 const std::vector<Element *> &typeElems,
458 const size_t numberOfTypes) {
459 for (
size_t iType = 0; iType < numberOfTypes; ++iType) {
460 Element *pTypeElem = typeElems[iType];
461 std::string typeName = pTypeElem->getAttribute(
"name");
465 Poco::AutoPtr<NodeList> pNL_type_combine_into_one_shape =
466 pTypeElem->getElementsByTagName(
"combine-components-into-one-shape");
467 if (pNL_type_combine_into_one_shape->length() == 0)
480 if (
auto csgObj = std::dynamic_pointer_cast<CSGObject>(
mapTypeNameToShape[typeName])) {
481 csgObj->setName(
static_cast<int>(iType));
496 Element *pTypeElem,
const std::string &typeName) {
497 Poco::AutoPtr<NodeList> pNL_local = pTypeElem->getElementsByTagName(
"component");
498 if (pNL_local->length() == 0) {
505 if (
auto csgObj = std::dynamic_pointer_cast<CSGObject>(
mapTypeNameToShape[typeName])) {
506 csgObj->setName(
static_cast<int>(iType));
510 if (pTypeElem->hasAttribute(
"outline")) {
511 pTypeElem->setAttribute(
"object_created",
"no");
524 std::vector<Element *> &typeElems,
525 std::vector<Element *> &compElems)
const {
526 for (
auto pNode = pRootElem->firstChild(); pNode !=
nullptr; pNode = pNode->nextSibling()) {
527 auto pElem =
dynamic_cast<Element *
>(pNode);
529 if (pElem->tagName() ==
"type")
530 typeElems.emplace_back(pElem);
531 else if (pElem->tagName() ==
"component")
532 compElems.emplace_back(pElem);
553 const Poco::XML::Element *pCompElem,
IdList &idList) {
558 const Element *pRootLocationsElem = pLocationsDoc->documentElement();
559 const bool assembly =
isAssembly(pCompElem->getAttribute(
"type"));
561 auto *pElem =
dynamic_cast<Poco::XML::Element *
>(pRootLocationsElem->firstChild());
564 if (pElem->tagName() !=
"location") {
565 pElem =
dynamic_cast<Poco::XML::Element *
>(pElem->nextSibling());
575 pElem =
dynamic_cast<Poco::XML::Element *
>(pElem->nextSibling());
590 Poco::XML::DOMWriter writer;
591 writer.setNewLine(
"\n");
592 writer.setOptions(Poco::XML::XMLWriter::PRETTY_PRINT);
595 std::ofstream outFile(outFilename.c_str());
596 writer.writeNode(outFile, pDoc);
601 if (pElem->hasAttribute(name)) {
602 const std::string &
value = pElem->getAttribute(name);
603 if (!
value.empty()) {
605 return std::stod(
value);
607 std::stringstream msg;
608 msg <<
"failed to convert \"" <<
value <<
"\" to double for xml attribute \"" << name
609 <<
"\" - using 0. instead";
632 const double angleConvertConst,
const bool deltaOffsets) {
636 if (pElem->hasAttribute(
"rot")) {
637 double rotAngle = angleConvertConst *
attrToDouble(pElem,
"rot");
643 if (pElem->hasAttribute(
"axis-x"))
644 axis_x = std::stod(pElem->getAttribute(
"axis-x"));
645 if (pElem->hasAttribute(
"axis-y"))
646 axis_y = std::stod(pElem->getAttribute(
"axis-y"));
647 if (pElem->hasAttribute(
"axis-z"))
648 axis_z = std::stod(pElem->getAttribute(
"axis-z"));
656 Element *pRecursive =
nullptr;
657 Element *tElem = pElem->getChildElement(
"trans");
658 Element *rElem = pElem->getChildElement(
"rot");
659 bool stillTransElement =
true;
660 bool firstRound =
true;
661 while (stillTransElement) {
666 }
else if (pRecursive !=
nullptr) {
667 tElem = pRecursive->getChildElement(
"trans");
668 rElem = pRecursive->getChildElement(
"rot");
671 if (tElem && rElem) {
676 if (!tElem && !rElem) {
677 stillTransElement =
false;
690 compToGetRot.
setPos(posTrans);
700 double rotAngle = angleConvertConst *
attrToDouble(rElem,
"val");
706 if (rElem->hasAttribute(
"axis-x"))
707 axis_x = std::stod(rElem->getAttribute(
"axis-x"));
708 if (rElem->hasAttribute(
"axis-y"))
709 axis_y = std::stod(rElem->getAttribute(
"axis-y"));
710 if (rElem->hasAttribute(
"axis-z"))
711 axis_z = std::stod(rElem->getAttribute(
"axis-z"));
737 const Poco::XML::Element *pElem,
738 const double angleConvertConst,
739 const bool deltaOffsets) {
743 if (pElem->hasAttribute(
"r") || pElem->hasAttribute(
"t") || pElem->hasAttribute(
"p") || pElem->hasAttribute(
"R") ||
744 pElem->hasAttribute(
"theta") || pElem->hasAttribute(
"phi")) {
747 double theta = angleConvertConst *
attrToDouble(pElem,
"t");
748 double phi = angleConvertConst *
attrToDouble(pElem,
"p");
750 if (pElem->hasAttribute(
"R"))
752 if (pElem->hasAttribute(
"theta"))
753 theta = angleConvertConst *
attrToDouble(pElem,
"theta");
754 if (pElem->hasAttribute(
"phi"))
768 std::map<const Geometry::IComponent *, SphVec>::iterator it;
778 theta += parent.theta;
781 parentPos.
spherical(parent.r, parent.theta, parent.phi);
797 retVal = absPos - parentPos;
825 if (((pLocElem->tagName()) !=
"location") && ((pLocElem->tagName()) !=
"locations")) {
826 const std::string &tagname = pLocElem->tagName();
827 g_log.
error(
"Argument to function getParentComponent must be a pointer to "
828 "an XML element with tag name location or locations.");
829 throw std::logic_error(std::string(
"Argument to function getParentComponent must be a pointer "
830 "to an XML element") +
831 "with tag name location or locations." +
" The tag name is " + tagname);
837 Node *pCompNode = pLocElem->parentNode();
840 if (pCompNode->nodeType() == 1) {
841 pCompElem =
static_cast<Element *
>(pCompNode);
842 if ((pCompElem->tagName()) !=
"component") {
843 g_log.
error(
"Argument to function getParentComponent must be a XML "
844 "element sitting inside a component element.");
845 throw std::logic_error(
"Argument to function getParentComponent must be "
846 "a XML element sitting inside a component "
850 g_log.
error(
"Argument to function getParentComponent must be a XML element "
851 "whos parent is an element.");
852 throw std::logic_error(
"Argument to function getParentComponent must be a "
853 "XML element whos parent is an element.");
872 const Poco::XML::Element *pCompElem) {
875 if (pElem->hasAttribute(
"name"))
876 retVal = pElem->getAttribute(
"name");
877 else if (pCompElem->hasAttribute(
"name")) {
878 retVal = pCompElem->getAttribute(
"name");
880 retVal = pCompElem->getAttribute(
"type");
891 const std::string filename =
m_xmlFile->getFileFullPathStr();
893 if (!pRootElem->hasAttribute(
"valid-from")) {
897 DateAndTime
d(pRootElem->getAttribute(
"valid-from"));
905 if (!pRootElem->hasAttribute(
"valid-to")) {
906 DateAndTime
d = DateAndTime::getCurrentTime();
913 DateAndTime
d(pRootElem->getAttribute(
"valid-to"));
926 }
else if (input ==
"y") {
928 }
else if (input ==
"z") {
931 std::stringstream msg;
932 msg <<
"Cannot create \"" << label <<
"\" with axis direction other than \"x\", \"y\", or \"z\", found \"" << input
953 Element *offsetElement = defaults->getChildElement(
"offsets");
955 offsets = offsetElement->getAttribute(
"spherical");
956 if (offsets ==
"delta")
960 Element *defaultFacingElement = defaults->getChildElement(
"components-are-facing");
961 if (defaultFacingElement) {
968 Element *defaultView = defaults->getChildElement(
"default-view");
970 m_instrument->setDefaultViewAxis(defaultView->getAttribute(
"axis-view"));
971 if (defaultView->hasAttribute(
"view")) {
972 m_instrument->setDefaultView(defaultView->getAttribute(
"view"));
977 Element *angleUnit = defaults->getChildElement(
"angle");
979 if (angleUnit->getAttribute(
"unit") ==
"radian") {
981 std::map<std::string, std::string> &units =
m_instrument->getLogfileUnit();
982 units[
"angle"] =
"radian";
990 if (defaults->getChildElement(
"indirect-neutronic-positions"))
997 Element *referenceFrameElement = defaults->getChildElement(
"reference-frame");
999 if (referenceFrameElement) {
1000 using Poco::XML::XMLString;
1002 Element *upElement = referenceFrameElement->getChildElement(
"pointing-up");
1003 Element *alongElement = referenceFrameElement->getChildElement(
"along-beam");
1004 Element *handednessElement = referenceFrameElement->getChildElement(
"handedness");
1005 Element *originElement = referenceFrameElement->getChildElement(
"origin");
1006 Element *thetaSignElement = referenceFrameElement->getChildElement(
"theta-sign");
1009 XMLString s_alongBeam(
"z");
1010 XMLString s_pointingUp(
"y");
1011 XMLString s_handedness(
"right");
1016 s_alongBeam = alongElement->getAttribute(
"axis");
1019 s_pointingUp = upElement->getAttribute(
"axis");
1021 if (handednessElement) {
1022 s_handedness = handednessElement->getAttribute(
"val");
1024 if (originElement) {
1025 s_origin = originElement->getAttribute(
"val");
1029 XMLString s_thetaSign(s_pointingUp);
1030 if (thetaSignElement) {
1031 s_thetaSign = thetaSignElement->getAttribute(
"axis");
1042 std::make_shared<ReferenceFrame>(pointingUp, alongBeam, thetaSign, handedness, s_origin));
1049 Poco::AutoPtr<NodeList> pNLexclude = location->getElementsByTagName(
"exclude");
1050 unsigned long numberExcludeEle = pNLexclude->length();
1051 std::vector<std::string> newExcludeList;
1052 for (
unsigned long i = 0; i < numberExcludeEle; i++) {
1053 auto *pExElem =
static_cast<Element *
>(pNLexclude->item(i));
1054 if (pExElem->hasAttribute(
"sub-part"))
1055 newExcludeList.emplace_back(pExElem->getAttribute(
"sub-part"));
1058 return newExcludeList;
1077 const Poco::XML::Element *pCompElem,
IdList &idList) {
1078 const std::string filename =
m_xmlFile->getFileFullPathStr();
1088 if (pCompElem->hasAttribute(
"idlist")) {
1089 std::string idlist = pCompElem->getAttribute(
"idlist");
1091 if (idlist != idList.
idname) {
1092 Element *pFound = pCompElem->ownerDocument()->getElementById(idlist,
"idname");
1094 if (pFound ==
nullptr) {
1096 "No <idlist> with name idname=\"" + idlist +
"\" present in instrument definition file.", filename);
1110 Element *pType =
getTypeElement[pCompElem->getAttribute(
"type")];
1111 std::string category;
1112 if (pType->hasAttribute(
"is"))
1113 category = pType->getAttribute(
"is");
1114 if (category ==
"SamplePos" || category ==
"samplePos") {
1116 }
else if (pType->hasAttribute(
"outline") && pType->getAttribute(
"outline") !=
"no") {
1135 if (category ==
"SamplePos" || category ==
"samplePos") {
1138 if (category ==
"Source" || category ==
"source") {
1144 Element *neutronic = pLocElem->getChildElement(
"neutronic");
1152 NodeIterator it(pType, NodeFilter::SHOW_ELEMENT);
1154 Node *pNode = it.nextNode();
1156 if (pNode->nodeName() ==
"location") {
1159 const Element *pElem =
static_cast<Element *
>(pNode);
1166 auto inExcluded = find(excludeList.cbegin(), excludeList.cend(),
1168 if (inExcluded == excludeList.end()) {
1179 if (pNode->nodeName() ==
"locations") {
1180 const Element *pLocationsElems =
static_cast<Element *
>(pNode);
1186 pNode = it.nextNode();
1190 if (pType->hasAttribute(
"outline") && pType->getAttribute(
"outline") !=
"no") {
1193 throw std::logic_error(
"Failed to cast ICompAssembly object to ObjCompAssembly");
1195 if (pType->getAttribute(
"object_created") ==
"no") {
1196 pType->setAttribute(
"object_created",
"yes");
1197 std::shared_ptr<Geometry::IObject>
obj = objAss->createOutline();
1201 pType->setAttribute(
"outline",
"no");
1202 g_log.
warning() <<
"Failed to create outline object for assembly " << pType->getAttribute(
"name") <<
'\n';
1211 const Poco::XML::Element *pLocElem,
1212 const Poco::XML::Element *pCompElem,
1213 const std::string &filename,
IdList &idList,
1214 const std::string &category) {
1222 if (idList.
counted >=
static_cast<int>(idList.
vec.size())) {
1223 std::stringstream ss1, ss2;
1224 ss1 << idList.
vec.size();
1226 if (idList.
idname.empty()) {
1227 g_log.
error(
"No list of detector IDs found for location element " + name);
1230 }
else if (idList.
vec.empty()) {
1231 g_log.
error(
"No detector IDs found for detectors in list " + idList.
idname);
1233 g_log.
error(
"The number of detector IDs listed in idlist named " + idList.
idname +
1234 " is less then the number of detectors");
1237 "Number of IDs listed in idlist (=" + ss1.str() +
") is less than the number of detectors.", filename);
1240 std::string typeName = pCompElem->getAttribute(
"type");
1246 parent->
add(detector);
1261 m_neutronicPos[detector] = pLocElem->getChildElement(
"neutronic");
1265 if (pCompElem->hasAttribute(
"mark-as") || pLocElem->hasAttribute(
"mark-as")) {
1266 g_log.
warning() <<
"Attribute 'mark-as' is a depricated attribute in "
1267 "Instrument Definition File."
1268 <<
" Please see the deprecated section of "
1269 "www.mantidproject.org/IDF for how to remove this "
1270 "warning message\n";
1274 if (category ==
"Monitor" || category ==
"monitor")
1278 if ((pCompElem->hasAttribute(
"mark-as") && pCompElem->getAttribute(
"mark-as") ==
"monitor") ||
1279 (pLocElem->hasAttribute(
"mark-as") && pLocElem->getAttribute(
"mark-as") ==
"monitor")) {
1286 std::stringstream convert;
1287 convert << detector->
getID();
1289 "Detector with ID = " + convert.str() +
" present more then once in XML instrument file", filename);
1299 const Poco::XML::Element *pCompElem,
const std::string &filename,
1300 const Poco::XML::Element *pType) {
1324 std::string idfillorder;
1325 int idstepbyrow = 0;
1331 const std::string shapeType = pType->getAttribute(
"type");
1334 if (pType->hasAttribute(
"xpixels"))
1335 xpixels = std::stoi(pType->getAttribute(
"xpixels"));
1339 if (pType->hasAttribute(
"ypixels"))
1340 ypixels = std::stoi(pType->getAttribute(
"ypixels"));
1344 if (pType->hasAttribute(
"zpixels"))
1345 zpixels = std::stoi(pType->getAttribute(
"zpixels"));
1351 if (pCompElem->hasAttribute(
"idstart"))
1352 idstart = std::stoi(pCompElem->getAttribute(
"idstart"));
1353 if (pCompElem->hasAttribute(
"idfillorder"))
1354 idfillorder = pCompElem->getAttribute(
"idfillorder");
1356 if (!idfillorder.empty() && idfillorder[0] ==
'x')
1357 idstepbyrow = xpixels;
1358 else if (!idfillorder.empty() && idfillorder[0] ==
'y')
1359 idstepbyrow = ypixels;
1361 idstepbyrow = zpixels;
1363 if (pCompElem->hasAttribute(
"idstepbyrow")) {
1364 idstepbyrow = std::stoi(pCompElem->getAttribute(
"idstepbyrow"));
1367 if (pCompElem->hasAttribute(
"idstep"))
1368 idstep = std::stoi(pCompElem->getAttribute(
"idstep"));
1371 bank->initialize(shape, xpixels, xstart, xstep, ypixels, ystart, ystep, zpixels, zstart, zstep, idstart, idfillorder,
1372 idstepbyrow, idstep);
1377 for (
int z = 0;
z < bank->nelements(); ++
z) {
1378 auto zLayer = std::dynamic_pointer_cast<Geometry::ICompAssembly>((*bank)[
z]);
1379 for (
int x = 0;
x < zLayer->nelements(); ++
x) {
1380 auto xColumn = std::dynamic_pointer_cast<Geometry::ICompAssembly>((*zLayer)[
x]);
1381 for (
int y = 0;
y < xColumn->nelements(); ++
y) {
1382 std::shared_ptr<Geometry::Detector> detector = std::dynamic_pointer_cast<Geometry::Detector>((*xColumn)[
y]);
1385 auto *comp =
static_cast<IComponent *
>(detector.get());
1389 m_instrument->markAsDetectorIncomplete(detector.get());
1396 " in XML instrument file" + filename);
1401 const Poco::XML::Element *pLocElem,
1402 const Poco::XML::Element *pCompElem,
1403 const std::string &filename,
1404 const Poco::XML::Element *pType) {
1426 bool idfillbyfirst_y =
true;
1427 int idstepbyrow = 0;
1433 const std::string shapeType = pType->getAttribute(
"type");
1437 if (pType->hasAttribute(
"xpixels"))
1438 xpixels = std::stoi(pType->getAttribute(
"xpixels"));
1442 if (pType->hasAttribute(
"ypixels"))
1443 ypixels = std::stoi(pType->getAttribute(
"ypixels"));
1449 if (pCompElem->hasAttribute(
"idstart"))
1450 idstart = std::stoi(pCompElem->getAttribute(
"idstart"));
1451 if (pCompElem->hasAttribute(
"idfillbyfirst"))
1452 idfillbyfirst_y = (pCompElem->getAttribute(
"idfillbyfirst") ==
"y");
1454 if (idfillbyfirst_y)
1455 idstepbyrow = ypixels;
1457 idstepbyrow = xpixels;
1458 if (pCompElem->hasAttribute(
"idstepbyrow")) {
1459 idstepbyrow = std::stoi(pCompElem->getAttribute(
"idstepbyrow"));
1462 if (pCompElem->hasAttribute(
"idstep"))
1463 idstep = std::stoi(pCompElem->getAttribute(
"idstep"));
1466 bank->initialize(shape, xpixels, xstart, xstep, ypixels, ystart, ystep, idstart, idfillbyfirst_y, idstepbyrow,
1472 for (
int x = 0;
x < bank->nelements();
x++) {
1473 std::shared_ptr<Geometry::ICompAssembly> xColumn = std::dynamic_pointer_cast<Geometry::ICompAssembly>((*bank)[
x]);
1474 for (
int y = 0;
y < xColumn->nelements();
y++) {
1475 std::shared_ptr<Geometry::Detector> detector = std::dynamic_pointer_cast<Geometry::Detector>((*xColumn)[
y]);
1478 auto *comp =
static_cast<IComponent *
>(detector.get());
1482 m_instrument->markAsDetectorIncomplete(detector.get());
1488 name +
" in XML instrument file" + filename);
1493 const Poco::XML::Element *pLocElem,
1494 const Poco::XML::Element *pCompElem,
1495 const std::string &filename,
1496 const Poco::XML::Element *pType) {
1517 bool idfillbyfirst_y =
true;
1518 int idstepbyrow = 0;
1520 std::vector<double> xValues;
1521 std::vector<double> yValues;
1526 const std::string shapeType = pType->getAttribute(
"type");
1529 std::string typeName = pType->getAttribute(
"name");
1531 if (pType->hasAttribute(
"xpixels"))
1532 xpixels = std::stoi(pType->getAttribute(
"xpixels"));
1533 if (pType->hasAttribute(
"ypixels"))
1534 ypixels = std::stoi(pType->getAttribute(
"ypixels"));
1538 if (pCompElem->hasAttribute(
"idstart"))
1539 idstart = std::stoi(pCompElem->getAttribute(
"idstart"));
1540 if (pCompElem->hasAttribute(
"idfillbyfirst"))
1541 idfillbyfirst_y = (pCompElem->getAttribute(
"idfillbyfirst") ==
"y");
1543 if (idfillbyfirst_y)
1544 idstepbyrow = ypixels;
1546 idstepbyrow = xpixels;
1547 if (pCompElem->hasAttribute(
"idstepbyrow")) {
1548 idstepbyrow = std::stoi(pCompElem->getAttribute(
"idstepbyrow"));
1551 if (pCompElem->hasAttribute(
"idstep"))
1552 idstep = std::stoi(pCompElem->getAttribute(
"idstep"));
1555 Element *pElem =
nullptr;
1556 NodeIterator tags(pCompElem->ownerDocument(), NodeFilter::SHOW_ELEMENT);
1557 Node *pNode = tags.nextNode();
1560 auto *check =
static_cast<Element *
>(pNode);
1561 if (pNode->nodeName() ==
"type" && check->hasAttribute(
"is")) {
1562 std::string is = check->getAttribute(
"is");
1569 pNode = tags.nextNode();
1572 if (pElem ==
nullptr)
1576 Poco::AutoPtr<NodeList> pNL = pElem->getElementsByTagName(
"vertex");
1577 if (pNL->length() == 0)
1580 NodeIterator it(pElem, NodeFilter::SHOW_ELEMENT);
1582 pNode = it.nextNode();
1585 if (pNode->nodeName() ==
"vertex") {
1586 auto *pVertElem =
static_cast<Element *
>(pNode);
1588 if (pVertElem->hasAttribute(
"x"))
1590 if (pVertElem->hasAttribute(
"y"))
1594 pNode = it.nextNode();
1597 V3D zVector(0, 0, 1);
1598 bool isZBeam =
m_instrument->getReferenceFrame()->isVectorPointingAlongBeam(zVector);
1600 bank->initialize(xpixels, ypixels, std::move(xValues), std::move(yValues), isZBeam, idstart, idfillbyfirst_y,
1601 idstepbyrow, idstep);
1606 for (
int x = 0;
x < bank->nelements();
x++) {
1607 std::shared_ptr<Geometry::ICompAssembly> xColumn = std::dynamic_pointer_cast<Geometry::ICompAssembly>((*bank)[
x]);
1608 for (
int y = 0;
y < xColumn->nelements();
y++) {
1609 std::shared_ptr<Geometry::Detector> detector = std::dynamic_pointer_cast<Geometry::Detector>((*xColumn)[
y]);
1612 auto *comp =
static_cast<IComponent *
>(detector.get());
1616 m_instrument->markAsDetectorIncomplete(detector.get());
1622 name +
" in XML instrument file" + filename);
1646 const Poco::XML::Element *pCompElem,
IdList &idList) {
1647 const std::string filename =
m_xmlFile->getFileFullPathStr();
1654 if (pCompElem->hasAttribute(
"idlist")) {
1655 std::string idlist = pCompElem->getAttribute(
"idlist");
1657 if (idlist != idList.
idname) {
1658 Element *pFound = pCompElem->ownerDocument()->getElementById(idlist,
"idname");
1660 if (pFound ==
nullptr) {
1662 "No <idlist> with name idname=\"" + idlist +
"\" present in instrument definition file.", filename);
1675 std::string typeName = pCompElem->getAttribute(
"type");
1678 std::string category;
1679 if (pType->hasAttribute(
"is"))
1680 category = pType->getAttribute(
"is");
1682 static const boost::regex exp(
"Detector|detector|Monitor|monitor");
1691 }
else if (boost::regex_match(category, exp)) {
1697 if (category ==
"SamplePos" || category ==
"samplePos") {
1710 if (category ==
"Source" || category ==
"source") {
1739 const std::string filename =
m_xmlFile->getFileFullPathStr();
1741 if ((pE->tagName()) !=
"idlist") {
1742 g_log.
error(
"Argument to function createIdList must be a pointer to an XML "
1743 "element with tag name idlist.");
1744 throw std::logic_error(
"Argument to function createIdList must be a "
1745 "pointer to an XML element with tag name idlist.");
1750 idList.
idname = pE->getAttribute(
"idname");
1756 if (pE->hasAttribute(
"start")) {
1757 int startID = std::stoi(pE->getAttribute(
"start"));
1760 if (pE->hasAttribute(
"end"))
1761 endID = std::stoi(pE->getAttribute(
"end"));
1766 if (pE->hasAttribute(
"step"))
1767 increment = std::stoi(pE->getAttribute(
"step"));
1769 if (0 == increment) {
1770 std::stringstream ss;
1771 ss <<
"The step element cannot be zero, got start: " << startID <<
", end: " << endID <<
", step: " << increment;
1776 int steps = (endID - startID) / increment;
1778 std::stringstream ss;
1779 ss <<
"The start, end, and step elements do not allow a single id in "
1782 ss <<
"start: " << startID <<
", end: " << endID <<
", step: " << increment;
1787 idList.
vec.reserve(steps);
1788 for (
int i = startID; i != endID + increment; i += increment) {
1789 idList.
vec.emplace_back(i);
1794 Poco::AutoPtr<NodeList> pNL = pE->getElementsByTagName(
"id");
1796 if (pNL->length() == 0) {
1803 NodeIterator it(pE, NodeFilter::SHOW_ELEMENT);
1805 Node *pNode = it.nextNode();
1807 if (pNode->nodeName() ==
"id") {
1808 auto *pIDElem =
static_cast<Element *
>(pNode);
1810 if (pIDElem->hasAttribute(
"val")) {
1811 int valID = std::stoi(pIDElem->getAttribute(
"val"));
1812 idList.
vec.emplace_back(valID);
1813 }
else if (pIDElem->hasAttribute(
"start")) {
1814 int startID = std::stoi(pIDElem->getAttribute(
"start"));
1817 if (pIDElem->hasAttribute(
"end"))
1818 endID = std::stoi(pIDElem->getAttribute(
"end"));
1823 if (pIDElem->hasAttribute(
"step"))
1824 increment = std::stoi(pIDElem->getAttribute(
"step"));
1827 if (0 == increment) {
1828 std::stringstream ss;
1829 ss <<
"The step element cannot be zero, found step: " << increment;
1833 int numSteps = (endID - startID) / increment;
1835 std::stringstream ss;
1836 ss <<
"The start, end, and step elements do not allow a single "
1838 "in the idlist entry - ";
1839 ss <<
"start: " << startID <<
", end: " << endID <<
", step: " << increment;
1844 idList.
vec.reserve(numSteps);
1845 for (
int i = startID; i != endID + increment; i += increment) {
1846 idList.
vec.emplace_back(i);
1850 "id subelement of idlist " + std::string(
"element wrongly specified in XML instrument file"), filename);
1854 pNode = it.nextNode();
1869 const std::string filename =
m_xmlFile->getFileFullPathStr();
1909 const auto facingDirLength = facingDirection.
norm();
1910 if (facingDirLength == 0.0)
1912 facingDirection /= facingDirLength;
1920 R.
rotate(facingDirection);
1923 const auto normalLength = normal.
norm();
1924 if (normalLength == 0.) {
1927 normal /= normalLength;
1929 double theta = (180.0 / M_PI) * facingDirection.
angle(
z);
1931 if (normal.
norm() > 0.0)
1950 if (pElem->hasAttribute(
"r") || pElem->hasAttribute(
"t") || pElem->hasAttribute(
"p") || pElem->hasAttribute(
"R") ||
1951 pElem->hasAttribute(
"theta") || pElem->hasAttribute(
"phi")) {
1956 if (pElem->hasAttribute(
"R"))
1958 if (pElem->hasAttribute(
"theta"))
1960 if (pElem->hasAttribute(
"phi"))
1992 if ((pElem->tagName()) !=
"location") {
1993 g_log.
error(
"Second argument to function setLocation must be a pointer to "
1994 "an XML element with tag name location.");
1995 throw std::logic_error(
"Second argument to function setLocation must be a "
1996 "pointer to an XML element with tag name location.");
1999 Element *facingElem = pElem->getChildElement(
"facing");
2004 if (facingElem->hasAttribute(
"rot")) {
2015 if (facingElem->hasAttribute(
"val"))
2046 const std::string filename =
m_xmlFile->getFileFullPathStr();
2055 Poco::AutoPtr<NodeList> pNL_comp = pElem->childNodes();
2056 unsigned long pNL_comp_length = pNL_comp->length();
2058 for (
unsigned long i = 0; i < pNL_comp_length; i++) {
2061 if (!((pNL_comp->item(i))->nodeType() == Node::ELEMENT_NODE && ((pNL_comp->item(i))->nodeName()) ==
"parameter"))
2064 auto *pParamElem =
static_cast<Element *
>(pNL_comp->item(i));
2066 if (!pParamElem->hasAttribute(
"name"))
2068 "XML element with name or type = " + comp->
getName() +
2069 " contain <parameter> element with no name attribute in XML "
2073 std::string paramName = pParamElem->getAttribute(
"name");
2075 if (paramName ==
"rot" || paramName ==
"pos") {
2077 <<
" contains <parameter> element with name=\"" << paramName <<
"\"."
2078 <<
" This is a reserved Mantid keyword. Please use other name, "
2079 <<
"and see www.mantidproject.org/IDF for list of reserved "
2081 <<
" This parameter is ignored";
2085 std::string visible =
"true";
2086 if (pParamElem->hasAttribute(
"visible")) {
2087 visible = pParamElem->getAttribute(
"visible");
2090 DateAndTime validityDate;
2092 if (requestedDate.empty()) {
2093 validityDate = DateAndTime::getCurrentTime();
2095 validityDate.setFromISO8601(requestedDate);
2098 std::string logfileID;
2101 DateAndTime validFrom;
2102 DateAndTime validTo;
2104 std::string type =
"double";
2105 std::string extractSingleValueAs =
"mean";
2108 Poco::AutoPtr<NodeList> pNLvalue = pParamElem->getElementsByTagName(
"value");
2109 size_t numberValueEle = pNLvalue->length();
2110 Element *pValueElem;
2112 Poco::AutoPtr<NodeList> pNLlogfile = pParamElem->getElementsByTagName(
"logfile");
2113 size_t numberLogfileEle = pNLlogfile->length();
2114 Element *pLogfileElem;
2116 Poco::AutoPtr<NodeList> pNLLookUp = pParamElem->getElementsByTagName(
"lookuptable");
2117 size_t numberLookUp = pNLLookUp->length();
2119 Poco::AutoPtr<NodeList> pNLFormula = pParamElem->getElementsByTagName(
"formula");
2120 size_t numberFormula = pNLFormula->length();
2122 if ((numberValueEle > 0 && numberLogfileEle + numberLookUp + numberFormula > 0) ||
2123 (numberValueEle == 0 && numberLogfileEle + numberLookUp + numberFormula > 1)) {
2125 <<
" contains <parameter> element where the value of the "
2126 <<
"parameter has been specified more than once. See "
2127 <<
"www.mantidproject.org/IDF for how the value of the "
2128 <<
"parameter is set in this case.";
2131 if (numberValueEle + numberLogfileEle + numberLookUp + numberFormula == 0) {
2133 <<
" contains <parameter> for which no value is specified."
2134 <<
" See www.mantidproject.org/IDF for how to set the value"
2135 <<
" of a parameter. This parameter is ignored.";
2139 DateAndTime currentValidFrom;
2140 DateAndTime currentValidTo;
2141 currentValidFrom.setToMinimum();
2142 currentValidTo.setToMaximum();
2146 if (numberValueEle >= 1) {
2147 bool hasValue =
false;
2149 for (
unsigned long j = 0; j < numberValueEle; ++j) {
2150 pValueElem =
static_cast<Element *
>(pNLvalue->item(j));
2152 if (!pValueElem->hasAttribute((
"val")))
2155 validFrom.setToMinimum();
2156 if (pValueElem->hasAttribute(
"valid-from"))
2157 validFrom.setFromISO8601(pValueElem->getAttribute(
"valid-from"));
2159 validTo.setToMaximum();
2160 if (pValueElem->hasAttribute(
"valid-to"))
2161 validTo.setFromISO8601(pValueElem->getAttribute(
"valid-to"));
2163 if (validFrom <= validityDate && validityDate <= validTo &&
2164 (validFrom > currentValidFrom || (validFrom == currentValidFrom && validTo <= currentValidTo))) {
2166 currentValidFrom = validFrom;
2167 currentValidTo = validTo;
2171 value = pValueElem->getAttribute(
"val");
2176 "XML element with name or type = " + comp->
getName() +
2177 " contains <parameter> element with invalid syntax for its "
2178 "subelement <value>. Correct syntax is <value val=\"\"/>",
2182 }
else if (numberLogfileEle >= 1) {
2184 pLogfileElem =
static_cast<Element *
>(pNLlogfile->item(0));
2185 if (!pLogfileElem->hasAttribute(
"id"))
2187 "XML element with name or type = " + comp->
getName() +
2188 " contains <parameter> element with invalid syntax for its "
2189 "subelement logfile>." +
2190 " Correct syntax is <logfile id=\"\"/>",
2192 logfileID = pLogfileElem->getAttribute(
"id");
2194 if (pLogfileElem->hasAttribute(
"eq"))
2195 eq = pLogfileElem->getAttribute(
"eq");
2196 if (pLogfileElem->hasAttribute(
"extract-single-value-as"))
2197 extractSingleValueAs = pLogfileElem->getAttribute(
"extract-single-value-as");
2200 if (pParamElem->hasAttribute(
"type"))
2201 type = pParamElem->getAttribute(
"type");
2206 Poco::AutoPtr<NodeList> pNLFixed = pParamElem->getElementsByTagName(
"fixed");
2207 size_t numberFixed = pNLFixed->length();
2208 if (numberFixed >= 1) {
2214 std::string fittingFunction;
2217 if (type ==
"fitting") {
2218 size_t found = paramName.find(
':');
2219 if (found != std::string::npos) {
2221 size_t index = paramName.find(
':', found + 1);
2222 if (
index != std::string::npos) {
2223 g_log.
error() <<
"Fitting <parameter> in instrument definition file defined "
2225 <<
" more than one column character :. One must used.\n";
2227 fittingFunction = paramName.substr(0, found);
2228 paramName = paramName.substr(found + 1, paramName.size());
2234 std::ostringstream str;
2235 str << paramName <<
"=" <<
value;
2241 std::vector<std::string> constraint(2,
"");
2243 Poco::AutoPtr<NodeList> pNLMin = pParamElem->getElementsByTagName(
"min");
2244 size_t numberMin = pNLMin->length();
2245 Poco::AutoPtr<NodeList> pNLMax = pParamElem->getElementsByTagName(
"max");
2246 size_t numberMax = pNLMax->length();
2248 if (numberMin >= 1) {
2249 auto *pMin =
static_cast<Element *
>(pNLMin->item(0));
2250 constraint[0] = pMin->getAttribute(
"val");
2252 if (numberMax >= 1) {
2253 auto *pMax =
static_cast<Element *
>(pNLMax->item(0));
2254 constraint[1] = pMax->getAttribute(
"val");
2259 std::string penaltyFactor;
2261 Poco::AutoPtr<NodeList> pNL_penaltyFactor = pParamElem->getElementsByTagName(
"penalty-factor");
2262 size_t numberPenaltyFactor = pNL_penaltyFactor->length();
2264 if (numberPenaltyFactor >= 1) {
2265 auto *pPenaltyFactor =
static_cast<Element *
>(pNL_penaltyFactor->item(0));
2266 penaltyFactor = pPenaltyFactor->getAttribute(
"val");
2273 std::shared_ptr<Interpolation> interpolation = std::make_shared<Interpolation>();
2275 if (numberLookUp >= 1) {
2276 auto *pLookUp =
static_cast<Element *
>(pNLLookUp->item(0));
2278 if (pLookUp->hasAttribute(
"interpolation"))
2279 interpolation->setMethod(pLookUp->getAttribute(
"interpolation"));
2280 if (pLookUp->hasAttribute(
"x-unit")) {
2281 std::vector<std::string>::iterator it;
2282 it = find(allowedUnits.begin(), allowedUnits.end(), pLookUp->getAttribute(
"x-unit"));
2283 if (it == allowedUnits.end()) {
2284 g_log.
warning() <<
"x-unit used with interpolation table must be "
2285 "one of the recognised units "
2286 <<
" see http://www.mantidproject.org/Unit_Factory";
2288 interpolation->setXUnit(pLookUp->getAttribute(
"x-unit"));
2290 if (pLookUp->hasAttribute(
"y-unit")) {
2291 std::vector<std::string>::iterator it;
2292 it = find(allowedUnits.begin(), allowedUnits.end(), pLookUp->getAttribute(
"y-unit"));
2293 if (it == allowedUnits.end()) {
2294 g_log.
warning() <<
"y-unit used with interpolation table must be "
2295 "one of the recognised units "
2296 <<
" see http://www.mantidproject.org/Unit_Factory";
2298 interpolation->setYUnit(pLookUp->getAttribute(
"y-unit"));
2301 Poco::AutoPtr<NodeList> pNLpoint = pLookUp->getElementsByTagName(
"point");
2302 unsigned long numberPoint = pNLpoint->length();
2304 for (
unsigned long j = 0; j < numberPoint; j++) {
2305 auto *pPoint =
static_cast<Element *
>(pNLpoint->item(j));
2308 interpolation->addPoint(
x,
y);
2314 std::string formula;
2315 std::string formulaUnit;
2316 std::string resultUnit;
2318 if (numberFormula >= 1) {
2319 auto *pFormula =
static_cast<Element *
>(pNLFormula->item(0));
2320 formula = pFormula->getAttribute(
"eq");
2321 if (pFormula->hasAttribute(
"unit")) {
2322 std::vector<std::string>::iterator it;
2323 it = find(allowedUnits.begin(), allowedUnits.end(), pFormula->getAttribute(
"unit"));
2324 if (it == allowedUnits.end()) {
2325 g_log.
warning() <<
"unit attribute used with formula must be one "
2326 "of the recognized units "
2327 <<
" see http://www.mantidproject.org/Unit_Factory";
2329 formulaUnit = pFormula->getAttribute(
"unit");
2331 if (pFormula->hasAttribute(
"result-unit"))
2332 resultUnit = pFormula->getAttribute(
"result-unit");
2335 std::string description;
2337 Poco::AutoPtr<NodeList> pNLDescription = pParamElem->getElementsByTagName(
"description");
2338 size_t numberDescription = pNLDescription->length();
2340 if (numberDescription >= 1) {
2342 auto *pDescription =
static_cast<Element *
>(pNLDescription->item(0));
2343 description = pDescription->getAttribute(
"is");
2346 auto cacheKey = std::make_pair(paramName, comp);
2347 auto cacheValue = std::make_shared<XMLInstrumentParameter>(
2348 logfileID,
value, interpolation, formula, formulaUnit, resultUnit, paramName, type, tie, constraint,
2349 penaltyFactor, fittingFunction, extractSingleValueAs, eq, comp,
m_angleConvertConst, description, visible);
2350 auto inserted = logfileCache.emplace(cacheKey, cacheValue);
2351 if (!inserted.second) {
2352 logfileCache[cacheKey] = cacheValue;
2373 const std::string &requestedDate) {
2376 std::map<std::string, std::string> &units = instrument->getLogfileUnit();
2377 std::map<std::string, std::string>::iterator unit_it;
2378 unit_it = units.find(
"angle");
2379 if (unit_it != units.end())
2380 if (unit_it->second ==
"radian")
2383 const std::string elemName =
"component-link";
2384 Poco::AutoPtr<NodeList> pNL_link = pRootElem->getElementsByTagName(elemName);
2385 unsigned long numberLinks = pNL_link->length();
2388 progress->
resetNumSteps(
static_cast<int64_t
>(numberLinks), 0.0, 0.95);
2390 Node *curNode = pRootElem->firstChild();
2392 if (curNode->nodeType() == Node::ELEMENT_NODE && curNode->nodeName() == elemName) {
2393 auto *curElem =
static_cast<Element *
>(curNode);
2398 progress->
report(
"Loading parameters");
2401 std::string
id = curElem->getAttribute(
"id");
2402 std::string name = curElem->getAttribute(
"name");
2403 std::vector<std::shared_ptr<const Geometry::IComponent>> sharedIComp;
2406 if (
id.length() > 0) {
2408 std::stringstream(
id) >> detid;
2409 std::shared_ptr<const Geometry::IComponent> detector = instrument->getDetector(
static_cast<detid_t>(detid));
2414 g_log.
error() <<
"Error whilst loading parameters. No detector "
2417 g_log.
error() <<
"Please check that your detectors' ids are correct.\n";
2421 sharedIComp.emplace_back(detector);
2426 if (name.length() > 0) {
2427 auto comp = std::dynamic_pointer_cast<const IComponent>(detector);
2429 bool consistent = (comp->getFullName() == name || comp->getName() == name);
2431 g_log.
warning() <<
"Error whilst loading parameters. Name '" << name <<
"' does not match id '" << detid
2433 g_log.
warning() <<
"Parameters have been applied to detector with id '" << detid
2434 <<
"'. Please check the name is correct.\n";
2441 if (name.find(
'/', 0) == std::string::npos) {
2444 sharedIComp = instrument->getAllComponentsWithName(name);
2446 std::shared_ptr<const Geometry::IComponent> shared = instrument->getComponentByName(name);
2447 sharedIComp.emplace_back(shared);
2451 for (
auto &ptr : sharedIComp) {
2452 std::shared_ptr<const Geometry::Component> sharedComp =
2453 std::dynamic_pointer_cast<const Geometry::Component>(ptr);
2456 if (sharedComp->isParametrized()) {
2457 setLogfile(sharedComp->base(), curElem, instrument->getLogfileCache(), requestedDate);
2459 setLogfile(ptr.get(), curElem, instrument->getLogfileCache(), requestedDate);
2464 curNode = curNode->nextSibling();
2473 const std::string cacheFullPath = cacheToApply->getFileFullPathStr();
2476 std::map<std::string, std::shared_ptr<Geometry::IObject>>::iterator objItr;
2477 std::shared_ptr<Mantid::Geometry::vtkGeometryCacheReader> reader(
2481 if (
auto csgObj = std::dynamic_pointer_cast<CSGObject>(((*objItr).second))) {
2482 csgObj->setVtkGeometryCacheReader(reader);
2500 Poco::File dir = usedCache->getParentDirectory();
2501 if (dir.path().empty() || !dir.exists() || !dir.canWrite()) {
2502 usedCache = std::move(fallBackCache);
2504 g_log.
information() <<
"Geometrycache directory is read only, writing cache "
2505 "to system temp.\n";
2507 }
catch (Poco::FileNotFoundException &) {
2508 g_log.
error() <<
"Unable to find instrument definition while attempting to "
2510 throw std::runtime_error(
"Unable to find instrument definition while "
2511 "attempting to write cache.\n");
2513 const std::string cacheFullPath = usedCache->getFileFullPathStr();
2514 g_log.
notice() <<
"Creating cache in " << cacheFullPath <<
"\n";
2516 std::map<std::string, std::shared_ptr<Geometry::IObject>>::iterator objItr;
2517 std::shared_ptr<Mantid::Geometry::vtkGeometryCacheWriter> writer(
2521 if (
auto csgObj = std::dynamic_pointer_cast<CSGObject>(((*objItr).second))) {
2522 csgObj->setVtkGeometryCacheWriter(writer);
2526 return cachingOption;
2543 }
else if (fallBackCache->exists()) {
2549 return cachingOption;
2562 auto physical = std::make_unique<Instrument>(*
m_instrument);
2564 m_instrument->setPhysicalInstrument(std::move(physical));
2569 if (component.second) {
2575 if (component.second->hasAttribute(
"type") &&
dynamic_cast<ObjComponent *
>(component.first)) {
2576 const Poco::XML::XMLString shapeName = component.second->getAttribute(
"type");
2580 auto objCmpt =
dynamic_cast<ObjComponent *
>(component.first);
2582 objCmpt->
setShape(shapeIt->second);
2591 auto *det =
dynamic_cast<Detector *
>(component.first);
2616 std::map<std::string, Poco::XML::Element *> &getTypeElement) {
2619 if (pElem->tagName() !=
"type")
2621 "must be a pointer to an XML "
2622 "element with tag name type.");
2625 Poco::AutoPtr<NodeList> pNLccioh = pElem->getElementsByTagName(
"combine-components-into-one-shape");
2626 if (pNLccioh->length() == 0) {
2628 "element with tag name type,") +
2629 " which contain a <combine-components-into-one-shape> element.");
2633 Poco::AutoPtr<NodeList> pNLalg = pElem->getElementsByTagName(
"algebra");
2634 if (pNLalg->length() == 0) {
2636 " includes a <combine-components-into-one-shape> element. See "
2637 "www.mantidproject.org/IDF.");
2641 Poco::AutoPtr<NodeList> pNL = pElem->getElementsByTagName(
"location");
2642 unsigned long numLocation = pNL->length();
2643 if (numLocation == 0) {
2646 " includes a <combine-components-into-one-shape> element. See "
2647 "www.mantidproject.org/IDF.");
2651 Poco::AutoPtr<NodeList> pNL_TransRot = pElem->getElementsByTagName(
"translate-rotate-combined-shape-to");
2652 Element *pTransRot =
nullptr;
2653 if (pNL_TransRot->length() == 1) {
2654 pTransRot =
static_cast<Element *
>(pNL_TransRot->item(0));
2661 std::unordered_set<Element *> allComponentInType;
2662 std::vector<std::string> allLocationName;
2663 for (
unsigned long i = 0; i < numLocation; i++) {
2664 auto *pLoc =
static_cast<Element *
>(pNL->item(i));
2673 std::string locationElementName = pLoc->getAttribute(
"name");
2674 if (std::find(allLocationName.begin(), allLocationName.end(), locationElementName) == allLocationName.end())
2675 allLocationName.emplace_back(locationElementName);
2678 "a <combine-components-into-one-shape> element must be unique. " +
2679 "Here error is that " + locationElementName +
2680 " appears at least twice. See www.mantidproject.org/IDF.");
2683 auto baseCoor = std::make_unique<CompAssembly>(
"base");
2698 baseCoor = std::make_unique<CompAssembly>(
"base");
2708 Poco::AutoPtr<Document> pDoc;
2710 pDoc = pParser.parseString(cuboidStr);
2715 Element *pCuboid = pDoc->documentElement();
2716 Poco::AutoPtr<Node> fisse = (pElem->ownerDocument())->importNode(pCuboid,
true);
2717 pElem->appendChild(fisse);
2719 allComponentInType.insert(pCompElem);
2723 for (
const auto &component : allComponentInType)
2724 pElem->removeChild(component);
2736 const Poco::XML::Element *cuboidEle,
2737 const std::string &cuboidName) {
2738 Element *pElem_lfb =
getShapeElement(cuboidEle,
"left-front-bottom-point");
2739 Element *pElem_lft =
getShapeElement(cuboidEle,
"left-front-top-point");
2740 Element *pElem_lbb =
getShapeElement(cuboidEle,
"left-back-bottom-point");
2741 Element *pElem_rfb =
getShapeElement(cuboidEle,
"right-front-bottom-point");
2755 std::ostringstream obj_str;
2757 obj_str <<
"<cuboid id=\"" << cuboidName <<
"\">";
2758 obj_str <<
"<left-front-bottom-point ";
2759 obj_str <<
"x=\"" << p_lfb.
X();
2760 obj_str <<
"\" y=\"" << p_lfb.
Y();
2761 obj_str <<
"\" z=\"" << p_lfb.
Z();
2763 obj_str <<
"<left-front-top-point ";
2764 obj_str <<
"x=\"" << p_lft.
X();
2765 obj_str <<
"\" y=\"" << p_lft.
Y();
2766 obj_str <<
"\" z=\"" << p_lft.
Z();
2768 obj_str <<
"<left-back-bottom-point ";
2769 obj_str <<
"x=\"" << p_lbb.
X();
2770 obj_str <<
"\" y=\"" << p_lbb.
Y();
2771 obj_str <<
"\" z=\"" << p_lbb.
Z();
2773 obj_str <<
"<right-front-bottom-point ";
2774 obj_str <<
"x=\"" << p_rfb.
X();
2775 obj_str <<
"\" y=\"" << p_rfb.
Y();
2776 obj_str <<
"\" z=\"" << p_rfb.
Z();
2778 obj_str <<
"</cuboid>";
2780 return obj_str.str();
2790 comp->
add(dummyComp);
2808 const std::string &cuboidName) {
2810 Poco::AutoPtr<Document> pDoc;
2812 pDoc = pParser.parseString(cuboidXML);
2817 Element *pCuboid = pDoc->documentElement();
2831Poco::AutoPtr<Poco::XML::Document>
2834 size_t nElements(0);
2835 if (pElem->hasAttribute(
"n-elements")) {
2836 auto n = boost::lexical_cast<int>(
Strings::strip(pElem->getAttribute(
"n-elements")));
2841 nElements =
static_cast<size_t>(
n);
2845 "www.mantidproject.org/IDF.");
2849 if (pElem->hasAttribute(
"name")) {
2850 name = pElem->getAttribute(
"name");
2853 int nameCountStart(0);
2854 if (pElem->hasAttribute(
"name-count-start")) {
2855 nameCountStart = boost::lexical_cast<int>(
Strings::strip(pElem->getAttribute(
"name-count-start")));
2858 int nameCountIncrement(1);
2859 if (pElem->hasAttribute(
"name-count-increment")) {
2860 nameCountIncrement = boost::lexical_cast<int>(
Strings::strip(pElem->getAttribute(
"name-count-increment")));
2862 if (nameCountIncrement <= 0)
2867 std::set<std::string> rangeAttrs = {
"x",
"y",
"z",
"r",
"t",
"p",
"rot"};
2872 std::set<std::string> rotAttrs = {
"axis-x",
"axis-y",
"axis-z"};
2875 std::set<std::string> allAttrs;
2876 allAttrs.insert(rangeAttrs.begin(), rangeAttrs.end());
2877 allAttrs.insert(rotAttrs.begin(), rotAttrs.end());
2883 std::map<std::string, double> attrValues;
2886 for (
const auto &attr : allAttrs) {
2887 if (pElem->hasAttribute(attr)) {
2888 attrValues[attr] = boost::lexical_cast<double>(
Strings::strip(pElem->getAttribute(attr)));
2893 std::map<std::string, double> rangeAttrSteps;
2896 for (
const auto &rangeAttr : rangeAttrs) {
2897 std::string endAttr = rangeAttr +
"-end";
2898 if (pElem->hasAttribute(endAttr)) {
2899 if (attrValues.find(rangeAttr) == attrValues.end()) {
2903 double from = attrValues[rangeAttr];
2904 auto to = boost::lexical_cast<double>(
Strings::strip(pElem->getAttribute(endAttr)));
2906 rangeAttrSteps[rangeAttr] = (to - from) / (
static_cast<double>(nElements) - 1);
2910 Poco::AutoPtr<Document> pDoc =
new Document;
2911 Poco::AutoPtr<Element> pRoot = pDoc->createElement(
"expansion-of-locations-element");
2912 pDoc->appendChild(pRoot);
2914 for (
size_t i = 0; i < nElements; ++i) {
2915 Poco::AutoPtr<Element> pLoc = pDoc->createElement(
"location");
2917 if (!name.empty()) {
2919 pLoc->setAttribute(
"name", name +
std::to_string(nameCountStart + (i * nameCountIncrement)));
2923 for (
auto &attrValue : attrValues) {
2924 pLoc->setAttribute(attrValue.first, boost::lexical_cast<std::string>(attrValue.second));
2927 if (rangeAttrSteps.find(attrValue.first) != rangeAttrSteps.end()) {
2928 attrValue.second += rangeAttrSteps[attrValue.first];
2932 pRoot->appendChild(pLoc);
2946 if (!filename.empty()) {
2948 path.makeDirectory();
2949 path.append(filename +
".vtp");
2950 retVal = path.toString();
2966 const std::string &name) {
2969 Poco::AutoPtr<NodeList> pNL = pElem->getElementsByTagName(name);
2970 if (pNL->length() != 1) {
2971 throw std::invalid_argument(
"XML element: <" + pElem->tagName() +
2972 "> must contain exactly one sub-element with name: <" + name +
">.");
2974 auto *retVal =
static_cast<Element *
>(pNL->item(0));
2986 if (pElem->hasAttribute(
"R") || pElem->hasAttribute(
"theta") || pElem->hasAttribute(
"phi")) {
2992 }
else if (pElem->hasAttribute(
"r") || pElem->hasAttribute(
"t") || pElem->hasAttribute(
"p"))
3033 Poco::XML::Element *pLocElem,
3034 std::map<std::string, Poco::XML::Element *> &getTypeElement,
3050 Element *pType =
getTypeElement[pCompElem->getAttribute(
"type")];
3058 Poco::AutoPtr<NodeList> pNL = pType->getElementsByTagName(
"location");
3059 if (pNL->length() == 0) {
3060 return pType->getAttribute(
"name");
3061 }
else if (pNL->length() == 1) {
3062 auto *pElem =
static_cast<Element *
>(pNL->item(0));
3066 " the containing component elements are not allowed to contain "
3067 "multiple nested components. See www.mantidproject.org/IDF.");
double value
The value of the point.
std::map< DeltaEMode::Type, std::string > index
#define UNUSED_ARG(x)
Function arguments are sometimes unused in certain implmentations but are required for documentation ...
double obj
the value of the quadratic function
Class for Assembly of geometric components.
Kernel::V3D getPos() const override
Gets the absolute position of the Parametrized CompAssembly This attempts to read the cached position...
Component is a wrapper for a Component which can modify some of its parameters, e....
void setRot(const Kernel::Quat &) override
Set the orientation Kernel::Quaternion relative to parent (if present)
void setParent(IComponent *) override
Assign a parent IComponent. Previous parent link is lost.
Kernel::V3D getPos() const override
Get the position of the IComponent. Tree structure is traverse through the.
void setPos(double, double, double) override
Set the IComponent position, x, y, z respective to parent (if present)
This class represents a detector - i.e.
detid_t getID() const override
Gets the detector id.
GridDetector is a type of CompAssembly, an assembly of components.
static bool compareName(const std::string &proposedMatch)
Matches name to Structured Detector.
Class for Assembly of geometric components.
virtual int add(IComponent *)=0
Add a component to the assembly.
base class for Geometric IComponent
virtual Kernel::V3D getPos() const =0
Get the position of the IComponent. Tree structure is traverse through the.
virtual void setPos(double, double, double)=0
Set the IComponent position, x, y, z respective to parent (if present)
virtual std::shared_ptr< const IComponent > getParent() const =0
Return a pointer to the current parent.
virtual Kernel::Quat getRotation() const =0
Get the absolute orientation of the IComponent.
virtual void translate(const Kernel::V3D &)=0
Copy the Rotation from another IComponent.
virtual void rotate(const Kernel::Quat &)=0
Rotate the IComponent. This is relative to parent.
virtual std::string getName() const =0
Get the IComponent name.
Creates an instrument data from a XML instrument description file.
bool m_deltaOffsets
Flag to indicate whether offsets given in spherical coordinates are to be added to the current positi...
void appendLocations(Geometry::ICompAssembly *parent, const Poco::XML::Element *pLocElems, const Poco::XML::Element *pCompElem, IdList &idList)
Append <locations> in a locations element.
void createNeutronicInstrument()
If appropriate, creates a second instrument containing neutronic detector positions.
std::shared_ptr< Instrument > parseXML(Kernel::ProgressBase *progressReporter)
Parse XML contents.
void createStructuredDetector(Geometry::ICompAssembly *parent, const Poco::XML::Element *pLocElem, const Poco::XML::Element *pCompElem, const std::string &filename, const Poco::XML::Element *pType)
void adjustTypesContainingCombineComponentsElement(ShapeFactory &shapeCreator, const std::string &filename, const std::vector< Poco::XML::Element * > &typeElems, size_t numberOfTypes)
Adjust each type which contains a <combine-components-into-one-shape> element.
void getTypeAndComponentPointers(const Poco::XML::Element *pRootElem, std::vector< Poco::XML::Element * > &typeElems, std::vector< Poco::XML::Element * > &compElems) const
Populate vectors of pointers to type and component xml elements.
void throwIfTypeNameNotUnique(const std::string &filename, const std::string &typeName) const
Throw exception if type name is not unique in the IDF.
std::map< const Geometry::IComponent *, SphVec > m_tempPosHolder
Map to store positions of parent components in spherical coordinates.
void createDetectorOrMonitor(Geometry::ICompAssembly *parent, const Poco::XML::Element *pLocElem, const Poco::XML::Element *pCompElem, const std::string &filename, IdList &idList, const std::string &category)
std::string translateRotateXMLcuboid(Geometry::ICompAssembly *comp, const Poco::XML::Element *cuboidEle, const std::string &cuboidName)
Returns a translated and rotated <cuboid> element.
void createRectangularDetector(Geometry::ICompAssembly *parent, const Poco::XML::Element *pLocElem, const Poco::XML::Element *pCompElem, const std::string &filename, const Poco::XML::Element *pType)
double m_angleConvertConst
when this const equals 1 it means that angle=degree (default) is set in IDF otherwise if this const e...
void appendLeaf(Geometry::ICompAssembly *parent, const Poco::XML::Element *pLocElem, const Poco::XML::Element *pCompElem, IdList &idList)
Add XML element to parent assuming the element contains no other component elements.
std::string getMangledName()
Handle used in the singleton constructor for instrument file should append the value file sha-1 check...
void setComponentLinks(std::shared_ptr< Geometry::Instrument > &instrument, Poco::XML::Element *pRootElem, Kernel::ProgressBase *progress=nullptr, const std::string &requestedDate=std::string())
Add/overwrite any parameters specified in instrument with param values specified in <component-link> ...
bool m_haveDefaultFacing
True if defaults->components-are-facing is set in instrument def. file.
void setLocation(Geometry::IComponent *comp, const Poco::XML::Element *pElem, const double angleConvertConst, const bool deltaOffsets=false)
Set location (position) of comp as specified in XML location element.
std::string getShapeCoorSysComp(Geometry::ICompAssembly *parent, Poco::XML::Element *pLocElem, std::map< std::string, Poco::XML::Element * > &getTypeElement, Geometry::ICompAssembly *&endAssembly)
This method returns the parent appended which its child components and also name of type of the last ...
Kernel::V3D m_defaultFacing
Hold default facing position.
CachingOption getAppliedCachingOption() const
Getter the the applied caching option.
std::map< Geometry::IComponent *, Poco::XML::Element * > m_neutronicPos
A map containing the neutronic position for each detector.
void checkComponentContainsLocationElement(Poco::XML::Element *pElem, const std::string &filename) const
Check component has a <location> or <locations> element.
Kernel::V3D parseFacingElementToV3D(Poco::XML::Element *pElem)
Parse position of facing element to V3D.
void collateTypeInformation(const std::string &filename, const std::vector< Poco::XML::Element * > &typeElems, ShapeFactory &shapeCreator)
Collect some information about types for later use.
IDFObject_const_sptr m_cacheFile
Input vtp file.
std::shared_ptr< Geometry::Instrument > m_instrument
For convenience added pointer to instrument here.
InstrumentDefinitionParser()
Default Constructor - not very functional in this state.
CachingOption writeAndApplyCache(IDFObject_const_sptr firstChoiceCache, IDFObject_const_sptr fallBackCache)
Write out a cache file.
Kernel::V3D parsePosition(Poco::XML::Element *pElem)
Get position coordinates from XML element.
void makeXYplaneFaceComponent(Geometry::IComponent *&in, const Geometry::ObjComponent *facing)
Make the shape defined in 1st argument face the component in the second argument.
Kernel::V3D getRelativeTranslation(const Geometry::IComponent *comp, const Poco::XML::Element *pElem, const double angleConvertConst, const bool deltaOffsets=false)
Calculate the position of comp relative to its parent from info provided by <location> element.
void adjust(Poco::XML::Element *pElem, std::map< std::string, bool > &isTypeAssembly, std::map< std::string, Poco::XML::Element * > &getTypeElement)
Takes as input a <type> element containing a <combine-components-into-one-shape>, and adjust the <typ...
std::vector< Poco::XML::Element * > m_hasParameterElement
Holds all the xml elements that have a <parameter> child element.
void setFacing(Geometry::IComponent *comp, const Poco::XML::Element *pElem)
Set facing of comp as specified in XML facing element.
void readDefaults(Poco::XML::Element *defaults)
Reads the contents of the <defaults> element to set member variables,.
Poco::AutoPtr< Poco::XML::Document > m_pDoc
XML document is lazy loaded.
void populateIdList(Poco::XML::Element *pE, IdList &idList)
Method for populating IdList.
std::map< std::string, std::shared_ptr< Geometry::IObject > > mapTypeNameToShape
map which maps the type name to a shared pointer to a geometric shape
void createShapeIfTypeIsNotAnAssembly(Mantid::Geometry::ShapeFactory &shapeCreator, size_t iType, Poco::XML::Element *pTypeElem, const std::string &typeName)
Record type as an assembly if it contains a component, otherwise create a shape for it.
std::map< std::string, bool > isTypeAssembly
map which holds names of types and whether or not they are categorized as being assemblies,...
void setLogfile(const Geometry::IComponent *comp, const Poco::XML::Element *pElem, InstrumentParameterCache &logfileCache, const std::string &requestedDate=std::string())
Set parameter/logfile info (if any) associated with component.
void createGridDetector(Geometry::ICompAssembly *parent, const Poco::XML::Element *pLocElem, const Poco::XML::Element *pCompElem, const std::string &filename, const Poco::XML::Element *pType)
const std::string createVTPFileName()
creates a vtp filename from a given xml filename
void parseLocationsForEachTopLevelComponent(Kernel::ProgressBase *progressReporter, const std::string &filename, const std::vector< Poco::XML::Element * > &compElems)
Aggregate locations and IDs for components.
static Poco::XML::Element * getParentComponent(const Poco::XML::Element *pLocElem)
Get parent component element of location element.
std::map< std::string, Poco::XML::Element * > getTypeElement
map which holds names of types and pointers to these type for fast retrieval in code
Poco::XML::Element * getShapeElement(const Poco::XML::Element *pElem, const std::string &name)
Return a subelement of an XML element.
void appendAssembly(Geometry::ICompAssembly *parent, const Poco::XML::Element *pLocElem, const Poco::XML::Element *pCompElem, IdList &idList)
Add XML element to parent assuming the element contains other component elements.
std::vector< std::string > buildExcludeList(const Poco::XML::Element *const location)
void createVectorOfElementsContainingAParameterElement(Poco::XML::Element *pRootElem)
Create a vector of elements which contain a <parameter>
CachingOption setupGeometryCache()
Reads in or creates the geometry cache ('vtp') file.
void setValidityRange(const Poco::XML::Element *pRootElem)
Check the validity range and add it to the instrument object.
bool m_hasParameterElement_beenSet
has m_hasParameterElement been set - used when public method setComponentLinks is used
IDFObject_const_sptr m_xmlFile
Input xml file.
double attrToDouble(const Poco::XML::Element *pElem, const std::string &name)
return 0 if the attribute doesn't exist.
void initialise(const std::string &filename, const std::string &instName, const std::string &xmlText, const std::string &vtpFilename)
shared Constructor logic
Poco::AutoPtr< Poco::XML::Document > convertLocationsElement(const Poco::XML::Element *pElem)
Take as input a <locations> element.
std::vector< Geometry::ObjComponent * > m_facingComponent
Container to hold all detectors and monitors added to the instrument.
std::string m_instName
Name of the instrument.
Kernel::V3D getAbsolutPositionInCompCoorSys(Geometry::ICompAssembly *comp, Kernel::V3D)
return absolute position of point which is set relative to the coordinate system of the input compone...
static std::string getNameOfLocationElement(const Poco::XML::Element *pElem, const Poco::XML::Element *pCompElem)
get name of location element
Poco::AutoPtr< Poco::XML::Document > getDocument()
lazy loads the document and returns a pointer
bool isAssembly(const std::string &) const
Return true if assembly, false if not assembly and throws exception if string not in assembly.
bool m_indirectPositions
Flag to indicate whether IDF contains physical & neutronic positions.
void checkIdListExistsAndDefinesEnoughIDs(const IdList &idList, Poco::XML::Element *pElem, const std::string &filename) const
Check IdList.
CachingOption m_cachingOption
Caching applied.
void saveDOM_Tree(std::string &outFilename)
Save DOM tree to xml file.
void applyCache(const IDFObject_const_sptr &cacheToApply)
Reads from a cache file.
Class for Assembly of geometric components.
Object Component class, this class brings together the physical attributes of the component to the po...
void setShape(std::shared_ptr< const IObject > newShape)
Set a new shape on the component void setShape(std::shared_ptr<const IObject> newShape);.
RectangularDetector is a type of CompAssembly, an assembly of components.
static bool compareName(const std::string &proposedMatch)
Matches name to Structured Detector.
Class originally intended to be used with the DataHandling 'LoadInstrument' algorithm.
std::shared_ptr< CSGObject > createShape(Poco::XML::Element *pElem)
Creates a geometric object from a DOM-element-node pointing to an element whose child nodes contain t...
StructuredDetector is a type of CompAssembly, an assembly of components.
static bool compareName(const std::string &proposedMatch)
Matches name to Structured Detector.
Reads the Geometry Cache from the file to the Object.
Writes the Geometry from Object to Cache.
Exception for when an item is already in a collection.
Exception for errors associated with the instrument definition.
The Logger class is in charge of the publishing messages from the framework through various channels.
void notice(const std::string &msg)
Logs at notice level.
void error(const std::string &msg)
Logs at error level.
void warning(const std::string &msg)
Logs at warning level.
void information(const std::string &msg)
Logs at information level.
void resetNumSteps(int64_t nsteps, double start, double end)
Change the number of steps between start/end.
virtual bool hasCancellationBeenRequested() const
Override so that the reporter can inform whether a cancellation request has been used.
void report()
Increments the loop counter by 1, then sends the progress notification on behalf of its algorithm.
void inverse()
Inverse a quaternion (in the sense of rotation inversion)
void rotate(V3D &) const
Rotate a vector.
static T & Instance()
Return a reference to the Singleton instance, creating it if it does not already exist Creation is do...
constexpr double X() const noexcept
Get x.
constexpr V3D cross_prod(const V3D &v) const noexcept
Cross product (this * argument)
constexpr double Y() const noexcept
Get y.
void spherical(const double R, const double theta, const double phi) noexcept
Sets the vector position based on spherical coordinates.
double angle(const V3D &) const
Angle between this and another vector.
double norm() const noexcept
constexpr double Z() const noexcept
Get z.
Handedness
Type to distingusih between l and r handedness.
std::map< std::pair< std::string, const IComponent * >, std::shared_ptr< XMLInstrumentParameter > > InstrumentParameterCache
Convenience typedef.
Mantid::Kernel::Logger g_log("Goniometer")
std::shared_ptr< const AbstractIDFObject > IDFObject_const_sptr
PointingAlong axisNameToAxisType(const std::string &label, const std::string &input)
std::shared_ptr< Instrument > Instrument_sptr
Shared pointer to an instrument object.
PointingAlong
Type to describe pointing along options.
MANTID_KERNEL_DLL std::string sha1FromString(const std::string &input)
create a SHA-1 checksum from a string
MANTID_KERNEL_DLL std::string strip(const std::string &A)
strip pre/post spaces
MANTID_KERNEL_DLL V3D normalize(V3D v)
Normalizes a V3D.
Helper class which provides the Collimation Length for SANS instruments.
int32_t detid_t
Typedef for a detector ID.
std::string to_string(const wide_integer< Bits, Signed > &n)
Structure for holding detector IDs.
std::vector< int > vec
list of detector IDs
int counted
Used to count the number of detector encounted so far.
std::string idname
name of idlist
Stripped down vector that holds position in terms of spherical coordinates, Needed when processing in...