CentroidPeaksMD.cpp 6.2 KB
Newer Older
1
2
#include "MantidAPI/IMDEventWorkspace.h"
#include "MantidDataObjects/PeaksWorkspace.h"
3
#include "MantidKernel/System.h"
4
#include "MantidMDEvents/CoordTransformDistance.h"
5
#include "MantidMDEvents/CentroidPeaksMD.h"
6
#include "MantidMDEvents/MDEventFactory.h"
7
#include "MantidMDEvents/IntegratePeaksMD.h"
8
9

using Mantid::DataObjects::PeaksWorkspace;
10
11
12
13
14
15
16

namespace Mantid
{
namespace MDEvents
{

  // Register the algorithm into the AlgorithmFactory
17
  DECLARE_ALGORITHM(CentroidPeaksMD)
18
19
  
  using namespace Mantid::API;
20
21
22
23
  using namespace Mantid::DataObjects;
  using namespace Mantid::Geometry;
  using namespace Mantid::Kernel;
  using namespace Mantid::MDEvents;
24
25
26
27
28


  //----------------------------------------------------------------------------------------------
  /** Constructor
   */
29
  CentroidPeaksMD::CentroidPeaksMD()
30
31
32
33
34
35
  {
  }
    
  //----------------------------------------------------------------------------------------------
  /** Destructor
   */
36
  CentroidPeaksMD::~CentroidPeaksMD()
37
38
39
40
41
42
  {
  }
  

  //----------------------------------------------------------------------------------------------
  /// Sets documentation strings for this algorithm
43
  void CentroidPeaksMD::initDocs()
44
45
46
47
48
49
50
51
  {
    this->setWikiSummary("Find the centroid of single-crystal peaks in a MDEventWorkspace, in order to refine their positions.");
    this->setOptionalMessage("Find the centroid of single-crystal peaks in a MDEventWorkspace, in order to refine their positions.");
  }

  //----------------------------------------------------------------------------------------------
  /** Initialize the algorithm's properties.
   */
52
  void CentroidPeaksMD::init()
53
  {
54
55
56
    declareProperty(new WorkspaceProperty<IMDEventWorkspace>("InputWorkspace","",Direction::Input), "An input MDEventWorkspace.");

    std::vector<std::string> propOptions;
57
58
    propOptions.push_back("Q (lab frame)");
    propOptions.push_back("Q (sample frame)");
59
60
61
62
63
64
65
66
    propOptions.push_back("HKL");
    declareProperty("CoordinatesToUse", "HKL",new ListValidator(propOptions),
      "Which coordinates of the peak center do you wish to use to find the center? This should match the InputWorkspace's dimensions."
       );

    declareProperty(new PropertyWithValue<double>("PeakRadius",1.0,Direction::Input),
        "Fixed radius around each peak position in which to calculate the centroid.");

67
68
69
70
71
72
    declareProperty(new WorkspaceProperty<PeaksWorkspace>("PeaksWorkspace","",Direction::Input),
        "A PeaksWorkspace containing the peaks to centroid.");

    declareProperty(new WorkspaceProperty<PeaksWorkspace>("OutputWorkspace","",Direction::Output),
        "The output PeaksWorkspace will be a copy of the input PeaksWorkspace "
        "with the peaks' positions modified by the new found centroids.");
73
74
75
  }

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

85
86
87
88
89
90
91
    /// 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)
      peakWS = inPeakWS->clone();
92
93
94
95
96
97
98
99
100
101
102
103
104

    /// Value of the CoordinatesToUse property.
    std::string CoordinatesToUse = getPropertyValue("CoordinatesToUse");

    // TODO: Confirm that the coordinates requested match those in the MDEventWorkspace

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

    PRAGMA_OMP(parallel for schedule(dynamic, 10) )
    for (int i=0; i < int(peakWS->getNumberPeaks()); ++i)
    {
      // Get a direct ref to that peak.
105
      IPeak & p = peakWS->getPeak(i);
106
      double detectorDistance = p.getL2();
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127

      // Get the peak center as a position in the dimensions of the workspace
      V3D pos;
      if (CoordinatesToUse == "Q (lab frame)")
        pos = p.getQLabFrame();
      else if (CoordinatesToUse == "Q (sample frame)")
        pos = p.getQSampleFrame();
      else if (CoordinatesToUse == "HKL")
        pos = p.getHKL();

      // Build the sphere transformation
      bool dimensionsUsed[nd];
      coord_t center[nd];
      for (size_t d=0; d<nd; ++d)
      {
        dimensionsUsed[d] = true; // Use all dimensions
        center[d] = pos[d];
      }
      CoordTransformDistance sphere(nd, center, dimensionsUsed);

      // Initialize the centroid to 0.0
128
      signal_t signal = 0;
129
130
131
132
133
134
135
136
137
138
139
140
141
      coord_t centroid[nd];
      for (size_t d=0; d<nd; d++)
        centroid[d] = 0.0;

      // Perform centroid
      ws->getBox()->centroidSphere(sphere, PeakRadius*PeakRadius, centroid, signal);

      // Normalize by signal
      if (signal != 0.0)
      {
        for (size_t d=0; d<nd; d++)
          centroid[d] /= signal;

142
143
144
145
146
147
148
149
150
151
        V3D vecCentroid(centroid[0], centroid[1], centroid[2]);

        // Save it back in the peak object, in the dimension specified.
        if (CoordinatesToUse == "Q (lab frame)")
          p.setQLabFrame( vecCentroid, detectorDistance);
        else if (CoordinatesToUse == "Q (sample frame)")
          p.setQSampleFrame( vecCentroid, detectorDistance);
        else if (CoordinatesToUse == "HKL")
          p.setHKL( vecCentroid );

152
153

        g_log.information() << "Peak " << i << " at " << pos << ": signal "
154
155
            << signal << ", centroid " << vecCentroid
            << " in " << CoordinatesToUse
156
157
158
159
160
161
162
163
164
            << std::endl;
      }
      else
      {
        g_log.information() << "Peak " << i << " at " << pos << " had no signal, and could not be centroided."
            << std::endl;
      }
    }

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

168
169
  }

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

177
    CALL_MDEVENT_FUNCTION3(this->integrate, inWS);
178
  }
179
180
181
182

} // namespace Mantid
} // namespace MDEvents