Mantid
Loading...
Searching...
No Matches
Stitch1D.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 +
13#include "MantidHistogramData/HistogramDx.h"
14#include "MantidHistogramData/HistogramE.h"
15#include "MantidHistogramData/HistogramX.h"
16#include "MantidHistogramData/HistogramY.h"
23
24#include <algorithm>
25#include <boost/format.hpp>
26#include <boost/math/special_functions.hpp>
27#include <boost/tuple/tuple.hpp>
28#include <map>
29
30using namespace Mantid::API;
31using namespace Mantid::Kernel;
33using Mantid::HistogramData::HistogramE;
34using Mantid::HistogramData::HistogramY;
35
36namespace {
39using MinMaxTuple = boost::tuple<double, double>;
40MinMaxTuple calculateXIntersection(MatrixWorkspace_const_sptr &lhsWS, MatrixWorkspace_const_sptr &rhsWS) {
41 return MinMaxTuple(rhsWS->x(0).front(), lhsWS->x(0).back());
42}
43
44bool hasSpecialValue(const Mantid::Algorithms::Stitch1D::SpecialTypeIndexes &specialIndexes, const size_t spectrumIndex,
45 const size_t binIndex) {
46 const auto &indexes = specialIndexes[spectrumIndex];
47 return std::binary_search(indexes.cbegin(), indexes.cend(), binIndex);
48}
49
50bool hasInvalidY(const Mantid::Algorithms::Stitch1D::SpecialValueIndexes &specialValues, const size_t spectrumIndex,
51 const size_t binIndex) {
52 return hasSpecialValue(specialValues.nanY, spectrumIndex, binIndex) ||
53 hasSpecialValue(specialValues.infY, spectrumIndex, binIndex);
54}
55
56double specialYValue(const Mantid::Algorithms::Stitch1D::SpecialValueIndexes &lhsSpecialValues,
58 const size_t spectrumIndex, const size_t binIndex) {
59 if (hasSpecialValue(lhsSpecialValues.infY, spectrumIndex, binIndex) ||
60 hasSpecialValue(rhsSpecialValues.infY, spectrumIndex, binIndex))
61 return std::numeric_limits<double>::infinity();
62 return std::numeric_limits<double>::quiet_NaN();
63}
64} // namespace
65
66namespace Mantid::Algorithms {
67
73const double Stitch1D::range_tolerance = 1e-9;
74// Register the algorithm into the AlgorithmFactory
75DECLARE_ALGORITHM(Stitch1D)
76
77
82MatrixWorkspace_sptr Stitch1D::maskAllBut(int a1, int a2, MatrixWorkspace_sptr &source) {
83 MatrixWorkspace_sptr product = source->clone();
84 const auto histogramCount = static_cast<int>(source->getNumberHistograms());
85 PARALLEL_FOR_IF(Kernel::threadSafe(*source, *product))
86 for (int i = 0; i < histogramCount; ++i) {
88 // Copy over the bin boundaries
89 product->setSharedX(i, source->sharedX(i));
90 // Copy over the data
91 const auto &sourceY = source->y(i);
92 const auto &sourceE = source->e(i);
93
94 // initially zero - out the data.
95 product->mutableY(i) = HistogramY(sourceY.size(), 0);
96 product->mutableE(i) = HistogramE(sourceE.size(), 0);
97
98 auto &newY = product->mutableY(i);
99 auto &newE = product->mutableE(i);
100
101 // Copy over the non-zero stuff
102 std::copy(sourceY.begin() + a1 + 1, sourceY.begin() + a2, newY.begin() + a1 + 1);
103 std::copy(sourceE.begin() + a1 + 1, sourceE.begin() + a2, newE.begin() + a1 + 1);
104
106 }
108 return product;
109}
110
117void Stitch1D::maskInPlace(int a1, int a2, MatrixWorkspace_sptr &source) {
118 const auto histogramCount = static_cast<int>(source->getNumberHistograms());
120 for (int i = 0; i < histogramCount; ++i) {
122 // Copy over the data
123 auto &sourceY = source->mutableY(i);
124 auto &sourceE = source->mutableE(i);
125 for (int binIndex = a1; binIndex < a2; ++binIndex) {
126 sourceY[binIndex] = 0;
127 sourceE[binIndex] = 0;
128 }
129
131 }
133}
134
135//----------------------------------------------------------------------------------------------
139
140 declareProperty(std::make_unique<WorkspaceProperty<MatrixWorkspace>>("LHSWorkspace", "", Direction::Input),
141 "LHS input workspace.");
142 declareProperty(std::make_unique<WorkspaceProperty<MatrixWorkspace>>("RHSWorkspace", "", Direction::Input),
143 "RHS input workspace, must be same type as LHSWorkspace "
144 "(histogram or point data).");
145 declareProperty(std::make_unique<WorkspaceProperty<MatrixWorkspace>>("OutputWorkspace", "", Direction::Output),
146 "Output stitched workspace.");
148 "Start overlap x-value in units of x-axis.");
150 "End overlap x-value in units of x-axis.");
151 declareProperty(std::make_unique<ArrayProperty<double>>("Params", std::make_shared<RebinParamsValidator>(true)),
152 "Rebinning Parameters. See Rebin for format. If only a "
153 "single value is provided, start and end are taken from "
154 "input workspaces.");
155 declareProperty(std::make_unique<PropertyWithValue<bool>>("ScaleRHSWorkspace", true, Direction::Input),
156 "Scaling either with respect to LHS workspace or RHS workspace");
157 declareProperty(std::make_unique<PropertyWithValue<bool>>("UseManualScaleFactor", false, Direction::Input),
158 "True to use a provided value for the scale factor.");
160 "OutputScalingWorkspace", "",
161 "Output WorkspaceSingleValue containing the scale factor and its error. No workspace creation if left empty.");
162 auto manualScaleFactorValidator = std::make_shared<BoundedValidator<double>>();
163 manualScaleFactorValidator->setLower(0);
164 manualScaleFactorValidator->setExclusive(true);
165 declareProperty(std::make_unique<PropertyWithValue<double>>("ManualScaleFactor", 1.0, manualScaleFactorValidator,
167 "Provided value for the scale factor.");
169 "The actual used value for the scaling factor.");
170 declareProperty(std::make_unique<PropertyWithValue<bool>>("UseValidDataOnly", false, Direction::Input),
171 "If true, invalid signal values do not contribute to overlap bins where the other workspace has "
172 "valid signal values.");
173}
174
178std::map<std::string, std::string> Stitch1D::validateInputs(void) {
179 std::map<std::string, std::string> issues;
180 MatrixWorkspace_sptr lhs = getProperty("LHSWorkspace");
181 MatrixWorkspace_sptr rhs = getProperty("RHSWorkspace");
182 if (!lhs) {
183 issues["LHSWorkspace"] = "The LHSWorkspace must be a MatrixWorkspace.";
184 }
185 if (!rhs) {
186 issues["RHSWorkspace"] = "The RHSWorkspace must be a MatrixWorkspace.";
187 }
188 if (!issues.empty()) {
189 return issues;
190 }
191 RunCombinationHelper combHelper;
192 combHelper.setReferenceProperties(lhs);
193 std::string compatible = combHelper.checkCompatibility(rhs, true);
194 if (!compatible.empty()) {
195 // histograms: no recalculation of Dx implemented -> do not treat Dx
196 if (!(compatible == "spectra must have either Dx values or not; ") ||
197 (rhs->isHistogramData())) // Issue only for point data
198 issues["RHSWorkspace"] = "Workspace " + rhs->getName() + " is not compatible: " + compatible + "\n";
199 }
200 return issues;
201}
202
210double Stitch1D::getStartOverlap(const double intesectionMin, const double intesectionMax) const {
211 Property const *startOverlapProp = this->getProperty("StartOverlap");
212 double startOverlapVal = this->getProperty("StartOverlap");
213 startOverlapVal -= this->range_tolerance;
214 const bool startOverlapBeyondRange = (startOverlapVal < intesectionMin) || (startOverlapVal > intesectionMax);
215 if (startOverlapProp->isDefault() || startOverlapBeyondRange) {
216 if (!startOverlapProp->isDefault() && startOverlapBeyondRange) {
217 char message[200];
218 std::sprintf(message,
219 "StartOverlap is outside range at %0.4f, Min is "
220 "%0.4f, Max is %0.4f . Forced to be: %0.4f",
221 startOverlapVal, intesectionMin, intesectionMax, intesectionMin);
222 g_log.warning(std::string(message));
223 }
224 startOverlapVal = intesectionMin;
225 std::stringstream buffer;
226 buffer << "StartOverlap calculated to be: " << startOverlapVal;
227 g_log.information(buffer.str());
228 }
229 return startOverlapVal;
230}
231
239double Stitch1D::getEndOverlap(const double intesectionMin, const double intesectionMax) const {
240 Property const *endOverlapProp = this->getProperty("EndOverlap");
241 double endOverlapVal = this->getProperty("EndOverlap");
242 endOverlapVal += this->range_tolerance;
243 const bool endOverlapBeyondRange = (endOverlapVal < intesectionMin) || (endOverlapVal > intesectionMax);
244 if (endOverlapProp->isDefault() || endOverlapBeyondRange) {
245 if (!endOverlapProp->isDefault() && endOverlapBeyondRange) {
246 char message[200];
247 std::sprintf(message,
248 "EndOverlap is outside range at %0.4f, Min is "
249 "%0.4f, Max is %0.4f . Forced to be: %0.4f",
250 endOverlapVal, intesectionMin, intesectionMax, intesectionMax);
251 g_log.warning(std::string(message));
252 }
253 endOverlapVal = intesectionMax;
254 std::stringstream buffer;
255 buffer << "EndOverlap calculated to be: " << endOverlapVal;
256 g_log.information(buffer.str());
257 }
258 return endOverlapVal;
259}
260
268 const bool scaleRHS) const {
269 std::vector<double> inputParams = this->getProperty("Params");
270 Property const *prop = this->getProperty("Params");
271 const bool areParamsDefault = prop->isDefault();
272
273 const auto &lhsX = lhsWS->x(0);
274 auto it = std::min_element(lhsX.begin(), lhsX.end());
275 const double minLHSX = *it;
276
277 const auto &rhsX = rhsWS->x(0);
278 it = std::max_element(rhsX.begin(), rhsX.end());
279 const double maxRHSX = *it;
280
281 std::vector<double> result;
282 if (areParamsDefault) {
283 std::vector<double> calculatedParams;
284
285 // Calculate the step size based on the existing step size of the LHS
286 // workspace. That way scale factors should be reasonably maintained.
287 double calculatedStep = 0;
288 if (scaleRHS) {
289 // Calculate the step from the workspace that will not be scaled. The LHS
290 // workspace.
291 calculatedStep = lhsX[1] - lhsX[0];
292 } else {
293 // Calculate the step from the workspace that will not be scaled. The RHS
294 // workspace.
295 calculatedStep = rhsX[1] - rhsX[0];
296 }
297
298 calculatedParams.emplace_back(minLHSX);
299 calculatedParams.emplace_back(calculatedStep);
300 calculatedParams.emplace_back(maxRHSX);
301 result = calculatedParams;
302 } else {
303 if (inputParams.size() == 1) {
304 std::vector<double> calculatedParams;
305 calculatedParams.emplace_back(minLHSX);
306 calculatedParams.emplace_back(inputParams.front()); // Use the step supplied.
307 calculatedParams.emplace_back(maxRHSX);
308 result = calculatedParams;
309 } else {
310 result = inputParams; // user has provided params. Use those.
311 }
312 }
313 return result;
314}
315
323MatrixWorkspace_sptr Stitch1D::rebin(MatrixWorkspace_sptr &input, const std::vector<double> &params,
324 SpecialValueIndexes &specialValues) {
325 auto rebin = this->createChildAlgorithm("Rebin");
326 rebin->setProperty("InputWorkspace", input);
327 rebin->setProperty("Params", params);
328 std::stringstream ssParams;
329 ssParams << params[0] << "," << params[1] << "," << params[2];
330 g_log.information("Rebinning Params: " + ssParams.str());
331 rebin->execute();
332 MatrixWorkspace_sptr outWS = rebin->getProperty("OutputWorkspace");
333
334 const auto histogramCount = static_cast<int>(outWS->getNumberHistograms());
335
336 // Record special values and then mask them out as zeros. Special values are
337 // remembered and then replaced post processing.
339 for (int i = 0; i < histogramCount; ++i) {
341 std::vector<size_t> &nanEIndexes = specialValues.nanE[i];
342 std::vector<size_t> &nanYIndexes = specialValues.nanY[i];
343 std::vector<size_t> &infEIndexes = specialValues.infE[i];
344 std::vector<size_t> &infYIndexes = specialValues.infY[i];
345 // Copy over the data
346 auto &sourceY = outWS->mutableY(i);
347 auto &sourceE = outWS->mutableE(i);
348
349 for (size_t j = 0; j < sourceY.size(); ++j) {
350 const double value = sourceY[j];
351 if (std::isnan(value)) {
352 nanYIndexes.emplace_back(j);
353 sourceY[j] = 0;
354 } else if (std::isinf(value)) {
355 infYIndexes.emplace_back(j);
356 sourceY[j] = 0;
357 }
358
359 const double eValue = sourceE[j];
360 if (std::isnan(eValue)) {
361 nanEIndexes.emplace_back(j);
362 sourceE[j] = 0;
363 } else if (std::isinf(eValue)) {
364 infEIndexes.emplace_back(j);
365 sourceE[j] = 0;
366 }
367 }
368
370 }
372
373 return outWS;
374}
375
382MatrixWorkspace_sptr Stitch1D::integration(MatrixWorkspace_sptr const &input, const double start, const double stop) {
383 auto integration = this->createChildAlgorithm("Integration");
384 integration->initialize();
385 integration->setProperty("InputWorkspace", input);
386 integration->setProperty("RangeLower", start);
387 integration->setProperty("RangeUpper", stop);
388 g_log.information("Integration RangeLower: " + boost::lexical_cast<std::string>(start));
389 g_log.information("Integration RangeUpper: " + boost::lexical_cast<std::string>(stop));
390 integration->execute();
391 return integration->getProperty("OutputWorkspace");
392}
393
400 auto weightedMean = this->createChildAlgorithm("WeightedMean");
401 weightedMean->initialize();
402 weightedMean->setProperty("InputWorkspace1", inOne);
403 weightedMean->setProperty("InputWorkspace2", inTwo);
404 weightedMean->execute();
405 return weightedMean->getProperty("OutputWorkspace");
406}
407
414 const std::string in1 = "__Stitch1D_intermediate_workspace_1__";
415 const std::string in2 = "__Stitch1D_intermediate_workspace_2__";
416 Mantid::API::AnalysisDataService::Instance().addOrReplace(in1, inOne);
417 Mantid::API::AnalysisDataService::Instance().addOrReplace(in2, inTwo);
418 auto conjoinX = this->createChildAlgorithm("ConjoinXRuns");
419 conjoinX->initialize();
420 conjoinX->setProperty("InputWorkspaces", std::vector<std::string>{in1, in2});
421 conjoinX->execute();
422 Mantid::API::AnalysisDataService::Instance().remove(in1);
423 Mantid::API::AnalysisDataService::Instance().remove(in2);
424 API::Workspace_sptr ws = conjoinX->getProperty("OutputWorkspace");
425 return std::dynamic_pointer_cast<Mantid::API::MatrixWorkspace>(ws);
426}
433boost::tuple<int, int> Stitch1D::findStartEndIndexes(double startOverlap, double endOverlap,
435 auto a1 = static_cast<int>(workspace->yIndexOfX(startOverlap));
436 auto a2 = static_cast<int>(workspace->yIndexOfX(endOverlap));
437 if (a1 == a2) {
438 throw std::runtime_error("The Params you have provided for binning yield a "
439 "workspace in which start and end overlap appear "
440 "in the same bin. Make binning finer via input "
441 "Params.");
442 }
443 return boost::tuple<int, int>(a1, a2);
444}
445
451 for (auto i = 0u; i < ws->getNumberHistograms(); ++i) {
452 const auto &e = ws->e(i);
453 // It's faster to sum and then check the result is non-zero than to check each element is non-zero individually
454 if (std::accumulate(e.begin(), e.end(), 0.0) != 0.0) {
455 return true;
456 }
457 }
458 return false;
459}
460
469 ws *= scaleFactorWS;
470 // We lost Dx values (Multiply) and need to get them back for point data
471 if (ws->size() == dxWS->size()) {
472 for (size_t i = 0; i < ws->getNumberHistograms(); ++i) {
473 if (dxWS->hasDx(i) && !ws->hasDx(i) && !ws->isHistogramData()) {
474 ws->setSharedDx(i, dxWS->sharedDx(i));
475 }
476 }
477 }
478 m_scaleFactor = scaleFactorWS->y(0).front();
479 m_errorScaleFactor = scaleFactorWS->e(0).front();
480 if (m_scaleFactor < 1e-2 || m_scaleFactor > 1e2 || std::isnan(m_scaleFactor)) {
481 std::stringstream messageBuffer;
482 messageBuffer << "Stitch1D calculated scale factor is: " << m_scaleFactor
483 << ". Check the overlap region is non-zero.";
484 g_log.warning(messageBuffer.str());
485 }
486}
487
488//----------------------------------------------------------------------------------------------
492 MatrixWorkspace_const_sptr lhsWS = this->getProperty("LHSWorkspace");
493 MatrixWorkspace_const_sptr rhsWS = this->getProperty("RHSWorkspace");
494 const MinMaxTuple intesectionXRegion = calculateXIntersection(lhsWS, rhsWS);
495
496 const size_t histogramCount = rhsWS->getNumberHistograms();
497 m_lhsSpecialValues.resize(histogramCount);
498 m_rhsSpecialValues.resize(histogramCount);
499 m_useValidDataOnly = this->getProperty("UseValidDataOnly");
500
501 const double intersectionMin = intesectionXRegion.get<0>();
502 const double intersectionMax = intesectionXRegion.get<1>();
503 double startOverlap = getStartOverlap(intersectionMin, intersectionMax);
504 double endOverlap = getEndOverlap(intersectionMin, intersectionMax);
505 if (startOverlap > endOverlap) {
506 std::string message = boost::str(boost::format("Stitch1D cannot have a StartOverlap > EndOverlap. "
507 "StartOverlap: %0.9f, EndOverlap: %0.9f") %
508 startOverlap % endOverlap);
509 throw std::runtime_error(message);
510 }
511
512 const bool scaleRHS = this->getProperty("ScaleRHSWorkspace");
513
514 MatrixWorkspace_sptr lhs = lhsWS->clone();
515 MatrixWorkspace_sptr rhs = rhsWS->clone();
516 if (lhsWS->isHistogramData()) {
517 MantidVec params = getRebinParams(lhsWS, rhsWS, scaleRHS);
518 const double xMin = params.front();
519 const double xMax = params.back();
520
521 if (Kernel::withinAbsoluteDifference(xMin, startOverlap, 1E-6))
522 startOverlap = xMin;
523
524 if (Kernel::withinAbsoluteDifference(xMax, endOverlap, 1E-6))
525 endOverlap = xMax;
526
527 if (startOverlap < xMin) {
528 std::string message = boost::str(boost::format("Stitch1D StartOverlap is outside the available X range. "
529 "StartOverlap: %10.9f, X min: %10.9f") %
530 startOverlap % xMin);
531 throw std::runtime_error(message);
532 }
533 if (endOverlap > xMax) {
534 std::string message = boost::str(boost::format("Stitch1D EndOverlap is outside the available X range. "
535 "EndOverlap: %10.9f, X max: %10.9f") %
536 endOverlap % xMax);
537 throw std::runtime_error(message);
538 }
539 lhs = rebin(lhs, params, m_lhsSpecialValues);
540 rhs = rebin(rhs, params, m_rhsSpecialValues);
541 }
542
543 m_scaleFactor = this->getProperty("ManualScaleFactor");
545 const bool useManualScaleFactor = this->getProperty("UseManualScaleFactor");
546 if (useManualScaleFactor) {
547 if (scaleRHS)
549 else
550 lhs *= m_scaleFactor;
551 } else {
552 auto rhsOverlapIntegrated = integration(rhs, startOverlap, endOverlap);
553 auto lhsOverlapIntegrated = integration(lhs, startOverlap, endOverlap);
554 if (scaleRHS) {
555 auto scalingFactors = lhsOverlapIntegrated / rhsOverlapIntegrated;
556 scaleWorkspace(rhs, scalingFactors, rhsWS);
557 } else {
558 auto scalingFactors = rhsOverlapIntegrated / lhsOverlapIntegrated;
559 scaleWorkspace(lhs, scalingFactors, lhsWS);
560 }
561 }
562 // Provide log information about the scale factors used in the calculations.
563 std::stringstream messageBuffer;
564 messageBuffer << "Scale Factor Y is: " << m_scaleFactor << " Scale Factor E is: " << m_errorScaleFactor;
565 g_log.notice(messageBuffer.str());
566
568 if (lhsWS->isHistogramData()) { // If the input workspaces are histograms ...
569 boost::tuple<int, int> startEnd = findStartEndIndexes(startOverlap, endOverlap, lhs);
570 int a1 = boost::tuples::get<0>(startEnd);
571 int a2 = boost::tuples::get<1>(startEnd);
572 // Mask out everything BUT the overlap region as a new workspace.
573 MatrixWorkspace_sptr overlap1 = maskAllBut(a1, a2, lhs);
574 // Mask out everything BUT the overlap region as a new workspace.
575 MatrixWorkspace_sptr overlap2 = maskAllBut(a1, a2, rhs);
576 // Mask out everything AFTER the overlap region as a new workspace.
577 maskInPlace(a1 + 1, static_cast<int>(lhs->blocksize()), lhs);
578 // Mask out everything BEFORE the overlap region as a new workspace.
579 maskInPlace(0, a2, rhs);
580 MatrixWorkspace_sptr overlapMeans;
581 if (hasNonzeroErrors(overlap1) && hasNonzeroErrors(overlap2)) {
582 overlapMeans = weightedMean(overlap1, overlap2);
583 } else {
584 g_log.information("Using un-weighted mean for Stitch1D overlap mean");
585 MatrixWorkspace_sptr sum = overlap1 + overlap2;
586 overlapMeans = sum * 0.5;
587 }
588 overlapBounds bounds;
589 if (m_useValidDataOnly) {
590 bounds = {a1, a2};
591 useValidOverlapData(overlapMeans, overlap1, overlap2, m_lhsSpecialValues, m_rhsSpecialValues, bounds);
592 }
593 result = lhs + overlapMeans + rhs;
595 } else { // The input workspaces are point data ... join & sort
596 result = conjoinXAxis(lhs, rhs);
597 if (!result)
598 g_log.error("Could not retrieve joined workspace.");
599
600 // Sort the X Axis
602 childAlg->setProperty("InputWorkspace", result);
603 childAlg->execute();
604 result = childAlg->getProperty("OutputWorkspace");
605 }
606 setProperty("OutputWorkspace", result);
607 setProperty("OutScaleFactor", m_scaleFactor);
608
609 // if required, create the output single value workspace containing the scaling factor and its error
610 const std::string scalingWsName = this->getPropertyValue("OutputScalingWorkspace");
611 if (!scalingWsName.empty()) {
612 auto createSingleAlg = createChildAlgorithm("CreateSingleValuedWorkspace");
613 createSingleAlg->setProperty("DataValue", m_scaleFactor);
614 createSingleAlg->setProperty("ErrorValue", m_errorScaleFactor);
615 createSingleAlg->executeAsChildAlg();
616 MatrixWorkspace_sptr singleWS = createSingleAlg->getProperty("OutputWorkspace");
617 AnalysisDataService::Instance().addOrReplace(scalingWsName, singleWS);
618 }
619}
620
628 const SpecialValueIndexes &rhsSpecialValues, overlapBounds bounds = {}) {
629 auto histogramCount = static_cast<int>(ws->getNumberHistograms());
630 bool defaultBounds = false;
631 if (bounds.a1 == -1 && bounds.a2 == -1) {
632 defaultBounds = true;
633 bounds.a2 = 0;
634 } else if (bounds.a1 < 0 || bounds.a2 < 0) {
635 throw std::runtime_error(
636 "Invalid bounds provided for re-inserting special values. Bounds must be either both -1 or both non-negative.");
637 }
638
640 for (int i = 0; i < histogramCount; ++i) {
642 if (defaultBounds)
643 bounds.a1 = static_cast<int>(ws->y(i).size()) - 1;
644
645 auto &sourceY = ws->mutableY(i);
646 auto &sourceE = ws->mutableE(i);
647
648 for (auto j : lhsSpecialValues.nanY[i])
649 if (static_cast<int>(j) <= bounds.a1)
650 sourceY[j] = std::numeric_limits<double>::quiet_NaN();
651 for (auto j : lhsSpecialValues.infY[i])
652 if (static_cast<int>(j) <= bounds.a1)
653 sourceY[j] = std::numeric_limits<double>::infinity();
654 for (auto j : lhsSpecialValues.nanE[i])
655 if (static_cast<int>(j) <= bounds.a1)
656 sourceE[j] = std::numeric_limits<double>::quiet_NaN();
657 for (auto j : lhsSpecialValues.infE[i])
658 if (static_cast<int>(j) <= bounds.a1)
659 sourceE[j] = std::numeric_limits<double>::infinity();
660
661 for (auto j : rhsSpecialValues.nanY[i])
662 if (static_cast<int>(j) >= bounds.a2)
663 sourceY[j] = std::numeric_limits<double>::quiet_NaN();
664 for (auto j : rhsSpecialValues.infY[i])
665 if (static_cast<int>(j) >= bounds.a2)
666 sourceY[j] = std::numeric_limits<double>::infinity();
667 for (auto j : rhsSpecialValues.nanE[i])
668 if (static_cast<int>(j) >= bounds.a2)
669 sourceE[j] = std::numeric_limits<double>::quiet_NaN();
670 for (auto j : rhsSpecialValues.infE[i])
671 if (static_cast<int>(j) >= bounds.a2)
672 sourceE[j] = std::numeric_limits<double>::infinity();
673
675 }
677}
678
688 const MatrixWorkspace_sptr &rhs, const SpecialValueIndexes &lhsSpecialValues,
689 const SpecialValueIndexes &rhsSpecialValues, const overlapBounds bounds) {
690 auto histogramCount = static_cast<int>(overlap->getNumberHistograms());
691 PARALLEL_FOR_IF(Kernel::threadSafe(*overlap, *lhs, *rhs))
692 for (int i = 0; i < histogramCount; ++i) {
694 auto &overlapY = overlap->mutableY(i);
695 auto &overlapE = overlap->mutableE(i);
696 const auto &lhsY = lhs->y(i);
697 const auto &lhsE = lhs->e(i);
698 const auto &rhsY = rhs->y(i);
699 const auto &rhsE = rhs->e(i);
700
701 for (size_t j = static_cast<size_t>(bounds.a1 + 1); j < static_cast<size_t>(bounds.a2); ++j) {
702 const bool lhsInvalidY = hasInvalidY(lhsSpecialValues, i, j);
703 const bool rhsInvalidY = hasInvalidY(rhsSpecialValues, i, j);
704 if (lhsInvalidY && !rhsInvalidY) {
705 overlapY[j] = rhsY[j];
706 overlapE[j] = rhsE[j];
707 } else if (!lhsInvalidY && rhsInvalidY) {
708 overlapY[j] = lhsY[j];
709 overlapE[j] = lhsE[j];
710 } else if (lhsInvalidY && rhsInvalidY) {
711 overlapY[j] = specialYValue(lhsSpecialValues, rhsSpecialValues, i, j);
712 overlapE[j] = specialYValue(lhsSpecialValues, rhsSpecialValues, i,
713 j); // If both workspaces have invalid values, use invalid error.
714 }
715 }
716
718 }
720}
721
722} // namespace Mantid::Algorithms
#define DECLARE_ALGORITHM(classname)
Definition Algorithm.h:542
const std::vector< double > & rhs
double value
The value of the point.
Definition FitMW.cpp:51
IPeaksWorkspace_sptr workspace
#define PARALLEL_START_INTERRUPT_REGION
Begins a block to skip processing is the algorithm has been interupted Note the end of the block if n...
#define PARALLEL_END_INTERRUPT_REGION
Ends a block to skip processing is the algorithm has been interupted Note the start of the block if n...
#define PARALLEL_FOR_IF(condition)
Empty definitions - to enable set your complier to enable openMP.
#define PARALLEL_CHECK_INTERRUPT_REGION
Adds a check after a Parallel region to see if it was interupted.
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.
Kernel::Logger & g_log
Definition Algorithm.h:423
A property class for workspaces.
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.
Stitch1D : Stitches two Matrix Workspaces together into a single output.
Definition Stitch1D.h:20
SpecialValueIndexes m_lhsSpecialValues
Index per workspace spectra of special values.
Definition Stitch1D.h:109
Mantid::API::MatrixWorkspace_sptr maskAllBut(int a1, int a2, Mantid::API::MatrixWorkspace_sptr &source)
Mask out everything but the data in the ranges.
Definition Stitch1D.cpp:82
bool hasNonzeroErrors(Mantid::API::MatrixWorkspace_sptr &ws)
Does the x-axis have non-zero errors.
Definition Stitch1D.cpp:450
Mantid::API::MatrixWorkspace_sptr rebin(Mantid::API::MatrixWorkspace_sptr &input, const std::vector< double > &params, SpecialValueIndexes &specialValues)
Perform rebin and record special values that are zeroed.
Definition Stitch1D.cpp:323
boost::tuple< int, int > findStartEndIndexes(double startOverlap, double endOverlap, Mantid::API::MatrixWorkspace_sptr &workspace)
Find the start and end indexes.
Definition Stitch1D.cpp:433
std::vector< std::vector< size_t > > SpecialTypeIndexes
Helper typedef for storing special-value indexes per spectrum.
Definition Stitch1D.h:37
void useValidOverlapData(const Mantid::API::MatrixWorkspace_sptr &overlap, const Mantid::API::MatrixWorkspace_sptr &lhs, const Mantid::API::MatrixWorkspace_sptr &rhs, const SpecialValueIndexes &lhsSpecialValues, const SpecialValueIndexes &rhsSpecialValues, const overlapBounds bounds)
Use valid overlap values where exactly one workspace has an invalid signal value.
Definition Stitch1D.cpp:687
std::vector< double > getRebinParams(Mantid::API::MatrixWorkspace_const_sptr &lhsWS, Mantid::API::MatrixWorkspace_const_sptr &rhsWS, const bool scaleRHS) const
Get the rebin parameters.
Definition Stitch1D.cpp:267
void maskInPlace(int a1, int a2, Mantid::API::MatrixWorkspace_sptr &source)
Mask out everything but the data in the ranges, but do it inplace.
Definition Stitch1D.cpp:117
SpecialValueIndexes m_rhsSpecialValues
Definition Stitch1D.h:110
Mantid::API::MatrixWorkspace_sptr integration(Mantid::API::MatrixWorkspace_sptr const &input, const double start, const double stop)
Perform integration.
Definition Stitch1D.cpp:382
void scaleWorkspace(API::MatrixWorkspace_sptr &ws, API::MatrixWorkspace_sptr &scaleFactorWS, API::MatrixWorkspace_const_sptr &dxWS)
Scale workspace (left hand side or right hand side)
Definition Stitch1D.cpp:467
double getStartOverlap(const double intesectionMin, const double intesectionMax) const
Get the start overlap.
Definition Stitch1D.cpp:210
void exec() override
Overwrites Algorithm method.
Definition Stitch1D.cpp:491
void reinsertSpecialValues(const Mantid::API::MatrixWorkspace_sptr &ws, const SpecialValueIndexes &lhsSpecialValues, const SpecialValueIndexes &rhsSpecialValues, overlapBounds bounds)
Add back special values only where no valid data contributes to the output.
Definition Stitch1D.cpp:627
double m_scaleFactor
Scaling factors.
Definition Stitch1D.h:102
void init() override
Overwrites Algorithm method.
Definition Stitch1D.cpp:138
double getEndOverlap(const double intesectionMin, const double intesectionMax) const
Get the end overlap.
Definition Stitch1D.cpp:239
static const double range_tolerance
Range tolerance.
Definition Stitch1D.h:100
Mantid::API::MatrixWorkspace_sptr weightedMean(Mantid::API::MatrixWorkspace_sptr const &inOne, Mantid::API::MatrixWorkspace_sptr const &inTwo)
Calculate the weighted mean.
Definition Stitch1D.cpp:399
Mantid::API::MatrixWorkspace_sptr conjoinXAxis(Mantid::API::MatrixWorkspace_sptr const &inOne, Mantid::API::MatrixWorkspace_sptr const &inTwo)
Conjoin x axis.
Definition Stitch1D.cpp:413
std::map< std::string, std::string > validateInputs() override
Cross-check properties with each other.
Definition Stitch1D.cpp:178
Concrete workspace implementation.
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
The concrete, templated class for properties.
Base class for properties.
Definition Property.h:94
virtual bool isDefault() const =0
Overriden function that returns if property has the same value that it was initialised with,...
std::shared_ptr< Workspace > Workspace_sptr
shared pointer to Mantid::API::Workspace
std::shared_ptr< const MatrixWorkspace > MatrixWorkspace_const_sptr
shared pointer to the matrix workspace base class (const version)
std::shared_ptr< Algorithm > Algorithm_sptr
Typedef for a shared pointer to an Algorithm.
Definition Algorithm.h:52
std::shared_ptr< MatrixWorkspace > MatrixWorkspace_sptr
shared pointer to the matrix workspace base class
MANTID_KERNEL_DLL bool withinAbsoluteDifference(T const x, T const y, S const tolerance)
Test whether x, y are within absolute tolerance tol.
std::enable_if< std::is_pointer< Arg >::value, bool >::type threadSafe(Arg workspace)
Thread-safety check Checks the workspace to ensure it is suitable for multithreaded access.
std::vector< double > MantidVec
typedef for the data storage used in Mantid matrix workspaces
Definition cow_ptr.h:172
constexpr double EMPTY_DBL() noexcept
Returns what we consider an "empty" double within a property.
Definition EmptyValues.h:42
STL namespace.
Indexes of Y and E values that were NaN or infinite before processing.
Definition Stitch1D.h:39
@ Input
An input workspace.
Definition Property.h:53
@ Output
An output workspace.
Definition Property.h:54