diff --git a/Framework/API/src/WorkspaceFactory.cpp b/Framework/API/src/WorkspaceFactory.cpp index 30dedbc1fe13fbb5d4707218919d8824470e3bbd..bc8b78456c8f83a02e5d0dc056e1052220827107 100644 --- a/Framework/API/src/WorkspaceFactory.cpp +++ b/Framework/API/src/WorkspaceFactory.cpp @@ -5,6 +5,7 @@ // & Institut Laue - Langevin // SPDX - License - Identifier: GPL - 3.0 + #include "MantidAPI/WorkspaceFactory.h" +#include "MantidAPI/BinEdgeAxis.h" #include "MantidAPI/IPeaksWorkspace.h" #include "MantidAPI/ITableWorkspace.h" #include "MantidAPI/MatrixWorkspace.h" @@ -127,21 +128,26 @@ void WorkspaceFactoryImpl::initializeFromParent( // deal with axis for (size_t i = 0; i < parent.m_axes.size(); ++i) { - const size_t newAxisLength = child.getAxis(i)->length(); - const size_t oldAxisLength = parent.getAxis(i)->length(); - - if (!differentSize || newAxisLength == oldAxisLength) { - // Need to delete the existing axis created in init above - delete child.m_axes[i]; + if (parent.m_axes[i]->isSpectra()) { + // By default the child already has a spectra axis which + // does not need to get cloned from the parent. + continue; + } + const bool isBinEdge = + dynamic_cast<const BinEdgeAxis *const>(parent.m_axes[i]) != nullptr; + const size_t newAxisLength = + child.m_axes[i]->length() + (isBinEdge ? 1 : 0); + const size_t oldAxisLength = parent.m_axes[i]->length(); + + // Need to delete the existing axis created in init above + delete child.m_axes[i]; + child.m_axes[i] = nullptr; + if (newAxisLength == oldAxisLength) { // Now set to a copy of the parent workspace's axis child.m_axes[i] = parent.m_axes[i]->clone(&child); } else { - if (!parent.getAxis(i)->isSpectra()) // WHY??? - { - delete child.m_axes[i]; - // Call the 'different length' clone variant - child.m_axes[i] = parent.m_axes[i]->clone(newAxisLength, &child); - } + // Call the 'different length' clone variant + child.m_axes[i] = parent.m_axes[i]->clone(newAxisLength, &child); } } } diff --git a/Framework/Algorithms/src/ExtractSpectra2.cpp b/Framework/Algorithms/src/ExtractSpectra2.cpp index c5b3dbfcabf98bf1fc4c1ca0a708aa45b92bbe65..3480c2ddc5214b269b11cc08d93a93e930f52ffb 100644 --- a/Framework/Algorithms/src/ExtractSpectra2.cpp +++ b/Framework/Algorithms/src/ExtractSpectra2.cpp @@ -6,6 +6,7 @@ // SPDX - License - Identifier: GPL - 3.0 + #include "MantidAlgorithms/ExtractSpectra2.h" #include "MantidAPI/Algorithm.tcc" +#include "MantidAPI/BinEdgeAxis.h" #include "MantidAPI/NumericAxis.h" #include "MantidAPI/TextAxis.h" #include "MantidDataObjects/EventWorkspace.h" @@ -68,12 +69,15 @@ void ExtractSpectra2::exec() { Axis *inAxis1(nullptr); TextAxis *outTxtAxis(nullptr); NumericAxis *outNumAxis(nullptr); + bool isBinEdgeAxis(false); if (inputWS->axes() > 1) { inAxis1 = inputWS->getAxis(1); auto outAxis1 = outputWS->getAxis(1); outTxtAxis = dynamic_cast<TextAxis *>(outAxis1); - if (!outTxtAxis) + if (!outTxtAxis) { outNumAxis = dynamic_cast<NumericAxis *>(outAxis1); + isBinEdgeAxis = dynamic_cast<BinEdgeAxis *>(inAxis1) != nullptr; + } } Progress prog(this, 0.0, 1.0, indexSet.size()); @@ -96,6 +100,17 @@ void ExtractSpectra2::exec() { prog.report(); } + if (isBinEdgeAxis) { + if (!indexSet.isContiguous()) { + throw std::invalid_argument("Cannot extract non-contiguous set of " + "spectra when the vertical axis has bin " + "edges."); + } + const auto outIndex = indexSet.size(); + const auto inIndex = indexSet[indexSet.size() - 1] + 1; + outNumAxis->setValue(outIndex, inAxis1->operator()(inIndex)); + } + setProperty("OutputWorkspace", std::move(outputWS)); } diff --git a/Framework/Algorithms/test/ExtractFFTSpectrumTest.h b/Framework/Algorithms/test/ExtractFFTSpectrumTest.h index a21bc0765b21cf739186bb1e9dddaaf2d2067b9d..66bdd6e3f52d989873d12543ae047035c38b6e71 100644 --- a/Framework/Algorithms/test/ExtractFFTSpectrumTest.h +++ b/Framework/Algorithms/test/ExtractFFTSpectrumTest.h @@ -87,7 +87,7 @@ public: TS_ASSERT_EQUALS(inputWS->blocksize(), outputWS->blocksize()); // Units ( Axis 1 should be the same, Axis 0 should be "Time/ns" - TS_ASSERT_EQUALS(inputWS->getAxis(1)->unit(), outputWS->getAxis(1)->unit()); + TS_ASSERT(*inputWS->getAxis(1)->unit() == *outputWS->getAxis(1)->unit()); TS_ASSERT_EQUALS(outputWS->getAxis(0)->unit()->caption(), "Time"); TS_ASSERT_EQUALS(outputWS->getAxis(0)->unit()->label(), "ns"); } diff --git a/Framework/Algorithms/test/ExtractSpectra2Test.h b/Framework/Algorithms/test/ExtractSpectra2Test.h index 818c857e42a70e36a878b0431a391e83cc51bf1b..b8b05a3220598cd725efbba7fea3f3a9373ee3cd 100644 --- a/Framework/Algorithms/test/ExtractSpectra2Test.h +++ b/Framework/Algorithms/test/ExtractSpectra2Test.h @@ -10,6 +10,7 @@ #include <cxxtest/TestSuite.h> #include "MantidAPI/AnalysisDataService.h" +#include "MantidAPI/BinEdgeAxis.h" #include "MantidAlgorithms/ExtractSpectra2.h" #include "MantidDataObjects/Workspace2D.h" #include "MantidDataObjects/WorkspaceCreation.h" @@ -125,6 +126,51 @@ public: } void test_parallel() { ParallelTestHelpers::runParallel(run_parallel); } + + void test_BinEdgeAxis() { + auto input = createWorkspace(); + BinEdgeAxis *axis = new BinEdgeAxis(input->getNumberHistograms() + 1); + for (size_t i = 0; i < axis->length(); ++i) { + axis->setValue(i, -2. + static_cast<double>(i)); + } + input->replaceAxis(1, axis); + ExtractSpectra2 alg; + alg.initialize(); + alg.setChild(true); + alg.setRethrows(true); + alg.setProperty("InputWorkspace", std::move(input)); + alg.setProperty("InputWorkspaceIndexSet", "1-3"); + alg.setProperty("OutputWorkspace", "out"); + alg.execute(); + MatrixWorkspace_sptr out = alg.getProperty("OutputWorkspace"); + auto outAxis = out->getAxis(1); + TS_ASSERT_DIFFERS(dynamic_cast<BinEdgeAxis *>(outAxis), nullptr) + TS_ASSERT_EQUALS(outAxis->length(), 4) + TS_ASSERT_EQUALS((*outAxis)(0), -1.) + TS_ASSERT_EQUALS((*outAxis)(1), 0.) + TS_ASSERT_EQUALS((*outAxis)(2), 1.) + TS_ASSERT_EQUALS((*outAxis)(3), 2.) + } + + void test_BinEdgeAxis_fails_with_non_contiguous_indices() { + auto input = createWorkspace(); + BinEdgeAxis *axis = new BinEdgeAxis(input->getNumberHistograms() + 1); + for (size_t i = 0; i < axis->length(); ++i) { + axis->setValue(i, -2. + static_cast<double>(i)); + } + input->replaceAxis(1, axis); + ExtractSpectra2 alg; + alg.initialize(); + alg.setChild(true); + alg.setRethrows(true); + alg.setProperty("InputWorkspace", std::move(input)); + alg.setProperty("InputWorkspaceIndexSet", "1,3"); + alg.setProperty("OutputWorkspace", "out"); + TS_ASSERT_THROWS_EQUALS( + alg.execute(), const std::invalid_argument &e, e.what(), + std::string("Cannot extract non-contiguous set of spectra when the " + "vertical axis has bin edges.")) + } }; #endif /* MANTID_ALGORITHMS_EXTRACTSPECTRA2TEST_H_ */ diff --git a/Framework/DataHandling/test/CompressEventsTest.h b/Framework/DataHandling/test/CompressEventsTest.h index f3a7b711f854c9333a988f70e36488ba037df57e..64c8568bfb1b09baf39cf1612b9474936a7c9d93 100644 --- a/Framework/DataHandling/test/CompressEventsTest.h +++ b/Framework/DataHandling/test/CompressEventsTest.h @@ -12,6 +12,7 @@ #include "MantidAPI/Axis.h" #include "MantidDataHandling/CompressEvents.h" #include "MantidDataObjects/Workspace2D.h" +#include "MantidKernel/Unit.h" #include "MantidTestHelpers/WorkspaceCreationHelper.h" using Mantid::MantidVecPtr; @@ -113,8 +114,8 @@ public: TS_ASSERT_DELTA(output->readY(0)[1], 2.0, 1e-5); TS_ASSERT_DELTA(output->readE(0)[1], M_SQRT2, 1e-5); TS_ASSERT_EQUALS(output->YUnit(), input->YUnit()); - TS_ASSERT_EQUALS(output->getAxis(0)->unit(), input->getAxis(0)->unit()); - TS_ASSERT_EQUALS(output->getAxis(1)->unit(), input->getAxis(1)->unit()); + TS_ASSERT(*output->getAxis(0)->unit() == *input->getAxis(0)->unit()); + TS_ASSERT(*output->getAxis(1)->unit() == *input->getAxis(1)->unit()); } // WEIGHTED_NOTIME tests diff --git a/Framework/DataObjects/test/WorkspaceCreationTest.h b/Framework/DataObjects/test/WorkspaceCreationTest.h index 82eee10415802f66fd473500d74251905831c32f..a7fe8b94993a82c5df0908200f969f18960ede5f 100644 --- a/Framework/DataObjects/test/WorkspaceCreationTest.h +++ b/Framework/DataObjects/test/WorkspaceCreationTest.h @@ -9,6 +9,7 @@ #include <cxxtest/TestSuite.h> +#include "MantidAPI/BinEdgeAxis.h" #include "MantidAPI/Run.h" #include "MantidDataObjects/EventWorkspace.h" #include "MantidDataObjects/SpecialWorkspace2D.h" @@ -419,6 +420,30 @@ public: check_zeroed_data(*ws); } + void test_create_parent_numeric_vertical_axis() { + constexpr size_t parentNhist{3}; + const auto parent = create<Workspace2D>(parentNhist, Histogram(Points{1})); + NumericAxis *parentAxis = new NumericAxis({-1.5, -0.5, 2.3}); + parent->replaceAxis(1, parentAxis); + constexpr size_t nhist{2}; + const auto ws = create<Workspace2D>(*parent, nhist, parent->histogram(0)); + auto axis = ws->getAxis(1); + TS_ASSERT_DIFFERS(dynamic_cast<NumericAxis *>(axis), nullptr) + TS_ASSERT_EQUALS(axis->length(), nhist); + } + + void test_create_parent_bin_edge_vertical_axis() { + constexpr size_t parentNhist{3}; + const auto parent = create<Workspace2D>(parentNhist, Histogram(Points{1})); + BinEdgeAxis *parentAxis = new BinEdgeAxis({-1.5, -0.5, 2.3, 3.4}); + parent->replaceAxis(1, parentAxis); + constexpr size_t nhist{2}; + const auto ws = create<Workspace2D>(*parent, nhist, parent->histogram(0)); + auto axis = ws->getAxis(1); + TS_ASSERT_DIFFERS(dynamic_cast<BinEdgeAxis *>(axis), nullptr) + TS_ASSERT_EQUALS(axis->length(), nhist + 1); + } + void test_create_drop_events() { auto eventWS = create<EventWorkspace>(1, Histogram(BinEdges(3))); auto ws = create<HistoWorkspace>(*eventWS); diff --git a/Framework/Indexing/inc/MantidIndexing/IndexSet.h b/Framework/Indexing/inc/MantidIndexing/IndexSet.h index dfb3c25774aa69eeff63db6be74df21ebbca5295..ed50cbb1229484d106900bd8f78fb414a784ce2e 100644 --- a/Framework/Indexing/inc/MantidIndexing/IndexSet.h +++ b/Framework/Indexing/inc/MantidIndexing/IndexSet.h @@ -91,6 +91,8 @@ public: return m_indices[index]; } + bool isContiguous() const noexcept; + protected: ~IndexSet() = default; @@ -139,6 +141,20 @@ IndexSet<T>::IndexSet(const std::vector<size_t> &indices, size_t fullRange) m_size = m_indices.size(); } +/** + * Check if the index range is contiguous and in ascending order. + */ +template <class T> bool IndexSet<T>::isContiguous() const noexcept { + if (!m_isRange || m_indices.size() > 1) { + for (size_t i = 0; i < m_indices.size() - 1; ++i) { + if (m_indices[i] + 1 != m_indices[i + 1]) { + return false; + } + } + } + return true; +} + } // namespace detail } // namespace Indexing } // namespace Mantid diff --git a/Framework/Indexing/test/IndexSetTest.h b/Framework/Indexing/test/IndexSetTest.h index 916f4429dd1990f9e9c9f9eccc7666c94cb2126b..7108f6770e5cbcda0bf5ca9ff08a792546440161 100644 --- a/Framework/Indexing/test/IndexSetTest.h +++ b/Framework/Indexing/test/IndexSetTest.h @@ -137,6 +137,17 @@ public: TS_ASSERT_THROWS_NOTHING(--it2); TS_ASSERT_EQUALS(*it2, 0); } + + void test_isContiguous() { + const IndexSetTester empty{}; + TS_ASSERT(empty.isContiguous()) + const IndexSetTester range(3); + TS_ASSERT(range.isContiguous()) + const IndexSetTester manualRange({3, 4, 5}, 6); + TS_ASSERT(manualRange.isContiguous()) + IndexSetTester nonContiguous({2, 1, 3}, 4); + TS_ASSERT(!nonContiguous.isContiguous()) + } }; #endif /* MANTID_INDEXING_INDEXSETTEST_H_ */ diff --git a/Testing/SystemTests/tests/analysis/reference/II.IRISMoments.nxs.md5 b/Testing/SystemTests/tests/analysis/reference/II.IRISMoments.nxs.md5 index 870024467e73790d3cf578ce13fa1e900a33ca4a..a9857f36b9e5022067e49ec3004d659683329c33 100644 --- a/Testing/SystemTests/tests/analysis/reference/II.IRISMoments.nxs.md5 +++ b/Testing/SystemTests/tests/analysis/reference/II.IRISMoments.nxs.md5 @@ -1 +1 @@ -d2185756bd31c3fce4bee9f4dc0bc441 +5019e21091a7b56a76b92b9f98cc59ec diff --git a/Testing/SystemTests/tests/analysis/reference/II.OSIRISMoments.nxs.md5 b/Testing/SystemTests/tests/analysis/reference/II.OSIRISMoments.nxs.md5 index 8bd1cff7ee995f771198fd4e5a5b861457a4292f..863af15f45b1492b2ffafa6f756b6fe7d7d0c84d 100644 --- a/Testing/SystemTests/tests/analysis/reference/II.OSIRISMoments.nxs.md5 +++ b/Testing/SystemTests/tests/analysis/reference/II.OSIRISMoments.nxs.md5 @@ -1 +1 @@ -a1a495cd3351cd56ed06c7c7844817bb +c23e62c08f2ced8496ce229b071be418 diff --git a/docs/source/release/v3.14.0/framework.rst b/docs/source/release/v3.14.0/framework.rst index 6fa2835b224cf9c32043fb620adc180b1c05fc12..cb09c9f08cd405141067812468a618e5bf6166ee 100644 --- a/docs/source/release/v3.14.0/framework.rst +++ b/docs/source/release/v3.14.0/framework.rst @@ -106,6 +106,7 @@ Bugfixes - `ConvertToMD <algm-ConvertToMD>` now uses the time-average value for logs when using them as ``OtherDimensions`` - The input validator is fixed in :ref:`MostLikelyMean <algm-MostLikelyMean>` avoiding a segmentation fault. - Fixed a bug in `AlignAndFocusPowder <algm-AlignAndFocusPowder>` where a histogram input workspace did not clone propertly to the output workspace and properly masking a grouping workspace passed to `DiffractionFocussing <algm-DiffractionFocussing>`. Also adds initial unit tests for `AlignAndFocusPowder <algm-AlignAndFocusPowder>`. +- Fixed a bug in :ref:`ExtractSpectra <algm-ExtractSpectra>` which was causing a wrong last value in the output's vertical axis if the axis type was ``BinEdgeAxis``. Python ------