WorkspaceOpOverloads.cpp 20.9 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
#include "MantidAPI/WorkspaceOpOverloads.h"
#include "MantidAPI/Algorithm.h"
#include "MantidAPI/AlgorithmManager.h"
LamarMoore's avatar
LamarMoore committed
10
11
#include "MantidAPI/IMDHistoWorkspace.h"
#include "MantidAPI/IMDWorkspace.h"
12
#include "MantidAPI/IWorkspaceProperty.h"
LamarMoore's avatar
LamarMoore committed
13
#include "MantidAPI/MatrixWorkspace.h"
Nick Draper's avatar
re #75  
Nick Draper committed
14
#include "MantidAPI/WorkspaceFactory.h"
15
#include "MantidAPI/WorkspaceGroup.h"
LamarMoore's avatar
LamarMoore committed
16
#include "MantidKernel/Property.h"
17
18

#include <numeric>
19

20
21
22
namespace Mantid {
namespace API {
namespace OperatorOverloads {
23

24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
/** Performs a binary operation on two workspaces
 *  @param algorithmName :: The name of the binary operation to perform
 *  @param lhs :: left hand side workspace shared pointer
 *  @param rhs :: right hand side workspace shared pointer
 *  @param lhsAsOutput :: If true, indicates that the lhs input is the same
 * workspace as the output one
 *  @param child :: If true the algorithm is run as a child
 *  @param name :: If child is true and this is not an inplace operation then
 * this name is used as output
 *  @param rethrow :: A flag indicating whether to rethrow exceptions
 *  @return The result in a workspace shared pointer
 */
template <typename LHSType, typename RHSType, typename ResultType>
ResultType executeBinaryOperation(const std::string &algorithmName,
                                  const LHSType lhs, const RHSType rhs,
                                  bool lhsAsOutput, bool child,
                                  const std::string &name, bool rethrow) {
  IAlgorithm_sptr alg =
      AlgorithmManager::Instance().createUnmanaged(algorithmName);
  alg->setChild(child);
  alg->setRethrows(rethrow);
  alg->initialize();
46

47
  if (lhs->getName().empty()) {
48
    alg->setProperty<LHSType>("LHSWorkspace", lhs);
49
  } else {
50
    alg->setPropertyValue("LHSWorkspace", lhs->getName());
51
52
53
54
  }
  if (rhs->getName().empty()) {
    alg->setProperty<RHSType>("RHSWorkspace", rhs);
  } else {
55
    alg->setPropertyValue("RHSWorkspace", rhs->getName());
56
57
58
  }
  if (lhsAsOutput) {
    if (!lhs->getName().empty()) {
59
60
      alg->setPropertyValue("OutputWorkspace", lhs->getName());
    } else {
61
      alg->setAlwaysStoreInADS(false);
62
63
      alg->setPropertyValue("OutputWorkspace", "dummy-output-name");
      alg->setProperty<LHSType>("OutputWorkspace", lhs);
64
    }
65
  } else {
66
67
68
69
70
71
    if (name.empty()) {
      alg->setAlwaysStoreInADS(false);
      alg->setPropertyValue("OutputWorkspace", "dummy-output-name");
    } else {
      alg->setPropertyValue("OutputWorkspace", name);
    }
72
  }
73

74
  alg->execute();
75

76
  if (!alg->isExecuted()) {
77
78
    std::string message = "Error while executing operation: " + algorithmName;
    throw std::runtime_error(message);
79
80
  }

81
  // Get the output workspace property
82
83
84
  if (!alg->getAlwaysStoreInADS()) {
    API::MatrixWorkspace_sptr result = alg->getProperty("OutputWorkspace");
    return boost::dynamic_pointer_cast<typename ResultType::element_type>(
85
        result);
86
  } else {
87
88
    API::Workspace_sptr result = API::AnalysisDataService::Instance().retrieve(
        alg->getPropertyValue("OutputWorkspace"));
89
90
91
    return boost::dynamic_pointer_cast<typename ResultType::element_type>(
        result);
  }
92
}
93

94
template MANTID_API_DLL MatrixWorkspace_sptr executeBinaryOperation(
LamarMoore's avatar
LamarMoore committed
95
96
    const std::string &, const MatrixWorkspace_sptr, const MatrixWorkspace_sptr,
    bool, bool, const std::string &, bool);
97
template MANTID_API_DLL WorkspaceGroup_sptr executeBinaryOperation(
LamarMoore's avatar
LamarMoore committed
98
99
    const std::string &, const WorkspaceGroup_sptr, const WorkspaceGroup_sptr,
    bool, bool, const std::string &, bool);
100
template MANTID_API_DLL WorkspaceGroup_sptr executeBinaryOperation(
LamarMoore's avatar
LamarMoore committed
101
102
    const std::string &, const WorkspaceGroup_sptr, const MatrixWorkspace_sptr,
    bool, bool, const std::string &, bool);
103
template MANTID_API_DLL WorkspaceGroup_sptr executeBinaryOperation(
LamarMoore's avatar
LamarMoore committed
104
105
    const std::string &, const MatrixWorkspace_sptr, const WorkspaceGroup_sptr,
    bool, bool, const std::string &, bool);
106

107
template MANTID_API_DLL IMDWorkspace_sptr executeBinaryOperation(
LamarMoore's avatar
LamarMoore committed
108
109
    const std::string &, const IMDWorkspace_sptr, const IMDWorkspace_sptr, bool,
    bool, const std::string &, bool);
110
template MANTID_API_DLL WorkspaceGroup_sptr executeBinaryOperation(
LamarMoore's avatar
LamarMoore committed
111
112
    const std::string &, const WorkspaceGroup_sptr, const IMDWorkspace_sptr,
    bool, bool, const std::string &, bool);
113
template MANTID_API_DLL WorkspaceGroup_sptr executeBinaryOperation(
LamarMoore's avatar
LamarMoore committed
114
115
    const std::string &, const IMDWorkspace_sptr, const WorkspaceGroup_sptr,
    bool, bool, const std::string &, bool);
116

117
template MANTID_API_DLL IMDWorkspace_sptr executeBinaryOperation(
LamarMoore's avatar
LamarMoore committed
118
119
    const std::string &, const IMDWorkspace_sptr, const MatrixWorkspace_sptr,
    bool, bool, const std::string &, bool);
120
template MANTID_API_DLL IMDWorkspace_sptr executeBinaryOperation(
LamarMoore's avatar
LamarMoore committed
121
122
    const std::string &, const MatrixWorkspace_sptr, const IMDWorkspace_sptr,
    bool, bool, const std::string &, bool);
123

124
template MANTID_API_DLL IMDHistoWorkspace_sptr executeBinaryOperation(
LamarMoore's avatar
LamarMoore committed
125
126
    const std::string &, const IMDHistoWorkspace_sptr,
    const IMDHistoWorkspace_sptr, bool, bool, const std::string &, bool);
127
template MANTID_API_DLL IMDHistoWorkspace_sptr executeBinaryOperation(
LamarMoore's avatar
LamarMoore committed
128
129
    const std::string &, const IMDHistoWorkspace_sptr,
    const MatrixWorkspace_sptr, bool, bool, const std::string &, bool);
130
template MANTID_API_DLL IMDHistoWorkspace_sptr executeBinaryOperation(
LamarMoore's avatar
LamarMoore committed
131
132
    const std::string &, const MatrixWorkspace_sptr,
    const IMDHistoWorkspace_sptr, bool, bool, const std::string &, bool);
133

134
} // namespace OperatorOverloads
135

136
/** Performs a comparison operation on two workspaces, using the
137
 * CompareWorkspaces algorithm
138
139
140
 *
 *  @param lhs :: left hand side workspace shared pointer
 *  @param rhs :: right hand side workspace shared pointer
141
 *  @param tolerance :: acceptable difference for floating point numbers
142
143
 *  @return bool, true if workspaces match
 */
David Fairbrother's avatar
David Fairbrother committed
144
bool equals(const MatrixWorkspace_sptr &lhs, const MatrixWorkspace_sptr &rhs,
145
146
            double tolerance) {
  IAlgorithm_sptr alg =
147
      AlgorithmManager::Instance().createUnmanaged("CompareWorkspaces");
148
149
150
  alg->setChild(true);
  alg->setRethrows(false);
  alg->initialize();
151
152
  alg->setProperty<MatrixWorkspace_sptr>("Workspace1", lhs);
  alg->setProperty<MatrixWorkspace_sptr>("Workspace2", rhs);
153
  alg->setProperty<double>("Tolerance", tolerance);
154
155
156
  // Rest: use default

  alg->execute();
157
  if (!alg->isExecuted()) {
158
    std::string message = "Error while executing operation: CompareWorkspaces";
159
    throw std::runtime_error(message);
160
  }
161
  return alg->getProperty("Result");
162
}
163

164
/** Creates a temporary single value workspace the error is set to zero
165
 *  @param rhsValue :: the value to use
166
 *  @return The value in a workspace shared pointer
167
 */
168
169
170
171
static MatrixWorkspace_sptr createWorkspaceSingleValue(const double &rhsValue) {
  MatrixWorkspace_sptr retVal =
      WorkspaceFactory::Instance().create("WorkspaceSingleValue", 1, 1, 1);
  retVal->dataY(0)[0] = rhsValue;
172
173
174

  return retVal;
}
175

176
177
using OperatorOverloads::executeBinaryOperation;

178
/** Adds two workspaces
179
 *  @param lhs :: left hand side workspace shared pointer
180
181
 *  @param rhs :: right hand side workspace shared pointer
 *  @return The result in a workspace shared pointer
182
 */
David Fairbrother's avatar
David Fairbrother committed
183
184
MatrixWorkspace_sptr operator+(const MatrixWorkspace_sptr &lhs,
                               const MatrixWorkspace_sptr &rhs) {
185
186
  return executeBinaryOperation<MatrixWorkspace_sptr, MatrixWorkspace_sptr,
                                MatrixWorkspace_sptr>("Plus", lhs, rhs);
187
188
189
}

/** Adds a workspace to a single value
190
191
 *  @param lhs ::      left hand side workspace shared pointer
 *  @param rhsValue :: the single value
192
 *  @return The result in a workspace shared pointer
193
 */
David Fairbrother's avatar
David Fairbrother committed
194
MatrixWorkspace_sptr operator+(const MatrixWorkspace_sptr &lhs,
195
196
197
198
                               const double &rhsValue) {
  return executeBinaryOperation<MatrixWorkspace_sptr, MatrixWorkspace_sptr,
                                MatrixWorkspace_sptr>(
      "Plus", lhs, createWorkspaceSingleValue(rhsValue));
199
200
201
}

/** Subtracts two workspaces
202
 *  @param lhs :: left hand side workspace shared pointer
203
204
 *  @param rhs :: right hand side workspace shared pointer
 *  @return The result in a workspace shared pointer
205
 */
David Fairbrother's avatar
David Fairbrother committed
206
207
MatrixWorkspace_sptr operator-(const MatrixWorkspace_sptr &lhs,
                               const MatrixWorkspace_sptr &rhs) {
208
209
  return executeBinaryOperation<MatrixWorkspace_sptr, MatrixWorkspace_sptr,
                                MatrixWorkspace_sptr>("Minus", lhs, rhs);
210
211
212
}

/** Subtracts  a single value from a workspace
213
214
 *  @param lhs ::      left hand side workspace shared pointer
 *  @param rhsValue :: the single value
215
 *  @return The result in a workspace shared pointer
216
 */
David Fairbrother's avatar
David Fairbrother committed
217
MatrixWorkspace_sptr operator-(const MatrixWorkspace_sptr &lhs,
218
219
220
221
                               const double &rhsValue) {
  return executeBinaryOperation<MatrixWorkspace_sptr, MatrixWorkspace_sptr,
                                MatrixWorkspace_sptr>(
      "Minus", lhs, createWorkspaceSingleValue(rhsValue));
222
223
}

224
/** Subtracts a workspace from a single value
225
226
 *  @param lhsValue :: the single value
 *  @param rhs :: right-hand side workspace shared pointer
227
 *  @return The result in a workspace shared pointer
228
 */
229
MatrixWorkspace_sptr operator-(const double &lhsValue,
David Fairbrother's avatar
David Fairbrother committed
230
                               const MatrixWorkspace_sptr &rhs) {
231
232
233
  return executeBinaryOperation<MatrixWorkspace_sptr, MatrixWorkspace_sptr,
                                MatrixWorkspace_sptr>(
      "Minus", createWorkspaceSingleValue(lhsValue), rhs);
234
}
235
/** Multiply two workspaces
236
 *  @param lhs :: left hand side workspace shared pointer
237
238
 *  @param rhs :: right hand side workspace shared pointer
 *  @return The result in a workspace shared pointer
239
 */
David Fairbrother's avatar
David Fairbrother committed
240
241
MatrixWorkspace_sptr operator*(const MatrixWorkspace_sptr &lhs,
                               const MatrixWorkspace_sptr &rhs) {
242
243
  return executeBinaryOperation<MatrixWorkspace_sptr, MatrixWorkspace_sptr,
                                MatrixWorkspace_sptr>("Multiply", lhs, rhs);
244
245
246
}

/** Multiply a workspace and a single value
247
248
 *  @param lhs ::      left hand side workspace shared pointer
 *  @param rhsValue :: the single value
249
 *  @return The result in a workspace shared pointer
250
 */
David Fairbrother's avatar
David Fairbrother committed
251
MatrixWorkspace_sptr operator*(const MatrixWorkspace_sptr &lhs,
252
253
254
255
                               const double &rhsValue) {
  return executeBinaryOperation<MatrixWorkspace_sptr, MatrixWorkspace_sptr,
                                MatrixWorkspace_sptr>(
      "Multiply", lhs, createWorkspaceSingleValue(rhsValue));
256
257
}

258
259
/** Multiply a workspace and a single value. Allows you to write, e.g.,
 * 2*workspace.
260
261
 *  @param lhsValue :: the single value
 *  @param rhs ::      workspace shared pointer
262
 *  @return The result in a workspace shared pointer
263
 */
264
MatrixWorkspace_sptr operator*(const double &lhsValue,
David Fairbrother's avatar
David Fairbrother committed
265
                               const MatrixWorkspace_sptr &rhs) {
266
267
268
  return executeBinaryOperation<MatrixWorkspace_sptr, MatrixWorkspace_sptr,
                                MatrixWorkspace_sptr>(
      "Multiply", createWorkspaceSingleValue(lhsValue), rhs);
269
270
}

271
/** Divide two workspaces
272
 *  @param lhs :: left hand side workspace shared pointer
273
274
 *  @param rhs :: right hand side workspace shared pointer
 *  @return The result in a workspace shared pointer
275
 */
David Fairbrother's avatar
David Fairbrother committed
276
277
MatrixWorkspace_sptr operator/(const MatrixWorkspace_sptr &lhs,
                               const MatrixWorkspace_sptr &rhs) {
278
279
  return executeBinaryOperation<MatrixWorkspace_sptr, MatrixWorkspace_sptr,
                                MatrixWorkspace_sptr>("Divide", lhs, rhs);
280
281
282
}

/** Divide a workspace by a single value
283
284
 *  @param lhs ::      left hand side workspace shared pointer
 *  @param rhsValue :: the single value
285
 *  @return The result in a workspace shared pointer
286
 */
David Fairbrother's avatar
David Fairbrother committed
287
MatrixWorkspace_sptr operator/(const MatrixWorkspace_sptr &lhs,
288
289
290
291
                               const double &rhsValue) {
  return executeBinaryOperation<MatrixWorkspace_sptr, MatrixWorkspace_sptr,
                                MatrixWorkspace_sptr>(
      "Divide", lhs, createWorkspaceSingleValue(rhsValue));
292
}
Nick Draper's avatar
re #75  
Nick Draper committed
293

294
295
/** Divide a single value and a workspace. Allows you to write, e.g.,
 * 2/workspace.
296
297
 *  @param lhsValue :: the single value
 *  @param rhs ::      workspace shared pointer
298
 *  @return The result in a workspace shared pointer
299
 */
300
MatrixWorkspace_sptr operator/(const double &lhsValue,
David Fairbrother's avatar
David Fairbrother committed
301
                               const MatrixWorkspace_sptr &rhs) {
302
303
304
  return executeBinaryOperation<MatrixWorkspace_sptr, MatrixWorkspace_sptr,
                                MatrixWorkspace_sptr>(
      "Divide", createWorkspaceSingleValue(lhsValue), rhs);
305
306
}

307
/** Adds two workspaces
308
 *  @param lhs :: left hand side workspace shared pointer
309
310
 *  @param rhs :: right hand side workspace shared pointer
 *  @return The result in a workspace shared pointer
311
 */
David Fairbrother's avatar
David Fairbrother committed
312
313
MatrixWorkspace_sptr operator+=(const MatrixWorkspace_sptr &lhs,
                                const MatrixWorkspace_sptr &rhs) {
314
315
  return executeBinaryOperation<MatrixWorkspace_sptr, MatrixWorkspace_sptr,
                                MatrixWorkspace_sptr>("Plus", lhs, rhs, true);
316
}
Nick Draper's avatar
re #75  
Nick Draper committed
317

318
/** Adds a single value to a workspace
319
320
 *  @param lhs ::      workspace shared pointer
 *  @param rhsValue :: the single value
321
 *  @return The result in a workspace shared pointer
322
 */
David Fairbrother's avatar
David Fairbrother committed
323
MatrixWorkspace_sptr operator+=(const MatrixWorkspace_sptr &lhs,
324
325
326
327
                                const double &rhsValue) {
  return executeBinaryOperation<MatrixWorkspace_sptr, MatrixWorkspace_sptr,
                                MatrixWorkspace_sptr>(
      "Plus", lhs, createWorkspaceSingleValue(rhsValue), true);
328
}
Nick Draper's avatar
re #75  
Nick Draper committed
329

330
/** Subtracts two workspaces
331
 *  @param lhs :: left hand side workspace shared pointer
332
333
 *  @param rhs :: right hand side workspace shared pointer
 *  @return The result in a workspace shared pointer
334
 */
David Fairbrother's avatar
David Fairbrother committed
335
336
MatrixWorkspace_sptr operator-=(const MatrixWorkspace_sptr &lhs,
                                const MatrixWorkspace_sptr &rhs) {
337
338
  return executeBinaryOperation<MatrixWorkspace_sptr, MatrixWorkspace_sptr,
                                MatrixWorkspace_sptr>("Minus", lhs, rhs, true);
339
340
341
}

/** Subtracts a single value from a workspace
342
343
 *  @param lhs ::      workspace shared pointer
 *  @param rhsValue :: the single value
344
 *  @return The result in a workspace shared pointer
345
 */
David Fairbrother's avatar
David Fairbrother committed
346
MatrixWorkspace_sptr operator-=(const MatrixWorkspace_sptr &lhs,
347
348
349
350
                                const double &rhsValue) {
  return executeBinaryOperation<MatrixWorkspace_sptr, MatrixWorkspace_sptr,
                                MatrixWorkspace_sptr>(
      "Minus", lhs, createWorkspaceSingleValue(rhsValue), true);
351
352
353
}

/** Multiply two workspaces
354
 *  @param lhs :: left hand side workspace shared pointer
355
356
 *  @param rhs :: right hand side workspace shared pointer
 *  @return The result in a workspace shared pointer
357
 */
David Fairbrother's avatar
David Fairbrother committed
358
359
MatrixWorkspace_sptr operator*=(const MatrixWorkspace_sptr &lhs,
                                const MatrixWorkspace_sptr &rhs) {
360
361
362
  return executeBinaryOperation<MatrixWorkspace_sptr, MatrixWorkspace_sptr,
                                MatrixWorkspace_sptr>("Multiply", lhs, rhs,
                                                      true);
363
364
365
}

/** Multiplies a workspace by a single value
366
367
 *  @param lhs ::      workspace shared pointer
 *  @param rhsValue :: the single value
368
 *  @return The result in a workspace shared pointer
369
 */
David Fairbrother's avatar
David Fairbrother committed
370
MatrixWorkspace_sptr operator*=(const MatrixWorkspace_sptr &lhs,
371
372
373
374
                                const double &rhsValue) {
  return executeBinaryOperation<MatrixWorkspace_sptr, MatrixWorkspace_sptr,
                                MatrixWorkspace_sptr>(
      "Multiply", lhs, createWorkspaceSingleValue(rhsValue), true);
375
376
377
}

/** Divide two workspaces
378
 *  @param lhs :: left hand side workspace shared pointer
379
380
 *  @param rhs :: right hand side workspace shared pointer
 *  @return The result in a workspace shared pointer
381
 */
David Fairbrother's avatar
David Fairbrother committed
382
383
MatrixWorkspace_sptr operator/=(const MatrixWorkspace_sptr &lhs,
                                const MatrixWorkspace_sptr &rhs) {
384
385
  return executeBinaryOperation<MatrixWorkspace_sptr, MatrixWorkspace_sptr,
                                MatrixWorkspace_sptr>("Divide", lhs, rhs, true);
386
387
388
}

/** Divides a workspace by a single value
389
390
 *  @param lhs ::      workspace shared pointer
 *  @param rhsValue :: the single value
391
 *  @return The result in a workspace shared pointer
392
 */
David Fairbrother's avatar
David Fairbrother committed
393
MatrixWorkspace_sptr operator/=(const MatrixWorkspace_sptr &lhs,
394
395
396
397
                                const double &rhsValue) {
  return executeBinaryOperation<MatrixWorkspace_sptr, MatrixWorkspace_sptr,
                                MatrixWorkspace_sptr>(
      "Divide", lhs, createWorkspaceSingleValue(rhsValue), true);
398
399
400
401
402
}

//----------------------------------------------------------------------
// Now the WorkspaceHelpers methods
//----------------------------------------------------------------------
403

404
/** Checks whether the bins (X values) of two workspace are the same
405
406
 *  @param ws1 :: The first workspace
 *  @param ws2 :: The second workspace
407
408
409
410
 *  @param firstOnly :: If true, only the first spectrum is checked. If false
 * (the default), all spectra
 *                   are checked and the two workspaces must have the same
 * number of spectra
411
412
 *  @return True if the test passes
 */
413
414
bool WorkspaceHelpers::matchingBins(const MatrixWorkspace &ws1,
                                    const MatrixWorkspace &ws2,
415
                                    const bool firstOnly) {
416
  // First of all, the first vector must be the same size
417
  if (ws1.x(0).size() != ws2.x(0).size())
418
    return false;
419
420

  // Now check the first spectrum
421
422
  const double firstWS = std::accumulate(ws1.x(0).begin(), ws1.x(0).end(), 0.);
  const double secondWS = std::accumulate(ws2.x(0).begin(), ws2.x(0).end(), 0.);
423
  if (std::abs(firstWS) < 1.0E-7 && std::abs(secondWS) < 1.0E-7) {
424
425
    for (size_t i = 0; i < ws1.x(0).size(); i++) {
      if (std::abs(ws1.x(0)[i] - ws2.x(0)[i]) > 1.0E-7)
426
        return false;
427
    }
428
429
430
431
  } else if (std::abs(firstWS - secondWS) /
                 std::max<double>(std::abs(firstWS), std::abs(secondWS)) >
             1.0E-7)
    return false;
432

433
  // If we were only asked to check the first spectrum, return now
434
435
  if (firstOnly)
    return true;
436
437

  // Check that total size of workspace is the same
438
  if (ws1.size() != ws2.size())
439
    return false;
440
  // If that passes then check whether all the X vectors are shared
441
442
  if (sharedXData(ws1) && sharedXData(ws2))
    return true;
443

444
445
  // If that didn't pass then explicitly check 1 in 10 of the vectors (min 10,
  // max 100)
446
  const size_t numHist = ws1.getNumberHistograms();
Doucet, Mathieu's avatar
Doucet, Mathieu committed
447
  size_t numberToCheck = numHist / 10;
448
449
450
451
  if (numberToCheck < 10)
    numberToCheck = 10;
  if (numberToCheck > 100)
    numberToCheck = 100;
Doucet, Mathieu's avatar
Doucet, Mathieu committed
452
  size_t step = numHist / numberToCheck;
453
454
455
  if (!step)
    step = 1;
  for (size_t i = step; i < numHist; i += step) {
456
    const double firstWSLoop =
457
        std::accumulate(ws1.x(i).begin(), ws1.x(i).end(), 0.);
458
    const double secondWSLoop =
459
        std::accumulate(ws2.x(i).begin(), ws2.x(i).end(), 0.);
460
    if (std::abs(firstWSLoop) < 1.0E-7 && std::abs(secondWSLoop) < 1.0E-7) {
461
462
      for (size_t j = 0; j < ws1.x(i).size(); j++) {
        if (std::abs(ws1.x(i)[j] - ws2.x(i)[j]) > 1.0E-7)
463
          return false;
464
      }
465
    } else if (std::abs(firstWSLoop - secondWSLoop) /
466
467
                   std::max<double>(std::abs(firstWSLoop),
                                    std::abs(secondWSLoop)) >
468
469
               1.0E-7)
      return false;
470
471
472
473
474
475
  }

  return true;
}

/// Checks whether all the X vectors in a workspace are the same one underneath
476
bool WorkspaceHelpers::sharedXData(const MatrixWorkspace &WS) {
477
  const double &first = WS.x(0)[0];
478
  const size_t numHist = WS.getNumberHistograms();
479
  for (size_t i = 1; i < numHist; ++i) {
480
    if (&first != &(WS.x(i)[0]))
481
      return false;
482
483
484
485
  }
  return true;
}

486
487
488
/** Divides the data in a workspace by the bin width to make it a distribution.
 *  Can also reverse this operation (i.e. multiply by the bin width).
 *  Sets the isDistribution() flag accordingly.
489
 *  @param workspace :: The workspace on which to carry out the operation
490
491
 *  @param forwards :: If true (the default) divides by bin width, if false
 * multiplies
492
 */
David Fairbrother's avatar
David Fairbrother committed
493
void WorkspaceHelpers::makeDistribution(const MatrixWorkspace_sptr &workspace,
494
                                        const bool forwards) {
495
496
497
498
499
500
  // If we're not able to get a writable reference to Y, then this is an event
  // workspace, which we can't operate on.
  if (workspace->id() == "EventWorkspace")
    throw std::runtime_error("Event workspaces cannot be directly converted "
                             "into distributions.");

501
  const size_t numberOfSpectra = workspace->getNumberHistograms();
Thomas Lohnert's avatar
Thomas Lohnert committed
502
503
  if (workspace->histogram(0).xMode() ==
      HistogramData::Histogram::XMode::Points) {
Thomas Lohnert's avatar
Thomas Lohnert committed
504
505
    throw std::runtime_error(
        "Workspace is using point data for x (should be bin edges).");
506
  }
507
508
  for (size_t i = 0; i < numberOfSpectra; ++i) {
    if (forwards) {
509
      workspace->convertToFrequencies(i);
510
    } else {
511
      workspace->convertToCounts(i);
512
    }
513
514
515
  }
}

516
517
} // namespace API
} // namespace Mantid