-
Nick Draper authored
Update copyright headers in all files Squashed commit of the following: * First version of a script to manage copyright statements re #23468 * Neatened up script, added comments re #23488 * move script to tools directory re #23488 * small script changes and a couple of manual file changes re #23488 * Minor chnage to whitespace detection in regex re #23488 * Add an excluded directory re #23488 * remove a repeasted copyright statement in a file re #23488 * Don't comsume the comment end if it is on the same line re #23488 * fix error in new copright parsing re #23488 * remove double copyrifght entry re #23488 * Improve handling of old copyrights at the start of comments re #23488 * remove empty comments re #23488 * exclude gsoapgenerated directories re #23488 * Sort out greedy line matching re #23488 * improve empty comment removal re #23488 * improve false positives re #23488 * impressive speedup by limiting regex matching length re #23488 * remove evil invisible non ascii character Also upadte the copyright at the same time re #23488 * resolve multiple copyrights in a single file re #23488 * resolve an issue with new statement detection re #23488 * another unprintable unicode character re #23488 * pep updates and cmake the new copyright fit clang format re #23488 * update already done new format headers re #23488 * wrong type of bracket re #23488 * Update class_maker and friends re #23488 * Update all copyright statements re #23488 * clang format re #23488 * flake8 warnings re #23488 * Flake8 warnings re #23488 * Exclude .cmake.in and rb.in files re #23488 * replace missing line re #23488 * exclude .py.in files as they are flasely recognized as C++ re #23488 * another setp.py.in re #23488 * another .py.in correction re #23488 * Hopefully the last of the .py.in files re #23488 * resolve utf-8 encoding of python files and changed ABINS checksum re #23488 * updates to unit tests that reference line numbers re #23488 * remaining unit test files and other fixes re #23488
Nick Draper authoredUpdate copyright headers in all files Squashed commit of the following: * First version of a script to manage copyright statements re #23468 * Neatened up script, added comments re #23488 * move script to tools directory re #23488 * small script changes and a couple of manual file changes re #23488 * Minor chnage to whitespace detection in regex re #23488 * Add an excluded directory re #23488 * remove a repeasted copyright statement in a file re #23488 * Don't comsume the comment end if it is on the same line re #23488 * fix error in new copright parsing re #23488 * remove double copyrifght entry re #23488 * Improve handling of old copyrights at the start of comments re #23488 * remove empty comments re #23488 * exclude gsoapgenerated directories re #23488 * Sort out greedy line matching re #23488 * improve empty comment removal re #23488 * improve false positives re #23488 * impressive speedup by limiting regex matching length re #23488 * remove evil invisible non ascii character Also upadte the copyright at the same time re #23488 * resolve multiple copyrights in a single file re #23488 * resolve an issue with new statement detection re #23488 * another unprintable unicode character re #23488 * pep updates and cmake the new copyright fit clang format re #23488 * update already done new format headers re #23488 * wrong type of bracket re #23488 * Update class_maker and friends re #23488 * Update all copyright statements re #23488 * clang format re #23488 * flake8 warnings re #23488 * Flake8 warnings re #23488 * Exclude .cmake.in and rb.in files re #23488 * replace missing line re #23488 * exclude .py.in files as they are flasely recognized as C++ re #23488 * another setp.py.in re #23488 * another .py.in correction re #23488 * Hopefully the last of the .py.in files re #23488 * resolve utf-8 encoding of python files and changed ABINS checksum re #23488 * updates to unit tests that reference line numbers re #23488 * remaining unit test files and other fixes re #23488
Code owners
Assign users and groups as approvers for specific file changes. Learn more.
InstrumentInfo.cpp 10.03 KiB
// Mantid Repository : https://github.com/mantidproject/mantid
//
// Copyright © 2018 ISIS Rutherford Appleton Laboratory UKRI,
// NScD Oak Ridge National Laboratory, European Spallation Source
// & Institut Laue - Langevin
// SPDX - License - Identifier: GPL - 3.0 +
//----------------------------------------------------------------------
// Includes
//----------------------------------------------------------------------
#include <algorithm>
#include "MantidKernel/FacilityInfo.h"
#include "MantidKernel/InstrumentInfo.h"
#include "MantidKernel/Logger.h"
#include "MantidKernel/Strings.h"
#include <boost/algorithm/string.hpp>
#include <boost/lexical_cast.hpp>
#include <Poco/AutoPtr.h>
#include <Poco/DOM/Element.h>
#include <Poco/DOM/NodeList.h>
#include <Poco/DOM/Text.h>
namespace Mantid {
namespace Kernel {
namespace {
// static logger object
Logger g_log("InstrumentInfo");
} // namespace
/** Constructor.
* @param f :: The facility
* @param elem :: The Poco::XML::Element to read the data from
* @throw std::runtime_error if name or at least one technique are not defined
*/
InstrumentInfo::InstrumentInfo(const FacilityInfo *f,
const Poco::XML::Element *elem)
: m_facility(f) {
m_name = elem->getAttribute("name");
if (m_name.empty()) {
throw std::runtime_error("Instrument name is not defined");
}
// The string to separate the instrument name and the run number.
m_delimiter = elem->getAttribute("delimiter");
if (m_delimiter.empty()) {
m_delimiter = f->delimiter();
}
m_shortName = elem->getAttribute("shortname");
if (m_shortName.empty()) {
m_shortName = m_name;
}
fillTechniques(elem);
fillLiveData(elem);
fillZeroPadding(elem);
}
/**
* Equality operator. Two objects are considered equal if their names and short
* names are the same.
* @param rhs :: The object to compare this with
* @returns True if the objects are considered equal, false otherwise
*/
bool InstrumentInfo::operator==(const InstrumentInfo &rhs) const {
return (this->name() == rhs.name() && this->shortName() == rhs.shortName());
}
/// Returns the default delimiter between instrument name and run number
std::string InstrumentInfo::delimiter() const { return m_delimiter; }
/// Return the name of the instrument
const std::string InstrumentInfo::name() const { return m_name; }
/// Return the short name of the instrument
const std::string InstrumentInfo::shortName() const { return m_shortName; }
/// Returns zero padding for this instrument
int InstrumentInfo::zeroPadding(unsigned int runNumber) const {
if (m_zeroPadding.empty())
return m_facility->zeroPadding();
if (m_zeroPadding.size() == 1) {
auto padding = m_zeroPadding.begin();
if (runNumber >= padding->first)
return getZeroPadding(padding);
else
return m_facility->zeroPadding();
}
auto last = m_zeroPadding.end();
--last;
for (auto it = m_zeroPadding.begin(); it != last; ++it) {
auto next = it;
++next;
if (runNumber >= it->first && runNumber < next->first) {
return getZeroPadding(it);
}
}
return getZeroPadding(last);
}
/**
* Returns file prefix for this instrument and a run number.
* @param runNumber :: A run number.
*/
std::string InstrumentInfo::filePrefix(unsigned int runNumber) const {
if (m_zeroPadding.empty())
return m_shortName;
if (m_zeroPadding.size() == 1) {
auto padding = m_zeroPadding.begin();
if (runNumber >= padding->first)
return getPrefix(padding);
else
return m_shortName;
}
auto last = m_zeroPadding.end();
--last;
for (auto it = m_zeroPadding.begin(); it != last; ++it) {
auto next = it;
++next;
if (runNumber >= it->first && runNumber < next->first) {
return getPrefix(it);
}
}
return getPrefix(last);
}
/// Returns the name of the live listener
std::string InstrumentInfo::liveListener(const std::string &name) const {
if (!hasLiveListenerInfo())
return "";
return liveListenerInfo(name).listener();
}
/** Returns the host & port to connect to for a live data stream
* No guarantees are given that the provided string is well-formed and valid
* - the caller should check this themselves
*/
std::string InstrumentInfo::liveDataAddress(const std::string &name) const {
if (!hasLiveListenerInfo())
return "";
return liveListenerInfo(name).address();
}
/**
* Get LiveListenerInfo for specified connection (or default).
*
* @param name Name attribute of connection to return info on
* @return Reference to LiveListenerInfo for specified connection
* @throw std::runtime_error When no listeners, or name not found
*/
const LiveListenerInfo &
InstrumentInfo::liveListenerInfo(std::string name) const {
if (!hasLiveListenerInfo())
throw std::runtime_error("Attempted to access live listener for " + m_name +
" instrument, which has no listeners.");
// Default to specified default connection
if (name.empty())
name = m_defaultListener;
// If no default connection specified, fallback to first connection
if (name.empty())
return m_listeners.front();
// Name specified, find requested connection
for (auto &listener : m_listeners) {
// Names are compared case insensitively
if (boost::iequals(listener.name(), name))
return listener;
}
// The provided name was not valid / did not match any listeners
throw std::runtime_error("Could not find connection " + name +
" for instrument " + m_name);
}
bool InstrumentInfo::hasLiveListenerInfo() const {
return !m_listeners.empty();
}
const std::vector<LiveListenerInfo> &
InstrumentInfo::liveListenerInfoList() const {
return m_listeners;
}
/// Return list of techniques
const std::set<std::string> &InstrumentInfo::techniques() const {
return m_technique;
}
/// Return the facility
const FacilityInfo &InstrumentInfo::facility() const { return *m_facility; }
/// Called from constructor to fill zero padding
void InstrumentInfo::fillZeroPadding(const Poco::XML::Element *elem) {
Poco::AutoPtr<Poco::XML::NodeList> pNL_zeropadding =
elem->getElementsByTagName("zeropadding");
unsigned long n = pNL_zeropadding->length();
for (unsigned long i = 0; i < n; ++i) {
auto elem = dynamic_cast<Poco::XML::Element *>(pNL_zeropadding->item(i));
if (!elem)
continue;
// read the zero padding size
if (!elem->hasAttribute("size")) {
throw std::runtime_error("Zeropadding size is missing for instrument " +
m_name);
}
auto &sizeStr = elem->getAttribute("size");
int size = 0;
if (!Mantid::Kernel::Strings::convert(sizeStr, size)) {
throw std::runtime_error(
"Zeropadding size must be an integer value (instrument " + m_name +
")");
}
// read the start run number
unsigned int startRunNumber = 0;
if (!elem->hasAttribute("startRunNumber")) {
if (!m_zeroPadding.empty()) {
throw std::runtime_error("Zeropadding size is missing for instrument " +
m_name);
}
} else {
auto &startRunNumberStr = elem->getAttribute("startRunNumber");
try {
startRunNumber = boost::lexical_cast<unsigned int>(startRunNumberStr);
} catch (...) {
throw std::runtime_error("Zeropadding start run number must be an "
"integer value (instrument " +
m_name + ")");
}
}
// read the file prefix
std::string prefix = m_shortName;
if (elem->hasAttribute("prefix")) {
prefix = elem->getAttribute("prefix");
}
m_zeroPadding[startRunNumber] = std::make_pair(prefix, size);
}
if (m_zeroPadding.empty()) {
m_zeroPadding[0] = std::make_pair(m_shortName, m_facility->zeroPadding());
}
}
/// Called from constructor to fill live listener name
void InstrumentInfo::fillTechniques(const Poco::XML::Element *elem) {
Poco::AutoPtr<Poco::XML::NodeList> pNL_technique =
elem->getElementsByTagName("technique");
unsigned long n = pNL_technique->length();
for (unsigned long i = 0; i < n; ++i) {
Poco::AutoPtr<Poco::XML::NodeList> pNL =
pNL_technique->item(i)->childNodes();
if (pNL->length() > 0) {
Poco::XML::Text *txt = dynamic_cast<Poco::XML::Text *>(pNL->item(0));
if (txt) {
const std::string &tech = txt->getData();
if (!tech.empty()) {
m_technique.insert(tech);
}
}
}
}
if (m_technique.empty()) {
throw std::runtime_error("No technique is defined for instrument " +
m_name);
}
}
/// Called from constructor to fill live listener name
void InstrumentInfo::fillLiveData(const Poco::XML::Element *elem) {
// See if we have a <livedata> element (will be NULL if there's none)
Poco::XML::Element *live = elem->getChildElement("livedata");
if (!live)
return;
// Load default connection name attribute
m_defaultListener = live->getAttribute("default");
// Get connections under <livedata>
Poco::AutoPtr<Poco::XML::NodeList> connections =
elem->getElementsByTagName("connection");
// Load connection info for each child element
for (unsigned long i = 0; i < connections->length(); ++i) {
auto *conn = dynamic_cast<Poco::XML::Element *>(connections->item(i));
try {
m_listeners.emplace_back(this, conn);
} catch (...) {
g_log.error() << "Exception occurred while loading livedata for "
<< m_name << " instrument. Skipping faulty connection.\n";
}
}
}
//-------------------------------------------------------------------------
// Non-member functions
//-------------------------------------------------------------------------
/**
* Prints the instrument name to the stream
* @param buffer :: A reference to an output stream
* @param instrumentDescriptor :: A reference to an InstrumentInfo object
* @return A reference to the stream written to
*/
std::ostream &operator<<(std::ostream &buffer,
const InstrumentInfo &instrumentDescriptor) {
buffer << instrumentDescriptor.name();
return buffer;
}
} // namespace Kernel
} // namespace Mantid