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 const &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
435std::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 std::optional<std::vector<double>> rebinParams{std::nullopt};
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));
465 VectorHelper::createAxisFromRebinParams(*rebinParams, bins);
466 }
467 }
468 return rebinParams;
469}
470
471//------------------------------------------------------------------------------------------------
479std::vector<double> MergeRuns::calculateRebinParams(std::span<double const> const bins1,
480 std::span<double const> const 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(std::span<double const> const X1, std::span<double const> const X2,
524 std::vector<double> &params) {
525 // Add all the bins from the first workspace
526 for (size_t i = 1; i < X1.size(); ++i) {
527 params.emplace_back(X1[i - 1]);
528 params.emplace_back(X1[i] - X1[i - 1]);
529 }
530 // Put a single bin in the 'gap' (but check first the 'gap' isn't zero)
531 if (X1.back() < X2.front()) {
532 params.emplace_back(X1.back());
533 params.emplace_back(X2.front() - X1.back());
534 }
535 // Now add all the bins from the second workspace
536 for (size_t j = 1; j < X2.size(); ++j) {
537 params.emplace_back(X2[j - 1]);
538 params.emplace_back(X2[j] - X2[j - 1]);
539 }
540 params.emplace_back(X2.back());
541}
542
543//------------------------------------------------------------------------------------------------
553void MergeRuns::intersectionParams(std::span<double const> const X1, size_t &i, std::span<double const> const X2,
554 std::vector<double> &params) {
555 // First calculate the number of bins in each workspace that are in the
556 // overlap region
557 auto const overlapbins1 = X1.size() - i;
558 auto const iterX2 = std::lower_bound(X2.begin(), X2.end(), X1.back());
559 if (iterX2 == X2.end()) {
560 throw std::runtime_error("MergerRuns::intersectionParams: no intersection "
561 "between the histograms.");
562 }
563 auto const overlapbins2 = std::distance(X2.begin(), iterX2);
564 // We want to use whichever one has the larger bins (on average)
565 if (overlapbins1 < static_cast<size_t>(overlapbins2)) {
566 // In this case we want the rest of the bins from the first workspace.....
567 for (; i < X1.size(); ++i) {
568 params.emplace_back(X1[i] - X1[i - 1]);
569 params.emplace_back(X1[i]);
570 }
571 // Now remove the last bin & boundary
572 params.pop_back();
573 params.pop_back();
574 // ....and then the non-overlap ones from the second workspace
575 for (size_t j = overlapbins2; j < X2.size(); ++j) {
576 params.emplace_back(X2[j] - params.back());
577 params.emplace_back(X2[j]);
578 }
579 } else {
580 // In this case we just have to add all the bins from the second workspace
581 for (size_t j = 1; j < X2.size(); ++j) {
582 params.emplace_back(X2[j] - params.back());
583 params.emplace_back(X2[j]);
584 }
585 }
586}
587
588//------------------------------------------------------------------------------------------------
599void MergeRuns::inclusionParams(std::span<double const> const X1, size_t &i, std::span<double const> const X2,
600 std::vector<double> &params) {
601 // First calculate the number of bins in each workspace that are in the
602 // overlap region
603 const auto iterX1 = std::lower_bound(X1.begin() + i, X1.end(), X2.back());
604 if (iterX1 == X1.end()) {
605 throw std::runtime_error("MergeRuns::inclusionParams: no overlap between the histograms");
606 }
607 auto const overlapbins1 = std::distance(X1.begin(), iterX1) - i;
608 auto const overlapbins2 = X2.size() - 1;
609
610 // In the overlap region, we want to use whichever one has the larger bins (on
611 // average)
612 if (overlapbins1 + 1 <= overlapbins2) {
613 // In the case where the first workspace has larger bins it's easy
614 // - just add the rest of X1's bins
615 for (; i < X1.size(); ++i) {
616 params.emplace_back(X1[i] - X1[i - 1]);
617 params.emplace_back(X1[i]);
618 }
619 } else {
620 // In this case we want all of X2's bins first (without the first and last
621 // boundaries)
622 for (size_t j = 1; j < X2.size() - 1; ++j) {
623 params.emplace_back(X2[j] - params.back());
624 params.emplace_back(X2[j]);
625 }
626 // And now those from X1 that lie above the overlap region
627 i += overlapbins1;
628 for (; i < X1.size(); ++i) {
629 params.emplace_back(X1[i] - params.back());
630 params.emplace_back(X1[i]);
631 }
632 }
633}
634
635//------------------------------------------------------------------------------------------------
643 const std::vector<double> &params) {
644 // Create a Rebin child algorithm
645 auto rebin = createChildAlgorithm("Rebin");
646 rebin->setProperty("InputWorkspace", workspace);
647 rebin->setProperty("Params", params);
648 rebin->executeAsChildAlg();
649 return rebin->getProperty("OutputWorkspace");
650}
651
656 // check if we were merging event or matrix workspaces
657 if (!m_inEventWS.empty()) {
658 copyHistoryFromInputWorkspaces<std::vector<EventWorkspace_sptr>>(m_inEventWS);
659 } else {
660 copyHistoryFromInputWorkspaces<std::list<MatrixWorkspace_sptr>>(m_inMatrixWS);
661 }
662}
663
664/*
665 * Here we build up the correct time indexes for the workspace being added. If
666 *the scan times for the addee workspace and output workspace are the same this
667 *builds the same indexing as the workspace had before. Otherwise, the correct
668 *time indexes are set here.
669 *
670 *This function translates time indices from the addee to the new workspace.
671 */
672std::vector<SpectrumDefinition> MergeRuns::buildScanIntervals(const std::vector<SpectrumDefinition> &addeeSpecDefs,
673 const DetectorInfo &addeeDetInfo,
674 const DetectorInfo &newOutDetInfo) {
675 std::vector<SpectrumDefinition> newAddeeSpecDefs(addeeSpecDefs.size());
676
677 auto addeeScanIntervals = addeeDetInfo.scanIntervals();
678 auto newOutScanIntervals = newOutDetInfo.scanIntervals();
679
681 for (int64_t i = 0; i < int64_t(addeeSpecDefs.size()); ++i) {
682 for (auto const &index : addeeSpecDefs[i]) {
683 SpectrumDefinition newSpecDef;
684 for (size_t time_index = 0; time_index < newOutDetInfo.scanCount(); time_index++) {
685 if (addeeScanIntervals[index.second] == newOutScanIntervals[time_index]) {
686 newSpecDef.add(index.first, time_index);
687 }
688 }
689 newAddeeSpecDefs[i] = newSpecDef;
690 }
691 }
692
693 return newAddeeSpecDefs;
694}
695
696} // namespace Mantid::Algorithms
#define DECLARE_ALGORITHM(classname)
Definition Algorithm.h:542
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 > &params)
Calls the Rebin algorithm as a ChildAlgorithm.
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:147
void buildAdditionTables()
Build up addition tables for merging eventlists together.
void exec() override
Executes the algorithm.
Definition MergeRuns.cpp:81
static void noOverlapParams(std::span< double const > X1, std::span< double const > X2, std::vector< double > &params)
Calculates the rebin paramters in the case where the two input workspaces do not overlap at all.
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.
Definition MergeRuns.h:141
std::unique_ptr< API::Progress > m_progress
Progress reporting.
Definition MergeRuns.h:138
void init() override
Initialisation method.
Definition MergeRuns.cpp:44
void execEvent()
Executes the algorithm for EventWorkspaces.
static std::vector< double > calculateRebinParams(std::span< double const > bins1, std::span< double const > bins2)
Calculates the parameters to hand to the Rebin algorithm.
std::vector< AdditionTable > m_tables
Addition tables for event workspaces.
Definition MergeRuns.h:145
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
std::optional< std::vector< double > > checkRebinning()
Checks if the workspaces need to be rebinned and if so, returns the rebinning parameters for the Rebi...
static void intersectionParams(std::span< double const > X1, size_t &i, std::span< double const > X2, std::vector< double > &params)
Calculates the rebin parameters in the case where the bins of the two workspaces intersect.
bool validateInputsForEventWorkspaces(const std::vector< std::string > &inputWorkspaces)
Validate the input event workspaces.
static void inclusionParams(std::span< double const > X1, size_t &i, std::span< double const > X2, std::vector< double > &params)
Calculates the rebin parameters in the case where the range of the second workspace is entirely withi...
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.
Definition MergeRuns.h:143
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:100
void execHistogram(const std::vector< std::string > &inputs)
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....
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.
Definition Logger.cpp:126
void error(const std::string &msg)
Logs at error level.
Definition Logger.cpp:108
void warning(const std::string &msg)
Logs at warning level.
Definition Logger.cpp:117
void information(const std::string &msg)
Logs at information level.
Definition Logger.cpp:136
std::shared_ptr< MatrixWorkspace > MatrixWorkspace_sptr
shared pointer to the matrix workspace base class
static const std::string FAIL_MERGE_TOLERANCES
Definition MergeRuns.h:61
static const std::string WARN_MERGE_TOLERANCES
Definition MergeRuns.h:59
static const std::string WARN_MERGE
Definition MergeRuns.h:58
static const std::string FAIL_MERGE
Definition MergeRuns.h:60
static const std::string SUM_MERGE
MergeRuns parameter names of the paramter file for sample log merging.
Definition MergeRuns.h:55
static const std::string TIME_SERIES_MERGE
Definition MergeRuns.h:56
static const std::string LIST_MERGE
Definition MergeRuns.h:57
Kernel::Logger g_log("DetermineSpinStateOrder")
std::shared_ptr< EventWorkspace > EventWorkspace_sptr
shared pointer to the EventWorkspace class
void MANTID_KERNEL_DLL rebin(std::span< double const > xold, std::span< double const > yold, std::span< double const > eold, std::span< double const > xnew, std::span< double > ynew, std::span< double > enew, bool distribution, bool addition=false)
The input and output ranges are taken as spans so that the size-checked histogram data types,...
std::size_t 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.
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 std::shared_ptr< const MatrixWorkspace > &ws1, const std::shared_ptr< 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