-
Karl Palmen authored
Signed-off-by:
Karl Palmen <karl.palmen@stfc.ac.uk>
Karl Palmen authoredSigned-off-by:
Karl Palmen <karl.palmen@stfc.ac.uk>
Code owners
Assign users and groups as approvers for specific file changes. Learn more.
InstrumentDefinitionParser.h 16.30 KiB
#ifndef MANTID_GEOMETRY_INSTRUMENTDEFINITIONPARSER_H_
#define MANTID_GEOMETRY_INSTRUMENTDEFINITIONPARSER_H_
#include <string>
#include <vector>
#include <Poco/AutoPtr.h>
#include <Poco/DOM/Document.h>
#include "MantidKernel/System.h"
#include "MantidKernel/V3D.h"
#include "MantidGeometry/Instrument.h"
#include "MantidGeometry/Instrument/IDFObject.h"
namespace Poco {
namespace XML {
class Element;
}
}
namespace Mantid {
namespace Kernel {
class ProgressBase;
}
namespace Geometry {
class ICompAssembly;
class IComponent;
class Instrument;
class ObjComponent;
class IObject;
class ShapeFactory;
/** Creates an instrument data from a XML instrument description file
@author Nick Draper, Tessella Support Services plc
@date 19/11/2007
@author Anders Markvardsen, ISIS, RAL
@date 7/3/2008
Copyright © 2007-2014 ISIS Rutherford Appleton Laboratory, NScD Oak Ridge
National Laboratory & European Spallation Source
This file is part of Mantid.
Mantid is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
Mantid is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
File change history is stored at: <https://github.com/mantidproject/mantid>
*/
class DLLExport InstrumentDefinitionParser {
public:
InstrumentDefinitionParser();
InstrumentDefinitionParser(const std::string &filename,
const std::string &instName,
const std::string &xmlText);
InstrumentDefinitionParser(const IDFObject_const_sptr xmlFile,
const IDFObject_const_sptr expectedCacheFile,
const std::string &instName,
const std::string &xmlText);
~InstrumentDefinitionParser() = default;
/// Caching
enum CachingOption {
NoneApplied,
ReadGeomCache,
ReadFallBack,
WroteGeomCache,
WroteCacheTemp
};
/// Parse XML contents
boost::shared_ptr<Instrument>
parseXML(Kernel::ProgressBase *progressReporter);
/// Add/overwrite any parameters specified in instrument with param values
/// specified in <component-link> XML elements
void setComponentLinks(boost::shared_ptr<Geometry::Instrument> &instrument,
Poco::XML::Element *pRootElem,
Kernel::ProgressBase *progress = nullptr);
std::string getMangledName();
/// Get parent component element of location element
static Poco::XML::Element *
getParentComponent(const Poco::XML::Element *pLocElem);
/// get name of location element
static std::string
getNameOfLocationElement(const Poco::XML::Element *pElem,
const Poco::XML::Element *pCompElem);
/// Save DOM tree to xml file
void saveDOM_Tree(std::string &outFilename);
/// Getter the the applied caching option.
CachingOption getAppliedCachingOption() const;
/// creates a vtp filename from a given xml filename
const std::string createVTPFileName();
private:
/// shared Constructor logic
void initialise(const std::string &filename, const std::string &instName,
const std::string &xmlText, const std::string &vtpFilename);
/// lazy loads the document and returns a pointer
Poco::AutoPtr<Poco::XML::Document> getDocument();
/// Set location (position) of comp as specified in XML location element
void setLocation(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
Kernel::V3D getRelativeTranslation(const Geometry::IComponent *comp,
const Poco::XML::Element *pElem,
const double angleConvertConst,
const bool deltaOffsets = false);
/// Check the validity range and add it to the instrument object
void setValidityRange(const Poco::XML::Element *pRootElem);
/// Reads the contents of the \<defaults\> element to set member variables,
void readDefaults(Poco::XML::Element *defaults);
/// Structure for holding detector IDs
struct IdList {
/// Used to count the number of detector encounted so far
int counted;
/// list of detector IDs
std::vector<int> vec;
/// name of idlist
std::string idname;
/// Constructor
IdList() : counted(0){};
/// return true if empty
bool empty() { return vec.empty(); };
/// reset idlist
void reset() {
counted = 0;
vec.clear();
};
};
/// Method for populating IdList
void populateIdList(Poco::XML::Element *pE, IdList &idList);
std::vector<std::string>
buildExcludeList(const Poco::XML::Element *const location);
/// Add XML element to parent assuming the element contains other component
/// elements
void appendAssembly(Geometry::ICompAssembly *parent,
const Poco::XML::Element *pLocElem,
const Poco::XML::Element *pCompElem, IdList &idList);
/// Return true if assembly, false if not assembly and throws exception if
/// string not in assembly
bool isAssembly(std::string) const;
/// Add XML element to parent assuming the element contains no other component
/// elements
void appendLeaf(Geometry::ICompAssembly *parent,
const Poco::XML::Element *pLocElem,
const Poco::XML::Element *pCompElem, IdList &idList);
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);
void createRectangularDetector(Geometry::ICompAssembly *parent,
const Poco::XML::Element *pLocElem,
const Poco::XML::Element *pCompElem,
const std::string &filename,
const Poco::XML::Element *pType);
void createStructuredDetector(Geometry::ICompAssembly *parent,
const Poco::XML::Element *pLocElem,
const Poco::XML::Element *pCompElem,
const std::string &filename,
const Poco::XML::Element *pType);
/// Append \<locations\> in a locations element
void appendLocations(Geometry::ICompAssembly *parent,
const Poco::XML::Element *pLocElems,
const Poco::XML::Element *pCompElem, IdList &idList);
/// Set parameter/logfile info (if any) associated with component
void setLogfile(const Geometry::IComponent *comp,
const Poco::XML::Element *pElem,
InstrumentParameterCache &logfileCache);
/// Parse position of facing element to V3D
Kernel::V3D parseFacingElementToV3D(Poco::XML::Element *pElem);
/// Set facing of comp as specified in XML facing element
void setFacing(Geometry::IComponent *comp, const Poco::XML::Element *pElem);
/// Make the shape defined in 1st argument face the component in the second
/// argument
void makeXYplaneFaceComponent(Geometry::IComponent *&in,
const Geometry::ObjComponent *facing);
/// Make the shape defined in 1st argument face the position in the second
/// argument
void makeXYplaneFaceComponent(Geometry::IComponent *&in,
const Kernel::V3D &facingPoint);
/// Reads in or creates the geometry cache ('vtp') file
CachingOption setupGeometryCache();
/// If appropriate, creates a second instrument containing neutronic detector
/// positions
void createNeutronicInstrument();
/// Takes as input a \<type\> element containing a
/// <combine-components-into-one-shape>, and
/// adjust the \<type\> element by replacing its containing \<component\>
/// elements with \<cuboid\>'s
/// (note for now this will only work for \<cuboid\>'s and when necessary this
/// can be extended).
void adjust(Poco::XML::Element *pElem,
std::map<std::string, bool> &isTypeAssembly,
std::map<std::string, Poco::XML::Element *> &getTypeElement);
/// Take as input a \<locations\> element. Such an element is a short-hand
/// notation for a sequence of \<location\> elements.
/// This method return this sequence as a xml string
Poco::AutoPtr<Poco::XML::Document>
convertLocationsElement(const Poco::XML::Element *pElem);
/// return 0 if the attribute doesn't exist. This is to follow the
/// behavior of atof which always returns 0 if there is a problem.
double attrToDouble(const Poco::XML::Element *pElem, const std::string &name);
/// Populate vectors of pointers to type and component xml elements
void getTypeAndComponentPointers(
const Poco::XML::Element *pRootElem,
std::vector<Poco::XML::Element *> &typeElems,
std::vector<Poco::XML::Element *> &compElems) const;
/// Throw exception if type name is not unique in the IDF
void throwIfTypeNameNotUnique(const std::string &filename,
const std::string &typeName) const;
/// Record type as an assembly if it contains a component, otherwise create a
/// shape for it
void
createShapeIfTypeIsNotAnAssembly(Mantid::Geometry::ShapeFactory &shapeCreator,
size_t iType, Poco::XML::Element *pTypeElem,
const std::string &typeName);
/// Adjust each type which contains a \<combine-components-into-one-shape\>
/// element
void adjustTypesContainingCombineComponentsElement(
ShapeFactory &shapeCreator, const std::string &filename,
const std::vector<Poco::XML::Element *> &typeElems, size_t numberOfTypes);
/// Create a vector of elements which contain a \<parameter\>
void createVectorOfElementsContainingAParameterElement(
Poco::XML::Element *pRootElem);
/// Check IdList
void checkIdListExistsAndDefinesEnoughIDs(IdList idList,
Poco::XML::Element *pElem,
const std::string &filename) const;
/// Check component has a \<location\> or \<locations\> element
void checkComponentContainsLocationElement(Poco::XML::Element *pElem,
const std::string &filename) const;
/// Aggregate locations and IDs for components
void parseLocationsForEachTopLevelComponent(
Kernel::ProgressBase *progressReporter, const std::string &filename,
const std::vector<Poco::XML::Element *> &compElems);
/// Collect some information about types for later use
void
collateTypeInformation(const std::string &filename,
const std::vector<Poco::XML::Element *> &typeElems,
ShapeFactory &shapeCreator);
public: // for testing
/// return absolute position of point which is set relative to the
/// coordinate system of the input component
Kernel::V3D getAbsolutPositionInCompCoorSys(Geometry::ICompAssembly *comp,
Kernel::V3D);
private:
/// Reads from a cache file.
void applyCache(IDFObject_const_sptr cacheToApply);
/// Write out a cache file.
CachingOption writeAndApplyCache(IDFObject_const_sptr firstChoiceCache,
IDFObject_const_sptr fallBackCache);
/// This method returns the parent appended which its child components and
/// also name of type of the last child component
std::string getShapeCoorSysComp(
Geometry::ICompAssembly *parent, Poco::XML::Element *pLocElem,
std::map<std::string, Poco::XML::Element *> &getTypeElement,
Geometry::ICompAssembly *&endAssembly);
/// Returns a translated and rotated \<cuboid\> element
std::string translateRotateXMLcuboid(Geometry::ICompAssembly *comp,
const Poco::XML::Element *cuboidEle,
const std::string &cuboidName);
/// Returns a translated and rotated \<cuboid\> element
std::string translateRotateXMLcuboid(Geometry::ICompAssembly *comp,
const std::string &cuboidXML,
const std::string &cuboidName);
/// Return a subelement of an XML element
Poco::XML::Element *getShapeElement(const Poco::XML::Element *pElem,
const std::string &name);
/// Get position coordinates from XML element
Kernel::V3D parsePosition(Poco::XML::Element *pElem);
/// Input xml file
IDFObject_const_sptr m_xmlFile;
/// Input vtp file
IDFObject_const_sptr m_cacheFile;
/// Name of the instrument
std::string m_instName;
/// XML document is lazy loaded
Poco::AutoPtr<Poco::XML::Document> m_pDoc;
/** Holds all the xml elements that have a \<parameter\> child element.
* Added purely for the purpose of computing speed and is used in
* setLogFile() for the purpose
* of quickly accessing if a component have a parameter/logfile associated
* with it or not
* - instead of using the comparatively slow poco call getElementsByTagName()
* (or getChildElement)
*/
std::vector<Poco::XML::Element *> m_hasParameterElement;
/// has m_hasParameterElement been set - used when public method
/// setComponentLinks is used
bool m_hasParameterElement_beenSet;
/** map which holds names of types and whether or not they are categorized as
* being
* assemblies, which means whether the type element contains component
* elements
*/
std::map<std::string, bool> isTypeAssembly;
/// map which maps the type name to a shared pointer to a geometric shape
std::map<std::string, boost::shared_ptr<Geometry::IObject>>
mapTypeNameToShape;
/// Container to hold all detectors and monitors added to the instrument. Used
/// for 'facing' these to component specified under \<defaults\>. NOTE: Seems
/// unused, ever.
std::vector<Geometry::ObjComponent *> m_facingComponent;
/// True if defaults->components-are-facing is set in instrument def. file
bool m_haveDefaultFacing;
/// Hold default facing position
Kernel::V3D m_defaultFacing;
/// map which holds names of types and pointers to these type for fast
/// retrieval in code
std::map<std::string, Poco::XML::Element *> getTypeElement;
/// For convenience added pointer to instrument here
boost::shared_ptr<Geometry::Instrument> m_instrument;
/// Flag to indicate whether offsets given in spherical coordinates are to be
/// added to the current
/// position (true) or are a vector from the current position (false, default)
bool m_deltaOffsets;
/// when this const equals 1 it means that angle=degree (default) is set in
/// IDF
/// otherwise if this const equals 180/pi it means that angle=radian is set in
/// IDF
double m_angleConvertConst;
bool m_indirectPositions; ///< Flag to indicate whether IDF contains physical
///& neutronic positions
/// A map containing the neutronic position for each detector. Used when
/// m_indirectPositions is true.
std::map<Geometry::IComponent *, Poco::XML::Element *> m_neutronicPos;
/** Stripped down vector that holds position in terms of spherical
* coordinates,
* Needed when processing instrument definition files that use the 'Ariel
* format'
*/
struct SphVec {
///@cond Exclude from doxygen documentation
double r, theta, phi;
SphVec() : r(0.0), theta(0.0), phi(0.0) {}
SphVec(const double &r, const double &theta, const double &phi)
: r(r), theta(theta), phi(phi) {}
///@endcond
};
/// Map to store positions of parent components in spherical coordinates
std::map<const Geometry::IComponent *, SphVec> m_tempPosHolder;
/// Caching applied.
CachingOption m_cachingOption;
};
} // namespace Geometry
} // namespace Mantid
#endif /* MANTID_GEOMETRY_INSTRUMENTDEFINITIONPARSER_H_ */