Newer
Older
#include "MantidMDAlgorithms/SaveIsawQvector.h"
#include <fstream>
#include "MantidAPI/FileProperty.h"
#include "MantidAPI/WorkspaceValidators.h"
#include "MantidDataObjects/EventWorkspace.h"
#include "MantidKernel/CompositeValidator.h"
#include "MantidMDAlgorithms/MDTransfFactory.h"
#include "MantidMDAlgorithms/UnitsConversionHelper.h"
using namespace Mantid::API;
using namespace Mantid::Kernel;
using namespace Mantid::DataObjects;
namespace MDAlgorithms {
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
// Register the algorithm into the AlgorithmFactory
DECLARE_ALGORITHM(SaveIsawQvector)
/// This only works for diffraction.
const std::string ELASTIC("Elastic");
/// Only convert to Q-vector.
const std::string Q3D("Q3D");
/// Q-vector is always three dimensional.
const std::size_t DIMS(3);
/// Constant for the size of the buffer to write to disk.
const std::size_t BUFF_SIZE(DIMS * sizeof(float));
//----------------------------------------------------------------------------------------------
/** Constructor
*/
SaveIsawQvector::SaveIsawQvector() {}
//----------------------------------------------------------------------------------------------
/** Destructor
*/
SaveIsawQvector::~SaveIsawQvector() {}
//----------------------------------------------------------------------------------------------
/// Algorithm's name for identification. @see Algorithm::name
const std::string SaveIsawQvector::name() const { return "SaveIsawQvector"; }
/// Algorithm's version for identification. @see Algorithm::version
int SaveIsawQvector::version() const { return 1; }
/// Algorithm's category for identification. @see Algorithm::category
const std::string SaveIsawQvector::category() const {
return "DataHandling\\Isaw";
}
//----------------------------------------------------------------------------------------------
/** Initialize the algorithm's properties.
*/
void SaveIsawQvector::init() {
auto ws_valid = boost::make_shared<CompositeValidator>();
//
ws_valid->add<InstrumentValidator>();
// the validator which checks if the workspace has axis and any units
ws_valid->add<WorkspaceUnitValidator>("TOF");
declareProperty(new WorkspaceProperty<EventWorkspace>(
"InputWorkspace", "", Direction::Input, ws_valid),
"An input EventWorkspace with units along X-axis and defined "
"instrument with defined sample");
std::vector<std::string> exts;
exts.push_back(".bin");
declareProperty(
new FileProperty("Filename", "", FileProperty::OptionalSave, exts),
"Optional path to an hkl file to save. Vectors returned if no file "
"requested.");
declareProperty("RightHanded", true, "Save the Q-vector as k_f - k_i");
declareProperty(
"ISAWcoords", true,
"Save the Q-vector with y gravitationally up and x pointing downstream");
std::vector<double> Qx_save, Qy_save, Qz_save;
declareProperty("Qx_vector", Qx_save,
"The name of the vector in which to store the list of Qx",
Direction::Output);
declareProperty("Qy_vector", Qy_save,
"The name of the vector in which to store the list of Qy",
Direction::Output);
declareProperty("Qz_vector", Qz_save,
"The name of the vector in which to store the list of Qz",
Direction::Output);
}
//----------------------------------------------------------------------------------------------
/** Execute the algorithm.
*/
void SaveIsawQvector::exec() {
// get the input workspace
EventWorkspace_sptr wksp = getProperty("InputWorkspace");
// this only works for unweighted events
if (wksp->getEventType() != API::TOF) {
throw std::runtime_error("SaveIsawQvector only works for raw events");
// error out if there are not events
if (wksp->getNumberEvents() <= 0) {
throw std::runtime_error(
"SaveIsawQvector does not work for empty event lists");
// open the output file
std::string filename = getPropertyValue("Filename");
std::ofstream handle;
if (!filename.empty()) {
handle.open(filename.c_str(), std::ios::out | std::ios::binary);
if (!handle.is_open())
throw std::runtime_error("Failed to open file for writing");
// set up a descripter of where we are going
this->initTargetWSDescr(wksp);
size_t coord_map[DIMS] = {0, 1, 2}; // x->x, y->y, z->z
double coord_signs[DIMS] = {1., 1., 1.}; // signs are unchanged
if (this->getProperty("ISAWcoords")) {
// x -> z
coord_map[0] = 2;
// z -> y
coord_map[2] = 1;
}
if (this->getProperty("RightHanded")) {
for (size_t dim = 0; dim < DIMS; ++dim)
coord_signs[dim] *= -1.; // everything changes sign
}
// units conersion helper
UnitsConversionHelper unitConv;
unitConv.initialize(m_targWSDescr, "Momentum");
// initialize the MD coordinates conversion class
MDTransf_sptr q_converter =
MDTransfFactory::Instance().create(m_targWSDescr.AlgID);
q_converter->initialize(m_targWSDescr);
// set up the progress bar
const size_t numSpectra = wksp->getNumberHistograms();
Progress prog(this, 0.5, 1.0, numSpectra);
// loop through the eventlists
float buffer[DIMS];
std::vector<double> Qx_save, Qy_save, Qz_save;
for (std::size_t i = 0; i < numSpectra; ++i) {
// get a reference to the event list
const EventList &events = wksp->getEventList(i);
// check to see if the event list is empty
if (events.empty()) {
prog.report();
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
// update which pixel is being converted
std::vector<coord_t> locCoord(DIMS, 0.);
unitConv.updateConversion(i);
q_converter->calcYDepCoordinates(locCoord, i);
// loop over the events
double signal(1.); // ignorable garbage
double errorSq(1.); // ignorable garbage
const std::vector<TofEvent> &raw_events = events.getEvents();
for (auto event = raw_events.begin(); event != raw_events.end(); ++event) {
double val = unitConv.convertUnits(event->tof());
q_converter->calcMatrixCoord(val, locCoord, signal, errorSq);
for (size_t dim = 0; dim < DIMS; ++dim) {
buffer[dim] =
static_cast<float>(coord_signs[dim] * locCoord[coord_map[dim]]);
}
if (filename.empty()) {
Qx_save.push_back(static_cast<double>(buffer[0]));
Qy_save.push_back(static_cast<double>(buffer[1]));
Qz_save.push_back(static_cast<double>(buffer[2]));
} else
handle.write(reinterpret_cast<char *>(buffer), BUFF_SIZE);
} // end of loop over events in list
prog.report();
} // end of loop over spectra
if (filename.empty()) {
setProperty("Qx_vector", Qx_save);
setProperty("Qy_vector", Qy_save);
setProperty("Qz_vector", Qz_save);
} else
handle.close(); // cleanup
}
/**
* @brief SaveIsawQvector::initTargetWSDescr Initialize the output information
* for the MD conversion framework.
*
* @param wksp The workspace to get information from.
*/
void SaveIsawQvector::initTargetWSDescr(EventWorkspace_sptr wksp) {
m_targWSDescr.setMinMax(std::vector<double>(3, -2000.),
std::vector<double>(3, 2000.));
m_targWSDescr.buildFromMatrixWS(wksp, Q3D, ELASTIC);
m_targWSDescr.setLorentsCorr(false);
// generate the detectors table
Mantid::API::Algorithm_sptr childAlg =
createChildAlgorithm("PreprocessDetectorsToMD", 0., .5);
childAlg->setProperty("InputWorkspace", wksp);
childAlg->executeAsChildAlg();
DataObjects::TableWorkspace_sptr table =
childAlg->getProperty("OutputWorkspace");
if (!table)
throw(std::runtime_error(
"Can not retrieve results of \"PreprocessDetectorsToMD\""));
else
m_targWSDescr.m_PreprDetTable = table;
}
} // namespace MDAlgorithms
} // namespace Mantid