IMDWorkspace.cpp 8.62 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 +
Peterson, Peter's avatar
Peterson, Peter committed
7
#include "MantidAPI/IMDWorkspace.h"
8
#include "MantidGeometry/MDGeometry/IMDDimension.h"
LamarMoore's avatar
LamarMoore committed
9
#include "MantidKernel/ConfigService.h"
10
#include "MantidKernel/Exception.h"
11
#include "MantidKernel/IPropertyManager.h"
12
13
#include "MantidKernel/VMD.h"

14
#include <sstream>
David Fairbrother's avatar
David Fairbrother committed
15
#include <utility>
16

17
using Mantid::Kernel::VMD;
Peterson, Peter's avatar
Peterson, Peter committed
18

19
20
21
22
namespace Mantid {
namespace API {
//-----------------------------------------------------------------------------------------------
/** Default constructor */
23
24
IMDWorkspace::IMDWorkspace(const Parallel::StorageMode storageMode)
    : Workspace(storageMode), Mantid::API::MDGeometry() {
25
  m_convention = Kernel::ConfigService::Instance().getString("Q.convention");
26
}
27
28
29
30
31
32
33
34
35

/** Creates a single iterator and returns it.
 *
 * This calls createIterators(), a pure virtual method on IMDWorkspace which
 * has custom implementations for other workspaces.
 *
 * @param function :: Implicit function limiting space to look at
 * @return a single IMDIterator pointer
 */
36
std::unique_ptr<IMDIterator> IMDWorkspace::createIterator(
37
    Mantid::Geometry::MDImplicitFunction *function) const {
38
39
  std::vector<std::unique_ptr<IMDIterator>> iterators =
      this->createIterators(1, function);
40
41
42
43
44
  if (iterators.empty())
    throw std::runtime_error("IMDWorkspace::createIterator(): iterator "
                             "creation was not successful. No iterators "
                             "returned by " +
                             this->id());
45
  return std::move(iterators[0]);
46
47
}

48
49
50
//---------------------------------------------------------------------------------------------
/** @return the convention
 */
51
52
53
54
55
56
std::string IMDWorkspace::getConvention() const { return m_convention; }

//---------------------------------------------------------------------------------------------
/** @return the convention
 */
void IMDWorkspace::setConvention(std::string convention) {
David Fairbrother's avatar
David Fairbrother committed
57
  m_convention = std::move(convention);
58
}
59

60
61
62
63
//---------------------------------------------------------------------------------------------
/** @return the convention
 */
std::string IMDWorkspace::changeQConvention() {
Lynch, Vickie's avatar
Lynch, Vickie committed
64
  if (this->getConvention() == "Crystallography")
65
    m_convention = "Inelastic";
Lynch, Vickie's avatar
Lynch, Vickie committed
66
  else
67
68
    m_convention = "Crystallography";
  return m_convention;
69
70
}

71
72
73
74
75
76
77
78
79
80
81
82
83
//-------------------------------------------------------------------------------------------
/** Returns the signal (normalized by volume) at a given coordinates
 *
 * @param coords :: coordinate as a VMD vector
 * @param normalization :: how to normalize the signal returned
 * @return normalized signal
 */
signal_t IMDWorkspace::getSignalAtVMD(
    const Mantid::Kernel::VMD &coords,
    const Mantid::API::MDNormalization &normalization) const {
  return this->getSignalAtCoord(coords.getBareArray(), normalization);
}

84
85
86
87
88
89
90
91
92
93
94
95
96
97
//-------------------------------------------------------------------------------------------
/** Returns the signal (normalized by volume) at a given coordinates
 * or 0 if masked
 *
 * @param coords :: coordinate as a VMD vector
 * @param normalization :: how to normalize the signal returned
 * @return normalized signal
 */
signal_t IMDWorkspace::getSignalWithMaskAtVMD(
    const Mantid::Kernel::VMD &coords,
    const Mantid::API::MDNormalization &normalization) const {
  return this->getSignalWithMaskAtCoord(coords.getBareArray(), normalization);
}

98
99
100
101
102
103
104
//-----------------------------------------------------------------------------------------------

const std::string IMDWorkspace::toString() const {
  std::ostringstream os;
  os << id() << "\n"
     << "Title: " + getTitle() << "\n";
  for (size_t i = 0; i < getNumDims(); i++) {
105
    const auto &dim = getDimension(i);
106
107
108
109
110
111
112
113
114
115
116
    os << "Dim " << i << ": (" << dim->getName() << ") " << dim->getMinimum()
       << " to " << dim->getMaximum() << " in " << dim->getNBins() << " bins";
    // Also show the dimension ID string, if different than name
    if (dim->getDimensionId() != dim->getName())
      os << ". Id=" << dim->getDimensionId();
    os << "\n";
  }
  if (hasOriginalWorkspace()) {
    os << "Binned from '" << getOriginalWorkspace()->getName();
  }
  os << "\n";
117
  if (this->getConvention() == "Crystallography")
118
    os << "Crystallography: kf-ki";
119
  else
120
    os << "Inelastic: ki-kf";
121
122
  os << "\n";

123
124
  return os.str();
}
125

126
127
128
129
130
131
132
133
134
135
136
//----------------------------------------------------------------------------------------------
/**
 * Make a single point with NaN as the signal and error
 * This can be returned when there would otherwise be nothing to plot
 * @param x :: position on the line
 * @param y :: signal value
 * @param e :: error value
 */
void IMDWorkspace::makeSinglePointWithNaN(std::vector<coord_t> &x,
                                          std::vector<signal_t> &y,
                                          std::vector<signal_t> &e) const {
137
  x.emplace_back(0.f);
138
139
  y.emplace_back(std::numeric_limits<signal_t>::quiet_NaN());
  e.emplace_back(std::numeric_limits<signal_t>::quiet_NaN());
140
141
}

142
143
144
145
146
147
148
149
150
//-----------------------------------------------------------------------------------------------
/** Obtain coordinates for a line plot through a IMDWorkspace.
 * Cross the workspace from start to end points, recording the signal along the
 *line.
 * Sets the x,y vectors to the histogram bin boundaries and counts
 *
 * @param start :: coordinates of the start point of the line
 * @param end :: coordinates of the end point of the line
 * @param normalize :: how to normalize the signal
151
152
153
154
 * @returns :: a LinePlot in which x is set to the boundaries of the bins,
 * relative to start of the line, y is set to the normalized signal for
 * each bin with Length = length(x) - 1 and e is set to the normalized
 * errors for each bin with Length = length(x) - 1.
155
 */
156
157
158
159
IMDWorkspace::LinePlot
IMDWorkspace::getLinePlot(const Mantid::Kernel::VMD &start,
                          const Mantid::Kernel::VMD &end,
                          Mantid::API::MDNormalization normalize) const {
160
161
162
163
164
165
  // TODO: Don't use a fixed number of points later
  size_t numPoints = 200;

  VMD step = (end - start) / double(numPoints);
  double stepLength = step.norm();

166
167
  // This will be the curve as plotted
  LinePlot line;
168
169
170
171
  for (size_t i = 0; i < numPoints; i++) {
    // Coordinate along the line
    VMD coord = start + step * double(i);
    // Record the position along the line
172
    line.x.emplace_back(static_cast<coord_t>(stepLength * double(i)));
173
174

    signal_t yVal = this->getSignalAtCoord(coord.getBareArray(), normalize);
175
176
    line.y.emplace_back(yVal);
    line.e.emplace_back(0.0);
Peterson, Peter's avatar
Peterson, Peter committed
177
  }
178
  // And the last point
179
  line.x.emplace_back((end - start).norm());
180
  return line;
181
}
Owen Arnold's avatar
Owen Arnold committed
182
183

/**
184
185
@return normalization preferred for visualization. Set to none for the generic
case, but overriden elsewhere.
Owen Arnold's avatar
Owen Arnold committed
186
187
188
189
*/
MDNormalization IMDWorkspace::displayNormalization() const {
  return NoNormalization;
}
190
191

/**
192
193
@return normalization preferred for visualization of histo workspaces. Set to
none for the generic case, but overriden elsewhere.
194
195
196
197
*/
MDNormalization IMDWorkspace::displayNormalizationHisto() const {
  return NoNormalization;
}
LamarMoore's avatar
LamarMoore committed
198
199
} // namespace API
} // namespace Mantid
200

