Mantid
Loading...
Searching...
No Matches
ConvertCWSDMDtoHKL.cpp
Go to the documentation of this file.
1// Mantid Repository : https://github.com/mantidproject/mantid
2//
3// Copyright © 2018 ISIS Rutherford Appleton Laboratory UKRI,
4// NScD Oak Ridge National Laboratory, European Spallation Source,
5// Institut Laue - Langevin & CSNS, Institute of High Energy Physics, CAS
6// SPDX - License - Identifier: GPL - 3.0 +
8
12#include "MantidAPI/Run.h"
13#include "MantidAPI/Sample.h"
15
23
31
32#include <fstream>
33
34namespace Mantid::MDAlgorithms {
35
36using namespace Mantid::API;
37using namespace Mantid::Kernel;
38using namespace Mantid::MDAlgorithms;
39using namespace Mantid::DataObjects;
40using namespace Mantid::Geometry;
41
43
44
46void ConvertCWSDMDtoHKL::init() {
47 declareProperty(std::make_unique<WorkspaceProperty<IMDEventWorkspace>>("InputWorkspace", "", Direction::Input),
48 "Name of the input MDEventWorkspace that stores detectors "
49 "counts from a constant-wave powder diffraction experiment.");
50
51 declareProperty(std::make_unique<WorkspaceProperty<PeaksWorkspace>>("PeaksWorkspace", "", Direction::Input,
53 "Input Peaks Workspace");
54
55 declareProperty(std::make_unique<ArrayProperty<double>>("UBMatrix"),
56 "A comma seperated list of doubles for UB matrix from (0,0), (0,1)"
57 "... (2,1),(2,2)");
58
59 declareProperty(std::make_unique<WorkspaceProperty<IMDEventWorkspace>>("OutputWorkspace", "", Direction::Output),
60 "Name of the output MDEventWorkspace in HKL-space.");
61
62 declareProperty(std::make_unique<FileProperty>("QSampleFileName", "", API::FileProperty::OptionalSave),
63 "Name of file for sample sample.");
64
65 declareProperty(std::make_unique<FileProperty>("HKLFileName", "", API::FileProperty::OptionalSave),
66 "Name of file for HKL.");
67}
68
72 // Get inputs
73 IMDEventWorkspace_sptr inputWS = getProperty("InputWorkspace");
74 if (inputWS->getSpecialCoordinateSystem() != Mantid::Kernel::QSample) {
75 std::stringstream errmsg;
76 errmsg << "Input MDEventWorkspace's coordinate system is not QSample but " << inputWS->getSpecialCoordinateSystem()
77 << ".";
78 throw std::invalid_argument(errmsg.str());
79 }
80
82
83 // Test indexing. Will be delete soon
84 if (false) {
85 Kernel::V3D qsample; // [1.36639,-2.52888,-4.77349]
86 qsample.setX(1.36639);
87 qsample.setY(-2.52888);
88 qsample.setZ(-4.77349);
89
90 std::vector<Kernel::V3D> vec_qsample;
91 vec_qsample.emplace_back(qsample);
92 std::vector<Kernel::V3D> vec_mindex(0);
93
94 convertFromQSampleToHKL(vec_qsample, vec_mindex);
95 g_log.notice() << "[DB Number of returned Miller Index = " << vec_mindex.size() << "\n";
96 g_log.notice() << "[DB] Output HKL = " << vec_mindex[0].toString() << "\n";
97 }
98
99 // Get events information for future processing
100 std::vector<Kernel::V3D> vec_event_qsample;
101 std::vector<signal_t> vec_event_signal;
102 std::vector<detid_t> vec_event_det;
103 exportEvents(inputWS, vec_event_qsample, vec_event_signal, vec_event_det);
104
105 std::string qsamplefilename = getPropertyValue("QSampleFileName");
106 // Abort with an empty string
107 if (!qsamplefilename.empty())
108 saveEventsToFile(qsamplefilename, vec_event_qsample, vec_event_signal, vec_event_det);
109
110 // Convert to HKL
111 std::vector<Kernel::V3D> vec_event_hkl;
112 convertFromQSampleToHKL(vec_event_qsample, vec_event_hkl);
113
114 // Get file name
115 std::string hklfilename = getPropertyValue("HKLFileName");
116 // Abort mission if no file name is given
117 if (!hklfilename.empty())
118 saveEventsToFile(hklfilename, vec_event_hkl, vec_event_signal, vec_event_det);
119
120 // Create output workspace
121 m_outputWS = createHKLMDWorkspace(vec_event_hkl, vec_event_signal, vec_event_det);
122 // Experiment info
123 ExperimentInfo_sptr expinfo = std::make_shared<ExperimentInfo>();
124 expinfo->setInstrument(inputWS->getExperimentInfo(0)->getInstrument());
125 expinfo->mutableRun().setGoniometer(inputWS->getExperimentInfo(0)->run().getGoniometer(), false);
126 expinfo->mutableRun().addProperty("run_number", 1);
127 m_outputWS->addExperimentInfo(expinfo);
128
129 setProperty("OutputWorkspace", m_outputWS);
130}
131
133 std::string peakwsname = getPropertyValue("PeaksWorkspace");
134 if (!peakwsname.empty() && AnalysisDataService::Instance().doesExist(peakwsname)) {
135 // Get from peak works
136 DataObjects::PeaksWorkspace_sptr peakws = getProperty("PeaksWorkspace");
137 m_UB = Kernel::Matrix<double>(peakws->sample().getOrientedLattice().getUB());
138 } else {
139 // Get from ...
140 std::vector<double> ub_array = getProperty("UBMatrix");
141 if (ub_array.size() != 9)
142 throw std::invalid_argument("Input UB matrix must have 9 elements");
143
145 for (size_t i = 0; i < 3; ++i) {
146 for (size_t j = 0; j < 3; ++j) {
147 m_UB[i][j] = ub_array[i * 3 + j];
148 }
149 }
150 }
151}
152
153//--------------------------------------------------------------------------
158void ConvertCWSDMDtoHKL::exportEvents(const IMDEventWorkspace_sptr &mdws, std::vector<Kernel::V3D> &vec_event_qsample,
159 std::vector<signal_t> &vec_event_signal, std::vector<detid_t> &vec_event_det) {
160 // Set the size of the output vectors
161 size_t numevents = mdws->getNEvents();
162 g_log.information() << "Number of events = " << numevents << "\n";
163
164 vec_event_qsample.resize(numevents);
165 vec_event_signal.resize(numevents);
166 vec_event_det.resize(numevents);
167
168 // Go through to get value
169 auto mditer = mdws->createIterator();
170 size_t nextindex = 1;
171 bool scancell = true;
172 size_t currindex = 0;
173 while (scancell) {
174 size_t numevent_cell = mditer->getNumEvents();
175 for (size_t iev = 0; iev < numevent_cell; ++iev) {
176 // Check
177 if (currindex >= vec_event_qsample.size())
178 throw std::runtime_error("Logic error in event size!");
179
180 float tempx = mditer->getInnerPosition(iev, 0);
181 float tempy = mditer->getInnerPosition(iev, 1);
182 float tempz = mditer->getInnerPosition(iev, 2);
183 signal_t signal = mditer->getInnerSignal(iev);
184 detid_t detid = mditer->getInnerDetectorID(iev);
185 Kernel::V3D qsample(tempx, tempy, tempz);
186 vec_event_qsample[currindex] = qsample;
187 vec_event_signal[currindex] = signal;
188 vec_event_det[currindex] = detid;
189
190 ++currindex;
191 }
192
193 // Advance to next cell
194 if (mditer->next()) {
195 // advance to next cell
196 mditer->jumpTo(nextindex);
197 ++nextindex;
198 } else {
199 // break the loop
200 scancell = false;
201 }
202 }
203}
204
205//--------------------------------------------------------------------------
208void ConvertCWSDMDtoHKL::saveMDToFile(const std::vector<std::vector<coord_t>> &vecEventQsample,
209 const std::vector<float> &vecEventSignal) {
210 // Get file name
211 std::string filename = getPropertyValue("QSampleFileName");
212
213 // Abort with an empty string
214 if (filename.empty())
215 return;
216 if (vecEventQsample.size() != vecEventSignal.size())
217 throw std::runtime_error("Input vectors of Q-sample and signal have different sizes.");
218
219 // Write to file
220 std::ofstream ofile;
221 ofile.open(filename.c_str());
222
223 size_t numevents = vecEventQsample.size();
224 for (size_t i = 0; i < numevents; ++i) {
225 ofile << vecEventQsample[i][0] << ", " << vecEventQsample[i][1] << ", " << vecEventQsample[i][2] << ", "
226 << vecEventSignal[i] << "\n";
227 }
228 ofile.close();
229}
230
231//--------------------------------------------------------------------------
234void ConvertCWSDMDtoHKL::saveEventsToFile(const std::string &filename, std::vector<Kernel::V3D> &vecEventPos,
235 const std::vector<signal_t> &vecEventSignal,
236 const std::vector<detid_t> &vecEventDetid) {
237 // Check
238 if (vecEventDetid.size() != vecEventPos.size() || vecEventPos.size() != vecEventSignal.size())
239 throw std::invalid_argument("Input vectors for HKL, signal and detector ID have different size.");
240
241 std::ofstream ofile;
242 ofile.open(filename.c_str());
243
244 for (size_t i = 0; i < vecEventPos.size(); ++i) {
245 ofile << vecEventPos[i].X() << ", " << vecEventPos[i].Y() << ", " << vecEventPos[i].Z() << ", " << vecEventSignal[i]
246 << ", " << vecEventDetid[i] << "\n";
247 }
248 ofile.close();
249}
250
251//--------------------------------------------------------------------------
254void ConvertCWSDMDtoHKL::convertFromQSampleToHKL(const std::vector<V3D> &q_vectors, std::vector<V3D> &miller_indices) {
255
256 Matrix<double> tempUB(m_UB);
257
258 int original_indexed = 0;
259 double original_error = 0;
260 double tolerance = 0.55; // to make sure no output is invalid
261 original_indexed =
262 IndexingUtils::CalculateMillerIndices(tempUB, q_vectors, tolerance, miller_indices, original_error);
263
264 g_log.notice() << "[DB] " << original_indexed << " peaks are indexed."
265 << "\n";
266}
267
268//----------------------------------------------------------------------------------------------
274 const std::vector<signal_t> &vec_signal,
275 const std::vector<detid_t> &vec_detid) {
276 // Check
277 if (vec_hkl.size() != vec_signal.size() || vec_signal.size() != vec_detid.size())
278 throw std::invalid_argument("Input vectors for HKL, signal and detector "
279 "IDs are of different size!");
280
281 // Create workspace in Q_sample with dimenion as 3
282 size_t nDimension = 3;
283 IMDEventWorkspace_sptr mdws = MDEventFactory::CreateMDWorkspace(nDimension, "MDEvent");
284
285 // Extract Dimensions and add to the output workspace.
286 std::vector<std::string> vec_ID(3);
287 vec_ID[0] = "H";
288 vec_ID[1] = "K";
289 vec_ID[2] = "L";
290
291 std::vector<std::string> dimensionNames(3);
292 dimensionNames[0] = "H";
293 dimensionNames[1] = "K";
294 dimensionNames[2] = "L";
295
297
298 // Add dimensions
299 std::vector<double> m_extentMins(3);
300 std::vector<double> m_extentMaxs(3);
301 std::vector<size_t> m_numBins(3, 100);
302 getRange(vec_hkl, m_extentMins, m_extentMaxs);
303
304 // Get MDFrame of HKL type with RLU
305 auto unitFactory = makeMDUnitFactoryChain();
306 auto unit = unitFactory->create(Units::Symbol::RLU.ascii());
307 Mantid::Geometry::HKL frame(unit);
308
309 for (size_t i = 0; i < nDimension; ++i) {
310 std::string id = vec_ID[i];
311 std::string name = dimensionNames[i];
312 // std::string units = "A^-1";
314 id, name, frame, static_cast<coord_t>(m_extentMins[i]), static_cast<coord_t>(m_extentMaxs[i]), m_numBins[i])));
315 }
316
317 // Set coordinate system
318 mdws->setCoordinateSystem(coordinateSystem);
319
320 // Creates a new instance of the MDEventInserter to output workspace
321 MDEventWorkspace<MDEvent<3>, 3>::sptr mdws_mdevt_3 = std::dynamic_pointer_cast<MDEventWorkspace<MDEvent<3>, 3>>(mdws);
322 MDEventInserter<MDEventWorkspace<MDEvent<3>, 3>::sptr> inserter(mdws_mdevt_3);
323
324 // Go though each spectrum to conver to MDEvent
325 for (size_t iq = 0; iq < vec_hkl.size(); ++iq) {
326 Kernel::V3D hkl = vec_hkl[iq];
327 std::vector<Mantid::coord_t> millerindex(3);
328 millerindex[0] = static_cast<float>(hkl.X());
329 millerindex[1] = static_cast<float>(hkl.Y());
330 millerindex[2] = static_cast<float>(hkl.Z());
331
332 signal_t signal = vec_signal[iq];
333 signal_t error = std::sqrt(signal);
334 uint16_t runnumber = 1;
335 detid_t detid = vec_detid[iq];
336
337 // Insert
338 inserter.insertMDEvent(static_cast<float>(signal), static_cast<float>(error * error),
339 static_cast<uint16_t>(runnumber), 0, detid, millerindex.data());
340 }
341
342 return mdws;
343}
344
345void ConvertCWSDMDtoHKL::getRange(const std::vector<Kernel::V3D> &vec_hkl, std::vector<double> &extentMins,
346 std::vector<double> &extentMaxs) {
347 assert(extentMins.size() == 3);
348 assert(extentMaxs.size() == 3);
349
350 for (size_t i = 0; i < 3; ++i) {
351 double minvalue = vec_hkl[0][i];
352 double maxvalue = vec_hkl[0][i];
353 for (size_t j = 1; j < vec_hkl.size(); ++j) {
354 double thisvalue = vec_hkl[j][i];
355 if (thisvalue < minvalue)
356 minvalue = thisvalue;
357 else if (thisvalue > maxvalue)
358 maxvalue = thisvalue;
359 }
360 extentMins[i] = minvalue;
361 extentMaxs[i] = maxvalue;
362 }
363}
364
365} // namespace Mantid::MDAlgorithms
#define DECLARE_ALGORITHM(classname)
Definition Algorithm.h:538
double error
double tolerance
std::string getPropertyValue(const std::string &name) const override
Get the value of a property as a string.
TypedValue getProperty(const std::string &name) const override
Get the value of a property.
Kernel::Logger & g_log
Definition Algorithm.h:422
@ OptionalSave
to specify a file to write to but an empty string is
A property class for workspaces.
static API::IMDEventWorkspace_sptr CreateMDWorkspace(size_t nd, const std::string &eventType="MDLeanEvent", const Mantid::API::MDNormalization &preferredNormalization=Mantid::API::MDNormalization::VolumeNormalization, const Mantid::API::MDNormalization &preferredNormalizationHisto=Mantid::API::MDNormalization::VolumeNormalization)
Create a MDEventWorkspace of the given type.
MDEventInserter : Helper class that provides a generic interface for adding events to an MDWorkspace ...
Templated class for the multi-dimensional event workspace.
HKL : HKL MDFrame.
Definition HKL.h:20
static int CalculateMillerIndices(const Kernel::DblMatrix &UB, const std::vector< Kernel::V3D > &q_vectors, double tolerance, std::vector< Kernel::V3D > &miller_indices, double &ave_error)
Given a UB, get list of Miller indices for specifed Qs and tolerance.
Support for a property that holds an array of values.
IPropertyManager * setProperty(const std::string &name, const T &value)
Templated method to set the value of a PropertyWithValue.
void notice(const std::string &msg)
Logs at notice level.
Definition Logger.cpp:126
void information(const std::string &msg)
Logs at information level.
Definition Logger.cpp:136
Numerical Matrix class.
Definition Matrix.h:42
static const UnitLabel RLU
Reciprocal lattice units.
Class for 3D vectors.
Definition V3D.h:34
constexpr double X() const noexcept
Get x.
Definition V3D.h:238
constexpr double Y() const noexcept
Get y.
Definition V3D.h:239
void setZ(const double zz) noexcept
Set is z position.
Definition V3D.h:236
void setX(const double xx) noexcept
Set is x position.
Definition V3D.h:224
void setY(const double yy) noexcept
Set is y position.
Definition V3D.h:230
constexpr double Z() const noexcept
Get z.
Definition V3D.h:240
ConvertCWSDMDtoHKL : TODO: DESCRIPTION.
void saveEventsToFile(const std::string &filename, std::vector< Kernel::V3D > &vecEventPos, const std::vector< signal_t > &vecEventSignal, const std::vector< detid_t > &vecEventDetid)
Save HKL to file for 3D visualization.
const std::string name() const override
Algorithm's name.
void getRange(const std::vector< Kernel::V3D > &vec_hkl, std::vector< double > &extentMins, std::vector< double > &extentMaxs)
API::IMDEventWorkspace_sptr createHKLMDWorkspace(const std::vector< Kernel::V3D > &vec_hkl, const std::vector< signal_t > &vec_signal, const std::vector< detid_t > &vec_detid)
Create output workspace.
void saveMDToFile(const std::vector< std::vector< coord_t > > &vecEventQsample, const std::vector< float > &vecEventSignal)
Save Q-sample to file.
void convertFromQSampleToHKL(const std::vector< Kernel::V3D > &q_vectors, std::vector< Kernel::V3D > &miller_indices)
Convert from Q-sample to HKL.
void exportEvents(const API::IMDEventWorkspace_sptr &mdws, std::vector< Kernel::V3D > &vec_event_qsample, std::vector< signal_t > &vec_event_signal, std::vector< detid_t > &vec_event_det)
Export events from an MDEventWorkspace for future processing It is a convenient algorithm if number o...
std::shared_ptr< IMDEventWorkspace > IMDEventWorkspace_sptr
Shared pointer to Mantid::API::IMDEventWorkspace.
std::shared_ptr< ExperimentInfo > ExperimentInfo_sptr
Shared pointer to ExperimentInfo.
std::shared_ptr< PeaksWorkspace > PeaksWorkspace_sptr
Typedef for a shared pointer to a peaks workspace.
std::shared_ptr< MDHistoDimension > MDHistoDimension_sptr
Shared pointer to a MDHistoDimension.
SpecialCoordinateSystem
Special coordinate systems for Q3D.
MDUnitFactory_uptr MANTID_KERNEL_DLL makeMDUnitFactoryChain()
Convience method. Pre-constructed builder chain.
float coord_t
Typedef for the data type to use for coordinate axes in MD objects such as MDBox, MDEventWorkspace,...
Definition MDTypes.h:27
int32_t detid_t
Typedef for a detector ID.
double signal_t
Typedef for the signal recorded in a MDBox, etc.
Definition MDTypes.h:36
@ Input
An input workspace.
Definition Property.h:53
@ Output
An output workspace.
Definition Property.h:54