23#include <boost/algorithm/string/classification.hpp>
24#include <boost/algorithm/string/split.hpp>
25#include <boost/algorithm/string/trim.hpp>
47 std::vector<double> &gl, std::vector<double> &gs, std::vector<double> &efix) {
48 std::ostringstream nonexistent;
49 for (
size_t i = input_data.size(); i > 0; i--) {
51 nonexistent << input_data[i - 1] <<
",";
52 input_data.erase(input_data.begin() + i - 1);
53 psi.erase(psi.begin() + i - 1);
54 gl.erase(gl.begin() + i - 1);
55 gs.erase(gs.begin() + i - 1);
56 efix.erase(efix.begin() + i - 1);
59 return nonexistent.str();
85 Poco::File test_file(filename);
86 return test_file.exists();
103std::string
filterToNew(std::vector<std::string> &input_data, std::vector<std::string> ¤t_data,
104 std::vector<double> &psi, std::vector<double> &gl, std::vector<double> &gs,
105 std::vector<double> &efix) {
106 std::ostringstream old_sources;
107 for (
size_t i = input_data.size(); i > 0; i--) {
109 old_sources << input_data[i - 1] <<
",";
110 input_data.erase(input_data.begin() + i - 1);
111 psi.erase(psi.begin() + i - 1);
112 gl.erase(gl.begin() + i - 1);
113 gs.erase(gs.begin() + i - 1);
114 efix.erase(efix.begin() + i - 1);
117 return old_sources.str();
129 for (
auto reverse_iter = current_data.rbegin(); reverse_iter != current_data.rend(); ++reverse_iter) {
130 if (data_source == *reverse_iter) {
145 const std::string &create_alg_name,
146 const std::string &accumulate_alg_name) {
148 std::unordered_set<std::string> historical_data_sources;
154 const std::vector<HistoryItem> history_items = view->getAlgorithmsList();
155 for (
const auto &history_item : history_items) {
156 auto alg_history = history_item.getAlgorithmHistory();
157 if (alg_history->name() == create_alg_name || alg_history->name() == accumulate_alg_name) {
158 auto props = alg_history->getProperties();
159 for (
auto &prop : props) {
161 if (prop_history->name() ==
"DataSources") {
168 std::vector<std::string> result(historical_data_sources.begin(), historical_data_sources.end());
179void insertDataSources(
const std::string &data_sources, std::unordered_set<std::string> &historical_data_sources) {
181 std::vector<std::string> data_split;
182 boost::split(data_split, data_sources, boost::is_any_of(
","));
185 std::for_each(data_split.begin(), data_split.end(),
186 std::bind(boost::algorithm::trim<std::string>, std::placeholders::_1, std::locale()));
189 historical_data_sources.insert(data_split.begin(), data_split.end());
212 "An input MDEventWorkspace to append data to.");
215 "MDEventWorkspace with new data appended.");
220 "Input workspaces to process, or filenames to load and process");
224 std::vector<std::string> e_mode_options{
"Elastic",
"Direct",
"Indirect"};
226 declareProperty(
"Emode",
"Direct", std::make_shared<StringListValidator>(e_mode_options),
227 "Analysis mode ['Elastic', 'Direct', 'Indirect'].");
231 "Lattice parameters");
239 "Lattice vector parallel to neutron beam");
243 "Lattice vector perpendicular to neutron beam in the horizontal plane");
246 "Psi rotation in degrees. Optional or one entry per run.");
249 "gl rotation in degrees. Optional or one entry per run.");
252 "gs rotation in degrees. Optional or one entry per run.");
255 "Execute conversions to MD and Merge in one-step. Less "
259 "Create workspace from fresh rather than appending to "
260 "existing workspace data.");
263 "The name of the Nexus file to write, as a full or relative path.\n"
264 "Only used if FileBackEnd is true.");
265 setPropertySettings(
"Filename", std::make_unique<EnabledWhenProperty>(
"FileBackEnd",
IS_EQUAL_TO,
"1"));
267 declareProperty(
"FileBackEnd",
false,
268 "If true, Filename must also be specified. The algorithm "
269 "will create the specified file in addition to an output "
270 "workspace. The workspace will load data from the file on "
271 "demand in order to reduce memory use.");
280 std::vector<std::string> input_data = this->
getProperty(
"DataSources");
282 const std::string out_filename = this->
getProperty(
"Filename");
283 const bool filebackend = this->
getProperty(
"FileBackEnd");
285 std::vector<double> psi = this->
getProperty(
"Psi");
291 std::vector<double> efix = this->
getProperty(
"EFix");
299 g_log.
notice() <<
"These data sources were not found: " << nonexistent <<
'\n';
302 if (input_data.empty()) {
303 g_log.
warning() <<
"No data found matching input in " << this->
name() <<
'\n';
304 this->setProperty(
"OutputWorkspace", input_ws);
307 this->interruption_point();
315 this->setProperty(
"OutputWorkspace", out_ws);
316 g_log.
notice() << this->
name() <<
" successfully created a clean workspace\n";
320 this->interruption_point();
330 const std::string old_sources =
filterToNew(input_data, current_data, psi, gl, gs, efix);
331 g_log.
notice() <<
"Data from these sources are already in the workspace: " << old_sources <<
'\n';
333 if (input_data.empty()) {
334 g_log.
notice() <<
"No new data to append to workspace in " << this->
name() <<
'\n';
335 this->setProperty(
"OutputWorkspace", input_ws);
338 this->interruption_point();
344 this->interruption_point();
347 const std::string temp_ws_name =
"TEMP_WORKSPACE_ACCUMULATEMD";
351 std::string ws_names_to_merge = input_ws->getName();
352 ws_names_to_merge.append(
",");
353 ws_names_to_merge.append(temp_ws_name);
356 merge_alg->setProperty(
"InputWorkspaces", ws_names_to_merge);
357 merge_alg->executeAsChildAlg();
361 this->setProperty(
"OutputWorkspace", out_ws);
383 const std::vector<double> &psi,
const std::vector<double> &gl,
384 const std::vector<double> &gs,
const std::vector<double> &efix,
385 const std::string &filename,
const bool filebackend) {
389 create_alg->setProperty(
"DataSources", data_sources);
390 create_alg->setProperty(
"EFix", efix);
396 create_alg->setProperty(
"Psi", psi);
397 create_alg->setProperty(
"Gl", gl);
398 create_alg->setProperty(
"Gs", gs);
401 create_alg->setProperty(
"Filename", filename);
402 create_alg->setProperty(
"FileBackEnd", filebackend);
404 create_alg->executeAsChildAlg();
406 return create_alg->getProperty(
"OutputWorkspace");
415 std::map<std::string, std::string> validation_output;
418 const std::vector<std::string> data_sources = this->
getProperty(
"DataSources");
419 const std::vector<double> u = this->
getProperty(
"u");
420 const std::vector<double> v = this->
getProperty(
"v");
421 const std::vector<double> alatt = this->
getProperty(
"Alatt");
422 const std::vector<double> angdeg = this->
getProperty(
"Angdeg");
423 const std::vector<double> psi = this->
getProperty(
"Psi");
424 const std::vector<double> gl = this->
getProperty(
"Gl");
425 const std::vector<double> gs = this->
getProperty(
"Gs");
426 const std::vector<double> efix = this->
getProperty(
"Efix");
427 const std::string filename = this->
getProperty(
"Filename");
428 const bool fileBackEnd = this->
getProperty(
"FileBackEnd");
430 if (fileBackEnd && filename.empty()) {
431 validation_output[
"Filename"] =
"Filename must be given if FileBackEnd is required.";
434 const size_t ws_entries = data_sources.size();
437 validation_output[
"u"] =
"u must have 3 components";
440 validation_output[
"v"] =
"v must have 3 components";
442 if (alatt.size() < 3) {
443 validation_output[
"Alatt"] =
"Lattice parameters must have 3 components";
445 if (angdeg.size() < 3) {
446 validation_output[
"Angdeg"] =
"Angle must have 3 components";
448 if (!psi.empty() && psi.size() != ws_entries) {
449 validation_output[
"Psi"] =
"If Psi is given an entry "
450 "should be provided for "
451 "every input datasource";
453 if (!gl.empty() && gl.size() != ws_entries) {
454 validation_output[
"Gl"] =
"If Gl is given an entry "
455 "should be provided for "
456 "every input datasource";
458 if (!gs.empty() && gs.size() != ws_entries) {
459 validation_output[
"Gs"] =
"If Gs is given an entry "
460 "should be provided for "
461 "every input datasource";
463 if (efix.size() > 1 && efix.size() != ws_entries) {
464 validation_output[
"EFix"] =
"Either specify a single EFix value, or as many "
465 "as there are input datasources";
468 return validation_output;
#define DECLARE_ALGORITHM(classname)
@ OptionalSave
to specify a file to write to but an empty string is
std::shared_ptr< Algorithm > createChildAlgorithm(const std::string &name, const double startProgress=-1., const double endProgress=-1., const bool enableLogging=true, const int &version=-1) override
Create a Child Algorithm.
Kernel::IPropertyManager::TypedValue getProperty(const std::string &name) const override
Get the property held by this object.
std::string getPropertyValue(const std::string &name) const override
Get the property held by this object.
This class stores information about the Workspace History used by algorithms on a workspace and the e...
std::shared_ptr< HistoryView > createView() const
Create a flat view of the workspaces algorithm history.
A property class for workspaces.
Support for a property that holds an array of values.
void notice(const std::string &msg)
Logs at notice level.
void warning(const std::string &msg)
Logs at warning level.
Validator to check that a property is not left empty.
The concrete, templated class for properties.
static T & Instance()
Return a reference to the Singleton instance, creating it if it does not already exist Creation is do...
AccumulateMD : Algorithm for appending new data to a MDHistoWorkspace.
Mantid::API::IMDEventWorkspace_sptr createMDWorkspace(const std::vector< std::string > &data_sources, const std::vector< double > &psi, const std::vector< double > &gl, const std::vector< double > &gs, const std::vector< double > &efix, const std::string &filename, const bool filebackend)
Use the CreateMD algorithm to create an MD workspace.
int version() const override
Algorithm's version for identification.
const std::string category() const override
Algorithm's category for identification.
const std::string summary() const override
Algorithm's summary for use in the GUI and help.
std::map< std::string, std::string > validateInputs() override
const std::string name() const override
Algorithms name for identification.
std::shared_ptr< IMDEventWorkspace > IMDEventWorkspace_sptr
Shared pointer to Mantid::API::IMDEventWorkspace.
Kernel::Logger g_log("ExperimentInfo")
static logger object
std::shared_ptr< Algorithm > Algorithm_sptr
Typedef for a shared pointer to an Algorithm.
std::shared_ptr< const PropertyHistory > PropertyHistory_const_sptr
void MANTID_MDALGORITHMS_DLL insertDataSources(const std::string &data_sources, std::unordered_set< std::string > &historical_data_sources)
Extract names of data sources from workspace history and form a set of historical data sources.
std::string MANTID_MDALGORITHMS_DLL filterToNew(std::vector< std::string > &input_data, std::vector< std::string > ¤t_data, std::vector< double > &psi, std::vector< double > &gl, std::vector< double > &gs, std::vector< double > &efix)
Reduce the vector of input data to only data files and workspaces which are not found in the vector o...
void MANTID_MDALGORITHMS_DLL padParameterVector(std::vector< double > ¶m_vector, const size_t grow_to_size)
Pad vector of parameters to given length.
bool MANTID_MDALGORITHMS_DLL dataExists(const std::string &data_name)
Check if the named data source is an existing workspace or file.
bool fileExists(const std::string &filename)
Test if a file with the given full path name exists.
bool appearsInCurrentData(const std::string &data_source, std::vector< std::string > ¤t_data)
Check if the named data source is in the vector of data currently in the workspace.
std::vector< std::string > getHistoricalDataSources(const API::WorkspaceHistory &ws_history, const std::string &create_alg_name, const std::string &accumulate_alg_name)
Return a vector of the names of files and workspaces which have been previously added to the workspac...
std::string MANTID_MDALGORITHMS_DLL filterToExistingSources(std::vector< std::string > &input_data, std::vector< double > &psi, std::vector< double > &gl, std::vector< double > &gs, std::vector< double > &efix)
Reduce the vector of input data to only data files and workspaces which can be found.
@ Input
An input workspace.
@ Output
An output workspace.