LoadMuonNexus.cpp 7.89 KB
Newer Older
1
2
3
// Mantid Repository : https://github.com/mantidproject/mantid
//
// Copyright © 2018 ISIS Rutherford Appleton Laboratory UKRI,
4
5
//   NScD Oak Ridge National Laboratory, European Spallation Source,
//   Institut Laue - Langevin & CSNS, Institute of High Energy Physics, CAS
6
// SPDX - License - Identifier: GPL - 3.0 +
7
8
9
//----------------------------------------------------------------------
// Includes
//----------------------------------------------------------------------
10
#include "MantidDataHandling/LoadMuonNexus.h"
11
#include "MantidAPI/FileProperty.h"
12
#include "MantidAPI/Progress.h"
13
#include "MantidAPI/TableRow.h"
Hahn, Steven's avatar
Hahn, Steven committed
14
15
16
17
#include "MantidDataObjects/Workspace2D.h"
#include "MantidGeometry/Instrument.h"
#include "MantidGeometry/Instrument/Detector.h"
#include "MantidKernel/ArrayProperty.h"
18
#include "MantidKernel/BoundedValidator.h"
Hahn, Steven's avatar
Hahn, Steven committed
19
#include "MantidKernel/ConfigService.h"
20
#include "MantidKernel/ListValidator.h"
Hahn, Steven's avatar
Hahn, Steven committed
21
22
23
#include "MantidKernel/OptionalBool.h"
#include "MantidKernel/TimeSeriesProperty.h"
#include "MantidKernel/UnitFactory.h"
24

25
26
#include "MantidNexus/MuonNexusReader.h"
#include "MantidNexus/NexusClasses.h"
LamarMoore's avatar
LamarMoore committed
27
28
29
#include <Poco/Path.h>
#include <cmath>
#include <limits>
30
#include <memory>
31
// clang-format off
32
33
#include <nexus/NeXusFile.hpp>
#include <nexus/NeXusException.hpp>
34
// clang-format on
35

