Mantid
Loading...
Searching...
No Matches
MergeRuns.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
11#include "MantidAPI/Axis.h"
12#include "MantidAPI/Run.h"
21#include "MantidIndexing/IndexInfo.h"
25#include "MantidKernel/Unit.h"
27
28#include "MantidTypes/SpectrumDefinition.h"
29
30using Mantid::HistogramData::HistogramX;
31
32namespace Mantid::Algorithms {
33
34// Register with the algorithm factory
35DECLARE_ALGORITHM(MergeRuns)
36
37using namespace Kernel;
38using namespace API;
39using namespace Geometry;
40using namespace DataObjects;
41using namespace RunCombinationOptions;
42
45 // declare arbitrary number of input workspaces as a list of strings at the
46 // moment
47 declareProperty(std::make_unique<ArrayProperty<std::string>>("InputWorkspaces", std::make_shared<ADSValidator>()),
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.");
51 declareProperty(std::make_unique<WorkspaceProperty<Workspace>>("OutputWorkspace", "", Direction::Output),
52 "Name of the output workspace");
60 const std::vector<std::string> rebinOptions = {REBIN_BEHAVIOUR, FAIL_BEHAVIOUR};
61 declareProperty("RebinBehaviour", REBIN_BEHAVIOUR, std::make_shared<StringListValidator>(rebinOptions),
62 "Choose whether to rebin when bins are different, or fail "
63 "(fail behaviour defined in FailBehaviour option).");
64 const std::vector<std::string> failBehaviourOptions = {SKIP_BEHAVIOUR, STOP_BEHAVIOUR};
65 declareProperty("FailBehaviour", SKIP_BEHAVIOUR, std::make_shared<StringListValidator>(failBehaviourOptions),
66 "Choose whether to skip the file and continue, or stop and "
67 "throw and error, when encountering a failure.");
68}
69
70// @return the name of the property used to supply in input workspace(s).
71std::string MergeRuns::fetchInputPropertyName() const { return "InputWorkspaces"; }
72
73// @returns true since "InputWorkspaces" is a non-workspace array property taken
74// to be the input.
75bool MergeRuns::useCustomInputPropertyName() const { return true; }
76
82 // Check that all input workspaces exist and match in certain important ways
83 const std::vector<std::string> inputs_orig = getProperty("InputWorkspaces");
84
85 // This will hold the inputs, with the groups separated off
86 std::vector<std::string> inputs = RunCombinationHelper::unWrapGroups(inputs_orig);
87 if (inputs.size() == 1) {
88 g_log.warning("Only one input workspace specified");
89 }
90
91 // First, try as event workspaces
92 if (this->validateInputsForEventWorkspaces(inputs)) {
93 // Yes, they are all event workspaces! ---------------------
94 this->execEvent();
95 } else {
96 // At least one is not event workspace ----------------
97 this->execHistogram(inputs);
98 }
99}
100
102 const MatrixWorkspace_sptr &addeeWS) {
103 const auto numOutputSpectra = outWS->getNumberHistograms() + addeeWS->getNumberHistograms();
104
105 MatrixWorkspace_sptr newOutWS =
106 DataObjects::create<MatrixWorkspace>(*outWS, numOutputSpectra, outWS->histogram(0).binEdges());
107
108 newOutWS->mutableComponentInfo().merge(addeeWS->componentInfo());
109
110 if (newOutWS->detectorInfo().size() * newOutWS->detectorInfo().scanCount() ==
111 outWS->detectorInfo().size() * outWS->detectorInfo().scanCount()) {
112 // In this case the detector info objects were identical. We just add the
113 // workspaces as we normally would for MergeRuns.
114 g_log.information() << "Workspaces had identical detector scan information and were "
115 "merged.";
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.");
121 }
122
123 g_log.information() << "Workspaces had different, non-overlapping scan intervals "
124 "so spectra will be appended.";
125
126 auto outSpecDefs = *(outWS->indexInfo().spectrumDefinitions());
127 const auto &addeeSpecDefs = *(addeeWS->indexInfo().spectrumDefinitions());
128
129 const auto newAddeeSpecDefs = buildScanIntervals(addeeSpecDefs, addeeWS->detectorInfo(), newOutWS->detectorInfo());
130
131 outSpecDefs.insert(outSpecDefs.end(), newAddeeSpecDefs.begin(), newAddeeSpecDefs.end());
132
133 auto newIndexInfo = Indexing::IndexInfo(numOutputSpectra);
134 newIndexInfo.setSpectrumDefinitions(std::move(outSpecDefs));
135 newOutWS->setIndexInfo(newIndexInfo);
136
137 for (size_t i = 0; i < outWS->getNumberHistograms(); ++i)
138 newOutWS->setHistogram(i, outWS->histogram(i));
139
140 for (size_t i = 0; i < addeeWS->getNumberHistograms(); ++i)
141 newOutWS->setHistogram(i + outWS->getNumberHistograms(), addeeWS->histogram(i));
142
143 return newOutWS;
144}
145
150 if (m_inEventWS.empty())
151 throw std::invalid_argument("MergeRuns: No workspaces found to merge.");
152
153 // This'll hold the addition tables.
154 m_tables.clear();
155
156 // This is the workspace against which everything will be added
158 auto lhs_nhist = static_cast<int>(lhs->getNumberHistograms());
159
160 detid2index_map lhs_det_to_wi;
161 try {
162 lhs_det_to_wi = lhs->getDetectorIDToWorkspaceIndexMap(true);
163 } catch (std::runtime_error &) {
164 // If it fails, then there are some grouped detector IDs, and the map cannot
165 // exist
166 }
167
168 m_outputSize = m_inEventWS[0]->getNumberHistograms();
169
170 for (size_t workspaceNum = 1; workspaceNum < m_inEventWS.size(); workspaceNum++) {
171 // Get the workspace
172 EventWorkspace_sptr ews = m_inEventWS[workspaceNum];
173
174 // An addition table is a list of pairs:
175 // First int = workspace index in the EW being added
176 // Second int = workspace index to which it will be added in the OUTPUT EW.
177 // -1 if it should add a new entry at the end.
178 AdditionTable table;
179
180 // Loop through the input workspace indices
181 std::size_t nhist = ews->getNumberHistograms();
182 table.reserve(nhist);
183 for (int inWI = 0; inWI < static_cast<int>(nhist); inWI++) {
184 // Get the set of detectors in the output
185 auto &inDets = ews->getSpectrum(inWI).getDetectorIDs();
186
187 bool done = false;
188
189 // First off, try to match the workspace indices. Most times, this will be
190 // ok right away.
191 int outWI = inWI;
192 if (outWI < lhs_nhist) // don't go out of bounds
193 {
194 auto &outDets = lhs->getSpectrum(outWI).getDetectorIDs();
195
196 // Checks that inDets is a subset of outDets
197 if (std::includes(outDets.begin(), outDets.end(), inDets.begin(), inDets.end())) {
198 // We found the workspace index right away. No need to keep looking
199 table.emplace_back(inWI, outWI);
200 done = true;
201 }
202 }
203
204 if (!done && !lhs_det_to_wi.empty() && (inDets.size() == 1)) {
205 // Didn't find it. Try to use the LHS map.
206
207 // First, we have to get the (single) detector ID of the RHS
208 auto inDets_it = inDets.begin();
209 detid_t rhs_detector_ID = *inDets_it;
210
211 // Now we use the LHS map to find it. This only works if both the lhs
212 // and rhs have 1 detector per pixel
213 detid2index_map::const_iterator map_it = lhs_det_to_wi.find(rhs_detector_ID);
214 if (map_it != lhs_det_to_wi.cend()) {
215 // This is the workspace index in the LHS that matched rhs_detector_ID
216 outWI = static_cast<int>(map_it->second);
217 } else {
218 // Did not find it!
219 outWI = -1; // Marker to mean its not in the LHS.
220 ++m_outputSize;
221 }
222 table.emplace_back(inWI, outWI);
223 done = true; // Great, we did it.
224 }
225
226 if (!done) {
227 // Didn't find it? Now we need to iterate through the output workspace
228 // to match the detector ID.
229 // NOTE: This can be SUPER SLOW!
230 for (outWI = 0; outWI < lhs_nhist; outWI++) {
231 const auto &outDets2 = lhs->getSpectrum(outWI).getDetectorIDs();
232 // Another subset check
233 if (std::includes(outDets2.begin(), outDets2.end(), inDets.begin(), inDets.end())) {
234 // This one is right. Now we can stop looking.
235 table.emplace_back(inWI, outWI);
236 done = true;
237 continue;
238 }
239 }
240 }
241
242 if (!done) {
243 // If we reach here, not a single match was found for this set of
244 // inDets.
245
246 // TODO: should we check that none of the output ones are subsets of
247 // this one?
248
249 // So we need to add it as a new workspace index
250 table.emplace_back(inWI, -1);
251 ++m_outputSize;
252 }
253 }
254
255 // Add this table to the list
256 m_tables.emplace_back(table);
257
258 } // each of the workspaces being added
259
260 if (m_tables.size() != m_inEventWS.size() - 1)
261 throw std::runtime_error("MergeRuns::buildAdditionTables: Mismatch between "
262 "the number of addition tables and the number of "
263 "workspaces");
264}
265
266//------------------------------------------------------------------------------------------------
270 g_log.information() << "Creating an output EventWorkspace\n";
271
272 // Make the addition tables, or throw an error if there was a problem.
273 this->buildAdditionTables();
274
275 // Create a new output event workspace, by copying the first WS in the list
276 EventWorkspace_sptr inputWS = m_inEventWS[0];
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);
281
282 int64_t n = m_inEventWS.size() - 1;
283 m_progress = std::make_unique<Progress>(this, 0.0, 1.0, n);
284
285 // Note that we start at 1, since we already have the 0th workspace
286 auto current = inputSize;
287 for (size_t workspaceNum = 1; workspaceNum < m_inEventWS.size(); workspaceNum++) {
288 const auto &addee = *m_inEventWS[workspaceNum];
289 const auto &table = m_tables[workspaceNum - 1];
290
291 // Add all the event lists together as the table says to do
292 for (auto &WI : table) {
293 int64_t inWI = WI.first;
294 int64_t outWI = WI.second;
295 if (outWI >= 0) {
296 outWS->getSpectrum(outWI) += addee.getSpectrum(inWI);
297 } else {
298 outWS->getSpectrum(current) = addee.getSpectrum(inWI);
299 ++current;
300 }
301 }
302
303 // Now we add up the runs
304 outWS->mutableRun() += addee.run();
305
306 m_progress->report();
307 }
308
309 // Set the final workspace to the output property
310 setProperty("OutputWorkspace", std::move(outWS));
311}
312
313void MergeRuns::execHistogram(const std::vector<std::string> &inputs) {
322
323 const std::string sampleLogsFailBehaviour = getProperty("FailBehaviour");
324
325 // This gets the list of workspaces
326 RunCombinationHelper combHelper;
327 m_inMatrixWS = combHelper.validateInputWorkspaces(inputs, g_log);
328 const auto rebinParams = checkRebinning();
329
330 // Take the first input workspace as the first argument to the addition
331 MatrixWorkspace_sptr outWS(m_inMatrixWS.front()->clone());
332 if (rebinParams) {
333 outWS = this->rebinInput(outWS, *rebinParams);
334 }
342 Algorithms::SampleLogsBehaviour sampleLogsBehaviour = SampleLogsBehaviour(outWS, g_log, logEntries, parName);
343
344 auto isScanning = outWS->detectorInfo().isScanning();
345
346 const size_t numberOfWSs = m_inMatrixWS.size();
347 m_progress = std::make_unique<Progress>(this, 0.0, 1.0, numberOfWSs - 1);
348 // Note that the iterator is incremented before first pass so that 1st
349 // workspace isn't added to itself
350 auto it = m_inMatrixWS.begin();
351 for (++it; it != m_inMatrixWS.end(); ++it) {
353 if (rebinParams) {
354 addee = this->rebinInput(*it, *rebinParams);
355 } else {
356 addee = *it;
357 }
358
359 // Add the current workspace to the total
360 // Update the sample logs
361 try {
362 sampleLogsBehaviour.mergeSampleLogs(*it, outWS);
363 sampleLogsBehaviour.removeSampleLogsFromWorkspace(addee);
364 if (isScanning)
365 outWS = buildScanningOutputWorkspace(outWS, addee);
366 else
367 outWS = outWS + addee;
368 sampleLogsBehaviour.setUpdatedSampleLogs(outWS);
369 sampleLogsBehaviour.readdSampleLogToWorkspace(addee);
370 } catch (std::invalid_argument &e) {
371 if (sampleLogsFailBehaviour == SKIP_BEHAVIOUR) {
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";
374 sampleLogsBehaviour.resetSampleLogs(outWS);
375 } else {
376 throw std::invalid_argument(e);
377 }
378 }
379 m_progress->report();
380 }
381
382 // Set the final workspace to the output property
383 setProperty("OutputWorkspace", outWS);
384}
385
386//------------------------------------------------------------------------------------------------
394bool MergeRuns::validateInputsForEventWorkspaces(const std::vector<std::string> &inputWorkspaces) {
395
396 m_inEventWS.clear();
397
398 // TODO: Check that name of instrument matches - think that's the best
399 // possible at the moment because if instrument is created from raw file it'll
400 // be a different object
401 // std::string instrument;
402
403 RunCombinationHelper combHelper;
404
405 for (size_t i = 0; i < inputWorkspaces.size(); ++i) {
406 // Fetch the next input workspace as an - throw an error if it's not there
407 EventWorkspace_sptr ws = AnalysisDataService::Instance().retrieveWS<EventWorkspace>(inputWorkspaces[i]);
408
409 if (!ws) { // Either it is not found, or it is not an EventWorkspace
410 return false;
411 }
412 m_inEventWS.emplace_back(ws);
413
414 // Check a few things are the same for all input workspaces
415 if (i == 0) {
416 combHelper.setReferenceProperties(ws);
417 } else {
418 std::string compatibility = combHelper.checkCompatibility(ws);
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);
422 }
423 }
424 } // for each input WS name
425
426 // We got here: all are event workspaces
427 return true;
428}
429
435boost::optional<std::vector<double>> MergeRuns::checkRebinning() {
436 const std::string rebinBehaviour = getProperty("RebinBehaviour");
437 const std::string sampleLogsFailBehaviour = getProperty("FailBehaviour");
438 // To properly cover all X spans of the input workspaces, one needs to
439 // sort the workspaces in ascending X before figuring out the rebinning.
440 std::vector<MatrixWorkspace_sptr> inputsSortedByX(m_inMatrixWS.cbegin(), m_inMatrixWS.cend());
441 std::sort(inputsSortedByX.begin(), inputsSortedByX.end(),
442 [](const MatrixWorkspace_sptr &ws1, const MatrixWorkspace_sptr &ws2) {
443 return ws1->x(0).front() < ws2->x(0).front();
444 });
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) {
450 if (!WorkspaceHelpers::matchingBins(*inputsSortedByX.front(), **it, true)) {
451 if (rebinBehaviour != REBIN_BEHAVIOUR) {
452 if (sampleLogsFailBehaviour == SKIP_BEHAVIOUR) {
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 "
456 "skipped.\n";
457 m_inMatrixWS.remove(*it);
458 continue;
459 } else {
460 throw std::invalid_argument("Could not merge run: " + (*it)->getName() +
461 ". Binning is different from the reference run.");
462 }
463 }
464 rebinParams = this->calculateRebinParams(bins, (*it)->x(0).rawData());
465 VectorHelper::createAxisFromRebinParams(*rebinParams, bins);
466 }
467 }
468 return rebinParams;
469}
470
471//------------------------------------------------------------------------------------------------
479std::vector<double> MergeRuns::calculateRebinParams(const std::vector<double> &bins1,
480 const std::vector<double> &bins2) {
481 std::vector<double> newParams;
482 // Try to reserve memory for the worst-case scenario: two non-overlapping
483 // ranges.
484 newParams.reserve(1 + 2 * (bins1.size() - 1) + 2 + 2 * (bins2.size() - 1));
485 // Sort by X axis which starts smaller
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();
492
493 if (end1 <= start2) {
494 // First case is if there's no overlap between the workspaces
495 noOverlapParams(smallerX, greaterX, newParams);
496 } else {
497 // Add the bins up to the start of the overlap
498 newParams.emplace_back(smallerX.front());
499 size_t i;
500 for (i = 1; smallerX[i] <= start2; ++i) {
501 newParams.emplace_back(smallerX[i] - smallerX[i - 1]);
502 newParams.emplace_back(smallerX[i]);
503 }
504 // If the range of one of the workspaces is completely within that
505 // of the other, call the 'inclusion' routine.
506 // Otherwise call the standard 'intersection' one.
507 if (end1 < end2) {
508 intersectionParams(smallerX, i, greaterX, newParams);
509 } else {
510 inclusionParams(smallerX, i, greaterX, newParams);
511 }
512 }
513 return newParams;
514}
515
516//------------------------------------------------------------------------------------------------
523void MergeRuns::noOverlapParams(const HistogramX &X1, const HistogramX &X2, std::vector<double> &params) {
524 // Add all the bins from the first workspace
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]);
528 }
529 // Put a single bin in the 'gap' (but check first the 'gap' isn't zero)
530 if (X1.back() < X2.front()) {
531 params.emplace_back(X1.back());
532 params.emplace_back(X2.front() - X1.back());
533 }
534 // Now add all the bins from the second workspace
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]);
538 }
539 params.emplace_back(X2.back());
540}
541
542//------------------------------------------------------------------------------------------------
552void MergeRuns::intersectionParams(const HistogramX &X1, size_t &i, const HistogramX &X2, std::vector<double> &params) {
553 // First calculate the number of bins in each workspace that are in the
554 // overlap region
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.");
560 }
561 auto const overlapbins2 = std::distance(X2.cbegin(), iterX2);
562 // We want to use whichever one has the larger bins (on average)
563 if (overlapbins1 < static_cast<size_t>(overlapbins2)) {
564 // In this case we want the rest of the bins from the first workspace.....
565 for (; i < X1.size(); ++i) {
566 params.emplace_back(X1[i] - X1[i - 1]);
567 params.emplace_back(X1[i]);
568 }
569 // Now remove the last bin & boundary
570 params.pop_back();
571 params.pop_back();
572 // ....and then the non-overlap ones from the second workspace
573 for (size_t j = overlapbins2; j < X2.size(); ++j) {
574 params.emplace_back(X2[j] - params.back());
575 params.emplace_back(X2[j]);
576 }
577 } else {
578 // In this case we just have to add all the bins from the second workspace
579 for (size_t j = 1; j < X2.size(); ++j) {
580 params.emplace_back(X2[j] - params.back());
581 params.emplace_back(X2[j]);
582 }
583 }
584}
585
586//------------------------------------------------------------------------------------------------
597void MergeRuns::inclusionParams(const HistogramX &X1, size_t &i, const HistogramX &X2, std::vector<double> &params) {
598 // First calculate the number of bins in each workspace that are in the
599 // overlap region
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");
603 }
604 auto const overlapbins1 = std::distance(X1.cbegin(), iterX1) - i;
605 auto const overlapbins2 = X2.size() - 1;
606
607 // In the overlap region, we want to use whichever one has the larger bins (on
608 // average)
609 if (overlapbins1 + 1 <= overlapbins2) {
610 // In the case where the first workspace has larger bins it's easy
611 // - just add the rest of X1's bins
612 for (; i < X1.size(); ++i) {
613 params.emplace_back(X1[i] - X1[i - 1]);
614 params.emplace_back(X1[i]);
615 }
616 } else {
617 // In this case we want all of X2's bins first (without the first and last
618 // boundaries)
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]);
622 }
623 // And now those from X1 that lie above the overlap region
624 i += overlapbins1;
625 for (; i < X1.size(); ++i) {
626 params.emplace_back(X1[i] - params.back());
627 params.emplace_back(X1[i]);
628 }
629 }
630}
631
632//------------------------------------------------------------------------------------------------
640 const std::vector<double> &params) {
641 // Create a Rebin child algorithm
642 auto rebin = createChildAlgorithm("Rebin");
643 rebin->setProperty("InputWorkspace", workspace);
644 rebin->setProperty("Params", params);
645 rebin->executeAsChildAlg();
646 return rebin->getProperty("OutputWorkspace");
647}
648
653 // check if we were merging event or matrix workspaces
654 if (!m_inEventWS.empty()) {
655 copyHistoryFromInputWorkspaces<std::vector<EventWorkspace_sptr>>(m_inEventWS);
656 } else {
657 copyHistoryFromInputWorkspaces<std::list<MatrixWorkspace_sptr>>(m_inMatrixWS);
658 }
659}
660
661/*
662 * Here we build up the correct time indexes for the workspace being added. If
663 *the scan times for the addee workspace and output workspace are the same this
664 *builds the same indexing as the workspace had before. Otherwise, the correct
665 *time indexes are set here.
666 *
667 *This function translates time indices from the addee to the new workspace.
668 */
669std::vector<SpectrumDefinition> MergeRuns::buildScanIntervals(const std::vector<SpectrumDefinition> &addeeSpecDefs,
670 const DetectorInfo &addeeDetInfo,
671 const DetectorInfo &newOutDetInfo) {
672 std::vector<SpectrumDefinition> newAddeeSpecDefs(addeeSpecDefs.size());
673
674 auto addeeScanIntervals = addeeDetInfo.scanIntervals();
675 auto newOutScanIntervals = newOutDetInfo.scanIntervals();
676
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);
684 }
685 }
686 newAddeeSpecDefs[i] = newSpecDef;
687 }
688 }
689
690 return newAddeeSpecDefs;
691}
692
693} // namespace Mantid::Algorithms
#define DECLARE_ALGORITHM(classname)
Definition: Algorithm.h:576
IPeaksWorkspace_sptr workspace
Definition: IndexPeaks.cpp:114
std::map< DeltaEMode::Type, std::string > index
Definition: DeltaEMode.cpp:19
#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.
Definition: Algorithm.cpp:1913
std::string getPropertyValue(const std::string &name) const override
Get the value of a property as a string.
Definition: Algorithm.cpp:2026
TypedValue getProperty(const std::string &name) const override
Get the value of a property.
Definition: Algorithm.cpp:2076
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.
Definition: Algorithm.cpp:842
Kernel::Logger & g_log
Definition: Algorithm.h:451
A property class for workspaces.
API::MatrixWorkspace_sptr rebinInput(const API::MatrixWorkspace_sptr &workspace, const std::vector< double > &params)
Calls the Rebin algorithm as a ChildAlgorithm.
Definition: MergeRuns.cpp:639
std::string fetchInputPropertyName() const override
Method to provide the name for the input workspace property.
Definition: MergeRuns.cpp:71
size_t m_outputSize
Total number of histograms in the output workspace.
Definition: MergeRuns.h:146
void buildAdditionTables()
Build up addition tables for merging eventlists together.
Definition: MergeRuns.cpp:149
void exec() override
Executes the algorithm.
Definition: MergeRuns.cpp:81
std::vector< SpectrumDefinition > buildScanIntervals(const std::vector< SpectrumDefinition > &addeeSpecDefs, const Geometry::DetectorInfo &addeeDetInfo, const Geometry::DetectorInfo &newOutDetInfo)
Definition: MergeRuns.cpp:669
std::vector< Mantid::DataObjects::EventWorkspace_sptr > m_inEventWS
List of input EVENT workspaces.
Definition: MergeRuns.h:140
static void inclusionParams(const HistogramData::HistogramX &X1, size_t &i, const HistogramData::HistogramX &X2, std::vector< double > &params)
Calculates the rebin parameters in the case where the range of the second workspace is entirely withi...
Definition: MergeRuns.cpp:597
std::unique_ptr< API::Progress > m_progress
Progress reporting.
Definition: MergeRuns.h:137
void init() override
Initialisation method.
Definition: MergeRuns.cpp:44
void execEvent()
Executes the algorithm for EventWorkspaces.
Definition: MergeRuns.cpp:269
static void noOverlapParams(const HistogramData::HistogramX &X1, const HistogramData::HistogramX &X2, std::vector< double > &params)
Calculates the rebin paramters in the case where the two input workspaces do not overlap at all.
Definition: MergeRuns.cpp:523
static std::vector< double > calculateRebinParams(const std::vector< double > &bins1, const std::vector< double > &bins2)
Calculates the parameters to hand to the Rebin algorithm.
Definition: MergeRuns.cpp:479
std::vector< AdditionTable > m_tables
Addition tables for event workspaces.
Definition: MergeRuns.h:144
bool useCustomInputPropertyName() const override
Method to indicate that a non-standard property is taken as the input, so will be specified via fetch...
Definition: MergeRuns.cpp:75
boost::optional< std::vector< double > > checkRebinning()
Checks if the workspaces need to be rebinned and if so, returns the rebinning parameters for the Rebi...
Definition: MergeRuns.cpp:435
bool validateInputsForEventWorkspaces(const std::vector< std::string > &inputWorkspaces)
Validate the input event workspaces.
Definition: MergeRuns.cpp:394
void fillHistory() override
Overriden fillHistory method to correctly store history from merged workspaces.
Definition: MergeRuns.cpp:652
API::MatrixWorkspace_sptr buildScanningOutputWorkspace(const API::MatrixWorkspace_sptr &outWS, const API::MatrixWorkspace_sptr &addee)
Definition: MergeRuns.cpp:101
std::list< API::MatrixWorkspace_sptr > m_inMatrixWS
List of input matrix workspace.
Definition: MergeRuns.h:142
std::vector< std::pair< int, int > > AdditionTable
An addition table is a list of pairs: First int = workspace index in the EW being added,...
Definition: MergeRuns.h:98
void execHistogram(const std::vector< std::string > &inputs)
Definition: MergeRuns.cpp:313
static void intersectionParams(const HistogramData::HistogramX &X1, size_t &i, const HistogramData::HistogramX &X2, std::vector< double > &params)
Calculates the rebin parameters in the case where the bins of the two workspaces intersect.
Definition: MergeRuns.cpp:552
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...
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...
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...
void setUpdatedSampleLogs(const API::MatrixWorkspace_sptr &outWS)
Set the values in the map to be the same as those in the output workspace.
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.
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....
Definition: DetectorInfo.h:49
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.
Definition: ArrayProperty.h:28
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:95
void error(const std::string &msg)
Logs at error level.
Definition: Logger.cpp:77
void warning(const std::string &msg)
Logs at warning level.
Definition: Logger.cpp:86
void information(const std::string &msg)
Logs at information level.
Definition: Logger.cpp:105
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
Definition: MergeRuns.h:59
static const std::string WARN_MERGE_TOLERANCES
Definition: MergeRuns.h:57
static const std::string WARN_MERGE
Definition: MergeRuns.h:56
static const std::string FAIL_MERGE
Definition: MergeRuns.h:58
static const std::string SUM_MERGE
MergeRuns parameter names of the paramter file for sample log merging.
Definition: MergeRuns.h:53
static const std::string TIME_SERIES_MERGE
Definition: MergeRuns.h:54
static const std::string LIST_MERGE
Definition: MergeRuns.h:55
std::shared_ptr< EventWorkspace > EventWorkspace_sptr
shared pointer to the EventWorkspace class
int MANTID_KERNEL_DLL createAxisFromRebinParams(const std::vector< double > &params, 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.
Definition: SpectrumInfo.h:21
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.
@ Output
An output workspace.
Definition: Property.h:54