24#include <boost/lexical_cast.hpp>
25#include <boost/regex.hpp>
28#include <Poco/DOM/DOMParser.h>
29#include <Poco/DOM/Document.h>
30#include <Poco/DOM/Element.h>
31#include <Poco/DOM/Node.h>
32#include <Poco/DOM/NodeList.h>
33#include <Poco/DOM/Text.h>
35#include <Poco/SAX/InputSource.h>
44using Poco::XML::Document;
45using Poco::XML::DOMParser;
46using Poco::XML::Element;
52using Types::Core::DateAndTime;
53using namespace Kernel;
55using namespace Geometry;
56using namespace DataObjects;
63 std::istringstream iss(s);
64 return !(iss >> f >> t).fail();
80 auto &
X = ws->mutableX(specID);
81 auto &
Y = ws->mutableY(specID);
82 auto &E = ws->mutableE(specID);
85 X[0] = wavelength - dwavelength / 2.0;
86 X[1] = wavelength + dwavelength / 2.0;
89 ws->getSpectrum(specID).setSpectrumNo(specID);
102 std::istream &is = descriptor.
data();
106 Poco::XML::InputSource src(is);
109 Poco::AutoPtr<Document> pDoc;
111 pDoc = pParser.parse(&src);
112 }
catch (Poco::Exception &e) {
118 Element *pRootElem = pDoc->documentElement();
120 if (pRootElem->tagName() ==
"SPICErack") {
132 "The name of the input xml file to load");
135 "The name of the Output workspace");
140 auto mustBePositive = std::make_shared<Kernel::BoundedValidator<double>>();
141 mustBePositive->setLower(0.0);
143 "Optional wavelength value to use when loading the data file "
144 "(Angstrom). This value will be used instead of the value "
145 "found in the data file.");
147 "Optional wavelength spread value to use when loading the "
148 "data file (Angstrom). This value will be used instead of "
149 "the value found in the data file.");
162 const std::vector<std::string> tags_to_ignore{
"Detector",
"DetectorWing"};
168 std::vector<int> data =
getData(
"//Data");
170 double monitorCounts = 0;
171 from_string<double>(monitorCounts, metadata[
"Counters/monitor"], std::dec);
172 double countingTime = 0;
173 from_string<double>(countingTime, metadata[
"Counters/time"], std::dec);
174 createWorkspace(data, metadata[
"Header/Scan_Title"], monitorCounts, countingTime);
182 std::string instrument = metadata[
"Header/Instrument"];
187 if (metadata.find(
"Motor_Positions/det_west_wing_rot") != metadata.end()) {
188 auto angle = boost::lexical_cast<double>(metadata[
"Motor_Positions/det_west_wing_rot"]);
206 std::pair<int, int> dims = std::make_pair(0, 0);
208 boost::regex b_re_sig(R
"(INT\d+\[(\d+),(\d+)\])");
209 if (boost::regex_match(dims_str, b_re_sig)) {
210 boost::match_results<std::string::const_iterator> match;
211 boost::regex_search(dims_str, match, b_re_sig);
216 if (dims.first == 0 || dims.second == 0)
217 g_log.
notice() <<
"Could not read in the number of pixels!" <<
'\n';
227 for (
const auto &keyValuePair : metadata) {
228 std::string key = keyValuePair.first;
229 std::replace(key.begin(), key.end(),
'/',
'_');
230 m_workspace->mutableRun().addProperty(key, keyValuePair.second,
true);
264 std::string s = metadata[
"Header/wavelength"];
266 s = metadata[
"Header/wavelength_spread"];
271 DateAndTime changingDate(
"2016-06-13 00:00:00");
273 g_log.
debug() <<
"Using wavelength spread as a ratio" <<
'\n';
291 std::vector<int> data;
292 unsigned int totalDataSize = 0;
296 g_log.
debug() <<
"Number the detectors found in Xpath " << dataXpath <<
" = " << detectors.size() <<
'\n';
299 for (
const auto &detector : detectors) {
300 std::string detectorXpath = std::string(dataXpath).append(
"/").append(detector);
308 if (detectorXpath.find(
"DetectorWing") != std::string::npos && dims.first * dims.second <= 4096)
311 totalDataSize += dims.first * dims.second;
312 g_log.
debug() <<
"Parsing detector XPath " << detectorXpath <<
" with dimensions: " << dims.first <<
" x "
313 << dims.second <<
" = " << dims.first * dims.second <<
'\n';
316 g_log.
debug() <<
"The size of detector contents (xpath = " << detectorXpath <<
") is " << data_str.size()
317 <<
" bytes." <<
'\n';
320 std::stringstream iss(data_str);
322 while (iss >> number) {
323 data.emplace_back(
static_cast<int>(number));
325 g_log.
debug() <<
"Detector XPath: " << detectorXpath
326 <<
" parsed. Total size of data processed up to now = " << data.size() <<
" from a total of "
327 << totalDataSize <<
'\n';
330 if (data.size() != totalDataSize) {
331 g_log.
error() <<
"Total data size = " << totalDataSize <<
". Parsed data size = " << data.size() <<
'\n';
333 "declared in the Spice XML meta-data.");
342 double monitor2_counts) {
346 m_workspace = std::dynamic_pointer_cast<DataObjects::Workspace2D>(
359 for (
auto count : data) {
363 double error = sqrt(0.5 +
fabs(
static_cast<double>(
count) - 0.5));
373 const std::string &newName,
const std::string &units) {
375 std::string value_str = metadata[oldName];
377 from_string<T>(
value, value_str, std::dec);
403 std::vector<double> trapDiameters = {76.2, 50.8, 76.2, 101.6};
405 double trapDiameterInUse = trapDiameters[1];
407 std::vector<double> trapMotorPositions;
408 trapMotorPositions.emplace_back(boost::lexical_cast<double>(metadata[
"Motor_Positions/trap_y_25mm"]));
409 trapMotorPositions.emplace_back(boost::lexical_cast<double>(metadata[
"Motor_Positions/trap_y_50mm"]));
410 trapMotorPositions.emplace_back(boost::lexical_cast<double>(metadata[
"Motor_Positions/trap_y_76mm"]));
411 trapMotorPositions.emplace_back(boost::lexical_cast<double>(metadata[
"Motor_Positions/trap_y_101mm"]));
414 std::vector<size_t> trapIndexInUse;
415 for (
size_t i = 0; i < trapMotorPositions.size(); i++) {
416 if (trapMotorPositions[i] > 26.0) {
418 trapIndexInUse.emplace_back(i);
422 g_log.
debug() <<
"trapIndexInUse length:" << trapIndexInUse.size() <<
"\n";
425 std::vector<double> trapDiametersInUse;
426 trapDiametersInUse.reserve(trapIndexInUse.size());
427 std::transform(trapIndexInUse.cbegin(), trapIndexInUse.cend(), std::back_inserter(trapDiametersInUse),
428 [&trapDiameters](
const auto index) { return trapDiameters[index]; });
430 g_log.
debug() <<
"trapDiametersInUse length:" << trapDiametersInUse.size() <<
"\n";
433 auto trapDiameterInUseIt = std::max_element(trapDiametersInUse.begin(), trapDiametersInUse.end());
434 if (trapDiameterInUseIt != trapDiametersInUse.end())
435 trapDiameterInUse = *trapDiameterInUseIt;
437 g_log.
debug() <<
"trapDiameterInUse:" << trapDiameterInUse <<
"\n";
439 addRunProperty<double>(
"beam-trap-diameter", trapDiameterInUse,
"mm");
446 m_startTime = DateAndTime(attributes[
"start_time"]);
447 m_endTime = DateAndTime(attributes[
"end_time"]);
454 addRunProperty<std::string>(
"start_time",
m_startTime.toISO8601String(),
"");
455 addRunProperty<std::string>(
"run_start",
m_startTime.toISO8601String(),
"");
461 double sample_thickness;
462 from_string<double>(sample_thickness, metadata[
"Header/Sample_Thickness"], std::dec);
464 g_log.
debug() <<
"sans_spice_xml_format_version >= 1.03 :: sample_thickness "
465 "in mm. Converting to cm...";
466 sample_thickness *= 0.1;
468 addRunProperty<double>(
"sample-thickness", sample_thickness,
"cm");
470 addRunProperty<double>(metadata,
"Header/Sample_Thickness",
"sample-thickness",
"mm");
472 addRunProperty<double>(metadata,
"Header/source_aperture_size",
"source-aperture-diameter",
"mm");
473 addRunProperty<double>(metadata,
"Header/sample_aperture_size",
"sample-aperture-diameter",
"mm");
476 double source_distance;
477 from_string<double>(source_distance, metadata[
"Header/source_distance"], std::dec);
479 g_log.
debug() <<
"sans_spice_xml_format_version >= 1.03 :: source_distance "
480 "in meters. Converting to mm...";
481 source_distance *= 1000.0;
483 addRunProperty<double>(
"source-sample-distance", source_distance,
"mm");
485 addRunProperty<int>(metadata,
"Motor_Positions/nguides",
"number-of-guides",
"");
487 addRunProperty<double>(
"wavelength",
m_wavelength,
"Angstrom");
488 addRunProperty<double>(
"wavelength-spread",
m_dwavelength,
"Angstrom");
491 addRunProperty<double>(metadata,
"Counters/monitor",
"monitor",
"");
492 addRunProperty<double>(metadata,
"Counters/time",
"timer",
"sec");
517 double sample_detector_distance = 0, sample_detector_distance_offset = 0, sample_si_window_distance = 0;
520 if (metadata.find(
"Motor_Positions/sample_det_dist") != metadata.end()) {
522 from_string<double>(sample_detector_distance, metadata[
"Motor_Positions/sample_det_dist"], std::dec);
523 sample_detector_distance *= 1000.0;
524 addRunProperty<double>(
"sample-detector-distance", sample_detector_distance,
"mm");
525 sample_detector_distance_offset =
526 addRunProperty<double>(metadata,
"Header/tank_internal_offset",
"sample-detector-distance-offset",
"mm");
527 sample_si_window_distance =
528 addRunProperty<double>(metadata,
"Header/sample_to_flange",
"sample-si-window-distance",
"mm");
532 from_string<double>(sample_detector_distance, metadata[
"Motor_Positions/flange_det_dist"], std::dec);
533 sample_detector_distance *= 1000.0;
534 addRunProperty<double>(
"sample-detector-distance-offset", 0,
"mm");
535 addRunProperty<double>(
"sample-detector-distance", sample_detector_distance,
"mm");
536 sample_si_window_distance =
537 addRunProperty<double>(metadata,
"Header/sample_to_flange",
"sample-si-window-distance",
"mm");
540 double total_sample_detector_distance;
541 if (metadata.find(
"Motor_Positions/sdd") != metadata.end()) {
544 from_string<double>(total_sample_detector_distance, metadata[
"Motor_Positions/sdd"], std::dec);
545 total_sample_detector_distance *= 1000.0;
546 sample_detector_distance = total_sample_detector_distance;
548 addRunProperty<double>(
"sample-detector-distance-offset", 0,
"mm");
549 addRunProperty<double>(
"sample-detector-distance", sample_detector_distance,
"mm");
550 addRunProperty<double>(
"sample-si-window-distance", 0,
"mm");
552 g_log.
debug() <<
"Sample-Detector-Distance from SDD tag = " << total_sample_detector_distance <<
'\n';
555 total_sample_detector_distance =
556 sample_detector_distance + sample_detector_distance_offset + sample_si_window_distance;
558 addRunProperty<double>(
"total-sample-detector-distance", total_sample_detector_distance,
"mm");
563 p->addValue(DateAndTime::getCurrentTime(), total_sample_detector_distance);
576 from_string<double>(
detectorTranslation, metadata[
"Motor_Positions/detector_trans"], std::dec);
596 loadInst->setPropertyValue(
"InstrumentName", inst_name);
600 }
catch (std::invalid_argument &) {
602 }
catch (std::runtime_error &) {
603 g_log.
information(
"Unable to successfully run LoadInstrument Child Algorithm");
627 g_log.
notice() <<
"Rotating Wing Detector " << angle <<
" degrees." <<
'\n';
634 p->addValue(DateAndTime::getCurrentTime(), angle);
646 if (metadata.find(
"Header/sans_spice_xml_format_version") != metadata.end()) {
double value
The value of the point.
std::map< DeltaEMode::Type, std::string > index
#define DECLARE_FILELOADER_ALGORITHM(classname)
DECLARE_FILELOADER_ALGORITHM should be used in place of the standard DECLARE_ALGORITHM macro when wri...
void declareProperty(std::unique_ptr< Kernel::Property > p, const std::string &doc="") override
Add a property to the list of managed properties.
std::string getPropertyValue(const std::string &name) const override
Get the value of a property as a string.
TypedValue getProperty(const std::string &name) const override
Get the value of a property.
virtual std::shared_ptr< Algorithm > createChildAlgorithm(const std::string &name, const double startProgress=-1., const double endProgress=-1., const bool enableLogging=true, const int &version=-1)
Create a Child Algorithm.
static bool isEmpty(const NumT toCheck)
checks that the value was not set by users, uses the value in empty double/int.
@ Load
allowed here which will be passed to the algorithm
void addLogData(Kernel::Property *p)
Add a log entry.
This class stores information regarding an experimental run as a series of log entries.
A property class for workspaces.
void setBeamTrapRunProperty(std::map< std::string, std::string > &metadata)
Sets the beam trap as Run Property There's several beamstrap position.
const std::string name() const override
Algorithm's name for identification overriding a virtual method.
int confidence(Kernel::FileDescriptor &descriptor) const override
Returns a confidence value that this algorithm can load a file.
static const int nMonitors
Number of monitors.
DataObjects::Workspace2D_sptr m_workspace
void setWavelength(std::map< std::string, std::string > &metadata)
Gets the wavelength and wavelength spread from the metadata and sets them as class attributes.
Mantid::Types::Core::DateAndTime m_endTime
std::pair< int, int > parseDetectorDimensions(const std::string &)
Parse the 2 integers of the form: INT32[192,256].
void runLoadInstrument(const std::string &inst_name, const DataObjects::Workspace2D_sptr &localWorkspace)
Run LoadInstrument Child Algorithm.
double m_wavelength_input
Mantid::Types::Core::DateAndTime m_startTime
void addMetadataAsRunProperties(const std::map< std::string, std::string > &)
Adds map of the form key:value as Workspace run properties.
void detectorTranslation(std::map< std::string, std::string > &metadata)
Puts a numeric series in the log with the value of detector translation.
void detectorDistance(std::map< std::string, std::string > &metadata)
Calculates the detector distances and sets them as Run properties Here fog starts: GPSANS: distance =...
void throwException(Poco::XML::Element *elem, const std::string &name, const std::string &fileName)
This method throws not found error if a element is not found in the xml file.
double m_sansSpiceXmlFormatVersion
std::vector< int > getData(const std::string &)
Parses the data dimensions and stores them as member variables Reads the data and returns a vector.
void init() override
Overwrites Algorithm method.
T addRunProperty(std::map< std::string, std::string > &metadata, const std::string &oldName, const std::string &newName, const std::string &units="")
Inserts a property in the run with a new name!
void setSansSpiceXmlFormatVersion(std::map< std::string, std::string > &metadata)
void setMetadataAsRunProperties(std::map< std::string, std::string > &metadata)
void rotateDetector(const double &)
This will rotate the detector named componentName around z-axis.
Mantid::DataHandling::XmlHandler m_xmlHandler
void exec() override
Overwrites Algorithm method.
double m_wavelength_spread_input
void setInputPropertiesAsMemberProperties()
Get the input algorithm properties and sets them as class attributes.
std::string get_text_from_tag(const std::string &)
std::map< std::string, std::string > get_metadata(const std::vector< std::string > &tags_to_ignore)
Build dictionary {string : string } of all tags in the dictionary Composed tags: / replaced by _.
std::map< std::string, std::string > get_attributes_from_tag(const std::string &)
std::vector< std::string > get_subnodes(const std::string &)
Returns list of sub-nodes for a xpath node For: xpath = //Data/ Returns: Detector ,...
Records the filename and the description of failure.
Exception for when an item is not found in a collection.
Marks code as not implemented yet.
Defines a wrapper around an open file.
const std::string & filename() const
Access the filename.
std::istream & data()
Access the open file stream.
const std::string & extension() const
Access the file extension.
IPropertyManager * setProperty(const std::string &name, const T &value)
Templated method to set the value of a PropertyWithValue.
void debug(const std::string &msg)
Logs at debug level.
void notice(const std::string &msg)
Logs at notice level.
void error(const std::string &msg)
Logs at error level.
void information(const std::string &msg)
Logs at information level.
OptionalBool : Tri-state bool.
static T & Instance()
Return a reference to the Singleton instance, creating it if it does not already exist Creation is do...
A specialised Property class for holding a series of time-value pairs.
Kernel::Logger g_log("ExperimentInfo")
static logger object
std::shared_ptr< MatrixWorkspace > MatrixWorkspace_sptr
shared pointer to the matrix workspace base class
bool from_string(T &t, const std::string &s, std::ios_base &(*f)(std::ios_base &))
void store_value(const DataObjects::Workspace2D_sptr &ws, int specID, double value, double error, double wavelength, double dwavelength)
Convenience function to store a detector value into a given spectrum.
std::shared_ptr< Workspace2D > Workspace2D_sptr
shared pointer to Mantid::DataObjects::Workspace2D
std::unique_ptr< T > create(const P &parent, const IndexArg &indexArg, const HistArg &histArg)
This is the create() method that all the other create() methods call.
int convert(const std::string &A, T &out)
Convert a string into a number.
constexpr double EMPTY_DBL() noexcept
Returns what we consider an "empty" double within a property.
Describes the direction (within an algorithm) of a Property.
@ Output
An output workspace.