36
37
38
39
40
41
42
43
44
45
namespace Mantid {
namespace DataHandling {

using namespace Kernel;
using namespace API;
using Geometry::Instrument;
using namespace Mantid::NeXus;

/// Empty default constructor
LoadMuonNexus::LoadMuonNexus()
Samuel Jones's avatar
Samuel Jones committed
46
47
    : m_filename(), m_entrynumber(0), m_numberOfSpectra(0), m_numberOfPeriods(0), m_list(false), m_interval(false),
      m_spec_list(), m_spec_min(0), m_spec_max(EMPTY_INT()) {}
48
49
50

/// Initialisation method.
void LoadMuonNexus::init() {
Samuel Jones's avatar
Samuel Jones committed
51
  declareProperty(std::make_unique<FileProperty>("Filename", "", FileProperty::Load, ".nxs"),
Sam Jenkins's avatar
Sam Jenkins committed
52
                  "The name of the Nexus file to load");
53

Samuel Jones's avatar
Samuel Jones committed
54
55
56
57
  declareProperty(std::make_unique<WorkspaceProperty<Workspace>>("OutputWorkspace", "", Direction::Output),
                  "The name of the workspace to be created as the output of the\n"
                  "algorithm. For multiperiod files, one workspace will be\n"
                  "generated for each period");
58

59
60
61
62
  auto mustBePositive = std::make_shared<BoundedValidator<specnum_t>>();
  mustBePositive->setLower(0);
  declareProperty("SpectrumMin", static_cast<specnum_t>(0), mustBePositive,
                  "Index number of the first spectrum to read\n");
Samuel Jones's avatar
Samuel Jones committed
63
  declareProperty("SpectrumMax", static_cast<specnum_t>(EMPTY_INT()), mustBePositive,
LamarMoore's avatar
LamarMoore committed
64
65
                  "Index of last spectrum to read\n"
                  "(default the last spectrum)");
66

67
  declareProperty(std::make_unique<ArrayProperty<specnum_t>>("SpectrumList"),
68
                  "Array, or comma separated list, of indexes of spectra to\n"
69
70
                  "load. If a range and a list of spectra are both supplied,\n"
                  "all the specified spectra will be loaded.");
71
72
73
  declareProperty("AutoGroup", false,
                  "Determines whether the spectra are automatically grouped\n"
                  "together based on the groupings in the NeXus file, only\n"
74
                  "for single period data (default no). Version 1 only.");
75

76
  auto mustBeNonNegative = std::make_shared<BoundedValidator<int64_t>>();
77
  mustBeNonNegative->setLower(0);
78
  declareProperty("EntryNumber", static_cast<int64_t>(0), mustBeNonNegative,
79
80
81
                  "0 indicates that every entry is loaded, into a separate "
                  "workspace within a group. "
                  "A positive number identifies one entry to be loaded, into "
82
                  "one workspace");
83

84
  std::vector<std::string> FieldOptions{"Transverse", "Longitudinal"};
Samuel Jones's avatar
Samuel Jones committed
85
  declareProperty("MainFieldDirection", "Transverse", std::make_shared<StringListValidator>(FieldOptions),
86
                  "Output the main field direction if specified in Nexus file "
87
88
                  "(run/instrument/detector/orientation, default "
                  "longitudinal). Version 1 only.",
89
90
                  Direction::Output);

Samuel Jones's avatar
Samuel Jones committed
91
92
  declareProperty("TimeZero", 0.0, "Time zero in units of micro-seconds (default to 0.0)", Direction::Output);
  declareProperty("FirstGoodData", 0.0, "First good data in units of micro-seconds (default to 0.0)",
93
94
                  Direction::Output);

95
  declareProperty(
Samuel Jones's avatar
Samuel Jones committed
96
      std::make_unique<WorkspaceProperty<Workspace>>("DeadTimeTable", "", Direction::Output, PropertyMode::Optional),
97
98
      "Table or a group of tables containing detector dead times. Version 1 "
      "only.");
99

100
101
102
103
104
105
106
107
108
109
  declareProperty(
      std::make_unique<WorkspaceProperty<Workspace>>("DetectorGroupingTable",
                                                     "", Direction::Output,
                                                     PropertyMode::Optional),
      "Table or a group of tables with information about the "
      "detector grouping stored in the file (if any). Version 1 only.");

  declareProperty(
      std::make_unique<ArrayProperty<std::string>>("PeriodsInformation"),
      "An array of strings which hold period information. This array is in the "
Matt Cumber's avatar
Matt Cumber committed
110
111
      "format ['NumberOfSequences', 'Labels', 'Frames', 'TotalFrames']. Empty "
      "strings "
112
113
      "show no value "
      "could be read from file.");
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
}

/// Validates the optional 'spectra to read' properties, if they have been set
void LoadMuonNexus::checkOptionalProperties() {
  // read in the settings passed to the algorithm
  m_spec_list = getProperty("SpectrumList");
  m_spec_max = getProperty("SpectrumMax");
  // Are we using a list of spectra or all the spectra in a range?
  m_list = !m_spec_list.empty();
  m_interval = (m_spec_max != EMPTY_INT());
  if (m_spec_max == EMPTY_INT())
    m_spec_max = 0;

  // Check validity of spectra list property, if set
  if (m_list) {
Samuel Jones's avatar
Samuel Jones committed
129
130
    const specnum_t minlist = *min_element(m_spec_list.begin(), m_spec_list.end());
    const specnum_t maxlist = *max_element(m_spec_list.begin(), m_spec_list.end());
131
132
133
    if (maxlist > m_numberOfSpectra || minlist == 0) {
      g_log.error("Invalid list of spectra");
      throw std::invalid_argument("Inconsistent properties defined");
134
    }
135
136
137
138
139
140
141
142
  }

  // Check validity of spectra range, if set
  if (m_interval) {
    m_spec_min = getProperty("SpectrumMin");
    if (m_spec_max < m_spec_min || m_spec_max > m_numberOfSpectra) {
      g_log.error("Invalid Spectrum min/max properties");
      throw std::invalid_argument("Inconsistent properties defined");
143
    }
144
145
146
147
  }
}

/// Run the Child Algorithm LoadInstrument
Samuel Jones's avatar
Samuel Jones committed
148
void LoadMuonNexus::runLoadInstrument(const DataObjects::Workspace2D_sptr &localWorkspace) {
149
150
151
152
153
154
155

  IAlgorithm_sptr loadInst = createChildAlgorithm("LoadInstrument");

  // Now execute the Child Algorithm. Catch and log any error, but don't stop.
  try {
    loadInst->setPropertyValue("InstrumentName", m_instrument_name);
    loadInst->setProperty<MatrixWorkspace_sptr>("Workspace", localWorkspace);
Samuel Jones's avatar
Samuel Jones committed
156
    loadInst->setProperty("RewriteSpectraMap", Mantid::Kernel::OptionalBool(false));
157
158
159
160
    loadInst->execute();
  } catch (std::invalid_argument &) {
    g_log.information("Invalid argument to LoadInstrument Child Algorithm");
  } catch (std::runtime_error &) {
Samuel Jones's avatar
Samuel Jones committed
161
    g_log.information("Unable to successfully run LoadInstrument Child Algorithm");
162
163
164
165
  }

  // If loading instrument definition file fails,
  // we may get instrument by some other means yet to be decided upon
166
167
  // at present just create a dummy instrument with the correct name.
  if (!loadInst->isExecuted()) {
168
    auto inst = std::make_shared<Geometry::Instrument>();
169
170
171
    inst->setName(m_instrument_name);
    localWorkspace->setInstrument(inst);
  }
172
173
174
175
176
177
178
179
180
181
182
183
184
185
}

/**
 * Return the confidence with with this algorithm can load the file
 * @param descriptor A descriptor for the file
 * @returns An integer specifying the confidence level. 0 indicates it will not
 * be used
 */
int LoadMuonNexus::confidence(Kernel::NexusDescriptor &descriptor) const {
  UNUSED_ARG(descriptor);
  return 0; // Not to be used but LoadMuonNexus2, which inherits from this will
}

} // namespace DataHandling
186
} // namespace Mantid