LoadMuonNexusV2.cpp 7.9 KB
Newer Older
1
2
3
// Mantid Repository : https://github.com/mantidproject/mantid
//
// Copyright © 2020 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 +
Stephen's avatar
Stephen committed
7
#include "MantidDataHandling/LoadMuonNexusV2.h"
8
9
10
11
#include "MantidAPI/FileProperty.h"
#include "MantidAPI/RegisterFileLoader.h"
#include "MantidAPI/WorkspaceFactory.h"
#include "MantidAPI/WorkspaceGroup.h"
12
#include "MantidDataHandling/LoadISISNexus2.h"
Stephen's avatar
Stephen committed
13
#include "MantidDataHandling/LoadMuonNexusV2Helper.h"
14
15
#include "MantidDataHandling/SinglePeriodLoadMuonStrategy.h"
#include "MantidDataObjects/Workspace2D.h"
16
17
#include "MantidKernel/ArrayProperty.h"
#include "MantidKernel/BoundedValidator.h"
Stephen's avatar
Stephen committed
18
#include "MantidKernel/ListValidator.h"
19
20
21
22
23
24

#include <vector>

namespace Mantid {
namespace DataHandling {

Stephen's avatar
Stephen committed
25
DECLARE_NEXUS_HDF5_FILELOADER_ALGORITHM(LoadMuonNexusV2)
26
27
28
29
30
31
32
33
34

using namespace Kernel;
using namespace API;
using namespace NeXus;
using namespace HistogramData;
using std::size_t;
using namespace DataObjects;

/// Empty default constructor
Stephen's avatar
Stephen committed
35
LoadMuonNexusV2::LoadMuonNexusV2()
Stephen's avatar
Stephen committed
36
37
    : m_filename(), m_entrynumber(0), m_isFileMultiPeriod(false),
      m_multiPeriodsLoaded(false) {}
38
39
40
41
42
43
44

/**
 * Return the confidence criteria for 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
 */
Stephen's avatar
Stephen committed
45
int LoadMuonNexusV2::confidence(NexusHDF5Descriptor &descriptor) const {
46
  // Without this entry we cannot use LoadISISNexus
47
  if (!descriptor.isEntry("/raw_data_1", "NXentry")) {
48
49
    return 0;
  }
50
  const std::string root = "/raw_data_1";
Stephen's avatar
Stephen committed
51
  // Check if Muon source in definition entry
52
53
54
55
56
57
  if (!descriptor.isEntry(root + "/definition"))
    return 0;
  ::NeXus::File file(descriptor.getFilename());
  file.openPath(root + "/definition");
  std::string def = file.getStrData();
  if (def == "muonTD" || def == "pulsedTD") {
Stephen's avatar
Stephen committed
58
    return 82; // have to return 82 to "beat" the LoadMuonNexus2 algorithm,
59
60
               // which returns 81 for this file as well
  } else {
61
    return 0;
62
63
64
  }
}
/// Initialization method.
Stephen's avatar
Stephen committed
65
void LoadMuonNexusV2::init() {
66
67
68
69
70
71
72
73
74
75
76
  declareProperty(std::make_unique<FileProperty>("Filename", "",
                                                 FileProperty::Load, ".nxs"),
                  "The name of the Nexus file to load");

  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");

77
  auto mustBePositive = std::make_shared<BoundedValidator<int64_t>>();
78
79
80
81
82
83
84
85
86
  mustBePositive->setLower(0);
  declareProperty("SpectrumMin", static_cast<int64_t>(0), mustBePositive);
  declareProperty("SpectrumMax", static_cast<int64_t>(EMPTY_INT()),
                  mustBePositive);
  declareProperty(std::make_unique<ArrayProperty<int64_t>>("SpectrumList"));
  declareProperty("EntryNumber", static_cast<int64_t>(0), mustBePositive,
                  "0 indicates that every entry is loaded, into a separate "
                  "workspace within a group. "
                  "A positive number identifies one entry to be loaded, into "
Stephen's avatar
Stephen committed
87
                  "one workspace");
88

Stephen's avatar
Stephen committed
89
90
  std::vector<std::string> FieldOptions{"Transverse", "Longitudinal"};
  declareProperty("MainFieldDirection", "Transverse",
91
                  std::make_shared<StringListValidator>(FieldOptions),
Stephen's avatar
Stephen committed
92
93
                  "Output the main field direction if specified in Nexus file "
                  "(run/instrument/detector/orientation, default "
Stephen's avatar
Stephen committed
94
                  "longitudinal).",
Stephen's avatar
Stephen committed
95
96
97
98
99
100
101
102
103
                  Direction::Output);

  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)",
                  Direction::Output);

104
105
106
  declareProperty(
      std::make_unique<WorkspaceProperty<Workspace>>(
          "DeadTimeTable", "", Direction::Output, PropertyMode::Optional),
Stephen's avatar
Stephen committed
107
      "Table or a group of tables containing detector dead times.");
108

Stephen's avatar
Stephen committed
109
110
111
112
113
  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).");
