ThresholdMD.cpp 5.05 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
#include "MantidMDAlgorithms/ThresholdMD.h"
LamarMoore's avatar
LamarMoore committed
8
#include "MantidAPI/Progress.h"
9
#include "MantidAPI/WorkspaceProperty.h"
10
#include "MantidDataObjects/MDHistoWorkspace.h"
11
#include "MantidKernel/EnabledWhenProperty.h"
LamarMoore's avatar
LamarMoore committed
12
#include "MantidKernel/ListValidator.h"
13
#include "MantidKernel/MultiThreaded.h"
LamarMoore's avatar
LamarMoore committed
14
#include <boost/function.hpp>
15
16
17

using namespace Mantid::Kernel;
using namespace Mantid::API;
18
using namespace Mantid::DataObjects;
19

20
21
22
23
24
25
26
27
28
29
30
31
namespace Mantid {
namespace MDAlgorithms {

// Register the algorithm into the AlgorithmFactory
DECLARE_ALGORITHM(ThresholdMD)

std::string LessThan() { return "Less Than"; }

std::string GreaterThan() { return "Greater Than"; }

//----------------------------------------------------------------------------------------------
/// Algorithm's name for identification. @see Algorithm::name
32
const std::string ThresholdMD::name() const { return "ThresholdMD"; }
33
34

/// Algorithm's version for identification. @see Algorithm::version
35
int ThresholdMD::version() const { return 1; }
36
37

/// Algorithm's category for identification. @see Algorithm::category
Nick Draper's avatar
Nick Draper committed
38
39
40
const std::string ThresholdMD::category() const {
  return "MDAlgorithms\\Transforms";
}
41
42
43
44
45
46
47

//----------------------------------------------------------------------------------------------

//----------------------------------------------------------------------------------------------
/** Initialize the algorithm's properties.
 */
void ThresholdMD::init() {
48
  declareProperty(std::make_unique<WorkspaceProperty<IMDHistoWorkspace>>(
49
                      "InputWorkspace", "", Direction::Input),
50
51
52
                  "An input workspace.");

  std::vector<std::string> propOptions;
53
54
  propOptions.emplace_back(LessThan());
  propOptions.emplace_back(GreaterThan());
55
56

  declareProperty("Condition", LessThan(),
57
                  std::make_shared<StringListValidator>(propOptions),
58
59
60
61
62
63
64
                  "Selected threshold condition. Any value which does meet "
                  "this condition with respect to the ReferenceValue will be "
                  "overwritten.");

  declareProperty("ReferenceValue", 0.0,
                  "Comparator value used by the Condition.");

LamarMoore's avatar
LamarMoore committed
65
66
67
68
  declareProperty("OverwriteWithZero", true,
                  "Flag for enabling overwriting "
                  "with a custom value. Defaults to "
                  "overwrite signals with zeros.");
69
70
71

  declareProperty("CustomOverwriteValue", 0.0,
                  "Custom overwrite value for the signal. Defaults to zero.");
Sam Jenkins's avatar
Sam Jenkins committed
72
73
74
  setPropertySettings("CustomOverwriteValue",
                      std::make_unique<EnabledWhenProperty>("OverwriteWithZero",
                                                            IS_NOT_DEFAULT));
75

76
  declareProperty(std::make_unique<WorkspaceProperty<IMDHistoWorkspace>>(
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
                      "OutputWorkspace", "", Direction::Output),
                  "Output thresholded workspace.");
}

//----------------------------------------------------------------------------------------------
/** Execute the algorithm.
 */
void ThresholdMD::exec() {
  IMDHistoWorkspace_sptr inputWS = getProperty("InputWorkspace");
  const std::string condition = getProperty("Condition");
  const double referenceValue = getProperty("ReferenceValue");
  const bool doOverwriteWithZero = getProperty("OverwriteWithZero");
  double customOverwriteValue = getProperty("CustomOverwriteValue");
  if (doOverwriteWithZero) {
    customOverwriteValue = 0;
  }

  IMDHistoWorkspace_sptr outWS = getProperty("OutputWorkspace");
  if (outWS != inputWS) {
    g_log.debug("Deep copy input workspace as output workspace.");
    IAlgorithm_sptr alg = createChildAlgorithm("CloneMDWorkspace");
    alg->setProperty("InputWorkspace", inputWS);
    alg->executeAsChildAlg();
    IMDWorkspace_sptr temp = alg->getProperty("OutputWorkspace");
101
    outWS = std::dynamic_pointer_cast<IMDHistoWorkspace>(temp);
102
103
104
105
  }

  const int64_t nPoints = inputWS->getNPoints();

106
  using namespace std::placeholders;
107
  boost::function<bool(double)> comparitor =
108
      std::bind(std::less<double>(), std::placeholders::_1, referenceValue);
109
  if (condition == GreaterThan()) {
110
111
    comparitor = std::bind(std::greater<double>(), std::placeholders::_1,
                           referenceValue);
112
113
  }

114
  Progress prog(this, 0.0, 1.0, 100);
115
116
117
118
119
  int64_t frequency = nPoints;
  if (nPoints > 100) {
    frequency = nPoints / 100;
  }

120
  PARALLEL_FOR_IF(Kernel::threadSafe(*inputWS, *outWS))
121
122
123
124
125
  for (int64_t i = 0; i < nPoints; ++i) {
    PARALLEL_START_INTERUPT_REGION
    const double signalAt = inputWS->getSignalAt(i);
    if (comparitor(signalAt)) {
      outWS->setSignalAt(i, customOverwriteValue);
126
    }
127
128
    if (i % frequency == 0) {
      prog.report();
129
    }
130
131
132
    PARALLEL_END_INTERUPT_REGION
  }
  PARALLEL_CHECK_INTERUPT_REGION
133

134
135
  setProperty("OutputWorkspace", outWS);
}
136

137
} // namespace MDAlgorithms
138
} // namespace Mantid