CentroidPeaksMD.cpp 6.78 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 +
LamarMoore's avatar
LamarMoore committed
7
#include "MantidMDAlgorithms/CentroidPeaksMD.h"
8
#include "MantidAPI/IMDEventWorkspace.h"
9
10
#include "MantidDataObjects/CoordTransformDistance.h"
#include "MantidDataObjects/MDEventFactory.h"
LamarMoore's avatar
LamarMoore committed
11
12
13
#include "MantidDataObjects/PeaksWorkspace.h"
#include "MantidKernel/ListValidator.h"
#include "MantidKernel/System.h"
14
15
#include "MantidMDAlgorithms/IntegratePeaksMD.h"

16
using Mantid::DataObjects::PeaksWorkspace;
17

18
19
20
21
22
23
24
25
26
27
namespace Mantid {
namespace MDAlgorithms {

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

using namespace Mantid::API;
using namespace Mantid::DataObjects;
using namespace Mantid::Geometry;
using namespace Mantid::Kernel;
28
using namespace Mantid::DataObjects;
29

Nick Draper's avatar
Nick Draper committed
30
31
CentroidPeaksMD::CentroidPeaksMD() { this->useAlgorithm("CentroidPeaksMD", 2); }

32
33
34
35
//----------------------------------------------------------------------------------------------
/** Initialize the algorithm's properties.
 */
void CentroidPeaksMD::init() {
36
  declareProperty(std::make_unique<WorkspaceProperty<IMDEventWorkspace>>(
37
                      "InputWorkspace", "", Direction::Input),
38
39
                  "An input MDEventWorkspace.");

40
41
  std::vector<std::string> propOptions{"Q (lab frame)", "Q (sample frame)",
                                       "HKL"};
42
  declareProperty("CoordinatesToUse", "HKL",
43
                  std::make_shared<StringListValidator>(propOptions),
44
45
46
                  "Ignored:  algorithm uses the InputWorkspace's coordinates.");

  declareProperty(
47
      std::make_unique<PropertyWithValue<double>>("PeakRadius", 1.0,
Sam Jenkins's avatar
Sam Jenkins committed
48
                                                  Direction::Input),
49
50
51
      "Fixed radius around each peak position in which to calculate the "
      "centroid.");

52
  declareProperty(std::make_unique<WorkspaceProperty<PeaksWorkspace>>(
53
                      "PeaksWorkspace", "", Direction::Input),
54
55
56
                  "A PeaksWorkspace containing the peaks to centroid.");

  declareProperty(
57
      std::make_unique<WorkspaceProperty<PeaksWorkspace>>("OutputWorkspace", "",
Sam Jenkins's avatar
Sam Jenkins committed
58
                                                          Direction::Output),
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
      "The output PeaksWorkspace will be a copy of the input PeaksWorkspace "
      "with the peaks' positions modified by the new found centroids.");
}

//----------------------------------------------------------------------------------------------
/** Integrate the peaks of the workspace using parameters saved in the algorithm
 * class
 * @param ws ::  MDEventWorkspace to integrate
 */
template <typename MDE, size_t nd>
void CentroidPeaksMD::integrate(typename MDEventWorkspace<MDE, nd>::sptr ws) {
  if (nd != 3)
    throw std::invalid_argument("For now, we expect the input MDEventWorkspace "
                                "to have 3 dimensions only.");

  /// Peak workspace to centroid
  Mantid::DataObjects::PeaksWorkspace_sptr inPeakWS =
      getProperty("PeaksWorkspace");

  /// Output peaks workspace, create if needed
  Mantid::DataObjects::PeaksWorkspace_sptr peakWS =
      getProperty("OutputWorkspace");
  if (peakWS != inPeakWS)
82
    peakWS = inPeakWS->clone();
83
84
85
86
87

  std::string CoordinatesToUseStr = getPropertyValue("CoordinatesToUse");
  int CoordinatesToUse = ws->getSpecialCoordinateSystem();
  if (CoordinatesToUse == 1 && CoordinatesToUseStr != "Q (lab frame)")
    g_log.warning() << "Warning: used Q (lab frame) coordinates for MD "
Hahn, Steven's avatar
Hahn, Steven committed
88
                       "workspace, not CoordinatesToUse from input \n";
89
90
  else if (CoordinatesToUse == 2 && CoordinatesToUseStr != "Q (sample frame)")
    g_log.warning() << "Warning: used Q (sample frame) coordinates for MD "
Hahn, Steven's avatar
Hahn, Steven committed
91
                       "workspace, not CoordinatesToUse from input \n";
92
93
  else if (CoordinatesToUse == 3 && CoordinatesToUseStr != "HKL")
    g_log.warning() << "Warning: used HKL coordinates for MD workspace, not "
94
                       "CoordinatesToUse from input \n";
95
96
97
98
99

  /// Radius to use around peaks
  double PeakRadius = getProperty("PeakRadius");

  // cppcheck-suppress syntaxError
100
    PRAGMA_OMP(parallel for schedule(dynamic, 10) )
101
    for (int i = 0; i < int(peakWS->getNumberPeaks()); ++i) {
102
      Peak &p = peakWS->getPeak(i);
103
      double detectorDistance = p.getL2();
104
105
106

      // Get the peak center as a position in the dimensions of the workspace
      V3D pos;
107
      if (CoordinatesToUse == 1) //"Q (lab frame)"
108
        pos = p.getQLabFrame();
109
      else if (CoordinatesToUse == 2) //"Q (sample frame)"
110
        pos = p.getQSampleFrame();
111
      else if (CoordinatesToUse == 3) //"HKL"
112
113
114
115
116
        pos = p.getHKL();

      // Build the sphere transformation
      bool dimensionsUsed[nd];
      coord_t center[nd];
117
      for (size_t d = 0; d < nd; ++d) {
118
        dimensionsUsed[d] = true; // Use all dimensions
119
        center[d] = static_cast<coord_t>(pos[d]);
120
121
122
123
      }
      CoordTransformDistance sphere(nd, center, dimensionsUsed);

      // Initialize the centroid to 0.0
124
      signal_t signal = 0;
125
      coord_t centroid[nd];
126
      for (size_t d = 0; d < nd; d++)
127
128
129
        centroid[d] = 0.0;

      // Perform centroid
130
131
132
      ws->getBox()->centroidSphere(
          sphere, static_cast<coord_t>(PeakRadius * PeakRadius), centroid,
          signal);
133
134

      // Normalize by signal
135
136
      if (signal != 0.0) {
        for (size_t d = 0; d < nd; d++)
137
          centroid[d] /= static_cast<coord_t>(signal);
138

139
140
141
        V3D vecCentroid(centroid[0], centroid[1], centroid[2]);

        // Save it back in the peak object, in the dimension specified.
142
        if (CoordinatesToUse == 1) //"Q (lab frame)"
143
        {
144
          p.setQLabFrame(vecCentroid, detectorDistance);
145
          p.findDetector();
146
        } else if (CoordinatesToUse == 2) //"Q (sample frame)"
147
        {
148
          p.setQSampleFrame(vecCentroid, detectorDistance);
149
          p.findDetector();
150
        } else if (CoordinatesToUse == 3) //"HKL"
151
        {
152
          p.setHKL(vecCentroid);
153
        }
154

155
        g_log.information() << "Peak " << i << " at " << pos << ": signal "
156
                            << signal << ", centroid " << vecCentroid << " in "
157
                            << CoordinatesToUse << '\n';
158
159
      } else {
        g_log.information() << "Peak " << i << " at " << pos
Hahn, Steven's avatar
Hahn, Steven committed
160
                            << " had no signal, and could not be centroided.\n";
161
162
163
      }
    }

164
165
    // Save the output
    setProperty("OutputWorkspace", peakWS);
166
}
167

168
169
170
171
172
//----------------------------------------------------------------------------------------------
/** Execute the algorithm.
 */
void CentroidPeaksMD::exec() {
  inWS = getProperty("InputWorkspace");
173

174
175
  CALL_MDEVENT_FUNCTION3(this->integrate, inWS);
}
176

LamarMoore's avatar
LamarMoore committed
177
} // namespace MDAlgorithms
178
} // namespace Mantid