17#include <nexus/NeXusFile.hpp>
18#include <nexus/NeXusException.hpp>
23#include <Poco/Exception.h>
27using namespace ::
NeXus;
38 : m_makeNexusCopy(false), m_instrumentLoadedCorrectly(false), m_logsLoadedCorrectly(false) {
40 setDeprecationDate(
"2021-09-14");
67 std::vector<std::string> extensions{
".nxs",
".h5"};
70 "The name of the NeXus file to append geometry to.");
75 "Copy the NeXus file first before appending (optional, default True).");
83 g_log.
warning() <<
"This is intended as a proof of principle and not a long "
84 "term implementation.\n";
85 g_log.
warning() <<
"(the created arrays in the NeXus file will have the '_new' suffix)\n";
97 if (originalFile.exists()) {
98 Poco::File destinationFile(Poco::Path(Poco::Path::temp(), originalPath.getFileName()));
101 originalFile.copyTo(destinationFile.path());
104 }
catch (Poco::FileAccessDeniedException &) {
105 throw std::runtime_error(
"A Problem occurred in making a copy of the "
106 "NeXus file. Failed to copy " +
107 originalFile.path() +
" to " + destinationFile.path() +
108 ". Please check file permissions.");
111 g_log.
error() <<
"Cannot copy a file that doesn't exist! (" << originalFile.path() <<
").\n";
117 throw std::runtime_error(
"The specified NeXus file (" +
m_filename +
") is not writable.");
125 throw std::runtime_error(
"Failed to get instrument name from " +
m_filename +
126 ". Can't identify instrument definition file.");
143 g_log.
debug() <<
"Run LoadNexusLogs Child Algorithm.\n";
147 throw std::runtime_error(
"Failed to run LoadNexusLogs Child Algorithm.");
150 g_log.
debug() <<
"Run LoadInstrument Child Algorithm.\n";
154 throw std::runtime_error(
"Failed to run LoadInstrument Child Algorithm.");
158 const size_t numDetectors =
ws->getInstrument()->getDetectorIDs().size();
174 std::map<std::string, std::string>::const_iterator root_iter;
175 std::map<std::string, std::string> entries = nxfile.getEntries();
177 for (root_iter = entries.begin(); root_iter != entries.end(); ++root_iter) {
179 if (root_iter->second ==
"NXentry") {
180 nxfile.openGroup(root_iter->first,
"NXentry");
183 std::map<std::string, std::string> entry_items = nxfile.getEntries();
185 std::map<std::string, std::string>::const_iterator entry_iter;
187 for (entry_iter = entry_items.begin(); entry_iter != entry_items.end(); ++entry_iter) {
189 if (entry_iter->second ==
"NXinstrument") {
191 nxfile.openGroup(entry_iter->first,
"NXinstrument");
192 std::map<std::string, std::string> instr_items = nxfile.getEntries();
193 std::map<std::string, std::string>::const_iterator instr_iter;
194 for (instr_iter = instr_items.begin(); instr_iter != instr_items.end(); ++instr_iter) {
196 if (instr_iter->second ==
"NXdetector") {
197 g_log.
debug() <<
"Detector called '" << instr_iter->first <<
"' found.\n";
198 std::string bankName = instr_iter->first;
199 std::vector<Geometry::IDetector_const_sptr> dets;
200 ws->getInstrument()->getDetectorsInBank(dets, bankName);
203 nxfile.openGroup(bankName,
"NXdetector");
207 std::vector<int> pixel_id;
208 std::vector<double> distance;
209 std::vector<double> polar_angle;
210 std::vector<double> azimuthal_angle;
212 pixel_id.reserve(dets.size());
213 distance.reserve(dets.size());
214 polar_angle.reserve(dets.size());
215 azimuthal_angle.reserve(dets.size());
217 for (
auto &det : dets) {
218 pixel_id.emplace_back(det->getID());
219 distance.emplace_back(det->getDistance(*sample));
220 azimuthal_angle.emplace_back(det->getPhi());
221 polar_angle.emplace_back(
ws->detectorTwoTheta(*det));
225 nxfile.writeData(
"pixel_id_new", pixel_id);
228 nxfile.writeData(
"distance_new", distance);
229 nxfile.openData(
"distance_new");
230 nxfile.putAttr(
"units",
"metre");
234 nxfile.writeData(
"polar_angle_new", polar_angle);
235 nxfile.openData(
"polar_angle_new");
236 nxfile.putAttr(
"units",
"radian");
240 nxfile.writeData(
"azimuthal_angle_new", azimuthal_angle);
241 nxfile.openData(
"azimuthal_angle_new");
242 nxfile.putAttr(
"units",
"radian");
249 throw std::runtime_error(
"Could not find any detectors for the bank named " + bankName +
250 " that is listed in the NeXus file."
251 "Check that it exists in the Instrument Definition File.");
260 else if (entry_iter->second ==
"NXmonitor") {
261 g_log.
debug() <<
"Monitor called '" << entry_iter->first <<
"' found.\n";
262 nxfile.openGroup(entry_iter->first,
"NXmonitor");
269 double source_monitor = source->getDistance(*monitor);
270 double source_sample = source->getDistance(*sample);
272 g_log.
debug() <<
"source->monitor=" << source_monitor <<
'\n';
273 g_log.
debug() <<
"source->sample=" << source_sample <<
'\n';
274 g_log.
debug() <<
"sample->monitor=" << (source_monitor - source_sample) <<
'\n';
277 nxfile.writeData(
"distance_new", (source_monitor - source_sample));
278 nxfile.openData(
"distance_new");
279 nxfile.putAttr(
"units",
"metre");
287 g_log.
error() <<
"There are no NXentry nodes in the specified NeXus file.\n";
299 std::string instrument;
302 ::NeXus::File nxfile(nxfilename);
304 std::map<std::string, std::string> entries = nxfile.getEntries();
307 nxfile.openGroup(entries.begin()->first,
"NXentry");
308 g_log.
debug() <<
"Using entry '" << entries.begin()->first <<
"' to determine instrument name.\n";
310 nxfile.openGroup(
"instrument",
"NXinstrument");
312 nxfile.openData(
"name");
313 instrument = nxfile.getStrData();
314 }
catch (::NeXus::Exception &) {
321 g_log.
debug() <<
" Instrument name read from NeXus file is " << instrument <<
'\n';
341 bool executionSuccessful(
true);
343 loadInst->setPropertyValue(
"Filename", idf_filename);
345 loadInst->setProperty(
"RewriteSpectraMap",
OptionalBool(
false));
347 }
catch (std::invalid_argument &e) {
350 executionSuccessful =
false;
351 }
catch (std::runtime_error &e) {
354 executionSuccessful =
false;
358 if (!executionSuccessful) {
361 return executionSuccessful;
377 bool executionSuccessful(
true);
380 loadLogs->setPropertyValue(
"Filename", nexusFileName);
382 loadLogs->executeAsChildAlg();
383 }
catch (std::invalid_argument &e) {
386 executionSuccessful =
false;
387 }
catch (std::runtime_error &) {
389 executionSuccessful =
false;
392 return executionSuccessful;
#define DECLARE_ALGORITHM(classname)
Base class from which all concrete algorithm classes should be derived.
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.
void progress(double p, const std::string &msg="", double estimatedTime=0.0, int progressPrecision=0)
Sends ProgressNotification.
Kernel::Logger & getLogger() const
Returns a reference to the logger.
@ Load
allowed here which will be passed to the algorithm
static std::string getInstrumentFilename(const std::string &instrumentName, const std::string &date="")
Get the IDF using the instrument name and date.
Helper class for reporting progress from algorithms.
SNSAppendGeometryToNexus : Appends geometry information to a NeXus file.
std::string m_filename
The filename of the NeXus file to append geometry info to.
API::MatrixWorkspace_sptr ws
The workspace to load instrument and logs.
std::string m_instrument
Instrument name.
std::string m_idf_filename
IDF filename.
bool m_instrumentLoadedCorrectly
Was the instrument loaded?
std::string getInstrumentName(const std::string &nxfilename)
Get the instrument name from the NeXus file.
bool m_logsLoadedCorrectly
Were the logs loaded?
int version() const override
Algorithm's version for identification.
bool runLoadInstrument(const std::string &idf_filename, const API::MatrixWorkspace_sptr &localWorkspace, Algorithm *alg)
Run LoadInstrument as a Child Algorithm.
~SNSAppendGeometryToNexus() override
Destructor.
const std::string category() const override
Algorithm's category for identification.
bool m_makeNexusCopy
Are we going to make a copy of the NeXus file to operate on ?
void init() override
Initialize the algorithm's properties.
const std::string name() const override
Algorithm's name for identification.
static bool runLoadNexusLogs(const std::string &nexusFileName, const API::MatrixWorkspace_sptr &localWorkspace, Algorithm *alg)
Load logs from the NeXus file.
void exec() override
Execute the algorithm.
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 warning(const std::string &msg)
Logs at warning level.
void information(const std::string &msg)
Logs at information level.
OptionalBool : Tri-state bool.
The concrete, templated class for properties.
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
std::shared_ptr< const IComponent > IComponent_const_sptr
Typdef of a shared pointer to a const IComponent.
std::shared_ptr< const Instrument > Instrument_const_sptr
Shared pointer to an const instrument object.
@ Input
An input workspace.