Mantid
Loading...
Searching...
No Matches
LoadPreNexusMonitors.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 +
8
9#include "MantidAPI/Axis.h"
16
17#include <boost/lexical_cast.hpp>
18#include <memory>
19
20#include <Poco/DOM/AutoPtr.h>
21#include <Poco/DOM/DOMParser.h>
22#include <Poco/DOM/Document.h>
23#include <Poco/DOM/Element.h>
24#include <Poco/DOM/NodeFilter.h>
25#include <Poco/DOM/NodeIterator.h>
26#include <Poco/DOM/NodeList.h>
27#include <Poco/Path.h>
28#include <Poco/SAX/InputSource.h>
29
30#include <cmath>
31#include <cstdlib>
32#include <fstream>
33#include <iterator>
34
35using Mantid::HistogramData::BinEdges;
36using Mantid::HistogramData::Counts;
37
38namespace Mantid::DataHandling {
39
40// Register the algorithm into the AlgorithmFactory
41DECLARE_ALGORITHM(LoadPreNexusMonitors)
42
43using namespace Mantid::Kernel;
44using namespace Mantid::API;
45
46// Some constants for property names
47static const std::string RUNINFO_FILENAME("RunInfoFilename");
48static const std::string WORKSPACE_OUT("OutputWorkspace");
49
50// A reference to the logger is provided by the base class, it is called g_log.
51// It is used to print out information, warning and error messages
52
54 : Mantid::API::Algorithm(), nMonitors(0), instrument_loaded_correctly(false) {}
55
57 // Filename for the runinfo file.
58 declareProperty(std::make_unique<FileProperty>(RUNINFO_FILENAME, "", FileProperty::Load, "_runinfo.xml"),
59 "The filename of the runinfo file for a particular run. "
60 "Allowed Values are: _runinfo.xml");
61
62 // The output workspace
64 "The workspace to load the monitors into.");
65
66 // Make sure things are initialised.
67 nMonitors = 0;
68}
69
71 // time of flight channel parameters
72 double tmin = 0.0;
73 double tstep = 0.0;
74 int tchannels = 0;
75 std::string instrumentName;
76
77 // Vectors to store monitor parameters
78 std::vector<std::string> monitorFilenames;
79 std::vector<int> monitorIDs;
80
81 // Get the Runinfo filename from the property
82 std::string runinfo_filename = this->getPropertyValue(RUNINFO_FILENAME);
83
84 // TODO: Extract the directory that the runinfo file is in.
85 // Create a Poco Path object for runinfo filename
86 Poco::Path runinfoPath(runinfo_filename, Poco::Path::PATH_GUESS);
87 // Now lets get the directory
88 Poco::Path dirPath(runinfoPath.parent());
89
90 this->g_log.information("Monitor File Dir: " + dirPath.toString());
91
92 // Some XML parsing magic...
93 std::ifstream in(runinfo_filename.c_str());
94 Poco::XML::InputSource src(in);
95
96 Poco::XML::DOMParser parser;
97 Poco::AutoPtr<Poco::XML::Document> pDoc = parser.parse(&src);
98
99 Poco::XML::NodeIterator it(pDoc, Poco::XML::NodeFilter::SHOW_ELEMENT);
100 Poco::XML::Node *pNode = it.nextNode();
101 while (pNode) {
102
103 // Get the beamline name.
104 if (pNode->nodeName() == "RunInfo") {
105 auto *pRunInfoElement = static_cast<Poco::XML::Element *>(pNode);
106 instrumentName = pRunInfoElement->getAttribute("instrument");
107 }
108
109 // Look for the section that contains the binning parameters.
110 // This will end up with using the binning for the last monitor that is
111 // found
112 // TODO: Modify to store (and use) the TCBs for each monitor separately.
113 if (pNode->nodeName() == "BeamMonitorInfo") {
114 // Increment the number of monitors we've found
115 ++nMonitors;
116
117 auto *pE = static_cast<Poco::XML::Element *>(pNode);
118 g_log.debug() << "Beam Monitor " << pE->getAttribute("id") << '\n';
119 g_log.debug() << "\tname: " << pE->getAttribute("name") << '\n';
120 g_log.debug() << "\tdescription: " << pE->getAttribute("description") << '\n';
121
122 // Now lets get the tof binning settings
123 Poco::XML::Element *pTimeChannels = pE->getChildElement("NumTimeChannels");
124 tmin = boost::lexical_cast<double>(pTimeChannels->getAttribute("startbin"));
125 tstep = boost::lexical_cast<double>(pTimeChannels->getAttribute("width"));
126 }
127
128 // Look for the 'DataList' node to get the monitor dims.
129 // TODO: Again we will only use the mast monitor value.
130 if (pNode->nodeName() == "DataList") {
131 // Get a list of the child elements
132 Poco::AutoPtr<Poco::XML::NodeList> pDataListChildren = pNode->childNodes();
133 for (unsigned long i = 0; i < pDataListChildren->length(); ++i) {
134 // We only care about monitors
135 if (pDataListChildren->item(i)->nodeName() == "monitor") {
136 auto *element = static_cast<Poco::XML::Element *>(pDataListChildren->item(i));
137 monitorIDs.emplace_back(boost::lexical_cast<int>(element->getAttribute("id")));
138 monitorFilenames.emplace_back(element->getAttribute("name"));
139 }
140 }
141 }
142
143 // Get the size of the files
144 if (pNode->nodeName() == "FileFormats") {
145 // Get a list of the child elements
146 Poco::AutoPtr<Poco::XML::NodeList> pDataListChildren = pNode->childNodes();
147 for (unsigned long i = 0; i < pDataListChildren->length(); ++i) {
148 // We only care about monitors
149 if (pDataListChildren->item(i)->nodeName() == "monitor") {
150 std::string dims = static_cast<Poco::XML::Element *>(pDataListChildren->item(i))->getAttribute("dims");
151 tchannels = boost::lexical_cast<int>(dims);
152 }
153 }
154 }
155
156 pNode = it.nextNode();
157 }
158
159 g_log.information() << "Found " << nMonitors << " beam monitors.\n";
160
161 g_log.information() << "Number of Time Channels = " << tchannels << '\n';
162
163 // Now lets create the time of flight array.
164 const int numberTimeBins = tchannels + 1;
165 MantidVec time_bins(numberTimeBins);
166 for (int i = 0; i < numberTimeBins; ++i) {
167 time_bins[i] = tmin + (i)*tstep;
168 }
169
170 // Create the new workspace
171 MatrixWorkspace_sptr localWorkspace =
172 WorkspaceFactory::Instance().create("Workspace2D", nMonitors, numberTimeBins, tchannels);
173
174 BinEdges edges(time_bins);
175 for (int i = 0; i < nMonitors; i++) {
176 // Now lets actually read the monitor files..
177 Poco::Path pMonitorFilename(dirPath, monitorFilenames[i]);
178
179 g_log.debug() << "Loading monitor file :" << pMonitorFilename.toString() << '\n';
180
181 Kernel::BinaryFile<uint32_t> monitorFile(pMonitorFilename.toString());
182 // temp buffer for file reading
183 std::vector<uint32_t> buffer = monitorFile.loadAllIntoVector();
184
185 localWorkspace->setHistogram(i, edges, Counts(buffer.begin(), buffer.end()));
186
187 // Just have spectrum number be the same as the monitor number but -ve.
188 auto &spectrum = localWorkspace->getSpectrum(i);
189 spectrum.setSpectrumNo(monitorIDs[i]);
190 spectrum.setDetectorID(-monitorIDs[i]);
191 }
192
193 g_log.debug() << "Setting axis zero to TOF\n";
194
195 // Set the units
196 localWorkspace->getAxis(0)->unit() = UnitFactory::Instance().create("TOF");
197 localWorkspace->setYUnit("Counts");
198 // TODO localWorkspace->setTitle(title);
199
200 // Actually load the instrument
201 this->runLoadInstrument(instrumentName, localWorkspace);
202
203 // Set the property
204 setProperty("OutputWorkspace", localWorkspace);
205}
206
207//-----------------------------------------------------------------------------
213void LoadPreNexusMonitors::runLoadInstrument(const std::string &instrument,
214 const MatrixWorkspace_sptr &localWorkspace) {
215
216 auto loadInst = createChildAlgorithm("LoadInstrument");
217
218 // Now execute the Child Algorithm. Catch and log any error, but don't stop.
219 bool executionSuccessful(true);
220 try {
221 loadInst->setPropertyValue("InstrumentName", instrument);
222 loadInst->setProperty<MatrixWorkspace_sptr>("Workspace", localWorkspace);
223 loadInst->setProperty("RewriteSpectraMap",
224 false); // We have a custom mapping
225 loadInst->execute();
226
227 // Populate the instrument parameters in this workspace - this works around
228 // a bug
229 localWorkspace->populateInstrumentParameters();
230 } catch (std::invalid_argument &e) {
231 g_log.information() << "Invalid argument to LoadInstrument Child Algorithm : " << e.what() << '\n';
232 executionSuccessful = false;
233 } catch (std::runtime_error &e) {
234 g_log.information() << "Unable to successfully run LoadInstrument Child Algorithm : " << e.what() << '\n';
235 executionSuccessful = false;
236 }
237
238 // If loading instrument definition file fails
239 if (!executionSuccessful) {
240 g_log.error() << "Error loading Instrument definition file\n";
241 } else {
242 this->instrument_loaded_correctly = true;
243 }
244}
245
246} // namespace Mantid::DataHandling
#define DECLARE_ALGORITHM(classname)
Definition: Algorithm.h:576
Base class from which all concrete algorithm classes should be derived.
Definition: Algorithm.h:85
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
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
Kernel::Logger & g_log
Definition: Algorithm.h:451
@ Load
allowed here which will be passed to the algorithm
Definition: FileProperty.h:52
A property class for workspaces.
bool instrument_loaded_correctly
Set to true when instrument geometry was loaded.
void init() override
Initialisation code.
void runLoadInstrument(const std::string &instrument, const API::MatrixWorkspace_sptr &localWorkspace)
Load the instrument geometry File.
The BinaryFile template is a helper function for loading simple binary files.
Definition: BinaryFile.h:44
std::vector< T > loadAllIntoVector()
Loads the entire contents of the file into a std::vector.
Definition: BinaryFile.h:145
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 error(const std::string &msg)
Logs at error level.
Definition: Logger.cpp:77
void information(const std::string &msg)
Logs at information level.
Definition: Logger.cpp:105
static T & Instance()
Return a reference to the Singleton instance, creating it if it does not already exist Creation is do...
std::shared_ptr< MatrixWorkspace > MatrixWorkspace_sptr
shared pointer to the matrix workspace base class
static const std::string RUNINFO_FILENAME("RunInfoFilename")
static const std::string WORKSPACE_OUT("OutputWorkspace")
Helper class which provides the Collimation Length for SANS instruments.
std::vector< double > MantidVec
typedef for the data storage used in Mantid matrix workspaces
Definition: cow_ptr.h:172
@ Output
An output workspace.
Definition: Property.h:54