Mantid
Loading...
Searching...
No Matches
LoadMuonNexusV2.cpp
Go to the documentation of this file.
1// Mantid Repository : https://github.com/mantidproject/mantid
2//
3// Copyright © 2020 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#include "MantidAPI/Axis.h"
11#include "MantidAPI/TableRow.h"
22#include "MantidKernel/Unit.h"
25
26#include <vector>
27
28namespace Mantid::DataHandling {
29
31
32using namespace Kernel;
33using namespace API;
34using namespace NeXus;
35using namespace HistogramData;
36using std::size_t;
37using namespace DataObjects;
38
39namespace NeXusEntry {
40const std::string RAWDATA{"/raw_data_1"};
41const std::string DEFINITION{"/raw_data_1/definition"};
42const std::string BEAMLINE{"/raw_data_1/beamline"};
43} // namespace NeXusEntry
44
47 : m_filename(), m_entrynumber(0), m_isFileMultiPeriod(false), m_multiPeriodsLoaded(false) {}
48
56 // Without this entry we cannot use LoadISISNexus
57 if (!descriptor.isEntry(NeXusEntry::RAWDATA, "NXentry")) {
58 return 0;
59 }
60
61 // Check if beamline entry exists beneath raw_data_1 - /raw_data_1/beamline
62 // Necessary to differentiate between ISIS and PSI nexus files.
63 if (!descriptor.isEntry(NeXusEntry::BEAMLINE))
64 return 0;
65
66 // Check if Muon source in definition entry
67 if (!descriptor.isEntry(NeXusEntry::DEFINITION))
68 return 0;
69
70 ::NeXus::File file(descriptor.getFilename());
71 file.openPath(NeXusEntry::DEFINITION);
72 std::string def = file.getStrData();
73 if (def == "muonTD" || def == "pulsedTD") {
74 return 82; // have to return 82 to "beat" the LoadMuonNexus2 algorithm,
75 // which returns 81 for this file as well
76 } else {
77 return 0;
78 }
79}
82
83 std::vector<std::string> extensions{".nxs", ".nxs_v2"};
84 declareProperty(std::make_unique<FileProperty>("Filename", "", FileProperty::Load, extensions),
85 "The name of the Nexus file to load");
86
87 declareProperty(std::make_unique<WorkspaceProperty<Workspace>>("OutputWorkspace", "", Direction::Output),
88 "The name of the workspace to be created as the output of the\n"
89 "algorithm. For multiperiod files, one workspace will be\n"
90 "generated for each period");
91
92 auto mustBePositiveSpectra = std::make_shared<BoundedValidator<specnum_t>>();
93 mustBePositiveSpectra->setLower(0);
94 declareProperty("SpectrumMin", static_cast<specnum_t>(0), mustBePositiveSpectra);
95 declareProperty("SpectrumMax", static_cast<specnum_t>(EMPTY_INT()), mustBePositiveSpectra);
96 declareProperty(std::make_unique<ArrayProperty<specnum_t>>("SpectrumList"));
97 auto mustBePositive = std::make_shared<BoundedValidator<int64_t>>();
98 mustBePositive->setLower(0);
99 declareProperty("EntryNumber", static_cast<int64_t>(0), mustBePositive,
100 "0 indicates that every entry is loaded, into a separate "
101 "workspace within a group. "
102 "A positive number identifies one entry to be loaded, into "
103 "one workspace");
104
105 std::vector<std::string> FieldOptions{"Transverse", "Longitudinal"};
106 declareProperty("MainFieldDirection", "Transverse", std::make_shared<StringListValidator>(FieldOptions),
107 "Output the main field direction if specified in Nexus file "
108 "(default longitudinal).",
110
111 declareProperty("TimeZero", 0.0, "Time zero in units of micro-seconds (default to 0.0)", Direction::Output);
112 declareProperty("FirstGoodData", 0.0, "First good data in units of micro-seconds (default to 0.0)",
114 declareProperty("LastGoodData", 0.0, "Last good data in the OutputWorkspace's spectra", Kernel::Direction::Output);
115
116 declareProperty(std::make_unique<ArrayProperty<double>>("TimeZeroList", Direction::Output),
117 "A vector of time zero values");
118
120 std::make_unique<WorkspaceProperty<Workspace>>("TimeZeroTable", "", Direction::Output, PropertyMode::Optional),
121 "TableWorkspace containing time zero values per spectra.");
122
123 declareProperty("CorrectTime", true, "Boolean flag controlling whether time should be corrected by timezero.",
125
127 std::make_unique<WorkspaceProperty<Workspace>>("DeadTimeTable", "", Direction::Output, PropertyMode::Optional),
128 "Table or a group of tables containing detector dead times.");
129
130 declareProperty(std::make_unique<WorkspaceProperty<Workspace>>("DetectorGroupingTable", "", Direction::Output,
132 "Table or a group of tables with information about the "
133 "detector grouping.");
134}
136 // prepare nexus entry
137 m_entrynumber = getProperty("EntryNumber");
138 m_filename = getPropertyValue("Filename");
139 NXRoot root(m_filename);
141 // Create MuonNexusV2 nexus loader
142 m_nexusLoader = std::make_unique<LoadMuonNexusV2NexusHelper>(entry);
144
145 // Execute child algorithm LoadISISNexus2
146 auto outWS = runLoadISISNexus();
147 // Create appropriate loading strategy
149 m_loadMuonStrategy->loadMuonLogData();
150 m_loadMuonStrategy->loadGoodFrames();
151 auto correctTime = getProperty("CorrectTime");
152 if (correctTime) {
153 m_loadMuonStrategy->applyTimeZeroCorrection();
154 }
155 // Grouping info should be returned if user has set the property
156 if (!getPropertyValue("DetectorGroupingTable").empty()) {
157 auto loadedGrouping = m_loadMuonStrategy->loadDetectorGrouping();
158 setProperty("DetectorGroupingTable", loadedGrouping);
159 };
160 // Deadtime table should be returned if user has set the property
161 auto deadtimeTable = m_loadMuonStrategy->loadDeadTimeTable();
162 if (!getPropertyValue("DeadTimeTable").empty()) {
163 setProperty("DeadTimeTable", deadtimeTable);
164 }
165
166 // Time Zero table should be returned if found
167 if (!getPropertyValue("TimeZerotable").empty()) {
168 // Create table and set property
169 auto timeZeroTable = m_loadMuonStrategy->getTimeZeroTable();
170 setProperty("TimeZeroTable", timeZeroTable);
171 }
172}
173
179 int numberOfPeriods = m_nexusLoader->getNumberOfPeriods();
180 if (numberOfPeriods > 1) {
181 m_isFileMultiPeriod = true;
182 if (m_entrynumber == 0) {
184 }
185 } else {
186 m_isFileMultiPeriod = false;
187 m_multiPeriodsLoaded = false;
188 }
189}
196 // Here we explicit set the number of OpenMP threads, as by default
197 // LoadISISNexus spawns up a large number of threads,
198 // which is unnecessary for the size (~100 spectra) of workspaces seen here.
199 // Through profiling it was found that a single threaded call to LoadISISNexus
200 // was quicker due to the overhead of setting up the threads, which outweighs
201 // the cost of the resulting operations.
202 // To prevent the omp_set_num_threads call having side effects, we use a RAII
203 // pattern to restore the default behavior once runLoadISISNexus is complete.
204 struct ScopedNumThreadsSetter {
205 ScopedNumThreadsSetter(const int numThreads) {
206 (void)numThreads; // Treat compiler warning in OSX
207 globalNumberOfThreads = PARALLEL_GET_MAX_THREADS;
208 PARALLEL_SET_NUM_THREADS(numThreads);
209 }
210 ~ScopedNumThreadsSetter() { PARALLEL_SET_NUM_THREADS(globalNumberOfThreads); }
211 int globalNumberOfThreads;
212 };
213 ScopedNumThreadsSetter restoreDefaultThreadsOnExit(1);
214 auto childAlg = createChildAlgorithm("LoadISISNexus", 0, 1, true, 2);
215 declareProperty("LoadMonitors", "Exclude"); // we need to set this property
216 auto ISISLoader = std::dynamic_pointer_cast<API::Algorithm>(childAlg);
217 ISISLoader->copyPropertiesFrom(*this);
218 ISISLoader->execute();
219 this->copyPropertiesFrom(*ISISLoader);
220 Workspace_sptr outWS = getProperty("OutputWorkspace");
222 loadPeriodInfo(*outWS);
223 return outWS;
224}
229 // Check if single or multi period file and create appropriate loading
230 // strategy
232 WorkspaceGroup_sptr workspaceGroup = std::dynamic_pointer_cast<WorkspaceGroup>(workspace);
233 assert(workspaceGroup);
234 auto numberHistograms = std::dynamic_pointer_cast<Workspace2D>(workspaceGroup->getItem(0))->getNumberHistograms();
235 loadMuonProperties(numberHistograms);
237 std::make_unique<MultiPeriodLoadMuonStrategy>(g_log, m_filename, *m_nexusLoader, *workspaceGroup);
238
239 } else {
240 // we just have a single workspace
241 Workspace2D_sptr workspace2D = std::dynamic_pointer_cast<Workspace2D>(workspace);
242 assert(workspace2D);
243 // Load Muon specific properties
244 loadMuonProperties(workspace2D->getNumberHistograms());
245 m_loadMuonStrategy = std::make_unique<SinglePeriodLoadMuonStrategy>(
246 g_log, m_filename, *m_nexusLoader, *workspace2D, static_cast<int>(m_entrynumber), m_isFileMultiPeriod);
247 }
248}
253void LoadMuonNexusV2::loadMuonProperties(size_t numSpectra) {
254
255 std::string mainFieldDirection = m_nexusLoader->loadMainFieldDirectionFromNexus();
256 setProperty("MainFieldDirection", mainFieldDirection);
257
258 double timeZero = m_nexusLoader->loadTimeZeroFromNexusFile();
259 setProperty("timeZero", timeZero);
260
261 auto firstGoodData = m_nexusLoader->loadFirstGoodDataFromNexus();
262 setProperty("FirstGoodData", firstGoodData);
263
264 auto lastGoodData = m_nexusLoader->loadLastGoodDataFromNexus();
265 setProperty("LastGoodData", lastGoodData);
266
267 auto timeZeroVector = m_nexusLoader->loadTimeZeroListFromNexusFile(numSpectra);
268 setProperty("TimeZeroList", timeZeroVector);
269}
270
271/*
272Changes the unit of the time axis, which is incorrect due to being loaded using
273LoadISISNexus
274*/
276 auto newUnit = std::dynamic_pointer_cast<Kernel::Units::Label>(Kernel::UnitFactory::Instance().create("Label"));
277 newUnit->setLabel("Time", Kernel::Units::Symbol::Microsecond);
278 auto workspaceGroup = dynamic_cast<WorkspaceGroup *>(&workspace);
279 if (workspaceGroup) {
280 for (int i = 0; i < workspaceGroup->getNumberOfEntries(); ++i) {
281 auto workspace2D = std::dynamic_pointer_cast<Workspace2D>(workspaceGroup->getItem(i));
282 workspace2D->getAxis(0)->unit() = newUnit;
283 }
284 } else {
285 auto &workspace2D = dynamic_cast<Workspace2D &>(workspace);
286 workspace2D.getAxis(0)->unit() = newUnit;
287 }
288}
290 // get value
291 int numberOfPeriods = m_nexusLoader->getNumberOfPeriods();
292 auto labels = m_nexusLoader->getPeriodLabels();
293 auto sequences = m_nexusLoader->getPeriodSequenceString(numberOfPeriods);
294 auto types = m_nexusLoader->getPeriodTypes(numberOfPeriods);
295 auto requested = m_nexusLoader->getPeriodFramesRequested(numberOfPeriods);
296 auto rawFrames = m_nexusLoader->getPeriodRawFrames(numberOfPeriods);
297 auto output = m_nexusLoader->getPeriodOutput(numberOfPeriods);
298 auto counts = m_nexusLoader->getPeriodTotalCounts(numberOfPeriods);
299 // put values into workspaces
300 auto workspaceGroup = dynamic_cast<WorkspaceGroup *>(&workspace);
301 if (workspaceGroup) {
302 for (int i = 0; i < workspaceGroup->getNumberOfEntries(); ++i) {
303 auto workspace2D = std::dynamic_pointer_cast<Workspace2D>(workspaceGroup->getItem(i));
304 auto &run = workspace2D->mutableRun();
305 run.addProperty("period_labels", labels);
306 run.addProperty("period_sequences", sequences);
307 run.addProperty("period_type", types);
308 run.addProperty("frames_period_requested", requested);
309 run.addProperty("frames_period_raw", rawFrames);
310 run.addProperty("period_output", output);
311 run.addProperty("total_counts_period", counts);
312 }
313 } else {
314 auto &workspace2D = dynamic_cast<Workspace2D &>(workspace);
315 auto &run = workspace2D.mutableRun();
316 run.addProperty("period_labels", labels);
317 run.addProperty("period_sequences", sequences);
318 run.addProperty("period_type", types);
319 run.addProperty("frames_period_requested", requested);
320 run.addProperty("frames_period_raw", rawFrames);
321 run.addProperty("period_output", output);
322 run.addProperty("total_counts_period", counts);
323 }
324}
325
326} // namespace Mantid::DataHandling
IPeaksWorkspace_sptr workspace
Definition: IndexPeaks.cpp:114
#define PARALLEL_SET_NUM_THREADS(MaxCores)
#define PARALLEL_GET_MAX_THREADS
#define DECLARE_NEXUS_HDF5_FILELOADER_ALGORITHM(classname)
DECLARE_NEXUS_HDF5_FILELOADER_ALGORITHM should be used in place of the standard DECLARE_ALGORITHM mac...
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 void copyPropertiesFrom(const Algorithm &alg)
Make m_properties point to the same PropertyManager as alg.m_properties.
Definition: Algorithm.h:332
const std::shared_ptr< Kernel::Unit > & unit() const
The unit for this axis.
Definition: Axis.cpp:28
Run & mutableRun()
Writable version of the run object.
@ Load
allowed here which will be passed to the algorithm
Definition: FileProperty.h:52
void addProperty(Kernel::Property *prop, bool overwrite=false)
Add data to the object in the form of a property.
Definition: LogManager.h:79
virtual Axis * getAxis(const std::size_t &axisIndex) const
Get a non owning pointer to a workspace axis.
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) override
Create a Child Algorithm.
Class to hold a set of workspaces.
A property class for workspaces.
Base Workspace Abstract Class.
Definition: Workspace.h:30
std::unique_ptr< LoadMuonStrategy > m_loadMuonStrategy
void isEntryMultiPeriod()
Determines whether the file is multi period If multi period the function determines whether multi per...
std::string m_filename
The name and path of the input file.
void applyTimeAxisUnitCorrection(API::Workspace &workspace)
std::unique_ptr< LoadMuonNexusV2NexusHelper > m_nexusLoader
void chooseLoaderStrategy(const API::Workspace_sptr &workspace)
Determines the loading strategy used by the Algorithm.
LoadMuonNexusV2()
Empty default constructor.
int64_t m_entrynumber
The number of the input entry.
void init() override
Overwrites Algorithm method.
void loadMuonProperties(size_t numSpectra)
Loads Muon specific data from the nexus entry and sets the appropriate output properties.
void execLoader() override
Overwrites Algorithm method.
int confidence(Kernel::NexusHDF5Descriptor &descriptor) const override
Returns a confidence value that this algorithm can load a file.
API::Workspace_sptr runLoadISISNexus()
Runs the child algorithm LoadISISNexus, which loads data into an output workspace.
void loadPeriodInfo(API::Workspace &workspace)
Concrete workspace implementation.
Definition: Workspace2D.h:29
Support for a property that holds an array of values.
Definition: ArrayProperty.h:28
IPropertyManager * setProperty(const std::string &name, const T &value)
Templated method to set the value of a PropertyWithValue.
std::string getFilename() const noexcept
Returns a copy of the current file name.
bool isEntry(const std::string &entryName, const std::string &groupClass) const noexcept
Checks if a full-path entry exists for a particular groupClass in a Nexus dataset.
static T & Instance()
Return a reference to the Singleton instance, creating it if it does not already exist Creation is do...
static const UnitLabel Microsecond
Microsecond.
Implements NXentry Nexus class.
Definition: NexusClasses.h:898
Implements NXroot Nexus class.
Definition: NexusClasses.h:922
NXEntry openEntry(const std::string &name)
Opens an entry – a topmost Nexus class.
Definition: NexusClasses.h:939
std::shared_ptr< WorkspaceGroup > WorkspaceGroup_sptr
shared pointer to Mantid::API::WorkspaceGroup
std::shared_ptr< Workspace > Workspace_sptr
shared pointer to Mantid::API::Workspace
Definition: Workspace_fwd.h:20
Kernel::Logger g_log("ExperimentInfo")
static logger object
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.
constexpr int EMPTY_INT() noexcept
Returns what we consider an "empty" integer within a property.
Definition: EmptyValues.h:25
int32_t specnum_t
Typedef for a spectrum Number.
Definition: IDTypes.h:16
@ Input
An input workspace.
Definition: Property.h:53
@ Output
An output workspace.
Definition: Property.h:54