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