LoadSINQFocus.cpp 8.28 KB
Newer Older
1
#include "MantidDataHandling/LoadSINQFocus.h"
2
3

#include "MantidAPI/Axis.h"
4
#include "MantidAPI/FileProperty.h"
5
#include "MantidAPI/MatrixWorkspace.h"
Ricardo Leal's avatar
Ricardo Leal committed
6
#include "MantidAPI/Progress.h"
7
#include "MantidAPI/RegisterFileLoader.h"
8
#include "MantidAPI/WorkspaceFactory.h"
Ricardo Leal's avatar
Ricardo Leal committed
9
#include "MantidGeometry/Instrument.h"
Hahn, Steven's avatar
Hahn, Steven committed
10
#include "MantidKernel/OptionalBool.h"
11
#include "MantidKernel/UnitFactory.h"
Ricardo Leal's avatar
Ricardo Leal committed
12
13
14
15
16

#include <limits>
#include <algorithm>
#include <vector>
#include <cmath>
17
18
19
20
21
22
23
24

namespace Mantid {
namespace DataHandling {

using namespace Kernel;
using namespace API;
using namespace NeXus;

25
DECLARE_NEXUS_FILELOADER_ALGORITHM(LoadSINQFocus)
26
27
28
29

//----------------------------------------------------------------------------------------------
/** Constructor
 */
30
LoadSINQFocus::LoadSINQFocus()
31
32
33
34
    : m_supportedInstruments{"FOCUS"}, m_numberOfTubes{0},
      m_numberOfPixelsPerTube{0}, m_numberOfChannels{0},
      m_numberOfHistograms{0} {

35
36
  this->useAlgorithm("LoadSINQ");
  this->deprecatedDate("2013-10-28");
37
38
39
40
}

//----------------------------------------------------------------------------------------------
/// Algorithm's name for identification. @see Algorithm::name
41
const std::string LoadSINQFocus::name() const { return "LoadSINQFocus"; }
42
43

/// Algorithm's version for identification. @see Algorithm::version
44
int LoadSINQFocus::version() const { return 1; }
45
46

/// Algorithm's category for identification. @see Algorithm::category
Nick Draper's avatar
Nick Draper committed
47
48
49
const std::string LoadSINQFocus::category() const {
  return "DataHandling\\Nexus";
}
50
51

//----------------------------------------------------------------------------------------------
52
53
54
55

/**
 * Return the confidence with with this algorithm can load the file
 * @param descriptor A descriptor for the file
56
57
 * @returns An integer specifying the confidence level. 0 indicates it will not
 * be used
58
 */
59
60
61
62
63
64
65
66
int LoadSINQFocus::confidence(Kernel::NexusDescriptor &descriptor) const {

  // fields existent only at the SINQ (to date Loader only valid for focus)
  if (descriptor.pathExists("/entry1/FOCUS/SINQ")) {
    return 80;
  } else {
    return 0;
  }
67
68
}

69
//-----------------------------------------1-----------------------------------------------------
70
71
/** Initialize the algorithm's properties.
 */
72
void LoadSINQFocus::init() {
73
74
75
76
77
78
79
  const std::vector<std::string> exts{".nxs", ".hdf"};
  declareProperty(Kernel::make_unique<FileProperty>("Filename", "",
                                                    FileProperty::Load, exts),
                  "The name of the Nexus file to load");
  declareProperty(make_unique<WorkspaceProperty<>>("OutputWorkspace", "",
                                                   Direction::Output),
                  "The name to use for the output workspace");
80
81
82
83
84
}

//----------------------------------------------------------------------------------------------
/** Execute the algorithm.
 */
85
void LoadSINQFocus::exec() {
86

87
88
89
90
  std::string filename = getPropertyValue("Filename");
  NXRoot root(filename);
  NXEntry entry = root.openFirstEntry();
  setInstrumentName(entry);
91

92
  initWorkSpace(entry);
93

94
  loadDataIntoTheWorkSpace(entry);
95

96
97
  loadRunDetails(entry);
  loadExperimentDetails(entry);
Ricardo Leal's avatar
Ricardo Leal committed
98

99
  runLoadInstrument();
Ricardo Leal's avatar
Ricardo Leal committed
100

101
  setProperty("OutputWorkspace", m_localWorkspace);
102
103
}

104
105
106
107
108
109
110
/*
 * Set global variables:
 * m_instrumentPath
 * m_instrumentName
 * Note that the instrument in the nexus file is of the form "FOCUS at SINQ"
 *
 */
111
112
113
114
void LoadSINQFocus::setInstrumentName(NeXus::NXEntry &entry) {

  m_instrumentPath = m_loader.findInstrumentNexusPath(entry);

115
  if (m_instrumentPath.empty()) {
116
117
118
119
120
    throw std::runtime_error(
        "Cannot set the instrument name from the Nexus file!");
  }
  m_instrumentName =
      m_loader.getStringFromNexusPath(entry, m_instrumentPath + "/name");
121
  size_t pos = m_instrumentName.find(' ');
122
  m_instrumentName = m_instrumentName.substr(0, pos);
123
124
}

125
126
127
128
129
130
131
132
133
134
135
136
137
void LoadSINQFocus::initWorkSpace(NeXus::NXEntry &entry) {

  // read in the data
  NXData dataGroup = entry.openNXData("merged");
  NXInt data = dataGroup.openIntData();

  m_numberOfTubes = static_cast<size_t>(data.dim0());
  m_numberOfPixelsPerTube = 1;
  m_numberOfChannels = static_cast<size_t>(data.dim1());

  // dim0 * m_numberOfPixelsPerTube is the total number of detectors
  m_numberOfHistograms = m_numberOfTubes * m_numberOfPixelsPerTube;

138
139
140
  g_log.debug() << "NumberOfTubes: " << m_numberOfTubes << '\n';
  g_log.debug() << "NumberOfPixelsPerTube: " << m_numberOfPixelsPerTube << '\n';
  g_log.debug() << "NumberOfChannels: " << m_numberOfChannels << '\n';
141
142
143
144
145
146
147
148
149
150
151
152
153

  // Now create the output workspace
  // Might need to get this value from the number of monitors in the Nexus file
  // params:
  // workspace type,
  // total number of spectra + (number of monitors = 0),
  // bin boundaries = m_numberOfChannels + 1
  // Z/time dimension
  m_localWorkspace = WorkspaceFactory::Instance().create(
      "Workspace2D", m_numberOfHistograms, m_numberOfChannels + 1,
      m_numberOfChannels);
  m_localWorkspace->getAxis(0)->unit() = UnitFactory::Instance().create("TOF");
  m_localWorkspace->setYUnitLabel("Counts");
154
155
}

156
157
158
159
160
161
162
163
164
void LoadSINQFocus::loadDataIntoTheWorkSpace(NeXus::NXEntry &entry) {

  // read in the data
  NXData dataGroup = entry.openNXData("merged");
  NXInt data = dataGroup.openIntData();
  data.load();

  std::vector<double> timeBinning =
      m_loader.getTimeBinningFromNexusPath(entry, "merged/time_binning");
165
166
  auto &x = m_localWorkspace->mutableX(0);
  x.assign(timeBinning.begin(), timeBinning.end());
167

168
  Progress progress(this, 0.0, 1.0, m_numberOfTubes * m_numberOfPixelsPerTube);
169
170
171
172
173
  size_t spec = 0;
  for (size_t i = 0; i < m_numberOfTubes; ++i) {
    for (size_t j = 0; j < m_numberOfPixelsPerTube; ++j) {
      if (spec > 0) {
        // just copy the time binning axis to every spectra
174
        m_localWorkspace->setSharedX(spec, m_localWorkspace->sharedX(0));
175
176
177
      }
      // Assign Y
      int *data_p = &data(static_cast<int>(i), static_cast<int>(j));
178
179
      m_localWorkspace->mutableY(spec)
          .assign(data_p, data_p + m_numberOfChannels);
180
      // Assign Error
181
      auto &E = m_localWorkspace->mutableE(spec);
182
183
184
185
186
187
      std::transform(data_p, data_p + m_numberOfChannels, E.begin(),
                     LoadSINQFocus::calculateError);
      ++spec;
      progress.report();
    }
  }
188
  g_log.debug() << "Data loading into WS done....\n";
Ricardo Leal's avatar
Ricardo Leal committed
189
190
}

191
void LoadSINQFocus::loadRunDetails(NXEntry &entry) {
Ricardo Leal's avatar
Ricardo Leal committed
192

193
  API::Run &runDetails = m_localWorkspace->mutableRun();
Ricardo Leal's avatar
Ricardo Leal committed
194

195
196
197
  //	int runNum = entry.getInt("run_number");
  //	std::string run_num = boost::lexical_cast<std::string>(runNum);
  //	runDetails.addProperty("run_number", run_num);
Ricardo Leal's avatar
Ricardo Leal committed
198

199
200
201
  std::string start_time = entry.getString("start_time");
  // start_time = getDateTimeInIsoFormat(start_time);
  runDetails.addProperty("run_start", start_time);
Ricardo Leal's avatar
Ricardo Leal committed
202

203
204
205
  std::string end_time = entry.getString("end_time");
  // end_time = getDateTimeInIsoFormat(end_time);
  runDetails.addProperty("run_end", end_time);
Ricardo Leal's avatar
Ricardo Leal committed
206

207
208
209
  double wavelength =
      entry.getFloat(m_instrumentPath + "/monochromator/lambda");
  runDetails.addProperty<double>("wavelength", wavelength);
Ricardo Leal's avatar
Ricardo Leal committed
210

211
212
  double energy = entry.getFloat(m_instrumentPath + "/monochromator/energy");
  runDetails.addProperty<double>("Ei", energy, true); // overwrite
Ricardo Leal's avatar
Ricardo Leal committed
213

214
215
216
  std::string title = entry.getString("title");
  runDetails.addProperty("title", title);
  m_localWorkspace->setTitle(title);
Ricardo Leal's avatar
Ricardo Leal committed
217
218
219
220
221
}

/*
 * Load data about the Experiment.
 *
222
223
 * TODO: This is very incomplete. In ISIS they much more info in the nexus file
 *than ILL.
Ricardo Leal's avatar
Ricardo Leal committed
224
225
226
 *
 * @param entry :: The Nexus entry
 */
227
void LoadSINQFocus::loadExperimentDetails(NXEntry &entry) {
Ricardo Leal's avatar
Ricardo Leal committed
228

229
230
231
  std::string name =
      boost::lexical_cast<std::string>(entry.getFloat("sample/name"));
  m_localWorkspace->mutableSample().setName(name);
Ricardo Leal's avatar
Ricardo Leal committed
232
233
234
235
236
}

/**
 * Run the Child Algorithm LoadInstrument.
 */
237
void LoadSINQFocus::runLoadInstrument() {
Ricardo Leal's avatar
Ricardo Leal committed
238

239
  IAlgorithm_sptr loadInst = createChildAlgorithm("LoadInstrument");
Ricardo Leal's avatar
Ricardo Leal committed
240

241
242
  // Now execute the Child Algorithm. Catch and log any error, but don't stop.
  try {
Ricardo Leal's avatar
Ricardo Leal committed
243

244
245
    // TODO: depending on the m_numberOfPixelsPerTube we might need to load a
    // different IDF
Ricardo Leal's avatar
Ricardo Leal committed
246

247
    loadInst->setPropertyValue("InstrumentName", m_instrumentName);
Owen Arnold's avatar
Owen Arnold committed
248
249
    loadInst->setProperty("RewriteSpectraMap",
                          Mantid::Kernel::OptionalBool(true));
250
251
252
253
254
    loadInst->setProperty<MatrixWorkspace_sptr>("Workspace", m_localWorkspace);
    loadInst->execute();
  } catch (...) {
    g_log.information("Cannot load the instrument definition.");
  }
Ricardo Leal's avatar
Ricardo Leal committed
255
256
}

257
258
} // namespace DataHandling
} // namespace Mantid