201
202
203
204
205
206
207
208
namespace Mantid {
namespace Kernel {
/** In order to be able to cast PropertyWithValue classes correctly a definition
 * for the PropertyWithValue<IMDEventWorkspace> is required */
template <>
MANTID_API_DLL Mantid::API::IMDWorkspace_sptr
IPropertyManager::getValue<Mantid::API::IMDWorkspace_sptr>(
    const std::string &name) const {
209
  auto *prop =
210
211
212
213
214
      dynamic_cast<PropertyWithValue<Mantid::API::IMDWorkspace_sptr> *>(
          getPointerToProperty(name));
  if (prop) {
    return *prop;
  } else {
215
216
217
    std::string message =
        "Attempt to assign property " + name +
        " to incorrect type. Expected shared_ptr<IMDWorkspace>.";
218
    throw std::runtime_error(message);
219
  }
220
}
221

222
223
224
225
226
227
/** In order to be able to cast PropertyWithValue classes correctly a definition
 * for the PropertyWithValue<IMDWorkspace_const_sptr> is required */
template <>
MANTID_API_DLL Mantid::API::IMDWorkspace_const_sptr
IPropertyManager::getValue<Mantid::API::IMDWorkspace_const_sptr>(
    const std::string &name) const {
228
  auto *prop =
229
230
231
232
233
      dynamic_cast<PropertyWithValue<Mantid::API::IMDWorkspace_sptr> *>(
          getPointerToProperty(name));
  if (prop) {
    return prop->operator()();
  } else {
234
235
236
    std::string message =
        "Attempt to assign property " + name +
        " to incorrect type. Expected const shared_ptr<IMDWorkspace>.";
237
    throw std::runtime_error(message);
238
  }
239
}
240
241
242

} // namespace Kernel
} // namespace Mantid