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();
68 const std::string filepath = Mantid::API::FileFinder::Instance().getFullPath(data_name);
74 return (AnalysisDataService::Instance().doesExist(data_name) ||
fileExists(filepath));
85 Poco::File test_file(filename);
86 return test_file.exists();
103std::string
filterToNew(std::vector<std::string> &input_data,
const 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 return std::any_of(current_data.rbegin(), current_data.rend(),
130 [&data_source](
const auto &source) { return data_source == source; });
141 const std::string &create_alg_name,
142 const std::string &accumulate_alg_name) {
144 std::unordered_set<std::string> historical_data_sources;
150 const std::vector<HistoryItem> history_items = view->getAlgorithmsList();
151 for (
const auto &history_item : history_items) {
152 auto alg_history = history_item.getAlgorithmHistory();
153 if (alg_history->name() == create_alg_name || alg_history->name() == accumulate_alg_name) {
154 auto props = alg_history->getProperties();
155 for (
const auto &prop : props) {
157 if (prop_history->name() ==
"DataSources") {
164 std::vector<std::string> result(historical_data_sources.begin(), historical_data_sources.end());
175void insertDataSources(
const std::string &data_sources, std::unordered_set<std::string> &historical_data_sources) {
177 std::vector<std::string> data_split;
178 boost::split(data_split, data_sources, boost::is_any_of(
","));
181 std::for_each(data_split.begin(), data_split.end(),
182 std::bind(boost::algorithm::trim<std::string>, std::placeholders::_1, std::locale()));
185 historical_data_sources.insert(data_split.begin(), data_split.end());
208 "An input MDEventWorkspace to append data to.");
211 "MDEventWorkspace with new data appended.");
216 "Input workspaces to process, or filenames to load and process");
220 std::vector<std::string> e_mode_options{
"Elastic",
"Direct",
"Indirect"};
222 declareProperty(
"Emode",
"Direct", std::make_shared<StringListValidator>(e_mode_options),
223 "Analysis mode ['Elastic', 'Direct', 'Indirect'].");
227 "Lattice parameters");
235 "Lattice vector parallel to neutron beam");
239 "Lattice vector perpendicular to neutron beam in the horizontal plane");
242 "Psi rotation in degrees. Optional or one entry per run.");
245 "gl rotation in degrees. Optional or one entry per run.");
248 "gs rotation in degrees. Optional or one entry per run.");
251 "Execute conversions to MD and Merge in one-step. Less "
255 "Create workspace from fresh rather than appending to "
256 "existing workspace data.");
259 "The name of the Nexus file to write, as a full or relative path.\n"
260 "Only used if FileBackEnd is true.");
261 setPropertySettings(
"Filename", std::make_unique<EnabledWhenProperty>(
"FileBackEnd",
IS_EQUAL_TO,
"1"));
263 declareProperty(
"FileBackEnd",
false,
264 "If true, Filename must also be specified. The algorithm "
265 "will create the specified file in addition to an output "
266 "workspace. The workspace will load data from the file on "
267 "demand in order to reduce memory use.");
276 std::vector<std::string> input_data = this->
getProperty(
"DataSources");
278 const std::string out_filename = this->
getProperty(
"Filename");
279 const bool filebackend = this->
getProperty(
"FileBackEnd");
281 std::vector<double> psi = this->
getProperty(
"Psi");
287 std::vector<double> efix = this->
getProperty(
"EFix");
295 g_log.
notice() <<
"These data sources were not found: " << nonexistent <<
'\n';
298 if (input_data.empty()) {
299 g_log.
warning() <<
"No data found matching input in " << this->
name() <<
'\n';
300 this->setProperty(
"OutputWorkspace", input_ws);
303 this->interruption_point();
311 this->setProperty(
"OutputWorkspace", out_ws);
312 g_log.
notice() << this->
name() <<
" successfully created a clean workspace\n";
316 this->interruption_point();
323 const std::vector<std::string> current_data =
getHistoricalDataSources(ws_history, create_alg->name(), this->name());
326 const std::string old_sources =
filterToNew(input_data, current_data, psi, gl, gs, efix);
327 g_log.
notice() <<
"Data from these sources are already in the workspace: " << old_sources <<
'\n';
329 if (input_data.empty()) {
330 g_log.
notice() <<
"No new data to append to workspace in " << this->
name() <<
'\n';
331 this->setProperty(
"OutputWorkspace", input_ws);
334 this->interruption_point();
340 this->interruption_point();
343 const std::string temp_ws_name =
"TEMP_WORKSPACE_ACCUMULATEMD";
346 AnalysisDataService::Instance().add(temp_ws_name, tmp_ws);
347 std::string ws_names_to_merge = input_ws->getName();
348 ws_names_to_merge.append(
",");
349 ws_names_to_merge.append(temp_ws_name);
352 merge_alg->setProperty(
"InputWorkspaces", ws_names_to_merge);
353 merge_alg->executeAsChildAlg();
357 this->setProperty(
"OutputWorkspace", out_ws);
363 AnalysisDataService::Instance().remove(temp_ws_name);
379 const std::vector<double> &psi,
const std::vector<double> &gl,
380 const std::vector<double> &gs,
const std::vector<double> &efix,
381 const std::string &filename,
const bool filebackend) {
385 create_alg->setProperty(
"DataSources", data_sources);
386 create_alg->setProperty(
"EFix", efix);
392 create_alg->setProperty(
"Psi", psi);
393 create_alg->setProperty(
"Gl", gl);
394 create_alg->setProperty(
"Gs", gs);
397 create_alg->setProperty(
"Filename", filename);
398 create_alg->setProperty(
"FileBackEnd", filebackend);
400 create_alg->executeAsChildAlg();
402 return create_alg->getProperty(
"OutputWorkspace");
411 std::map<std::string, std::string> validation_output;
414 const std::vector<std::string> data_sources = this->
getProperty(
"DataSources");
415 const std::vector<double> u = this->
getProperty(
"u");
416 const std::vector<double> v = this->
getProperty(
"v");
417 const std::vector<double> alatt = this->
getProperty(
"Alatt");
418 const std::vector<double> angdeg = this->
getProperty(
"Angdeg");
419 const std::vector<double> psi = this->
getProperty(
"Psi");
420 const std::vector<double> gl = this->
getProperty(
"Gl");
421 const std::vector<double> gs = this->
getProperty(
"Gs");
422 const std::vector<double> efix = this->
getProperty(
"Efix");
423 const std::string filename = this->
getProperty(
"Filename");
424 const bool fileBackEnd = this->
getProperty(
"FileBackEnd");
426 if (fileBackEnd && filename.empty()) {
427 validation_output[
"Filename"] =
"Filename must be given if FileBackEnd is required.";
430 const size_t ws_entries = data_sources.size();
433 validation_output[
"u"] =
"u must have 3 components";
436 validation_output[
"v"] =
"v must have 3 components";
438 if (alatt.size() < 3) {
439 validation_output[
"Alatt"] =
"Lattice parameters must have 3 components";
441 if (angdeg.size() < 3) {
442 validation_output[
"Angdeg"] =
"Angle must have 3 components";
444 if (!psi.empty() && psi.size() != ws_entries) {
445 validation_output[
"Psi"] =
"If Psi is given an entry "
446 "should be provided for "
447 "every input datasource";
449 if (!gl.empty() && gl.size() != ws_entries) {
450 validation_output[
"Gl"] =
"If Gl is given an entry "
451 "should be provided for "
452 "every input datasource";
454 if (!gs.empty() && gs.size() != ws_entries) {
455 validation_output[
"Gs"] =
"If Gs is given an entry "
456 "should be provided for "
457 "every input datasource";
459 if (efix.size() > 1 && efix.size() != ws_entries) {
460 validation_output[
"EFix"] =
"Either specify a single EFix value, or as many "
461 "as there are input datasources";
464 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.
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, const 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.
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.
bool appearsInCurrentData(const std::string &data_source, const std::vector< std::string > ¤t_data)
Check if the named data source is in the vector of data currently in the workspace.
@ Input
An input workspace.
@ Output
An output workspace.