114
}
Stephen's avatar
Stephen committed
115
void LoadMuonNexusV2::execLoader() {
116

117
  // prepare nexus entry
118
119
120
121
  m_entrynumber = getProperty("EntryNumber");
  m_filename = getPropertyValue("Filename");
  NXRoot root(m_filename);
  NXEntry entry = root.openEntry("raw_data_1");
122
123
124

  // Execute child algorithm LoadISISNexus2 and load Muon specific properties
  runLoadISISNexus();
Stephen's avatar
Stephen committed
125
  loadMuonProperties(entry);
126

Stephen's avatar
Stephen committed
127
128
  // Check if single or multi period file and create appropriate loading
  // strategy
129
130
  isEntryMultiPeriod(entry);
  Workspace_sptr outWS = getProperty("OutputWorkspace");
131
132
  if (m_multiPeriodsLoaded) {
    WorkspaceGroup_sptr wksp_grp =
133
        std::dynamic_pointer_cast<WorkspaceGroup>(outWS);
Stephen's avatar
Stephen committed
134
135
    g_log.warning("Multi period files not yet supported by LoadMuonNexusV2");
    return;
136
137
138
  } else {
    // we just have a single workspace
    Workspace2D_sptr workspace2D =
139
        std::dynamic_pointer_cast<Workspace2D>(outWS);
140
    m_loadMuonStrategy = std::make_unique<SinglePeriodLoadMuonStrategy>(
Stephen's avatar
Stephen committed
141
        g_log, m_filename, entry, workspace2D, static_cast<int>(m_entrynumber),
Stephen Smith's avatar
Stephen Smith committed
142
        m_isFileMultiPeriod);
143
  }
Stephen Smith's avatar
Stephen Smith committed
144
  m_loadMuonStrategy->loadMuonLogData();
145
  m_loadMuonStrategy->loadGoodFrames();
Stephen's avatar
Stephen committed
146
147
148
  m_loadMuonStrategy->applyTimeZeroCorrection();
  // Grouping info should be returned if user has set the property
  if (!getPropertyValue("DetectorGroupingTable").empty()) {
Stephen's avatar
Stephen committed
149
    auto loadedGrouping = m_loadMuonStrategy->loadDetectorGrouping();
Stephen's avatar
Stephen committed
150
151
152
    setProperty("DetectorGroupingTable", loadedGrouping);
  };
  // Deadtime table should be returned if user has set the property
Stephen's avatar
Stephen committed
153
  auto deadtimeTable = m_loadMuonStrategy->loadDeadTimeTable();
Stephen's avatar
Stephen committed
154
155
156
  if (!getPropertyValue("DeadTimeTable").empty()) {
    setProperty("DeadTimeTable", deadtimeTable);
  }
157
}
Stephen's avatar
Stephen committed
158
159
160
161
162

/**
 * Determines whether the file is multi period
 * If multi period the function determines whether multi periods are loaded
 */
Stephen's avatar
Stephen committed
163
void LoadMuonNexusV2::isEntryMultiPeriod(const NXEntry &entry) {
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
  NXClass periodClass = entry.openNXGroup("periods");
  int numberOfPeriods = periodClass.getInt("number");
  if (numberOfPeriods > 1) {
    m_isFileMultiPeriod = true;
    if (m_entrynumber == 0) {
      m_multiPeriodsLoaded = true;
    }
  } else {
    m_isFileMultiPeriod = false;
    m_multiPeriodsLoaded = false;
  }
}
/**
 * Runs the child algorithm LoadISISNexus, which loads data into an output
 * workspace
 */
Stephen's avatar
Stephen committed
180
void LoadMuonNexusV2::runLoadISISNexus() {
181
182
183
  IAlgorithm_sptr childAlg =
      createChildAlgorithm("LoadISISNexus", 0, 1, true, 2);
  declareProperty("LoadMonitors", "Exclude"); // we need to set this property
184
  auto ISISLoader = std::dynamic_pointer_cast<API::Algorithm>(childAlg);
185
186
187
188
  ISISLoader->copyPropertiesFrom(*this);
  ISISLoader->executeAsChildAlg();
  this->copyPropertiesFrom(*ISISLoader);
}
189
190
191
192
/**
 * Loads Muon specific data from the nexus entry
 * and sets the appropriate output properties
 */
Stephen's avatar
Stephen committed
193
void LoadMuonNexusV2::loadMuonProperties(const NXEntry &entry) {
194

195
  std::string mainFieldDirection =
Stephen's avatar
Stephen committed
196
      LoadMuonNexusV2Helper::loadMainFieldDirectionFromNexus(entry);
Stephen's avatar
Stephen committed
197
  setProperty("MainFieldDirection", mainFieldDirection);
198

Stephen's avatar
Stephen committed
199
  double timeZero = LoadMuonNexusV2Helper::loadTimeZeroFromNexusFile(entry);
Stephen's avatar
Stephen committed
200
201
  setProperty("timeZero", timeZero);

Stephen's avatar
Stephen committed
202
  auto firstGoodData = LoadMuonNexusV2Helper::loadFirstGoodDataFromNexus(entry);
203
  setProperty("FirstGoodData", firstGoodData);
204
205
206
}
} // namespace DataHandling
} // namespace Mantid