21#include "MantidIndexing/IndexInfo.h"
28#include "MantidTypes/SpectrumDefinition.h"
30using Mantid::HistogramData::HistogramX;
37using namespace Kernel;
39using namespace Geometry;
40using namespace DataObjects;
41using namespace RunCombinationOptions;
48 "The names of the input workspaces as a list. You may "
49 "also group workspaces using the GUI or [[GroupWorkspaces]], and specify "
50 "the name of the group instead.");
52 "Name of the output workspace");
62 "Choose whether to rebin when bins are different, or fail "
63 "(fail behaviour defined in FailBehaviour option).");
66 "Choose whether to skip the file and continue, or stop and "
67 "throw and error, when encountering a failure.");
83 const std::vector<std::string> inputs_orig =
getProperty(
"InputWorkspaces");
87 if (inputs.size() == 1) {
103 const auto numOutputSpectra = outWS->getNumberHistograms() + addeeWS->getNumberHistograms();
106 DataObjects::create<MatrixWorkspace>(*outWS, numOutputSpectra, outWS->histogram(0).binEdges());
108 newOutWS->mutableComponentInfo().merge(addeeWS->componentInfo());
110 if (newOutWS->detectorInfo().size() * newOutWS->detectorInfo().scanCount() ==
111 outWS->detectorInfo().size() * outWS->detectorInfo().scanCount()) {
114 g_log.
information() <<
"Workspaces had identical detector scan information and were "
116 return outWS + addeeWS;
117 }
else if (newOutWS->detectorInfo().size() * newOutWS->detectorInfo().scanCount() != numOutputSpectra) {
118 throw std::runtime_error(
"Unexpected DetectorInfo size. Merging workspaces "
119 "with some, but not all overlapping scan "
120 "intervals is not currently supported.");
123 g_log.
information() <<
"Workspaces had different, non-overlapping scan intervals "
124 "so spectra will be appended.";
126 auto outSpecDefs = *(outWS->indexInfo().spectrumDefinitions());
127 const auto &addeeSpecDefs = *(addeeWS->indexInfo().spectrumDefinitions());
129 const auto newAddeeSpecDefs =
buildScanIntervals(addeeSpecDefs, addeeWS->detectorInfo(), newOutWS->detectorInfo());
131 outSpecDefs.insert(outSpecDefs.end(), newAddeeSpecDefs.begin(), newAddeeSpecDefs.end());
133 auto newIndexInfo = Indexing::IndexInfo(numOutputSpectra);
134 newIndexInfo.setSpectrumDefinitions(std::move(outSpecDefs));
135 newOutWS->setIndexInfo(newIndexInfo);
137 for (
size_t i = 0; i < outWS->getNumberHistograms(); ++i)
138 newOutWS->setHistogram(i, outWS->histogram(i));
140 for (
size_t i = 0; i < addeeWS->getNumberHistograms(); ++i)
141 newOutWS->setHistogram(i + outWS->getNumberHistograms(), addeeWS->histogram(i));
151 throw std::invalid_argument(
"MergeRuns: No workspaces found to merge.");
158 auto lhs_nhist =
static_cast<int>(lhs->getNumberHistograms());
162 lhs_det_to_wi = lhs->getDetectorIDToWorkspaceIndexMap(
true);
163 }
catch (std::runtime_error &) {
170 for (
size_t workspaceNum = 1; workspaceNum <
m_inEventWS.size(); workspaceNum++) {
181 std::size_t nhist = ews->getNumberHistograms();
182 table.reserve(nhist);
183 for (
int inWI = 0; inWI < static_cast<int>(nhist); inWI++) {
185 auto &inDets = ews->getSpectrum(inWI).getDetectorIDs();
192 if (outWI < lhs_nhist)
194 auto &outDets = lhs->getSpectrum(outWI).getDetectorIDs();
197 if (std::includes(outDets.begin(), outDets.end(), inDets.begin(), inDets.end())) {
199 table.emplace_back(inWI, outWI);
204 if (!done && !lhs_det_to_wi.empty() && (inDets.size() == 1)) {
208 auto inDets_it = inDets.begin();
209 detid_t rhs_detector_ID = *inDets_it;
213 detid2index_map::const_iterator map_it = lhs_det_to_wi.find(rhs_detector_ID);
214 if (map_it != lhs_det_to_wi.cend()) {
216 outWI =
static_cast<int>(map_it->second);
222 table.emplace_back(inWI, outWI);
230 for (outWI = 0; outWI < lhs_nhist; outWI++) {
231 const auto &outDets2 = lhs->getSpectrum(outWI).getDetectorIDs();
233 if (std::includes(outDets2.begin(), outDets2.end(), inDets.begin(), inDets.end())) {
235 table.emplace_back(inWI, outWI);
250 table.emplace_back(inWI, -1);
261 throw std::runtime_error(
"MergeRuns::buildAdditionTables: Mismatch between "
262 "the number of addition tables and the number of "
277 auto outWS = create<EventWorkspace>(*inputWS,
m_outputSize, inputWS->binEdges(0));
278 const auto inputSize = inputWS->getNumberHistograms();
279 for (
size_t i = 0; i < inputSize; ++i)
280 outWS->getSpectrum(i) = inputWS->getSpectrum(i);
283 m_progress = std::make_unique<Progress>(
this, 0.0, 1.0,
n);
286 auto current = inputSize;
287 for (
size_t workspaceNum = 1; workspaceNum <
m_inEventWS.size(); workspaceNum++) {
289 const auto &table =
m_tables[workspaceNum - 1];
292 for (
auto &WI : table) {
293 int64_t inWI = WI.first;
294 int64_t outWI = WI.second;
296 outWS->getSpectrum(outWI) += addee.getSpectrum(inWI);
298 outWS->getSpectrum(current) = addee.getSpectrum(inWI);
304 outWS->mutableRun() += addee.run();
323 const std::string sampleLogsFailBehaviour =
getProperty(
"FailBehaviour");
333 outWS = this->
rebinInput(outWS, *rebinParams);
344 auto isScanning = outWS->detectorInfo().isScanning();
347 m_progress = std::make_unique<Progress>(
this, 0.0, 1.0, numberOfWSs - 1);
367 outWS = outWS + addee;
370 }
catch (std::invalid_argument &e) {
372 g_log.
error() <<
"Could not merge run: " << it->get()->getName() <<
". Reason: \"" << e.what()
373 <<
"\". MergeRuns will continue but this run will be skipped.\n";
376 throw std::invalid_argument(e);
405 for (
size_t i = 0; i < inputWorkspaces.size(); ++i) {
419 if (!compatibility.empty()) {
420 g_log.
error(
"Input workspaces are not compatible: " + compatibility);
421 throw std::invalid_argument(
"Input workspaces are not compatible: " + compatibility);
436 const std::string rebinBehaviour =
getProperty(
"RebinBehaviour");
437 const std::string sampleLogsFailBehaviour =
getProperty(
"FailBehaviour");
441 std::sort(inputsSortedByX.begin(), inputsSortedByX.end(),
443 return ws1->x(0).front() < ws2->x(0).front();
445 auto it = inputsSortedByX.cbegin();
446 g_log.
notice() <<
"Using run '" << (*it)->getName() <<
"' as a reference to determine possible rebinning.\n";
447 boost::optional<std::vector<double>> rebinParams{boost::none};
448 std::vector<double> bins{(*it)->x(0).rawData()};
449 for (++it; it != inputsSortedByX.cend(); ++it) {
453 g_log.
error() <<
"Could not merge run: " << (*it)->getName()
454 <<
". Binning is different from the reference run. "
455 "MergeRuns will continue but this run will be "
460 throw std::invalid_argument(
"Could not merge run: " + (*it)->getName() +
461 ". Binning is different from the reference run.");
480 const std::vector<double> &bins2) {
481 std::vector<double> newParams;
484 newParams.reserve(1 + 2 * (bins1.size() - 1) + 2 + 2 * (bins2.size() - 1));
486 bool const oldIsFirst = bins1.front() < bins2.front();
487 auto const &smallerX = oldIsFirst ? bins1 : bins2;
488 auto const &greaterX = oldIsFirst ? bins2 : bins1;
489 double const end1 = smallerX.back();
490 double const start2 = greaterX.front();
491 double const end2 = greaterX.back();
493 if (end1 <= start2) {
498 newParams.emplace_back(smallerX.front());
500 for (i = 1; smallerX[i] <= start2; ++i) {
501 newParams.emplace_back(smallerX[i] - smallerX[i - 1]);
502 newParams.emplace_back(smallerX[i]);
525 for (
size_t i = 1; i < X1.size(); ++i) {
526 params.emplace_back(X1[i - 1]);
527 params.emplace_back(X1[i] - X1[i - 1]);
530 if (X1.back() < X2.front()) {
531 params.emplace_back(X1.back());
532 params.emplace_back(X2.front() - X1.back());
535 for (
size_t j = 1; j < X2.size(); ++j) {
536 params.emplace_back(X2[j - 1]);
537 params.emplace_back(X2[j] - X2[j - 1]);
539 params.emplace_back(X2.back());
555 auto const overlapbins1 = X1.size() - i;
556 auto const iterX2 = std::lower_bound(X2.cbegin(), X2.cend(), X1.back());
557 if (iterX2 == X2.end()) {
558 throw std::runtime_error(
"MergerRuns::intersectionParams: no intersection "
559 "between the histograms.");
561 auto const overlapbins2 = std::distance(X2.cbegin(), iterX2);
563 if (overlapbins1 <
static_cast<size_t>(overlapbins2)) {
565 for (; i < X1.size(); ++i) {
566 params.emplace_back(X1[i] - X1[i - 1]);
567 params.emplace_back(X1[i]);
573 for (
size_t j = overlapbins2; j < X2.size(); ++j) {
574 params.emplace_back(X2[j] - params.back());
575 params.emplace_back(X2[j]);
579 for (
size_t j = 1; j < X2.size(); ++j) {
580 params.emplace_back(X2[j] - params.back());
581 params.emplace_back(X2[j]);
600 const auto iterX1 = std::lower_bound(X1.cbegin() + i, X1.cend(), X2.back());
601 if (iterX1 == X1.cend()) {
602 throw std::runtime_error(
"MergeRuns::inclusionParams: no overlap between the histograms");
604 auto const overlapbins1 = std::distance(X1.cbegin(), iterX1) - i;
605 auto const overlapbins2 = X2.size() - 1;
609 if (overlapbins1 + 1 <= overlapbins2) {
612 for (; i < X1.size(); ++i) {
613 params.emplace_back(X1[i] - X1[i - 1]);
614 params.emplace_back(X1[i]);
619 for (
size_t j = 1; j < X2.size() - 1; ++j) {
620 params.emplace_back(X2[j] - params.back());
621 params.emplace_back(X2[j]);
625 for (; i < X1.size(); ++i) {
626 params.emplace_back(X1[i] - params.back());
627 params.emplace_back(X1[i]);
640 const std::vector<double> ¶ms) {
644 rebin->setProperty(
"Params", params);
645 rebin->executeAsChildAlg();
646 return rebin->getProperty(
"OutputWorkspace");
655 copyHistoryFromInputWorkspaces<std::vector<EventWorkspace_sptr>>(
m_inEventWS);
657 copyHistoryFromInputWorkspaces<std::list<MatrixWorkspace_sptr>>(
m_inMatrixWS);
672 std::vector<SpectrumDefinition> newAddeeSpecDefs(addeeSpecDefs.size());
678 for (int64_t i = 0; i < int64_t(addeeSpecDefs.size()); ++i) {
679 for (
auto &
index : addeeSpecDefs[i]) {
680 SpectrumDefinition newSpecDef;
681 for (
size_t time_index = 0; time_index < newOutDetInfo.
scanCount(); time_index++) {
682 if (addeeScanIntervals[
index.second] == newOutScanIntervals[time_index]) {
683 newSpecDef.add(
index.first, time_index);
686 newAddeeSpecDefs[i] = newSpecDef;
690 return newAddeeSpecDefs;
#define DECLARE_ALGORITHM(classname)
IPeaksWorkspace_sptr workspace
std::map< DeltaEMode::Type, std::string > index
#define PARALLEL_FOR_NO_WSP_CHECK()
void declareProperty(std::unique_ptr< Kernel::Property > p, const std::string &doc="") override
Add a property to the list of managed properties.
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.
virtual 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)
Create a Child Algorithm.
A property class for workspaces.
API::MatrixWorkspace_sptr rebinInput(const API::MatrixWorkspace_sptr &workspace, const std::vector< double > ¶ms)
Calls the Rebin algorithm as a ChildAlgorithm.
std::string fetchInputPropertyName() const override
Method to provide the name for the input workspace property.
size_t m_outputSize
Total number of histograms in the output workspace.
void buildAdditionTables()
Build up addition tables for merging eventlists together.
void exec() override
Executes the algorithm.
std::vector< SpectrumDefinition > buildScanIntervals(const std::vector< SpectrumDefinition > &addeeSpecDefs, const Geometry::DetectorInfo &addeeDetInfo, const Geometry::DetectorInfo &newOutDetInfo)
std::vector< Mantid::DataObjects::EventWorkspace_sptr > m_inEventWS
List of input EVENT workspaces.
static void inclusionParams(const HistogramData::HistogramX &X1, size_t &i, const HistogramData::HistogramX &X2, std::vector< double > ¶ms)
Calculates the rebin parameters in the case where the range of the second workspace is entirely withi...
std::unique_ptr< API::Progress > m_progress
Progress reporting.
void init() override
Initialisation method.
void execEvent()
Executes the algorithm for EventWorkspaces.
static void noOverlapParams(const HistogramData::HistogramX &X1, const HistogramData::HistogramX &X2, std::vector< double > ¶ms)
Calculates the rebin paramters in the case where the two input workspaces do not overlap at all.
static std::vector< double > calculateRebinParams(const std::vector< double > &bins1, const std::vector< double > &bins2)
Calculates the parameters to hand to the Rebin algorithm.
std::vector< AdditionTable > m_tables
Addition tables for event workspaces.
bool useCustomInputPropertyName() const override
Method to indicate that a non-standard property is taken as the input, so will be specified via fetch...
boost::optional< std::vector< double > > checkRebinning()
Checks if the workspaces need to be rebinned and if so, returns the rebinning parameters for the Rebi...
bool validateInputsForEventWorkspaces(const std::vector< std::string > &inputWorkspaces)
Validate the input event workspaces.
void fillHistory() override
Overriden fillHistory method to correctly store history from merged workspaces.
API::MatrixWorkspace_sptr buildScanningOutputWorkspace(const API::MatrixWorkspace_sptr &outWS, const API::MatrixWorkspace_sptr &addee)
std::list< API::MatrixWorkspace_sptr > m_inMatrixWS
List of input matrix workspace.
std::vector< std::pair< int, int > > AdditionTable
An addition table is a list of pairs: First int = workspace index in the EW being added,...
void execHistogram(const std::vector< std::string > &inputs)
static void intersectionParams(const HistogramData::HistogramX &X1, size_t &i, const HistogramData::HistogramX &X2, std::vector< double > ¶ms)
Calculates the rebin parameters in the case where the bins of the two workspaces intersect.
static std::vector< std::string > unWrapGroups(const std::vector< std::string > &)
Flattens the list of group workspaces (if any) into list of workspaces.
std::list< API::MatrixWorkspace_sptr > validateInputWorkspaces(const std::vector< std::string > &inputWorkspaces, Kernel::Logger &g_log)
Checks that the input workspace all exist, that they are the same size, have the same units and the s...
void setReferenceProperties(const API::MatrixWorkspace_sptr &)
Sets the properties of the reference (usually first) workspace, to later check the compatibility of t...
std::string checkCompatibility(const API::MatrixWorkspace_sptr &, bool checkNumberHistograms=false)
Compares the properties of the input workspace with the reference.
SampleLogsBehaviour : This class holds information relating to the behaviour of the sample log mergin...
static const std::string LIST_DOC
static const std::string FAIL_DOC
static const std::string WARN_DOC
void removeSampleLogsFromWorkspace(const API::MatrixWorkspace_sptr &addeeWS)
When doing a time series merge we need to remove, then add back the sample log in the addee workspace...
static const std::string FAIL_PROP
static const std::string LIST_PROP
static const std::string TIME_SERIES_PROP
static const std::string TIME_SERIES_DOC
static const std::string SUM_DOC
static const std::string WARN_TOL_PROP
void readdSampleLogToWorkspace(const API::MatrixWorkspace_sptr &addeeWS)
When doing a time series merge we need to remove, then add back the sample log in the addee workspace...
static const std::string FAIL_TOL_DOC
void setUpdatedSampleLogs(const API::MatrixWorkspace_sptr &outWS)
Set the values in the map to be the same as those in the output workspace.
static const std::string WARN_PROP
void resetSampleLogs(const API::MatrixWorkspace_sptr &ws)
Resets the sample logs in the workspace to the values in the map.
void mergeSampleLogs(const API::MatrixWorkspace_sptr &addeeWS, const API::MatrixWorkspace_sptr &outWS)
Create and update sample logs according to instrument parameters.
static const std::string FAIL_TOL_PROP
static const std::string SUM_PROP
static const std::string WARN_TOL_DOC
This class is intended to fulfill the design specified in <https://github.com/mantidproject/documents...
Geometry::DetectorInfo is an intermediate step towards a DetectorInfo that is part of Instrument-2....
size_t scanCount() const
Returns the scan count of the detector with given detector index.
const std::vector< std::pair< Types::Core::DateAndTime, Types::Core::DateAndTime > > scanIntervals() const
Returns the scan interval of the detector with given index.
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.
void error(const std::string &msg)
Logs at error level.
void warning(const std::string &msg)
Logs at warning level.
void information(const std::string &msg)
Logs at information level.
static T & Instance()
Return a reference to the Singleton instance, creating it if it does not already exist Creation is do...
std::shared_ptr< MatrixWorkspace > MatrixWorkspace_sptr
shared pointer to the matrix workspace base class
static const std::string FAIL_MERGE_TOLERANCES
static const std::string WARN_MERGE_TOLERANCES
static const std::string WARN_MERGE
static const std::string FAIL_MERGE
static const std::string SUM_MERGE
MergeRuns parameter names of the paramter file for sample log merging.
static const std::string TIME_SERIES_MERGE
static const std::string LIST_MERGE
static const std::string STOP_BEHAVIOUR
static const std::string REBIN_BEHAVIOUR
static const std::string FAIL_BEHAVIOUR
static const std::string SKIP_BEHAVIOUR
std::shared_ptr< EventWorkspace > EventWorkspace_sptr
shared pointer to the EventWorkspace class
int MANTID_KERNEL_DLL createAxisFromRebinParams(const std::vector< double > ¶ms, std::vector< double > &xnew, const bool resize_xnew=true, const bool full_bins_only=false, const double xMinHint=std::nan(""), const double xMaxHint=std::nan(""), const bool useReverseLogarithmic=false, const double power=-1)
Creates a new output X array given a 'standard' set of rebinning parameters.
void MANTID_KERNEL_DLL rebin(const std::vector< double > &xold, const std::vector< double > &yold, const std::vector< double > &eold, const std::vector< double > &xnew, std::vector< double > &ynew, std::vector< double > &enew, bool distribution, bool addition=false)
Rebins data according to a new output X array.
int32_t detid_t
Typedef for a detector ID.
std::unordered_map< detid_t, size_t > detid2index_map
Map with key = detector ID, value = workspace index.
static bool matchingBins(const MatrixWorkspace &ws1, const MatrixWorkspace &ws2, const bool firstOnly=false)
Checks whether the bins (X values) of two workspace are the same.
std::string sampleLogsWarnTolerances
std::string sampleLogsWarn
std::string sampleLogsFail
std::string sampleLogsSum
std::string sampleLogsList
std::string sampleLogsTimeSeries
std::string sampleLogsFailTolerances
@ Output
An output workspace.