Mantid
Loading...
Searching...
No Matches
LoadHFIRSANS.cpp
Go to the documentation of this file.
1// Mantid Repository : https://github.com/mantidproject/mantid
2//
3// Copyright © 2018 ISIS Rutherford Appleton Laboratory UKRI,
4// NScD Oak Ridge National Laboratory, European Spallation Source,
5// Institut Laue - Langevin & CSNS, Institute of High Energy Physics, CAS
6// SPDX - License - Identifier: GPL - 3.0 +
9#include "MantidAPI/Axis.h"
12#include "MantidAPI/Run.h"
23
24#include <boost/algorithm/string/split.hpp>
25#include <boost/algorithm/string/trim.hpp>
26#include <boost/lexical_cast.hpp>
27#include <boost/regex.hpp>
28#include <memory>
29
31#include <Poco/DOM/DOMParser.h>
32#include <Poco/DOM/Document.h>
33#include <Poco/DOM/Element.h>
34#include <Poco/DOM/Node.h>
35#include <Poco/DOM/NodeList.h>
36#include <Poco/DOM/Text.h>
37#include <Poco/SAX/InputSource.h>
38
39#include <algorithm>
40#include <cmath>
41#include <iostream>
42#include <limits>
43#include <memory>
44#include <sstream>
45#include <string>
46#include <utility>
47#include <vector>
48
49namespace Mantid::DataHandling {
50
53using Types::Core::DateAndTime;
54using namespace Kernel;
55using namespace API;
56using namespace Geometry;
57using namespace DataObjects;
58
59// Register the algorithm into the AlgorithmFactory
61
63 : m_sansSpiceXmlFormatVersion(0.0), m_wavelength(0.0), m_dwavelength(0.0), m_sampleDetectorDistance(0.0) {}
64
72 if (descriptor.extension() != ".xml")
73 return 0;
74
75 std::istream &is = descriptor.data();
76 int confidence(0);
77
78 { // start of inner scope
79 Poco::XML::InputSource src(is);
80 // Set up the DOM parser and parse xml file
81 Poco::XML::DOMParser pParser;
82 Poco::AutoPtr<Poco::XML::Document> pDoc;
83 try {
84 pDoc = pParser.parse(&src);
85 } catch (Poco::Exception &e) {
86 throw Kernel::Exception::FileError("Unable to parse File (" + descriptor.filename() + ")", e.displayText());
87 } catch (...) {
88 throw Kernel::Exception::FileError("Unable to parse File:", descriptor.filename());
89 }
90 // Get pointer to root element
91 Poco::XML::Element *pRootElem = pDoc->documentElement();
92 if (pRootElem) {
93 if (pRootElem->tagName() == "SPICErack") {
94 confidence = 80;
95 }
96 }
97 } // end of inner scope
98
99 return confidence;
100}
101
104 declareProperty(std::make_unique<API::FileProperty>("Filename", "", API::FileProperty::Load, ".xml"),
105 "The name of the input xml file to load");
107 std::make_unique<API::WorkspaceProperty<API::Workspace>>("OutputWorkspace", "", Kernel::Direction::Output),
108 "The name of the Output workspace");
109
110 // Optionally, we can specify the wavelength and wavelength spread and
111 // overwrite the value in the data file (used when the data file is not
112 // populated)
113 auto mustBePositive = std::make_shared<Kernel::BoundedValidator<double>>();
114 mustBePositive->setLower(0.0);
115 declareProperty("Wavelength", EMPTY_DBL(), mustBePositive,
116 "Optional wavelength value to use when loading the data file "
117 "(Angstrom). This value will be used instead of the value "
118 "found in the data file.");
119 declareProperty("WavelengthSpread", EMPTY_DBL(), mustBePositive,
120 "Optional wavelength spread value to use when loading the "
121 "data file (Angstrom). This value will be used instead of "
122 "the value found in the data file.");
123 declareProperty("SampleDetectorDistance", EMPTY_DBL(),
124 "Sample to detector distance to use (overrides meta data), in mm");
125}
126
127/*******************************************************************************
128 * Main method.
129 */
131
132 // Parse the XML metadata
134 setTimes();
138 // ugly hack for Biosans wing detector:
139 // it tests if there is metadata tagged with the wing detector
140 // if so, puts the detector in the right angle
141 if (m_metadata.find("Motor_Positions/det_west_wing_rot") != m_metadata.end()) {
143 }
144 moveDetector();
146 // This needs parameters from IDF! Run load instrument before!
148 setProperty("OutputWorkspace", m_workspace);
149}
150
158 // Set up the XmlHandler handler and parse xml file
159 std::string fileName = getPropertyValue("Filename");
160 try {
161 m_xmlHandler = XmlHandler(fileName);
162 } catch (...) {
163 throw Kernel::Exception::FileError("Unable to parse File:", std::move(fileName));
164 }
167}
168
169/***
170 * 2016/11/09 : There is a new tag sans_spice_xml_format_version in the XML
171 * It identifies changes in the XML format.
172 * Useful to test tags rather than using the date.
173 * @param metadata
174 */
176
177 if (m_metadata.find("Header/sans_spice_xml_format_version") != m_metadata.end()) {
178 m_sansSpiceXmlFormatVersion = boost::lexical_cast<double>(m_metadata["Header/sans_spice_xml_format_version"]);
179 }
180 g_log.debug() << "Sans_spice_xml_format_version == " << m_sansSpiceXmlFormatVersion << "\n";
181}
182
184 // start_time
185 std::map<std::string, std::string> attributes = m_xmlHandler.get_attributes_from_tag("/");
186
187 m_startTime = DateAndTime(attributes["start_time"]);
188 m_endTime = DateAndTime(attributes["end_time"]);
189}
190
195
196 double wavelength_input = getProperty("Wavelength");
197 double wavelength_spread_input = getProperty("WavelengthSpread");
198
199 if (isEmpty(wavelength_input)) {
200 m_wavelength = boost::lexical_cast<double>(m_metadata["Header/wavelength"]);
201 } else {
202 m_wavelength = wavelength_input;
203 }
204
205 if (isEmpty(wavelength_spread_input)) {
206 m_dwavelength = boost::lexical_cast<double>(m_metadata["Header/wavelength_spread"]);
207 // 20160720: New wavelength will be a ratio
208 // UGLY HACK! Comparing dates...
209 DateAndTime changingDate("2016-06-13 00:00:00");
210 if (m_startTime >= changingDate) {
211 g_log.debug() << "Using wavelength spread as a ratio..." << '\n';
213 }
214 } else {
215 m_dwavelength = wavelength_spread_input;
216 }
217
218 g_log.debug() << "Final Wavelength: " << m_wavelength << " :: Wavelength Spread: " << m_dwavelength << '\n';
219}
220
225std::pair<int, int> LoadHFIRSANS::parseDetectorDimensions(const std::string &dims_str) {
226
227 // Read in the detector dimensions from the Detector tag
228
229 std::pair<int, int> dims = std::make_pair(0, 0);
230
231 boost::regex b_re_sig(R"(INT\d+\[(\d+),(\d+)\])");
232 if (boost::regex_match(dims_str, b_re_sig)) {
233 boost::match_results<std::string::const_iterator> match;
234 boost::regex_search(dims_str, match, b_re_sig);
235 // match[0] is the full string
236 Kernel::Strings::convert(match[1], dims.first);
237 Kernel::Strings::convert(match[2], dims.second);
238 }
239 if (dims.first == 0 || dims.second == 0)
240 g_log.notice() << "Could not read in the number of pixels!" << '\n';
241 return dims;
242}
243
248std::vector<int> LoadHFIRSANS::readData(const std::string &dataXpath) {
249
250 // data container
251 std::vector<int> data;
252 unsigned int totalDataSize = 0;
253
254 // let's see how many detectors we have
255 std::vector<std::string> detectors = m_xmlHandler.get_subnodes(dataXpath);
256 g_log.debug() << "Number the detectors found in Xpath " << dataXpath << " = " << detectors.size() << '\n';
257
258 // iterate every detector in the xml file
259 for (const auto &detector : detectors) {
260 std::string detectorXpath = std::string(dataXpath).append("/").append(detector);
261 // type : INT32[192,256]
262 std::map<std::string, std::string> attributes = m_xmlHandler.get_attributes_from_tag(detectorXpath);
263 std::pair<int, int> dims = parseDetectorDimensions(attributes["type"]);
264
265 // Horrible hack:
266 // Some old files had a: //Data/DetectorWing with dimensions:
267 // 16 x 256 = 4096. This must be ignored as it is not in the IDF
268 // The real wing detector is larger than that
269 if (detectorXpath.find("DetectorWing") != std::string::npos && dims.first * dims.second <= 4096)
270 break;
271
272 totalDataSize += dims.first * dims.second;
273 g_log.debug() << "Parsing detector XPath " << detectorXpath << " with dimensions: " << dims.first << " x "
274 << dims.second << " = " << dims.first * dims.second << '\n';
275
276 std::string data_str = m_xmlHandler.get_text_from_tag(detectorXpath);
277 g_log.debug() << "The size of detector contents (xpath = " << detectorXpath << ") is " << data_str.size()
278 << " bytes." << '\n';
279
280 // convert string data into a vector<int>
281 std::stringstream iss(data_str);
282 double number;
283 while (iss >> number) {
284 data.emplace_back(static_cast<int>(number));
285 }
286 g_log.debug() << "Detector XPath: " << detectorXpath
287 << " parsed. Total size of data processed up to now = " << data.size() << " from a total of "
288 << totalDataSize << '\n';
289 }
290
291 if (data.size() != totalDataSize) {
292 g_log.error() << "Total data size = " << totalDataSize << ". Parsed data size = " << data.size() << '\n';
293 throw Kernel::Exception::NotImplementedError("Inconsistent data set: There were more data pixels found than "
294 "declared in the Spice XML meta-data.");
295 }
296 return data;
297}
298
304void LoadHFIRSANS::permuteTubes(std::vector<int> &data) {
305 const std::string &instrumentName = m_metadata["Header/Instrument"];
306
307 if (instrumentName.compare("CG2") == 0 || instrumentName.compare("GPSANS") == 0) {
308 std::vector<int> temp(data.size());
309 size_t nTubes(std::stoul(m_metadata["Header/Number_of_X_Pixels"]));
310 size_t nEightPacks = nTubes / 8;
311 size_t nPixelPerTube(std::stoul(m_metadata["Header/Number_of_Y_Pixels"]));
312 // permutation that takes us from a tube ID in the IDF to a tube ID in the
313 // XML file
314 std::vector<size_t> perm{0, 2, 4, 6, 1, 3, 5, 7};
315 size_t newStartPixelID, oldStartPixelID;
316 for (size_t e = 0; e < nEightPacks; ++e) { // iterate over all eightpacks
317 for (size_t t = 0; t < 8; t++) { // iterate over each tube in an eightpack
318 newStartPixelID = (t + 8 * e) * nPixelPerTube; // t+8*e is the new tube ID
319 oldStartPixelID = (perm[t] + 8 * e) * nPixelPerTube; // perm[t]+8*e is the old tube ID
320 for (size_t p = 0; p < nPixelPerTube; p++) { // copy the "contents of the tube"
321 temp[p + newStartPixelID] = data[p + oldStartPixelID];
322 }
323 }
324 }
325 for (size_t i = 0; i < data.size(); i++) {
326 data[i] = temp[i];
327 }
328 }
329}
330
341void LoadHFIRSANS::storeValue(int specID, double value, double error, double wavelength, double dwavelength) {
342 auto &X = m_workspace->mutableX(specID);
343 auto &Y = m_workspace->mutableY(specID);
344 auto &E = m_workspace->mutableE(specID);
345 // The following is mostly to make Mantid happy by defining a histogram with
346 // a single bin around the neutron wavelength
347 X[0] = wavelength - dwavelength / 2.0;
348 X[1] = wavelength + dwavelength / 2.0;
349 Y[0] = value;
350 E[0] = error;
351 m_workspace->getSpectrum(specID).setSpectrumNo(specID);
352}
353
355
356 std::vector<int> data = readData("//Data");
357 permuteTubes(data);
358
359 int numSpectra = static_cast<int>(data.size()) + m_nMonitors;
360
361 m_workspace = std::dynamic_pointer_cast<DataObjects::Workspace2D>(
362 API::WorkspaceFactory::Instance().create("Workspace2D", numSpectra, 2, 1));
363 m_workspace->setTitle(m_metadata["Header/Scan_Title"]);
364 m_workspace->getAxis(0)->unit() = Kernel::UnitFactory::Instance().create("Wavelength");
365 m_workspace->setYUnit("Counts");
366
367 auto monitorCounts = boost::lexical_cast<double>(m_metadata["Counters/monitor"]);
368 auto countingTime = boost::lexical_cast<double>(m_metadata["Counters/time"]);
369
370 int specID = 0;
371 // Store monitor counts in the beggining
372 storeValue(specID++, monitorCounts, monitorCounts > 0 ? sqrt(monitorCounts) : 0.0, m_wavelength, m_dwavelength);
373
374 storeValue(specID++, countingTime, 0.0, m_wavelength, m_dwavelength);
375
376 // Store detector pixels
377 for (auto count : data) {
378 // Data uncertainties, computed according to the HFIR/IGOR reduction code
379 // The following is what I would suggest instead...
380 // error = count > 0 ? sqrt((double)count) : 0.0;
381 double error = sqrt(0.5 + fabs(static_cast<double>(count) - 0.5));
383 }
384}
385
386template <class T>
387void LoadHFIRSANS::addRunProperty(const std::string &name, const T &value, const std::string &units) {
388 g_log.debug() << "Adding Property to the Run: " << name << " -> " << value << "\n";
389 m_workspace->mutableRun().addProperty(name, value, units, true);
390}
391
392template <class T> void LoadHFIRSANS::addRunTimeSeriesProperty(const std::string &name, const T &value) {
393 g_log.debug() << "Adding Time Series Property to the Run: " << name << " -> " << value << "\n";
394 API::Run &runDetails = m_workspace->mutableRun();
396 p->addValue(DateAndTime::getCurrentTime(), value);
397 runDetails.addLogData(p);
398}
399
416
417 std::vector<double> trapDiameters = {76.2, 50.8, 76.2, 101.6};
418 // default use the shortest trap
419 double trapDiameterInUse = trapDiameters[1];
420
421 std::vector<double> trapMotorPositions;
422 trapMotorPositions.emplace_back(boost::lexical_cast<double>(m_metadata["Motor_Positions/trap_y_25mm"]));
423 trapMotorPositions.emplace_back(boost::lexical_cast<double>(m_metadata["Motor_Positions/trap_y_50mm"]));
424 trapMotorPositions.emplace_back(boost::lexical_cast<double>(m_metadata["Motor_Positions/trap_y_76mm"]));
425 trapMotorPositions.emplace_back(boost::lexical_cast<double>(m_metadata["Motor_Positions/trap_y_101mm"]));
426
427 // Check how many traps are in use (store indexes):
428 std::vector<size_t> trapIndexInUse;
429 for (size_t i = 0; i < trapMotorPositions.size(); i++) {
430 if (trapMotorPositions[i] > 26.0) {
431 // Resting positions are below 25. Make sure we have one trap in use!
432 trapIndexInUse.emplace_back(i);
433 }
434 }
435
436 g_log.debug() << "trapIndexInUse length:" << trapIndexInUse.size() << "\n";
437
438 // store trap diameters in use
439 std::vector<double> trapDiametersInUse;
440 trapDiametersInUse.reserve(trapIndexInUse.size());
441 std::transform(trapIndexInUse.cbegin(), trapIndexInUse.cend(), std::back_inserter(trapDiametersInUse),
442 [&trapDiameters](auto index) { return trapDiameters[index]; });
443
444 g_log.debug() << "trapDiametersInUse length:" << trapDiametersInUse.size() << "\n";
445
446 // The maximum value for the trapDiametersInUse is the trap in use
447 auto trapDiameterInUseIt = std::max_element(trapDiametersInUse.begin(), trapDiametersInUse.end());
448 if (trapDiameterInUseIt != trapDiametersInUse.end())
449 trapDiameterInUse = *trapDiameterInUseIt;
450
451 g_log.debug() << "trapDiameterInUse:" << trapDiameterInUse << "\n";
452
453 addRunProperty<double>("beam-trap-diameter", trapDiameterInUse, "mm");
454}
455
461
462 for (const auto &keyValuePair : m_metadata) {
463 std::string key = keyValuePair.first;
464 std::replace(key.begin(), key.end(), '/', '_');
465 m_workspace->mutableRun().addProperty(key, keyValuePair.second, true);
466 }
467
468 addRunProperty<std::string>("start_time", m_startTime.toISO8601String(), "");
469 addRunProperty<std::string>("run_start", m_startTime.toISO8601String(), "");
470 m_workspace->mutableRun().setStartAndEndTime(m_startTime, m_endTime);
471
473
474 addRunProperty<double>("wavelength", m_wavelength, "Angstrom");
475 addRunProperty<double>("wavelength-spread", m_dwavelength, "Angstrom");
476 addRunProperty<double>("wavelength-spread-ratio", m_dwavelength / m_wavelength);
477
478 addRunProperty<double>("monitor", boost::lexical_cast<double>(m_metadata["Counters/monitor"]));
479 addRunProperty<double>("timer", boost::lexical_cast<double>(m_metadata["Counters/time"]), "sec");
480
481 // XML 1.03: sample thickness is now in meters
482 auto sample_thickness = boost::lexical_cast<double>(m_metadata["Header/Sample_Thickness"]);
483 if (m_sansSpiceXmlFormatVersion >= 1.03) {
484 g_log.debug() << "sans_spice_xml_format_version >= 1.03 :: "
485 "sample_thickness in mm. Converting to cm...";
486 sample_thickness *= 0.1;
487 }
488 addRunProperty<double>("sample-thickness", sample_thickness, "cm");
489
490 addRunProperty<double>("source-aperture-diameter",
491 boost::lexical_cast<double>(m_metadata["Header/source_aperture_size"]), "mm");
492 addRunProperty<double>("source_aperture_diameter",
493 boost::lexical_cast<double>(m_metadata["Header/source_aperture_size"]), "mm");
494
495 addRunProperty<double>("sample-aperture-diameter",
496 boost::lexical_cast<double>(m_metadata["Header/sample_aperture_size"]), "mm");
497 addRunProperty<double>("sample_aperture_diameter",
498 boost::lexical_cast<double>(m_metadata["Header/sample_aperture_size"]), "mm");
499
500 addRunProperty<double>("number-of-guides", boost::lexical_cast<double>(m_metadata["Motor_Positions/nguides"]));
501}
502
507
508 const std::string &instrumentName = m_metadata["Header/Instrument"];
509
510 auto loadInstrumentAlgorithm = createChildAlgorithm("LoadInstrument");
511
512 // Now execute the Child Algorithm. Catch and log any error, but don't stop.
513 try {
514 loadInstrumentAlgorithm->setPropertyValue("InstrumentName", instrumentName);
515 loadInstrumentAlgorithm->setProperty<API::MatrixWorkspace_sptr>("Workspace", m_workspace);
516 loadInstrumentAlgorithm->setProperty("RewriteSpectraMap", Mantid::Kernel::OptionalBool(true));
517 loadInstrumentAlgorithm->execute();
518 } catch (std::invalid_argument &) {
519 g_log.information("Invalid argument to LoadInstrument Child Algorithm");
520 } catch (std::runtime_error &) {
521 g_log.information("Unable to successfully run LoadInstrument Child Algorithm");
522 }
523}
524
529
530 // The angle is negative!
531 double angle = -boost::lexical_cast<double>(m_metadata["Motor_Positions/det_west_wing_rot"]);
532 g_log.notice() << "Rotating Wing Detector " << angle << " degrees." << '\n';
533 addRunTimeSeriesProperty<double>("rotangle", angle);
534}
535
540
541 m_sampleDetectorDistance = getProperty("SampleDetectorDistance");
542
544 // SDD is as input
545 g_log.debug() << "Getting the SampleDetectorDistance = " << m_sampleDetectorDistance
546 << " from the Algorithm input property.\n";
547 } else if (m_metadata.find("Motor_Positions/sdd") != m_metadata.end()) {
548 // Newest version: SDD as a specific tag
549 m_sampleDetectorDistance = boost::lexical_cast<double>(m_metadata["Motor_Positions/sdd"]);
550 m_sampleDetectorDistance *= 1000.0;
551 } else if (m_metadata.find("Motor_Positions/sample_det_dist") != m_metadata.end()) {
552 // Old Format
553 auto sampleDetectorDistancePartial = boost::lexical_cast<double>(m_metadata["Motor_Positions/sample_det_dist"]);
554 sampleDetectorDistancePartial *= 1000.0;
555
556 auto sampleDetectorDistanceOffset = boost::lexical_cast<double>(m_metadata["Header/tank_internal_offset"]);
557
558 auto sampleDetectorDistanceWindow = boost::lexical_cast<double>(m_metadata["Header/sample_to_flange"]);
559
561 sampleDetectorDistancePartial + sampleDetectorDistanceOffset + sampleDetectorDistanceWindow;
562 } else {
563 // New format:
564 m_sampleDetectorDistance = boost::lexical_cast<double>(m_metadata["Motor_Positions/sample_det_dist"]);
565 m_sampleDetectorDistance *= 1000.0;
566 }
567 g_log.debug() << "Sample Detector Distance = " << m_sampleDetectorDistance << " mm." << '\n';
568 addRunProperty<double>("sample-detector-distance", m_sampleDetectorDistance, "mm");
569 addRunProperty<double>("sample_detector_distance", m_sampleDetectorDistance, "mm");
570
571 addRunTimeSeriesProperty<double>("sdd", m_sampleDetectorDistance);
572}
573
578
580 auto translationDistance = boost::lexical_cast<double>(m_metadata["Motor_Positions/detector_trans"]);
581 g_log.debug() << "Detector Translation = " << translationDistance << " mm." << '\n';
582 addRunTimeSeriesProperty<double>("detector-translation", translationDistance);
583}
584
588std::string LoadHFIRSANS::getInstrumentStringParameter(const std::string &parameter) {
589 std::vector<std::string> pars = m_workspace->getInstrument()->getStringParameter(parameter);
590 if (pars.empty()) {
591 g_log.warning() << "Parameter not found: " << parameter << " in the instrument parameter file.\n";
592 return std::string();
593 } else {
594 g_log.debug() << "Found the parameter: " << parameter << " = " << pars[0] << " in the instrument parameter file.\n";
595 return pars[0];
596 }
597}
598
602double LoadHFIRSANS::getInstrumentDoubleParameter(const std::string &parameter) {
603 std::vector<double> pars = m_workspace->getInstrument()->getNumberParameter(parameter);
604 if (pars.empty()) {
605 g_log.warning() << "Parameter not found in the instrument parameter file: " << parameter << "\n";
606 return std::numeric_limits<double>::quiet_NaN();
607 } else {
608 g_log.debug() << "Found the parameter in the instrument parameter file: " << parameter << " = " << pars[0] << "\n";
609 return pars[0];
610 }
611}
624 // First let's try to get source_distance first:
625 auto sourceToSampleDistance = boost::lexical_cast<double>(m_metadata["Header/source_distance"]);
626 // XML 1.03: source distance is now in meters
627 if (m_sansSpiceXmlFormatVersion >= 1.03) {
628 sourceToSampleDistance *= 1000; // convert to mm
629 }
630 if (sourceToSampleDistance <= 0) {
631 g_log.warning() << "Source To Sample Distance: Header/source_distance = " << sourceToSampleDistance
632 << ". Trying to calculate it from the number of guides used and offset." << '\n';
633 const int nGuides = static_cast<int>(boost::lexical_cast<double>(m_metadata["Motor_Positions/nguides"]));
634 // aperture-distances: array from the instrument parameters
635 std::string guidesDistances = getInstrumentStringParameter("aperture-distances");
636 std::vector<std::string> guidesDistancesSplit;
637 boost::split(guidesDistancesSplit, guidesDistances, boost::is_any_of("\t ,"), boost::token_compress_on);
638 sourceToSampleDistance = boost::lexical_cast<double>(guidesDistancesSplit[nGuides]);
639 g_log.debug() << "Number of guides used = " << nGuides << " --> Raw SSD = " << sourceToSampleDistance << "mm.\n";
640 auto sourceToSampleDistanceOffset = boost::lexical_cast<double>(m_metadata["Header/sample_aperture_to_flange"]);
641 g_log.debug() << "SSD offset = " << sourceToSampleDistanceOffset << "mm.\n";
642 sourceToSampleDistance -= sourceToSampleDistanceOffset;
643 }
644 g_log.information() << "Source To Sample Distance = " << sourceToSampleDistance << "mm.\n";
645 return sourceToSampleDistance;
646}
647
652
653 double sourceToSampleDistance = getSourceToSampleDistance();
654 addRunProperty<double>("source-sample-distance", sourceToSampleDistance, "mm");
655 addRunProperty<double>("source_sample_distance", sourceToSampleDistance, "mm");
656
657 const auto sampleAperture = boost::lexical_cast<double>(m_metadata["Header/sample_aperture_size"]);
658 const auto sourceAperture = boost::lexical_cast<double>(m_metadata["Header/source_aperture_size"]);
659 g_log.debug() << "Computing beam diameter. m_sampleDetectorDistance=" << m_sampleDetectorDistance
660 << " SourceToSampleDistance=" << sourceToSampleDistance << " sourceAperture= " << sourceAperture
661 << " sampleAperture=" << sampleAperture << "\n";
662
663 const double beamDiameter =
664 m_sampleDetectorDistance / sourceToSampleDistance * (sourceAperture + sampleAperture) + sampleAperture;
665 addRunProperty<double>("beam-diameter", beamDiameter, "mm");
666}
667
668} // namespace Mantid::DataHandling
std::string name
Definition Run.cpp:60
double value
The value of the point.
Definition FitMW.cpp:51
double error
std::map< DeltaEMode::Type, std::string > index
#define fabs(x)
Definition Matrix.cpp:22
int count
counter
Definition Matrix.cpp:37
#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.
Kernel::Logger & g_log
Definition Algorithm.h:422
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.
Definition LogManager.h:127
This class stores information regarding an experimental run as a series of log entries.
Definition Run.h:35
A property class for workspaces.
This algorithm loads a SPICE2D file for HFIR SANS into a workspace.
void permuteTubes(std::vector< int > &data)
Reorder data to take into account that the sequence of tubes in the XML file is different than the se...
void storeMetaDataIntoWS()
Add all metadata parsed values as log entries Add any other metadata needed.
std::pair< int, int > parseDetectorDimensions(const std::string &dims_str)
Parse the 2 integers of the form: INT32[192,256].
void addRunProperty(const std::string &name, const T &value, const std::string &units="")
static const int m_nMonitors
Number of monitors.
void runLoadInstrument()
Run the Child Algorithm LoadInstrument.
Mantid::Types::Core::DateAndTime m_startTime
DataObjects::Workspace2D_sptr m_workspace
const std::vector< std::string > m_tags_to_ignore
void setBeamTrapRunProperty()
Sets the beam trap as Run Property There's several beamstrap position.
void rotateDetector()
This will rotate the detector named componentName around z-axis.
double getSourceToSampleDistance()
Source to Detector Distance is already calculated in the metadata tag source_distance (if source_dist...
void setWavelength()
Sets the wavelength as class atributes.
std::vector< int > readData(const std::string &dataXpath="//Data")
Loads the data from the XML file.
void init() override
Overwrites Algorithm method.
double getInstrumentDoubleParameter(const std::string &parameter)
From the parameters file get a double parameter.
Mantid::DataHandling::XmlHandler m_xmlHandler
void moveDetector()
Places the detector at the right sample_detector_distance.
void exec() override
Overwrites Algorithm method.
void setDetectorDistance()
Calculates the detector distances and sets them as Run properties.
std::string getInstrumentStringParameter(const std::string &parameter)
From the parameters file get a string parameter.
std::map< std::string, std::string > m_metadata
int confidence(Kernel::FileDescriptor &descriptor) const override
Returns a confidence value that this algorithm can load a file.
const std::string name() const override
Algorithm's name for identification overriding a virtual method.
void addRunTimeSeriesProperty(const std::string &name, const T &value)
void storeValue(int specID, double value, double error, double wavelength, double dwavelength)
Convenience function to store a detector value into a given spectrum.
void setBeamDiameter()
Compute beam diameter at the detector.
Mantid::Types::Core::DateAndTime m_endTime
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.
Definition Exception.h:98
Marks code as not implemented yet.
Definition Exception.h:138
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.
Definition Logger.cpp:145
void notice(const std::string &msg)
Logs at notice level.
Definition Logger.cpp:126
void error(const std::string &msg)
Logs at error level.
Definition Logger.cpp:108
void warning(const std::string &msg)
Logs at warning level.
Definition Logger.cpp:117
void information(const std::string &msg)
Logs at information level.
Definition Logger.cpp:136
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.
std::shared_ptr< MatrixWorkspace > MatrixWorkspace_sptr
shared pointer to the matrix workspace base class
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.
Definition Strings.cpp:696
constexpr double EMPTY_DBL() noexcept
Returns what we consider an "empty" double within a property.
Definition EmptyValues.h:42
Describes the direction (within an algorithm) of a Property.
Definition Property.h:50
@ Output
An output workspace.
Definition Property.h:54