From edbe3b68e9bdebe0067c439b62d766d37f8294ff Mon Sep 17 00:00:00 2001 From: Anton Piccardo-Selg <anton.piccardo-selg@tessella.com> Date: Tue, 8 Mar 2016 12:35:06 +0000 Subject: [PATCH] Refs #15482 Implement correct behaviour for spectra list --- .../MantidDataHandling/DataBlockComposite.h | 152 +- .../DataHandling/src/DataBlockComposite.cpp | 665 ++++--- Framework/DataHandling/src/LoadISISNexus2.cpp | 21 +- .../test/DataBlockCompositeTest.h | 1660 ++++++++++------- .../DataHandling/test/LoadISISNexusTest.h | 8 + 5 files changed, 1456 insertions(+), 1050 deletions(-) diff --git a/Framework/DataHandling/inc/MantidDataHandling/DataBlockComposite.h b/Framework/DataHandling/inc/MantidDataHandling/DataBlockComposite.h index 0d91d4e222a..76cde9bb0cd 100644 --- a/Framework/DataHandling/inc/MantidDataHandling/DataBlockComposite.h +++ b/Framework/DataHandling/inc/MantidDataHandling/DataBlockComposite.h @@ -4,8 +4,10 @@ #include "MantidDataHandling/DataBlock.h" #include "MantidDataHandling/DllConfig.h" -namespace Mantid { -namespace DataHandling { +namespace Mantid +{ +namespace DataHandling +{ /** DataBlockComposite: The DataBlockComposite handles a collection of DataBlocks. It represents a set of contiguous spectrum numbers @@ -33,81 +35,133 @@ File change history is stored at: <https://github.com/mantidproject/mantid> Code Documentation is available at: <http://doxygen.mantidproject.org> */ -class DLLExport DataBlockComposite : public DataBlock { +class DLLExport DataBlockComposite : public DataBlock +{ public: - int64_t getMinSpectrumID() const override; - void setMinSpectrumID(int64_t) override; + int64_t getMinSpectrumID() const override; + void setMinSpectrumID(int64_t) override; - int64_t getMaxSpectrumID() const override; - void setMaxSpectrumID(int64_t) override; + int64_t getMaxSpectrumID() const override; + void setMaxSpectrumID(int64_t) override; - size_t getNumberOfSpectra() const override; - size_t getNumberOfChannels() const override; - int getNumberOfPeriods() const override; + size_t getNumberOfSpectra() const override; + size_t getNumberOfChannels() const override; + int getNumberOfPeriods() const override; - std::unique_ptr<DataBlockGenerator> getGenerator() const override; + std::unique_ptr<DataBlockGenerator> getGenerator() const override; - bool operator==(const DataBlockComposite &other) const; + bool operator==(const DataBlockComposite &other) const; - // DataBlockComposite only mehtods - void addDataBlock(DataBlock dataBlock); - std::vector<DataBlock> getDataBlocks(); - DataBlockComposite operator+(const DataBlockComposite &other); - void removeSpectra(DataBlockComposite &toRemove); - void truncate(int64_t specMin, int64_t specMax); + // DataBlockComposite only mehtods + void addDataBlock(DataBlock dataBlock); + std::vector<DataBlock> getDataBlocks(); + DataBlockComposite operator+(const DataBlockComposite &other); + void removeSpectra(DataBlockComposite &toRemove); + void truncate(int64_t specMin, int64_t specMax); + std::vector<int64_t> getAllSpectrumNumbers(); private: - std::vector<DataBlock> m_dataBlocks; + std::vector<DataBlock> m_dataBlocks; }; +namespace +{ +void handleWhenElementIsMonitor( + Mantid::DataHandling::DataBlockComposite &dataBlockComposite, + int numberOfPeriods, size_t numberOfChannels, int64_t previousValue, + int64_t startValue) +{ + if (previousValue - startValue > 0) { + auto numberOfSpectra + = previousValue + - startValue; /* Should be from [start, previousValue -1]*/ + DataBlock dataBlock(numberOfPeriods, numberOfSpectra, numberOfChannels); + dataBlock.setMinSpectrumID(startValue); + dataBlock.setMaxSpectrumID(previousValue - 1); + dataBlockComposite.addDataBlock(dataBlock); + } + + // Save out the monitor + DataBlock dataBlock(numberOfPeriods, 1, numberOfChannels); + dataBlock.setMinSpectrumID(previousValue); + dataBlock.setMaxSpectrumID(previousValue); + dataBlockComposite.addDataBlock(dataBlock); +} + + +void handleWhenElementMadeAJump( + Mantid::DataHandling::DataBlockComposite &dataBlockComposite, + int numberOfPeriods, size_t numberOfChannels, int64_t previousValue, + int64_t startValue) +{ + auto numberOfSpectra = previousValue - startValue + 1; + DataBlock dataBlock(numberOfPeriods, numberOfSpectra, + numberOfChannels); + dataBlock.setMinSpectrumID(startValue); + dataBlock.setMaxSpectrumID(previousValue); + dataBlockComposite.addDataBlock(dataBlock); +} + +} + /** * Populates a DataBlockComposite with DataBlocks which are extracted from a * indexable collection (array-type). Note that std::is_array does not * work on boost::shared_array which is one of the use cases. Hence this -* function could get abused. +* function could get abused. Monitor spectra get their own data block * @param dataBlockComposite: the detector block composite which will get * populated * @param indexContainer: the container of indices * @param nArray: the number of array elements * @param numberOfPeriods: the number of periods * @param numberOfChannels: the number of channels +* @param monitorSpectra: a collection of monitor spectrum numbers */ template <typename T> void DLLExport populateDataBlockCompositeWithContainer(DataBlockComposite &dataBlockComposite, T &indexContainer, int64_t nArray, int numberOfPeriods, - size_t numberOfChannels) { - - // Find all intervals among the index array (this assumes that spectrum index - // increases monotonically, else we would have to sort first) - int64_t startValue = indexContainer[0]; - int64_t previousValue = startValue; - - for (int64_t arrayIndex = 1; arrayIndex < nArray; ++arrayIndex) { - auto isSequential = (indexContainer[arrayIndex] - previousValue) == 1; - if (!isSequential) { - // We must have completed an interval, we create a DataBlock and add it - auto numberOfSpectra = previousValue - startValue + 1; - DataBlock dataBlock(numberOfPeriods, numberOfSpectra, numberOfChannels); - dataBlock.setMinSpectrumID(startValue); - dataBlock.setMaxSpectrumID(previousValue); - dataBlockComposite.addDataBlock(dataBlock); - - // Now reset the startValue to the beginning of the new index - startValue = indexContainer[arrayIndex]; + size_t numberOfChannels, + std::vector<int64_t> monitorSpectra) +{ + auto isMonitor = [&monitorSpectra](int64_t index) { + return std::find(std::begin(monitorSpectra), std::end(monitorSpectra), + index) != std::end(monitorSpectra); + }; + + auto startValue = indexContainer[0]; + auto previousValue = startValue; + + for (int64_t arrayIndex = 1; arrayIndex < nArray; ++arrayIndex) { + // There are two ways to write data out. Either when we have a jump of + // the indices or there is a monitor. In case of a monitor we also need + // to clear the data that was potentially before the monitor. + + if (isMonitor(previousValue)) { + handleWhenElementIsMonitor(dataBlockComposite, numberOfPeriods, + numberOfChannels, previousValue, startValue); + startValue = indexContainer[arrayIndex]; + } else if ((indexContainer[arrayIndex] - previousValue) != 1) { + // We must have completed an interval, we create a DataBlock and add + // it + handleWhenElementMadeAJump(dataBlockComposite, numberOfPeriods, + numberOfChannels, previousValue, startValue); + startValue = indexContainer[arrayIndex]; + } + + // Set the previous value to the current value; + previousValue = indexContainer[arrayIndex]; } - // Set the previous value to the current value; - previousValue = indexContainer[arrayIndex]; - } - - // The last interval would not have been added - auto numberOfSpectra = previousValue - startValue + 1; - DataBlock dataBlock(numberOfPeriods, numberOfSpectra, numberOfChannels); - dataBlock.setMinSpectrumID(startValue); - dataBlock.setMaxSpectrumID(previousValue); - dataBlockComposite.addDataBlock(dataBlock); + // The last interval would not have been added. + if (isMonitor(previousValue)) { + handleWhenElementIsMonitor(dataBlockComposite, numberOfPeriods, + numberOfChannels, previousValue, startValue); + } else { + handleWhenElementMadeAJump(dataBlockComposite, numberOfPeriods, + numberOfChannels, previousValue, startValue); + } } } } diff --git a/Framework/DataHandling/src/DataBlockComposite.cpp b/Framework/DataHandling/src/DataBlockComposite.cpp index 189d88ad536..88aecc05847 100644 --- a/Framework/DataHandling/src/DataBlockComposite.cpp +++ b/Framework/DataHandling/src/DataBlockComposite.cpp @@ -3,7 +3,8 @@ #include <algorithm> #include <cassert> -namespace { +namespace +{ const int64_t invalidIntervalValue = std::numeric_limits<int64_t>::min(); @@ -19,25 +20,26 @@ const int64_t invalidIntervalValue = std::numeric_limits<int64_t>::min(); std::vector<std::pair<int64_t, int64_t>> getRemovalIntervalsRelevantForTheCurrentOriginalInterval( const std::pair<int64_t, int64_t> &original, - const std::vector<std::pair<int64_t, int64_t>> &removeIntervals) { - - auto hasOverlap = [](const std::pair<int64_t, int64_t> &original, - const std::pair<int64_t, int64_t> &toRemove) { - return ((original.first <= toRemove.first) && - (toRemove.first <= original.second)) || - ((original.first <= toRemove.second) && - (toRemove.second <= original.second)) || - ((toRemove.first <= original.first) && - (original.first <= toRemove.second)); - }; - - std::vector<std::pair<int64_t, int64_t>> overlaps; - for (auto &removeInterval : removeIntervals) { - if (hasOverlap(original, removeInterval)) { - overlaps.push_back(removeInterval); + const std::vector<std::pair<int64_t, int64_t>> &removeIntervals) +{ + + auto hasOverlap = [](const std::pair<int64_t, int64_t> &original, + const std::pair<int64_t, int64_t> &toRemove) { + return ((original.first <= toRemove.first) + && (toRemove.first <= original.second)) + || ((original.first <= toRemove.second) + && (toRemove.second <= original.second)) + || ((toRemove.first <= original.first) + && (original.first <= toRemove.second)); + }; + + std::vector<std::pair<int64_t, int64_t>> overlaps; + for (auto &removeInterval : removeIntervals) { + if (hasOverlap(original, removeInterval)) { + overlaps.push_back(removeInterval); + } } - } - return overlaps; + return overlaps; } /** @@ -49,8 +51,9 @@ getRemovalIntervalsRelevantForTheCurrentOriginalInterval( return: NONE */ void handleLeftHandSideOverlap(std::pair<int64_t, int64_t> &original, - const std::pair<int64_t, int64_t> &toRemove) { - original.first = toRemove.second + 1; + const std::pair<int64_t, int64_t> &toRemove) +{ + original.first = toRemove.second + 1; } /** @@ -63,11 +66,12 @@ void handleLeftHandSideOverlap(std::pair<int64_t, int64_t> &original, */ std::pair<int64_t, int64_t> handleRightHandSideOverlap(std::pair<int64_t, int64_t> &original, - const std::pair<int64_t, int64_t> &toRemove) { - auto newInterval = std::make_pair(original.first, toRemove.first - 1); - original.first = invalidIntervalValue; - original.second = invalidIntervalValue; - return newInterval; + const std::pair<int64_t, int64_t> &toRemove) +{ + auto newInterval = std::make_pair(original.first, toRemove.first - 1); + original.first = invalidIntervalValue; + original.second = invalidIntervalValue; + return newInterval; } /** @@ -80,288 +84,315 @@ handleRightHandSideOverlap(std::pair<int64_t, int64_t> &original, */ std::pair<int64_t, int64_t> handleFullyContained(std::pair<int64_t, int64_t> &original, - const std::pair<int64_t, int64_t> &toRemove) { - // It is important to first creat the new pair and then perform the cut - auto newPair = std::make_pair(original.first, toRemove.first - 1); - original.first = toRemove.second + 1; - return newPair; + const std::pair<int64_t, int64_t> &toRemove) +{ + // It is important to first creat the new pair and then perform the cut + auto newPair = std::make_pair(original.first, toRemove.first - 1); + original.first = toRemove.second + 1; + return newPair; } std::vector<std::pair<int64_t, int64_t>> getSlicedIntervals( std::pair<int64_t, int64_t> original, - const std::vector<std::pair<int64_t, int64_t>> &removeIntervals) { - // If there is nothing to remove return the original - if (removeIntervals.empty()) { - return std::vector<std::pair<int64_t, int64_t>>{original}; - } - - // There are several overlap scenarios. - // 1. Full overlap - // original : |-------| and |------| - // toRemove: ...------------... and |------| - // 2. Left hand side overlap - // original : |------... and |-----.... - // toRemove: |------| and |---| - // 3. Right hand side overlap - // original : ...-------| and ...-----| - // toRemove: |-----| and |---| - // 4. Fully contained - // original : ...-------... - // toRemove: |---| - - auto isFullOverlap = [](const std::pair<int64_t, int64_t> &original, - const std::pair<int64_t, int64_t> &toRemove) { - return (toRemove.first <= original.first) && - (original.first <= toRemove.second) && - (toRemove.first <= original.second) && - (original.second <= toRemove.second); - }; - - auto isLeftHandSideOverlap = [](const std::pair<int64_t, int64_t> &original, - const std::pair<int64_t, int64_t> &toRemove) { - return (toRemove.first <= original.first) && - (original.first <= toRemove.second) && - (toRemove.second < original.second); - }; - - auto isRightHandSideOverlap = - [](const std::pair<int64_t, int64_t> &original, - const std::pair<int64_t, int64_t> &toRemove) { - return (original.first < toRemove.first) && - (toRemove.first <= original.second) && - (original.second <= toRemove.second); - }; - - auto isFullyContained = [](const std::pair<int64_t, int64_t> &original, - const std::pair<int64_t, int64_t> &toRemove) { - return (original.first < toRemove.first) && - (toRemove.first < original.second) && - (original.first < toRemove.second) && - (toRemove.second < original.second); - }; - - // Use that removeIntervals has oredred, non-overlapping intervals - // Subtract all the removeIntervals - std::vector<std::pair<int64_t, int64_t>> newIntervals; - for (auto &removeInterval : removeIntervals) { - - if (isFullOverlap(original, removeInterval)) { - // In this case we should remove everything. At this point newIntervals - // should still be empty, since the remove intervals should not be - // overlapping - assert(newIntervals.empty() && - "DataBlockComposite: The newIntervals container should be empty"); - // Set the remainder of the original to invalid, such that we don't pick - // it up at the very end - original.first = invalidIntervalValue; - original.second = invalidIntervalValue; - break; - } else if (isRightHandSideOverlap(original, removeInterval)) { - auto newInterval = handleRightHandSideOverlap(original, removeInterval); - newIntervals.push_back(newInterval); - } else if (isLeftHandSideOverlap(original, removeInterval)) { - handleLeftHandSideOverlap(original, removeInterval); - } else if (isFullyContained(original, removeInterval)) { - auto newInterval = handleFullyContained(original, removeInterval); - newIntervals.push_back(newInterval); - } else { - throw std::runtime_error( - "DataBlockComposite: The intervals don't seem to overlap."); + const std::vector<std::pair<int64_t, int64_t>> &removeIntervals) +{ + // If there is nothing to remove return the original + if (removeIntervals.empty()) { + return std::vector<std::pair<int64_t, int64_t>>{original}; + } + + // There are several overlap scenarios. + // 1. Full overlap + // original : |-------| and |------| + // toRemove: ...------------... and |------| + // 2. Left hand side overlap + // original : |------... and |-----.... + // toRemove: |------| and |---| + // 3. Right hand side overlap + // original : ...-------| and ...-----| + // toRemove: |-----| and |---| + // 4. Fully contained + // original : ...-------... + // toRemove: |---| + + auto isFullOverlap = [](const std::pair<int64_t, int64_t> &original, + const std::pair<int64_t, int64_t> &toRemove) { + return (toRemove.first <= original.first) + && (original.first <= toRemove.second) + && (toRemove.first <= original.second) + && (original.second <= toRemove.second); + }; + + auto isLeftHandSideOverlap = + [](const std::pair<int64_t, int64_t> &original, + const std::pair<int64_t, int64_t> &toRemove) { + return (toRemove.first <= original.first) + && (original.first <= toRemove.second) + && (toRemove.second < original.second); + }; + + auto isRightHandSideOverlap = + [](const std::pair<int64_t, int64_t> &original, + const std::pair<int64_t, int64_t> &toRemove) { + return (original.first < toRemove.first) + && (toRemove.first <= original.second) + && (original.second <= toRemove.second); + }; + + auto isFullyContained = [](const std::pair<int64_t, int64_t> &original, + const std::pair<int64_t, int64_t> &toRemove) { + return (original.first < toRemove.first) + && (toRemove.first < original.second) + && (original.first < toRemove.second) + && (toRemove.second < original.second); + }; + + // Use that removeIntervals has oredred, non-overlapping intervals + // Subtract all the removeIntervals + std::vector<std::pair<int64_t, int64_t>> newIntervals; + for (auto &removeInterval : removeIntervals) { + + if (isFullOverlap(original, removeInterval)) { + // In this case we should remove everything. At this point + // newIntervals + // should still be empty, since the remove intervals should not be + // overlapping + assert(newIntervals.empty() && "DataBlockComposite: The " + "newIntervals container should be " + "empty"); + // Set the remainder of the original to invalid, such that we don't + // pick + // it up at the very end + original.first = invalidIntervalValue; + original.second = invalidIntervalValue; + break; + } else if (isRightHandSideOverlap(original, removeInterval)) { + auto newInterval + = handleRightHandSideOverlap(original, removeInterval); + newIntervals.push_back(newInterval); + } else if (isLeftHandSideOverlap(original, removeInterval)) { + handleLeftHandSideOverlap(original, removeInterval); + } else if (isFullyContained(original, removeInterval)) { + auto newInterval = handleFullyContained(original, removeInterval); + newIntervals.push_back(newInterval); + } else { + throw std::runtime_error( + "DataBlockComposite: The intervals don't seem to overlap."); + } } - } - // There might be some remainder in the original interval, e.g if there wasn't - // a full overlap removal - // or no righ-hand-side overlap of a removal interval - if ((original.first != invalidIntervalValue) && - (original.second != invalidIntervalValue)) { - newIntervals.push_back(original); - } + // There might be some remainder in the original interval, e.g if there + // wasn't + // a full overlap removal + // or no righ-hand-side overlap of a removal interval + if ((original.first != invalidIntervalValue) + && (original.second != invalidIntervalValue)) { + newIntervals.push_back(original); + } - return newIntervals; + return newIntervals; } /** * Sorts a data block collection. */ -template <typename T> void sortDataBlocks(T &dataBlcokCollection) { - // Sort the intervals. We sort them by minimum value - using namespace Mantid::DataHandling; - auto comparison = [](const DataBlock &el1, const DataBlock &el2) { - return el1.getMinSpectrumID() < el2.getMinSpectrumID(); - }; - std::sort(std::begin(dataBlcokCollection), std::end(dataBlcokCollection), - comparison); +template <typename T> void sortDataBlocks(T &dataBlcokCollection) +{ + // Sort the intervals. We sort them by minimum value + using namespace Mantid::DataHandling; + auto comparison = [](const DataBlock &el1, const DataBlock &el2) { + return el1.getMinSpectrumID() < el2.getMinSpectrumID(); + }; + std::sort(std::begin(dataBlcokCollection), std::end(dataBlcokCollection), + comparison); } } -namespace Mantid { -namespace DataHandling { - -int64_t DataBlockComposite::getMinSpectrumID() const { - int64_t min = std::numeric_limits<int64_t>::max(); - for (const auto &child : m_dataBlocks) { - auto temp = child.getMinSpectrumID(); - if (temp < min) { - min = temp; +namespace Mantid +{ +namespace DataHandling +{ + +int64_t DataBlockComposite::getMinSpectrumID() const +{ + int64_t min = std::numeric_limits<int64_t>::max(); + for (const auto &child : m_dataBlocks) { + auto temp = child.getMinSpectrumID(); + if (temp < min) { + min = temp; + } } - } - return min; + return min; } -void DataBlockComposite::setMinSpectrumID(int64_t) { - // DO NOTHING +void DataBlockComposite::setMinSpectrumID(int64_t) +{ + // DO NOTHING } -int64_t DataBlockComposite::getMaxSpectrumID() const { - int64_t max = std::numeric_limits<int64_t>::min(); - for (const auto &child : m_dataBlocks) { - auto temp = child.getMaxSpectrumID(); - if (temp > max) { - max = temp; +int64_t DataBlockComposite::getMaxSpectrumID() const +{ + int64_t max = std::numeric_limits<int64_t>::min(); + for (const auto &child : m_dataBlocks) { + auto temp = child.getMaxSpectrumID(); + if (temp > max) { + max = temp; + } } - } - return max; + return max; } -void DataBlockComposite::setMaxSpectrumID(int64_t) { - // DO NOTHING +void DataBlockComposite::setMaxSpectrumID(int64_t) +{ + // DO NOTHING } -std::unique_ptr<DataBlockGenerator> DataBlockComposite::getGenerator() const { - std::vector<std::pair<int64_t, int64_t>> intervals; - for (const auto &dataBlock : m_dataBlocks) { - intervals.push_back(std::make_pair(dataBlock.getMinSpectrumID(), - dataBlock.getMaxSpectrumID())); - } - return Mantid::Kernel::make_unique<DataBlockGenerator>(intervals); +std::unique_ptr<DataBlockGenerator> DataBlockComposite::getGenerator() const +{ + std::vector<std::pair<int64_t, int64_t>> intervals; + for (const auto &dataBlock : m_dataBlocks) { + intervals.push_back(std::make_pair(dataBlock.getMinSpectrumID(), + dataBlock.getMaxSpectrumID())); + } + return Mantid::Kernel::make_unique<DataBlockGenerator>(intervals); } -void DataBlockComposite::addDataBlock(DataBlock dataBlock) { - // Set the number of periods, number of spectra and number of channel - m_numberOfPeriods = dataBlock.getNumberOfPeriods(); - m_numberOfChannels = dataBlock.getNumberOfChannels(); - m_numberOfSpectra = dataBlock.getNumberOfSpectra(); +void DataBlockComposite::addDataBlock(DataBlock dataBlock) +{ + // Set the number of periods, number of spectra and number of channel + m_numberOfPeriods = dataBlock.getNumberOfPeriods(); + m_numberOfChannels = dataBlock.getNumberOfChannels(); + m_numberOfSpectra = dataBlock.getNumberOfSpectra(); - // Insert the data block - m_dataBlocks.push_back(dataBlock); + // Insert the data block + m_dataBlocks.push_back(dataBlock); } -size_t DataBlockComposite::getNumberOfSpectra() const { - size_t total = 0; - for (const auto &element : m_dataBlocks) { - total += element.getNumberOfSpectra(); - } - return total; +size_t DataBlockComposite::getNumberOfSpectra() const +{ + size_t total = 0; + for (const auto &element : m_dataBlocks) { + total += element.getNumberOfSpectra(); + } + return total; } -size_t DataBlockComposite::getNumberOfChannels() const { - return m_dataBlocks.empty() ? 0 : m_dataBlocks[0].getNumberOfChannels(); +size_t DataBlockComposite::getNumberOfChannels() const +{ + return m_dataBlocks.empty() ? 0 : m_dataBlocks[0].getNumberOfChannels(); } -int DataBlockComposite::getNumberOfPeriods() const { - return m_dataBlocks.empty() ? 0 : m_dataBlocks[0].getNumberOfPeriods(); +int DataBlockComposite::getNumberOfPeriods() const +{ + return m_dataBlocks.empty() ? 0 : m_dataBlocks[0].getNumberOfPeriods(); } DataBlockComposite DataBlockComposite:: -operator+(const DataBlockComposite &other) { - DataBlockComposite output; - output.m_dataBlocks.insert(std::end(output.m_dataBlocks), - std::begin(m_dataBlocks), std::end(m_dataBlocks)); - output.m_dataBlocks.insert(std::end(output.m_dataBlocks), - std::begin(other.m_dataBlocks), - std::end(other.m_dataBlocks)); - return output; +operator+(const DataBlockComposite &other) +{ + DataBlockComposite output; + output.m_dataBlocks.insert(std::end(output.m_dataBlocks), + std::begin(m_dataBlocks), + std::end(m_dataBlocks)); + output.m_dataBlocks.insert(std::end(output.m_dataBlocks), + std::begin(other.m_dataBlocks), + std::end(other.m_dataBlocks)); + return output; } -std::vector<DataBlock> DataBlockComposite::getDataBlocks() { - // Sort the intervals. We sort them by minimum value - sortDataBlocks(m_dataBlocks); - return m_dataBlocks; +std::vector<DataBlock> DataBlockComposite::getDataBlocks() +{ + // Sort the intervals. We sort them by minimum value + sortDataBlocks(m_dataBlocks); + return m_dataBlocks; } -void DataBlockComposite::truncate(int64_t specMin, int64_t specMax) { - sortDataBlocks(m_dataBlocks); - // Find the first data block which is not completely cut off by specMin - // original: |-----| |--------| |------| - // spec_min: | or | or | or| - // result: this one - auto isNotCompletelyCutOffFromMin = [&specMin](DataBlock &block) { - return (specMin <= block.getMinSpectrumID()) || - (specMin <= block.getMaxSpectrumID()); - }; - - // Find the last data block which is not completely cut off by specMax - // original: |-----| |--------| |------| - // spec_min: | or | or| or | - // result: this one - auto isNotCompletelyCutOffFromMax = [&specMax](DataBlock &block) { - return (block.getMinSpectrumID() <= specMax) || - (block.getMaxSpectrumID() <= specMax); - }; - - auto firstDataBlock = - std::find_if(std::begin(m_dataBlocks), std::end(m_dataBlocks), - isNotCompletelyCutOffFromMin); - - // Note that we have to start from the back. - auto lastDataBlockReverseIterator = std::find_if( - m_dataBlocks.rbegin(), m_dataBlocks.rend(), isNotCompletelyCutOffFromMax); - auto lastDataBlock = - std::find(std::begin(m_dataBlocks), std::end(m_dataBlocks), - *lastDataBlockReverseIterator); - - // Create datablocks - // Increment since we want to include the last data block - ++lastDataBlock; - std::vector<DataBlock> newDataBlocks(firstDataBlock, lastDataBlock); - - // Adjust the spec_min and spec_max value. Only change the block if - // the it cuts the block. - if (newDataBlocks[0].getMinSpectrumID() < specMin) { - auto numberOfSpectra = newDataBlocks[0].getMaxSpectrumID() - specMin + 1; - DataBlock block(newDataBlocks[0].getNumberOfPeriods(), numberOfSpectra, - newDataBlocks[0].getNumberOfChannels()); - block.setMinSpectrumID(specMin); - block.setMaxSpectrumID(newDataBlocks[0].getMaxSpectrumID()); - newDataBlocks[0] = block; - } - - auto lastIndex = newDataBlocks.size() - 1; - if (specMax < newDataBlocks[lastIndex].getMaxSpectrumID()) { - auto numberOfSpectra = - specMax - newDataBlocks[lastIndex].getMaxSpectrumID() + 1; - DataBlock block(newDataBlocks[lastIndex].getNumberOfPeriods(), - numberOfSpectra, - newDataBlocks[lastIndex].getNumberOfChannels()); - block.setMinSpectrumID(newDataBlocks[lastIndex].getMinSpectrumID()); - block.setMaxSpectrumID(specMax); - newDataBlocks[lastIndex] = block; - } - - m_dataBlocks.swap(newDataBlocks); +void DataBlockComposite::truncate(int64_t specMin, int64_t specMax) +{ + sortDataBlocks(m_dataBlocks); + // Find the first data block which is not completely cut off by specMin + // original: |-----| |--------| |------| + // spec_min: | or | or | or| + // result: this one + auto isNotCompletelyCutOffFromMin = [&specMin](DataBlock &block) { + return (specMin <= block.getMinSpectrumID()) + || (specMin <= block.getMaxSpectrumID()); + }; + + // Find the last data block which is not completely cut off by specMax + // original: |-----| |--------| |------| + // spec_min: | or | or| or | + // result: this one + auto isNotCompletelyCutOffFromMax = [&specMax](DataBlock &block) { + return (block.getMinSpectrumID() <= specMax) + || (block.getMaxSpectrumID() <= specMax); + }; + + auto firstDataBlock + = std::find_if(std::begin(m_dataBlocks), std::end(m_dataBlocks), + isNotCompletelyCutOffFromMin); + + // Note that we have to start from the back. + auto lastDataBlockReverseIterator + = std::find_if(m_dataBlocks.rbegin(), m_dataBlocks.rend(), + isNotCompletelyCutOffFromMax); + auto lastDataBlock + = std::find(std::begin(m_dataBlocks), std::end(m_dataBlocks), + *lastDataBlockReverseIterator); + + // Create datablocks + // Increment since we want to include the last data block + ++lastDataBlock; + std::vector<DataBlock> newDataBlocks(firstDataBlock, lastDataBlock); + + // Adjust the spec_min and spec_max value. Only change the block if + // the it cuts the block. + if (newDataBlocks[0].getMinSpectrumID() < specMin) { + auto numberOfSpectra = newDataBlocks[0].getMaxSpectrumID() - specMin + + 1; + DataBlock block(newDataBlocks[0].getNumberOfPeriods(), numberOfSpectra, + newDataBlocks[0].getNumberOfChannels()); + block.setMinSpectrumID(specMin); + block.setMaxSpectrumID(newDataBlocks[0].getMaxSpectrumID()); + newDataBlocks[0] = block; + } + + auto lastIndex = newDataBlocks.size() - 1; + if (specMax < newDataBlocks[lastIndex].getMaxSpectrumID()) { + auto numberOfSpectra + = specMax - newDataBlocks[lastIndex].getMaxSpectrumID() + 1; + DataBlock block(newDataBlocks[lastIndex].getNumberOfPeriods(), + numberOfSpectra, + newDataBlocks[lastIndex].getNumberOfChannels()); + block.setMinSpectrumID(newDataBlocks[lastIndex].getMinSpectrumID()); + block.setMaxSpectrumID(specMax); + newDataBlocks[lastIndex] = block; + } + + m_dataBlocks.swap(newDataBlocks); } -bool DataBlockComposite::operator==(const DataBlockComposite &other) const { - if (other.m_dataBlocks.size() != m_dataBlocks.size()) { - return false; - } - - // Create a copy of the intervals, since the comparison operator should not - // have - // side effects!!!!! We need the vector sorted to compare though - auto otherDataBlocks = other.m_dataBlocks; - auto thisDataBlocks = m_dataBlocks; - sortDataBlocks(otherDataBlocks); - sortDataBlocks(thisDataBlocks); - - auto isEqual = true; - auto itOther = otherDataBlocks.cbegin(); - auto itThis = thisDataBlocks.cbegin(); - for (; itOther != otherDataBlocks.cend(); ++itOther, ++itThis) { - isEqual = isEqual && *itOther == *itThis; - } - return isEqual; +bool DataBlockComposite::operator==(const DataBlockComposite &other) const +{ + if (other.m_dataBlocks.size() != m_dataBlocks.size()) { + return false; + } + + // Create a copy of the intervals, since the comparison operator should not + // have + // side effects!!!!! We need the vector sorted to compare though + auto otherDataBlocks = other.m_dataBlocks; + auto thisDataBlocks = m_dataBlocks; + sortDataBlocks(otherDataBlocks); + sortDataBlocks(thisDataBlocks); + + auto isEqual = true; + auto itOther = otherDataBlocks.cbegin(); + auto itThis = thisDataBlocks.cbegin(); + for (; itOther != otherDataBlocks.cend(); ++itOther, ++itThis) { + isEqual = isEqual && *itOther == *itThis; + } + return isEqual; } /** @@ -372,49 +403,67 @@ bool DataBlockComposite::operator==(const DataBlockComposite &other) const { * toRemove: |------| |--| * result: |---| |------| |----| */ -void DataBlockComposite::removeSpectra(DataBlockComposite &toRemove) { - // Get intervals for current data blocks - std::vector<std::pair<int64_t, int64_t>> originalIntervals; - for (auto &dataBlock : m_dataBlocks) { - originalIntervals.emplace_back(std::make_pair( - dataBlock.getMinSpectrumID(), dataBlock.getMaxSpectrumID())); - } - - // Get intervals for the data blocks which should be removed - auto removeBlocks = toRemove.getDataBlocks(); - std::vector<std::pair<int64_t, int64_t>> toRemoveIntervals; - for (auto &dataBlock : removeBlocks) { - toRemoveIntervals.emplace_back(std::make_pair( - dataBlock.getMinSpectrumID(), dataBlock.getMaxSpectrumID())); - } - - // Now create the new intervals which don't include the removeInterval values - std::vector<std::pair<int64_t, int64_t>> newIntervals; - for (auto &originalInterval : originalIntervals) { - // Find all relevant remove intervals. In principal this could - // be made more efficient. - auto currentRemovalIntervals = - getRemovalIntervalsRelevantForTheCurrentOriginalInterval( - originalInterval, toRemoveIntervals); - auto slicedIntervals = - getSlicedIntervals(originalInterval, currentRemovalIntervals); - newIntervals.insert(std::end(newIntervals), std::begin(slicedIntervals), - std::end(slicedIntervals)); - } - - // Create a new set of data blocks - auto numberOfPeriods = m_dataBlocks[0].getNumberOfPeriods(); - auto numberOfChannels = m_dataBlocks[0].getNumberOfChannels(); - - m_dataBlocks.clear(); - for (auto &newInterval : newIntervals) { - DataBlock dataBlock(numberOfPeriods, - newInterval.second - newInterval.first + 1, - numberOfChannels); - dataBlock.setMinSpectrumID(newInterval.first); - dataBlock.setMaxSpectrumID(newInterval.second); - m_dataBlocks.push_back(dataBlock); - } +void DataBlockComposite::removeSpectra(DataBlockComposite &toRemove) +{ + // Get intervals for current data blocks + std::vector<std::pair<int64_t, int64_t>> originalIntervals; + for (auto &dataBlock : m_dataBlocks) { + originalIntervals.emplace_back(std::make_pair( + dataBlock.getMinSpectrumID(), dataBlock.getMaxSpectrumID())); + } + + // Get intervals for the data blocks which should be removed + auto removeBlocks = toRemove.getDataBlocks(); + std::vector<std::pair<int64_t, int64_t>> toRemoveIntervals; + for (auto &dataBlock : removeBlocks) { + toRemoveIntervals.emplace_back(std::make_pair( + dataBlock.getMinSpectrumID(), dataBlock.getMaxSpectrumID())); + } + + // Now create the new intervals which don't include the removeInterval + // values + std::vector<std::pair<int64_t, int64_t>> newIntervals; + for (auto &originalInterval : originalIntervals) { + // Find all relevant remove intervals. In principal this could + // be made more efficient. + auto currentRemovalIntervals + = getRemovalIntervalsRelevantForTheCurrentOriginalInterval( + originalInterval, toRemoveIntervals); + auto slicedIntervals + = getSlicedIntervals(originalInterval, currentRemovalIntervals); + newIntervals.insert(std::end(newIntervals), std::begin(slicedIntervals), + std::end(slicedIntervals)); + } + + // Create a new set of data blocks + auto numberOfPeriods = m_dataBlocks[0].getNumberOfPeriods(); + auto numberOfChannels = m_dataBlocks[0].getNumberOfChannels(); + + m_dataBlocks.clear(); + for (auto &newInterval : newIntervals) { + DataBlock dataBlock(numberOfPeriods, + newInterval.second - newInterval.first + 1, + numberOfChannels); + dataBlock.setMinSpectrumID(newInterval.first); + dataBlock.setMaxSpectrumID(newInterval.second); + m_dataBlocks.push_back(dataBlock); + } +} + +/** + * Provides a container with all spectrum numbers + * @returns a container with all sepctrum numbers + */ +std::vector<int64_t> DataBlockComposite::getAllSpectrumNumbers() +{ + auto generator = getGenerator(); + std::vector<int64_t> allSpectra; + + for (; !generator->isDone(); generator->next()) { + allSpectra.push_back(generator->getValue()); + } + + return allSpectra; } } } diff --git a/Framework/DataHandling/src/LoadISISNexus2.cpp b/Framework/DataHandling/src/LoadISISNexus2.cpp index 08f19fecc8c..fe8bf9a25da 100644 --- a/Framework/DataHandling/src/LoadISISNexus2.cpp +++ b/Framework/DataHandling/src/LoadISISNexus2.cpp @@ -553,12 +553,22 @@ void LoadISISNexus2::checkOptionalProperties(bool bseparateMonitors, } } + auto monitorSpectra = m_monBlockInfo.getAllSpectrumNumbers(); + // Create DataBlocks from the spectrum list DataBlockComposite composite; populateDataBlockCompositeWithContainer( composite, spec_list, spec_list.size(), m_loadBlockInfo.getNumberOfPeriods(), - m_loadBlockInfo.getNumberOfChannels()); + m_loadBlockInfo.getNumberOfChannels(), + monitorSpectra); + + // If the monitors are to be loaded separately, then we have + // to remove them at this point + if (bseparateMonitors || bexcludeMonitor) { + composite.removeSpectra(m_monBlockInfo); + } + m_loadBlockInfo = composite; hasSpecList = true; @@ -625,8 +635,8 @@ LoadISISNexus2::prepareSpectraBlocks(std::map<int64_t, std::string> &monitors, std::vector<int64_t> includedMonitors; // Setup the SpectraBlocks based on the DataBlocks auto dataBlocks = LoadBlock.getDataBlocks(); - auto isMonitor = [&monitors](int64_t spectrumIndex) { - return monitors.find(spectrumIndex) != monitors.end(); + auto isMonitor = [&monitors](int64_t spectrumNumber) { + return monitors.find(spectrumNumber) != monitors.end(); }; for (const auto &dataBlock : dataBlocks) { auto min = dataBlock.getMinSpectrumID(); @@ -1131,9 +1141,12 @@ bool LoadISISNexus2::findSpectraDetRangeInFile( // not be contiguous. NXData nxData = entry.openNXData("detector_1"); NXInt data = nxData.openIntData(); + + auto monitorSpectra = m_monBlockInfo.getAllSpectrumNumbers(); populateDataBlockCompositeWithContainer(m_detBlockInfo, spectrum_index, ndets, data.dim0() /*Number of Periods*/, - data.dim2() /*Number of channels*/); + data.dim2() /*Number of channels*/, + monitorSpectra); // We should handle legacy files which include the spectrum number of the // monitors diff --git a/Framework/DataHandling/test/DataBlockCompositeTest.h b/Framework/DataHandling/test/DataBlockCompositeTest.h index 3c60a929e17..431255c103e 100644 --- a/Framework/DataHandling/test/DataBlockCompositeTest.h +++ b/Framework/DataHandling/test/DataBlockCompositeTest.h @@ -11,702 +11,984 @@ using Mantid::DataHandling::DataBlock; using Mantid::DataHandling::DataBlockComposite; -class DataBlockCompositeTest : public CxxTest::TestSuite { +class DataBlockCompositeTest : public CxxTest::TestSuite +{ public: - // This pair of boilerplate methods prevent the suite being created statically - // This means the constructor isn't called when running other tests - static DataBlockCompositeTest *createSuite() { - return new DataBlockCompositeTest(); - } - static void destroySuite(DataBlockCompositeTest *suite) { delete suite; } - - void - test_that_data_block_composite_produces_generator_which_generates_range() { - // Arrange - int64_t min1 = 2; - int64_t max1 = 8; - DataBlock dataBlock1; - dataBlock1.setMinSpectrumID(min1); - dataBlock1.setMaxSpectrumID(max1); - - int64_t min2 = 45; - int64_t max2 = 49; - DataBlock dataBlock2; - dataBlock2.setMinSpectrumID(min2); - dataBlock2.setMaxSpectrumID(max2); - - int64_t min3 = 23; - int64_t max3 = 27; - DataBlock dataBlock3; - dataBlock3.setMinSpectrumID(min3); - dataBlock3.setMaxSpectrumID(max3); - - DataBlockComposite dataBlockCompsite; - dataBlockCompsite.addDataBlock(dataBlock1); - dataBlockCompsite.addDataBlock(dataBlock2); - dataBlockCompsite.addDataBlock(dataBlock3); - - // Act - auto generator = dataBlockCompsite.getGenerator(); - - // Assert - std::vector<int64_t> expected = {2, 3, 4, 5, 6, 7, 8, 23, 24, - 25, 26, 27, 45, 46, 47, 48, 49}; - auto index = 0; - for (; !generator->isDone(); generator->next(), ++index) { - TSM_ASSERT_EQUALS("Should take elements out of the DataBlock interval", - expected[index], generator->getValue()); + // This pair of boilerplate methods prevent the suite being created + // statically + // This means the constructor isn't called when running other tests + static DataBlockCompositeTest *createSuite() + { + return new DataBlockCompositeTest(); + } + static void destroySuite(DataBlockCompositeTest *suite) { delete suite; } + + void + test_that_data_block_composite_produces_generator_which_generates_range() + { + // Arrange + int64_t min1 = 2; + int64_t max1 = 8; + DataBlock dataBlock1; + dataBlock1.setMinSpectrumID(min1); + dataBlock1.setMaxSpectrumID(max1); + + int64_t min2 = 45; + int64_t max2 = 49; + DataBlock dataBlock2; + dataBlock2.setMinSpectrumID(min2); + dataBlock2.setMaxSpectrumID(max2); + + int64_t min3 = 23; + int64_t max3 = 27; + DataBlock dataBlock3; + dataBlock3.setMinSpectrumID(min3); + dataBlock3.setMaxSpectrumID(max3); + + DataBlockComposite dataBlockCompsite; + dataBlockCompsite.addDataBlock(dataBlock1); + dataBlockCompsite.addDataBlock(dataBlock2); + dataBlockCompsite.addDataBlock(dataBlock3); + + // Act + auto generator = dataBlockCompsite.getGenerator(); + + // Assert + std::vector<int64_t> expected + = {2, 3, 4, 5, 6, 7, 8, 23, 24, 25, 26, 27, 45, 46, 47, 48, 49}; + auto index = 0; + for (; !generator->isDone(); generator->next(), ++index) { + TSM_ASSERT_EQUALS( + "Should take elements out of the DataBlock interval", + expected[index], generator->getValue()); + } + + TSM_ASSERT_EQUALS("Should be equal", index, expected.size()); + } + + void test_that_getting_dataBlocks_returns_them_sorted() + { + // Arrange + int64_t min1 = 2; + int64_t max1 = 8; + DataBlock dataBlock1; + dataBlock1.setMinSpectrumID(min1); + dataBlock1.setMaxSpectrumID(max1); + + int64_t min2 = 45; + int64_t max2 = 49; + DataBlock dataBlock2; + dataBlock2.setMinSpectrumID(min2); + dataBlock2.setMaxSpectrumID(max2); + + int64_t min3 = 23; + int64_t max3 = 27; + DataBlock dataBlock3; + dataBlock3.setMinSpectrumID(min3); + dataBlock3.setMaxSpectrumID(max3); + + DataBlockComposite dataBlockCompsite; + dataBlockCompsite.addDataBlock(dataBlock1); + dataBlockCompsite.addDataBlock(dataBlock2); + dataBlockCompsite.addDataBlock(dataBlock3); + + // Act + auto dataBlocks = dataBlockCompsite.getDataBlocks(); + + // Assert + TSM_ASSERT_EQUALS("There should be three data blocks", 3, + dataBlocks.size()); + TSM_ASSERT_EQUALS("The first min should be 2", min1, + dataBlocks[0].getMinSpectrumID()); + TSM_ASSERT_EQUALS("The first max should be 8", max1, + dataBlocks[0].getMaxSpectrumID()); + TSM_ASSERT_EQUALS("The second min should be 23", min3, + dataBlocks[1].getMinSpectrumID()); + TSM_ASSERT_EQUALS("The second max should be 27", max3, + dataBlocks[1].getMaxSpectrumID()); + TSM_ASSERT_EQUALS("The first min should be 45", min2, + dataBlocks[2].getMinSpectrumID()); + TSM_ASSERT_EQUALS("The first min should be 49", max2, + dataBlocks[2].getMaxSpectrumID()); + } + + void + test_that_add_number_of_spectra_is_returned_as_well_as_correct_min_and_max() + { + // Arrange + int64_t min1 = 2; + int64_t max1 = 8; + DataBlock dataBlock1; + dataBlock1.setMinSpectrumID(min1); + dataBlock1.setMaxSpectrumID(max1); + + int64_t min2 = 45; + int64_t max2 = 49; + DataBlock dataBlock2; + dataBlock2.setMinSpectrumID(min2); + dataBlock2.setMaxSpectrumID(max2); + + int64_t min3 = 23; + int64_t max3 = 27; + DataBlock dataBlock3; + dataBlock3.setMinSpectrumID(min3); + dataBlock3.setMaxSpectrumID(max3); + + DataBlockComposite dataBlockCompsite; + dataBlockCompsite.addDataBlock(dataBlock1); + dataBlockCompsite.addDataBlock(dataBlock2); + dataBlockCompsite.addDataBlock(dataBlock3); + + // Act + auto numberOfSpectra = dataBlockCompsite.getNumberOfSpectra(); + auto min = dataBlockCompsite.getMinSpectrumID(); + auto max = dataBlockCompsite.getMaxSpectrumID(); + + // Assert + auto expectedNumberOfSpectra = dataBlock1.getNumberOfSpectra() + + dataBlock2.getNumberOfSpectra() + + dataBlock3.getNumberOfSpectra(); + TSM_ASSERT_EQUALS( + "The total number of spectra should be the sum of the " + "spectra of the sub datablocks", + expectedNumberOfSpectra, numberOfSpectra); + + TSM_ASSERT_EQUALS("The min should be the absolute min of 2", min1, min); + TSM_ASSERT_EQUALS("The max should be the aboslute max of 49", max2, + max); + } + + void test_adding_composites_prouduces_correct_new_composite() + { + // Arrange + int64_t min1 = 2; + int64_t max1 = 8; + DataBlock dataBlock1; + dataBlock1.setMinSpectrumID(min1); + dataBlock1.setMaxSpectrumID(max1); + + int64_t min2 = 45; + int64_t max2 = 49; + DataBlock dataBlock2; + dataBlock2.setMinSpectrumID(min2); + dataBlock2.setMaxSpectrumID(max2); + + int64_t min4 = 17; + int64_t max4 = 20; + DataBlock dataBlock4; + dataBlock4.setMinSpectrumID(min4); + dataBlock4.setMaxSpectrumID(max4); + + int64_t min3 = 23; + int64_t max3 = 27; + DataBlock dataBlock3; + dataBlock3.setMinSpectrumID(min3); + dataBlock3.setMaxSpectrumID(max3); + + DataBlockComposite dataBlockCompsite1; + dataBlockCompsite1.addDataBlock(dataBlock1); + dataBlockCompsite1.addDataBlock(dataBlock3); + + DataBlockComposite dataBlockCompsite2; + dataBlockCompsite2.addDataBlock(dataBlock2); + dataBlockCompsite2.addDataBlock(dataBlock4); + + // Act + auto dataBlockCompositeAdded = dataBlockCompsite1 + dataBlockCompsite2; + + // Assert + auto dataBlocks = dataBlockCompositeAdded.getDataBlocks(); + size_t expectedNumberOfDataBlocks = 4; + TSM_ASSERT_EQUALS("Should have 4 data blocks.", + expectedNumberOfDataBlocks, dataBlocks.size()); + + auto min = dataBlockCompositeAdded.getMinSpectrumID(); + TSM_ASSERT_EQUALS("Shouldd have a min value of 2", min1, min); + + auto max = dataBlockCompositeAdded.getMaxSpectrumID(); + TSM_ASSERT_EQUALS("Shouldd have a min value of 49", max2, max); + + auto numberOfSpectra = dataBlockCompositeAdded.getNumberOfSpectra(); + auto expectedNumberOfSpectra = dataBlock1.getNumberOfSpectra() + + dataBlock2.getNumberOfSpectra() + + dataBlock3.getNumberOfSpectra() + + dataBlock4.getNumberOfSpectra(); + TSM_ASSERT_EQUALS("Should have full number of spectra", + expectedNumberOfSpectra, numberOfSpectra); + } + + void test_that_boost_array_can_be_loaded_into_composite() + { + // Arrange + constexpr int64_t size = 11; + // Has intervals [1,1], [3,5], [8,11], [16, 16], [21,22] + boost::shared_array<int> indexArray( + new int[size]{1, 3, 4, 5, 8, 9, 10, 11, 16, 21, 22}); + DataBlockComposite composite; + int numberOfPeriods = 1; + size_t numberOfChannels = 100; + std::vector<int64_t> monitors; + + // Act + Mantid::DataHandling::populateDataBlockCompositeWithContainer( + composite, indexArray, size, numberOfPeriods, numberOfChannels, + monitors); + + // Assert + auto dataBlocks = composite.getDataBlocks(); + TSM_ASSERT_EQUALS("There should be 5 datablocks present", + dataBlocks.size(), 5); + + TSM_ASSERT_EQUALS("The min of the first data block should be 1", 1, + dataBlocks[0].getMinSpectrumID()); + TSM_ASSERT_EQUALS("The max of the first data block should be 1", 1, + dataBlocks[0].getMaxSpectrumID()); + TSM_ASSERT_EQUALS("The number of spectra should be 1", 1, + dataBlocks[0].getNumberOfSpectra()); + + TSM_ASSERT_EQUALS("The min of the second data block should be 3", 3, + dataBlocks[1].getMinSpectrumID()); + TSM_ASSERT_EQUALS("The max of the second data block should be 5", 5, + dataBlocks[1].getMaxSpectrumID()); + TSM_ASSERT_EQUALS("The number of spectra should be 3", 3, + dataBlocks[1].getNumberOfSpectra()); + + TSM_ASSERT_EQUALS("The min of the third data block should be 8", 8, + dataBlocks[2].getMinSpectrumID()); + TSM_ASSERT_EQUALS("The max of the third data block should be 11", 11, + dataBlocks[2].getMaxSpectrumID()); + TSM_ASSERT_EQUALS("The number of spectra should be 4", 4, + dataBlocks[2].getNumberOfSpectra()); + + TSM_ASSERT_EQUALS("The min of the fourth data block should be 16", 16, + dataBlocks[3].getMinSpectrumID()); + TSM_ASSERT_EQUALS("The max of the fourth data block should be 16", 16, + dataBlocks[3].getMaxSpectrumID()); + TSM_ASSERT_EQUALS("The number of spectra should be 1", 1, + dataBlocks[3].getNumberOfSpectra()); + + TSM_ASSERT_EQUALS("The min of the fifth data block should be 21", 21, + dataBlocks[4].getMinSpectrumID()); + TSM_ASSERT_EQUALS("The max of the fiffth data block should be 22", 22, + dataBlocks[4].getMaxSpectrumID()); + TSM_ASSERT_EQUALS("The number of spectra should be 2", 2, + dataBlocks[4].getNumberOfSpectra()); + } + + void test_that_boost_array_can_be_loaded_into_composite_with_monitors() + { + // Arrange + constexpr int64_t size = 11; + // Has intervals [1,1], [3,5], [8,11], [16, 16], [21,22] + boost::shared_array<int> indexArray( + new int[size]{1, 3, 4, 5, 8, 9, 10, 11, 16, 21, 22}); + DataBlockComposite composite; + int numberOfPeriods = 1; + size_t numberOfChannels = 100; + std::vector<int64_t> monitors{9}; + + // Act + Mantid::DataHandling::populateDataBlockCompositeWithContainer( + composite, indexArray, size, numberOfPeriods, numberOfChannels, + monitors); + + // Assert + auto dataBlocks = composite.getDataBlocks(); + TSM_ASSERT_EQUALS("There should be 7 datablocks present", + dataBlocks.size(), 7); + + TSM_ASSERT_EQUALS("The min of the first data block should be 1", 1, + dataBlocks[0].getMinSpectrumID()); + TSM_ASSERT_EQUALS("The max of the first data block should be 1", 1, + dataBlocks[0].getMaxSpectrumID()); + TSM_ASSERT_EQUALS("The number of spectra should be 1", 1, + dataBlocks[0].getNumberOfSpectra()); + + TSM_ASSERT_EQUALS("The min of the second data block should be 3", 3, + dataBlocks[1].getMinSpectrumID()); + TSM_ASSERT_EQUALS("The max of the second data block should be 5", 5, + dataBlocks[1].getMaxSpectrumID()); + TSM_ASSERT_EQUALS("The number of spectra should be 3", 3, + dataBlocks[1].getNumberOfSpectra()); + + TSM_ASSERT_EQUALS("The min of the third data block should be 8", 8, + dataBlocks[2].getMinSpectrumID()); + TSM_ASSERT_EQUALS("The max of the third data block should be 8", 8, + dataBlocks[2].getMaxSpectrumID()); + TSM_ASSERT_EQUALS("The number of spectra should be 1", 1, + dataBlocks[2].getNumberOfSpectra()); + + TSM_ASSERT_EQUALS("The min of the fourth data block should be 9", 9, + dataBlocks[3].getMinSpectrumID()); + TSM_ASSERT_EQUALS("The max of the fourth data block should be 9", 9, + dataBlocks[3].getMaxSpectrumID()); + TSM_ASSERT_EQUALS("The number of spectra should be 1", 1, + dataBlocks[3].getNumberOfSpectra()); + + TSM_ASSERT_EQUALS("The min of the fifth data block should be 10", 10, + dataBlocks[4].getMinSpectrumID()); + TSM_ASSERT_EQUALS("The max of the fifth data block should be 11", 11, + dataBlocks[4].getMaxSpectrumID()); + TSM_ASSERT_EQUALS("The number of spectra should be 2", 2, + dataBlocks[4].getNumberOfSpectra()); + + TSM_ASSERT_EQUALS("The min of the sixth data block should be 16", 16, + dataBlocks[5].getMinSpectrumID()); + TSM_ASSERT_EQUALS("The max of the sixth data block should be 16", 16, + dataBlocks[5].getMaxSpectrumID()); + TSM_ASSERT_EQUALS("The number of spectra should be 1", 1, + dataBlocks[5].getNumberOfSpectra()); + + TSM_ASSERT_EQUALS("The min of the seventh data block should be 21", 21, + dataBlocks[6].getMinSpectrumID()); + TSM_ASSERT_EQUALS("The max of the seventh data block should be 22", 22, + dataBlocks[6].getMaxSpectrumID()); + TSM_ASSERT_EQUALS("The number of spectra should be 2", 2, + dataBlocks[6].getNumberOfSpectra()); + } + + void + test_that_boost_array_can_be_loaded_into_composite_with_monitors_at_the_beginning() + { + // Arrange + constexpr int64_t size = 12; + // Has intervals [1,5], [8,11], [16, 16], [21,22] + boost::shared_array<int> indexArray( + new int[size]{1, 2, 3, 4, 5, 8, 9, 10, 11, 16, 21, 22}); + DataBlockComposite composite; + int numberOfPeriods = 1; + size_t numberOfChannels = 100; + std::vector<int64_t> monitors{1}; + + // Act + Mantid::DataHandling::populateDataBlockCompositeWithContainer( + composite, indexArray, size, numberOfPeriods, numberOfChannels, + monitors); + + // Assert + auto dataBlocks = composite.getDataBlocks(); + TSM_ASSERT_EQUALS("There should be 5 datablocks present", + dataBlocks.size(), 5); + + TSM_ASSERT_EQUALS("The min of the first data block should be 1", 1, + dataBlocks[0].getMinSpectrumID()); + TSM_ASSERT_EQUALS("The max of the first data block should be 1", 1, + dataBlocks[0].getMaxSpectrumID()); + TSM_ASSERT_EQUALS("The number of spectra should be 1", 1, + dataBlocks[0].getNumberOfSpectra()); + + TSM_ASSERT_EQUALS("The min of the second data block should be 2", 2, + dataBlocks[1].getMinSpectrumID()); + TSM_ASSERT_EQUALS("The max of the second data block should be 5", 5, + dataBlocks[1].getMaxSpectrumID()); + TSM_ASSERT_EQUALS("The number of spectra should be 4", 4, + dataBlocks[1].getNumberOfSpectra()); + + TSM_ASSERT_EQUALS("The min of the third data block should be 8", 8, + dataBlocks[2].getMinSpectrumID()); + TSM_ASSERT_EQUALS("The max of the third data block should be 11", 11, + dataBlocks[2].getMaxSpectrumID()); + TSM_ASSERT_EQUALS("The number of spectra should be 4", 4, + dataBlocks[2].getNumberOfSpectra()); + + TSM_ASSERT_EQUALS("The min of the fourth data block should be 16", 16, + dataBlocks[3].getMinSpectrumID()); + TSM_ASSERT_EQUALS("The max of the fourth data block should be 16", 16, + dataBlocks[3].getMaxSpectrumID()); + TSM_ASSERT_EQUALS("The number of spectra should be 1", 1, + dataBlocks[3].getNumberOfSpectra()); + + TSM_ASSERT_EQUALS("The min of the fifth data block should be 21", 21, + dataBlocks[4].getMinSpectrumID()); + TSM_ASSERT_EQUALS("The max of the fiffth data block should be 22", 22, + dataBlocks[4].getMaxSpectrumID()); + TSM_ASSERT_EQUALS("The number of spectra should be 2", 2, + dataBlocks[4].getNumberOfSpectra()); + } + + void + test_that_boost_array_can_be_loaded_into_composite_with_monitor_at_end() + { + // Arrange + constexpr int64_t size = 11; + // Has intervals [1,1], [3,5], [8,11], [16, 16], [21,22] + boost::shared_array<int> indexArray( + new int[size]{1, 3, 4, 5, 8, 9, 10, 11, 16, 21, 22}); + DataBlockComposite composite; + int numberOfPeriods = 1; + size_t numberOfChannels = 100; + std::vector<int64_t> monitors{22}; + + // Act + Mantid::DataHandling::populateDataBlockCompositeWithContainer( + composite, indexArray, size, numberOfPeriods, numberOfChannels, + monitors); + + // Assert + auto dataBlocks = composite.getDataBlocks(); + TSM_ASSERT_EQUALS("There should be 6 datablocks present", + dataBlocks.size(), 6); + + TSM_ASSERT_EQUALS("The min of the first data block should be 1", 1, + dataBlocks[0].getMinSpectrumID()); + TSM_ASSERT_EQUALS("The max of the first data block should be 1", 1, + dataBlocks[0].getMaxSpectrumID()); + TSM_ASSERT_EQUALS("The number of spectra should be 1", 1, + dataBlocks[0].getNumberOfSpectra()); + + TSM_ASSERT_EQUALS("The min of the second data block should be 3", 3, + dataBlocks[1].getMinSpectrumID()); + TSM_ASSERT_EQUALS("The max of the second data block should be 5", 5, + dataBlocks[1].getMaxSpectrumID()); + TSM_ASSERT_EQUALS("The number of spectra should be 3", 3, + dataBlocks[1].getNumberOfSpectra()); + + TSM_ASSERT_EQUALS("The min of the third data block should be 8", 8, + dataBlocks[2].getMinSpectrumID()); + TSM_ASSERT_EQUALS("The max of the third data block should be 11", 11, + dataBlocks[2].getMaxSpectrumID()); + TSM_ASSERT_EQUALS("The number of spectra should be 4", 4, + dataBlocks[2].getNumberOfSpectra()); + + TSM_ASSERT_EQUALS("The min of the fourth data block should be 16", 16, + dataBlocks[3].getMinSpectrumID()); + TSM_ASSERT_EQUALS("The max of the fourth data block should be 16", 16, + dataBlocks[3].getMaxSpectrumID()); + TSM_ASSERT_EQUALS("The number of spectra should be 1", 1, + dataBlocks[3].getNumberOfSpectra()); + + TSM_ASSERT_EQUALS("The min of the fifth data block should be 21", 21, + dataBlocks[4].getMinSpectrumID()); + TSM_ASSERT_EQUALS("The max of the fiffth data block should be 21", 21, + dataBlocks[4].getMaxSpectrumID()); + TSM_ASSERT_EQUALS("The number of spectra should be 1", 1, + dataBlocks[4].getNumberOfSpectra()); + + TSM_ASSERT_EQUALS("The min of the sixth data block should be 22", 22, + dataBlocks[5].getMinSpectrumID()); + TSM_ASSERT_EQUALS("The max of the sixth data block should be 22", 22, + dataBlocks[5].getMaxSpectrumID()); + TSM_ASSERT_EQUALS("The number of spectra should be 1", 1, + dataBlocks[5].getNumberOfSpectra()); + } + + void + test_that_removing_data_blocks_which_dont_overlap_leave_the_composite_unaffected() + { + // Arrange + std::vector<std::pair<int64_t, int64_t>> intervals + = {std::make_pair(2, 8), std::make_pair(10, 17), + std::make_pair(34, 39)}; + auto dataBlockComposite = getSampleDataBlockComposite(intervals); + + auto copiedDataBlockComposite(dataBlockComposite); + + std::vector<std::pair<int64_t, int64_t>> removeIntervals + = {std::make_pair(9, 9), std::make_pair(21, 27), + std::make_pair(100, 210)}; + auto dataBlockCompositeForRemoval + = getSampleDataBlockComposite(removeIntervals); + + // Act + dataBlockComposite.removeSpectra(dataBlockCompositeForRemoval); + + // Assert + auto original = copiedDataBlockComposite.getDataBlocks(); + auto newDataBlocks = dataBlockComposite.getDataBlocks(); + + TSM_ASSERT_EQUALS("SHould have the same number of data blocks", + original.size(), newDataBlocks.size()); + for (size_t index = 0; index < original.size(); ++index) { + TSM_ASSERT_EQUALS("Should have the same min spectrum", + original[index].getMinSpectrumID(), + newDataBlocks[index].getMinSpectrumID()); + + TSM_ASSERT_EQUALS("Should have the same max spectrum", + original[index].getMaxSpectrumID(), + newDataBlocks[index].getMaxSpectrumID()); + + TSM_ASSERT_EQUALS("Should have the same number of periods", + original[index].getNumberOfPeriods(), + newDataBlocks[index].getNumberOfPeriods()); + + TSM_ASSERT_EQUALS("Should have the same number of channels", + original[index].getNumberOfChannels(), + newDataBlocks[index].getNumberOfChannels()); + + TSM_ASSERT_EQUALS("Should have the same number of spectra", + original[index].getNumberOfSpectra(), + newDataBlocks[index].getNumberOfSpectra()); + } + } + + void test_that_exact_match_removes_everything() + { + // Arrange + std::vector<std::pair<int64_t, int64_t>> intervals + = {std::make_pair(2, 8), std::make_pair(10, 17), + std::make_pair(34, 39)}; + auto dataBlockComposite = getSampleDataBlockComposite(intervals); + + auto dataBlockCompositeForRemoval + = getSampleDataBlockComposite(intervals); + // Act + dataBlockComposite.removeSpectra(dataBlockCompositeForRemoval); + // Assert + auto newDataBlocks = dataBlockComposite.getDataBlocks(); + + // TSM_ASSERT("There should be no data blocks.", newDataBlocks.empty()); + } + + void test_that_left_hand_overlap_is_handled_correctly_scenario1() + { + // Arrange + // Scaneario: + // original: |------| + // removal: |------| + std::vector<std::pair<int64_t, int64_t>> intervals + = {std::make_pair(5, 10)}; + auto dataBlockComposite = getSampleDataBlockComposite(intervals); + std::vector<std::pair<int64_t, int64_t>> intervalsRemoval + = {std::make_pair(1, 7)}; + auto dataBlockCompositeRemoval + = getSampleDataBlockComposite(intervalsRemoval); + + // Act + dataBlockComposite.removeSpectra(dataBlockCompositeRemoval); + + // Assert + auto dataBlock = dataBlockComposite.getDataBlocks(); + TSM_ASSERT_EQUALS("Should have a single data block", 1, + dataBlock.size()); + TSM_ASSERT_EQUALS("Should have a min of 8", 8, + dataBlock[0].getMinSpectrumID()); + TSM_ASSERT_EQUALS("Should have a max of 10", 10, + dataBlock[0].getMaxSpectrumID()); + } + + void test_that_left_hand_overlap_is_handled_correctly_scenario2() + { + // Arrange + // Scaneario: + // original: |------| + // removal: |------| + std::vector<std::pair<int64_t, int64_t>> intervals + = {std::make_pair(5, 10)}; + auto dataBlockComposite = getSampleDataBlockComposite(intervals); + std::vector<std::pair<int64_t, int64_t>> intervalsRemoval + = {std::make_pair(1, 5)}; + auto dataBlockCompositeRemoval + = getSampleDataBlockComposite(intervalsRemoval); + + // Act + dataBlockComposite.removeSpectra(dataBlockCompositeRemoval); + + // Assert + auto dataBlock = dataBlockComposite.getDataBlocks(); + TSM_ASSERT_EQUALS("Should have a single data block", 1, + dataBlock.size()); + TSM_ASSERT_EQUALS("Should have a min of 6", 6, + dataBlock[0].getMinSpectrumID()); + TSM_ASSERT_EQUALS("Should have a max of 10", 10, + dataBlock[0].getMaxSpectrumID()); + } + + void test_that_right_hand_overlap_is_handled_correctly_scenario1() + { + // Arrange + // Scaneario: + // original: |------| + // removal: |------| + std::vector<std::pair<int64_t, int64_t>> intervals + = {std::make_pair(5, 10)}; + auto dataBlockComposite = getSampleDataBlockComposite(intervals); + std::vector<std::pair<int64_t, int64_t>> intervalsRemoval + = {std::make_pair(7, 12)}; + auto dataBlockCompositeRemoval + = getSampleDataBlockComposite(intervalsRemoval); + + // Act + dataBlockComposite.removeSpectra(dataBlockCompositeRemoval); + + // Assert + auto dataBlock = dataBlockComposite.getDataBlocks(); + TSM_ASSERT_EQUALS("Should have a single data block", 1, + dataBlock.size()); + TSM_ASSERT_EQUALS("Should have a min of 5", 5, + dataBlock[0].getMinSpectrumID()); + TSM_ASSERT_EQUALS("Should have a max of 6", 6, + dataBlock[0].getMaxSpectrumID()); + } + + void test_that_right_hand_overlap_is_handled_correctly_scenario2() + { + // Arrange + // Scaneario: + // original: |------| + // removal: |------| + std::vector<std::pair<int64_t, int64_t>> intervals + = {std::make_pair(5, 10)}; + auto dataBlockComposite = getSampleDataBlockComposite(intervals); + std::vector<std::pair<int64_t, int64_t>> intervalsRemoval + = {std::make_pair(10, 12)}; + auto dataBlockCompositeRemoval + = getSampleDataBlockComposite(intervalsRemoval); + + // Act + dataBlockComposite.removeSpectra(dataBlockCompositeRemoval); + + // Assert + auto dataBlock = dataBlockComposite.getDataBlocks(); + TSM_ASSERT_EQUALS("Should have a single data block", 1, + dataBlock.size()); + TSM_ASSERT_EQUALS("Should have a min of 5", 5, + dataBlock[0].getMinSpectrumID()); + TSM_ASSERT_EQUALS("Should have a max of 9", 9, + dataBlock[0].getMaxSpectrumID()); + } + + void test_that_fully_contained_overlap_is_handled_correctly_scenario1() + { + // Arrange + // Scaneario: + // original: |------| + // removal: |---| + std::vector<std::pair<int64_t, int64_t>> intervals + = {std::make_pair(5, 12)}; + auto dataBlockComposite = getSampleDataBlockComposite(intervals); + std::vector<std::pair<int64_t, int64_t>> intervalsRemoval + = {std::make_pair(7, 9)}; + auto dataBlockCompositeRemoval + = getSampleDataBlockComposite(intervalsRemoval); + + // Act + dataBlockComposite.removeSpectra(dataBlockCompositeRemoval); + + // Assert + auto dataBlock = dataBlockComposite.getDataBlocks(); + TSM_ASSERT_EQUALS("Should have two data block", 2, dataBlock.size()); + TSM_ASSERT_EQUALS("Should have a min of 5", 5, + dataBlock[0].getMinSpectrumID()); + TSM_ASSERT_EQUALS("Should have a max of 6", 6, + dataBlock[0].getMaxSpectrumID()); + TSM_ASSERT_EQUALS("Should have a min of 10", 10, + dataBlock[1].getMinSpectrumID()); + TSM_ASSERT_EQUALS("Should have a max of 12", 12, + dataBlock[1].getMaxSpectrumID()); + } + + void test_that_fully_contained_overlap_is_handled_correctly_scenario2() + { + // Arrange + // Scaneario: + // original: |------| + // removal: |---| + std::vector<std::pair<int64_t, int64_t>> intervals + = {std::make_pair(5, 12)}; + auto dataBlockComposite = getSampleDataBlockComposite(intervals); + std::vector<std::pair<int64_t, int64_t>> intervalsRemoval + = {std::make_pair(5, 9)}; + auto dataBlockCompositeRemoval + = getSampleDataBlockComposite(intervalsRemoval); + + // Act + dataBlockComposite.removeSpectra(dataBlockCompositeRemoval); + + // Assert + auto dataBlock = dataBlockComposite.getDataBlocks(); + TSM_ASSERT_EQUALS("Should have a single data block", 1, + dataBlock.size()); + TSM_ASSERT_EQUALS("Should have a min of 10", 10, + dataBlock[0].getMinSpectrumID()); + TSM_ASSERT_EQUALS("Should have a max of 12", 12, + dataBlock[0].getMaxSpectrumID()); + } + + void test_that_fully_contained_overlap_is_handled_correctly_scenario3() + { + // Arrange + // Scaneario: + // original: |------| + // removal: |----| + std::vector<std::pair<int64_t, int64_t>> intervals + = {std::make_pair(5, 12)}; + auto dataBlockComposite = getSampleDataBlockComposite(intervals); + std::vector<std::pair<int64_t, int64_t>> intervalsRemoval + = {std::make_pair(8, 12)}; + auto dataBlockCompositeRemoval + = getSampleDataBlockComposite(intervalsRemoval); + + // Act + dataBlockComposite.removeSpectra(dataBlockCompositeRemoval); + + // Assert + auto dataBlock = dataBlockComposite.getDataBlocks(); + TSM_ASSERT_EQUALS("Should have a single data block", 1, + dataBlock.size()); + TSM_ASSERT_EQUALS("Should have a min of 5", 5, + dataBlock[0].getMinSpectrumID()); + TSM_ASSERT_EQUALS("Should have a max of 7", 7, + dataBlock[0].getMaxSpectrumID()); + } + + void test_that_full_overlap_is_handled_correctly() + { + // Arrange + // Scaneario: + // original: |------| + // removal: |--------| + std::vector<std::pair<int64_t, int64_t>> intervals + = {std::make_pair(5, 12)}; + auto dataBlockComposite = getSampleDataBlockComposite(intervals); + std::vector<std::pair<int64_t, int64_t>> intervalsRemoval + = {std::make_pair(4, 14)}; + auto dataBlockCompositeRemoval + = getSampleDataBlockComposite(intervalsRemoval); + + // Act + dataBlockComposite.removeSpectra(dataBlockCompositeRemoval); + + // Assert + auto dataBlock = dataBlockComposite.getDataBlocks(); + TSM_ASSERT("Should have no data blocks", dataBlock.empty()); + } + + void + test_that_multipiece_overlap_for_single_original_intervals_is_handled_correctly() + { + // Arrange + // Scaneario: + // original: |------------------| + // removal: |-----| |--| |-| + std::vector<std::pair<int64_t, int64_t>> intervals + = {std::make_pair(5, 16)}; + auto dataBlockComposite = getSampleDataBlockComposite(intervals); + std::vector<std::pair<int64_t, int64_t>> intervalsRemoval + = {std::make_pair(4, 7), std::make_pair(9, 10), + std::make_pair(13, 13)}; + auto dataBlockCompositeRemoval + = getSampleDataBlockComposite(intervalsRemoval); + + // Act + dataBlockComposite.removeSpectra(dataBlockCompositeRemoval); + + // Assert + auto dataBlock = dataBlockComposite.getDataBlocks(); + TSM_ASSERT_EQUALS("Should have three data blocks", 3, dataBlock.size()); + TSM_ASSERT_EQUALS("The min of the first ata block should be 8", 8, + dataBlock[0].getMinSpectrumID()); + TSM_ASSERT_EQUALS("The max of the first data block should be 8", 8, + dataBlock[0].getMaxSpectrumID()); + TSM_ASSERT_EQUALS("The min of the second ata block should be 11", 11, + dataBlock[1].getMinSpectrumID()); + TSM_ASSERT_EQUALS("The max of the second data block should be 12", 12, + dataBlock[1].getMaxSpectrumID()); + TSM_ASSERT_EQUALS("The min of the third ata block should be 14", 14, + dataBlock[2].getMinSpectrumID()); + TSM_ASSERT_EQUALS("The max of the third data block should be 16", 16, + dataBlock[2].getMaxSpectrumID()); + } + + void + test_that_multipiece_overlap_for_mulitple_original_intervals_is_handled_correctly() + { + // Arrange + // Scaneario: + // original: |------------------| |-------| + // removal: |-----| |--| |-| |--| |--| + std::vector<std::pair<int64_t, int64_t>> intervals + = {std::make_pair(5, 16), std::make_pair(20, 26)}; + auto dataBlockComposite = getSampleDataBlockComposite(intervals); + std::vector<std::pair<int64_t, int64_t>> intervalsRemoval = { + std::make_pair(4, 7), std::make_pair(9, 10), std::make_pair(13, 13), + std::make_pair(21, 22), std::make_pair(25, 30)}; + auto dataBlockCompositeRemoval + = getSampleDataBlockComposite(intervalsRemoval); + + // Act + dataBlockComposite.removeSpectra(dataBlockCompositeRemoval); + + // Assert + auto dataBlock = dataBlockComposite.getDataBlocks(); + TSM_ASSERT_EQUALS("Should have three data blocks", 5, dataBlock.size()); + TSM_ASSERT_EQUALS("The min of the first ata block should be 8", 8, + dataBlock[0].getMinSpectrumID()); + TSM_ASSERT_EQUALS("The max of the first data block should be 8", 8, + dataBlock[0].getMaxSpectrumID()); + TSM_ASSERT_EQUALS("The min of the second ata block should be 11", 11, + dataBlock[1].getMinSpectrumID()); + TSM_ASSERT_EQUALS("The max of the second data block should be 12", 12, + dataBlock[1].getMaxSpectrumID()); + TSM_ASSERT_EQUALS("The min of the third ata block should be 14", 14, + dataBlock[2].getMinSpectrumID()); + TSM_ASSERT_EQUALS("The max of the third data block should be 16", 16, + dataBlock[2].getMaxSpectrumID()); + TSM_ASSERT_EQUALS("The min of the third ata block should be 20", 20, + dataBlock[3].getMinSpectrumID()); + TSM_ASSERT_EQUALS("The max of the third data block should be 20", 20, + dataBlock[3].getMaxSpectrumID()); + TSM_ASSERT_EQUALS("The min of the third ata block should be 23", 23, + dataBlock[4].getMinSpectrumID()); + TSM_ASSERT_EQUALS("The max of the third data block should be 24", 24, + dataBlock[4].getMaxSpectrumID()); + } + + void test_that_truncation_of_interval_handles_correctly_scenario1() + { + // Arrange + // Scenario: + // original |------| |------| + // truncation | | + // result |----| |----| + std::vector<std::pair<int64_t, int64_t>> intervals + = {std::make_pair(5, 16), std::make_pair(20, 26)}; + auto dataBlockComposite = getSampleDataBlockComposite(intervals); + int64_t min = 8; + int64_t max = 22; + + // Act + dataBlockComposite.truncate(min, max); + + // Assert + auto dataBlocks = dataBlockComposite.getDataBlocks(); + TSM_ASSERT_EQUALS("Should have one datablock", 2, dataBlocks.size()); + TSM_ASSERT_EQUALS("Should have a minimum of 8", 8, + dataBlocks[0].getMinSpectrumID()); + TSM_ASSERT_EQUALS("Should have a maximum of 16", 16, + dataBlocks[0].getMaxSpectrumID()); + TSM_ASSERT_EQUALS("Should have a minimum of 20", 20, + dataBlocks[1].getMinSpectrumID()); + TSM_ASSERT_EQUALS("Should have a maximum of 22", 22, + dataBlocks[1].getMaxSpectrumID()); + } + + void test_that_truncation_of_interval_handles_correctly_scenario2() + { + // Arrange + // Scenario: + // original |------| |------| + // truncation | | + // result |------| + std::vector<std::pair<int64_t, int64_t>> intervals + = {std::make_pair(5, 16), std::make_pair(20, 26)}; + auto dataBlockComposite = getSampleDataBlockComposite(intervals); + int64_t min = 5; + int64_t max = 18; + + // Act + dataBlockComposite.truncate(min, max); + + // Assert + auto dataBlocks = dataBlockComposite.getDataBlocks(); + TSM_ASSERT_EQUALS("Should have one datablock", 1, dataBlocks.size()); + TSM_ASSERT_EQUALS("Should have a minimum of 5", 5, + dataBlocks[0].getMinSpectrumID()); + TSM_ASSERT_EQUALS("Should have a maximum of 16", 16, + dataBlocks[0].getMaxSpectrumID()); + } + + void test_that_truncation_of_interval_handles_correctly_scenario3() + { + // Arrange + // Scenario: + // original |------| |------| + // truncation | | + // result |------| |------| + std::vector<std::pair<int64_t, int64_t>> intervals + = {std::make_pair(5, 16), std::make_pair(20, 26)}; + auto dataBlockComposite = getSampleDataBlockComposite(intervals); + int64_t min = 4; + int64_t max = 34; + auto dataBlockCompositeCopy = dataBlockComposite; + + // Act + dataBlockComposite.truncate(min, max); + + // Assert + TSM_ASSERT("Should be equal", + dataBlockComposite == dataBlockCompositeCopy); + } + + void test_that_data_block_composites_are_equal() + { + // Arrange + std::vector<std::pair<int64_t, int64_t>> intervals + = {std::make_pair(5, 16), std::make_pair(20, 26)}; + auto dataBlockComposite = getSampleDataBlockComposite(intervals); + + // Act + Assert + TSM_ASSERT("Should be equal", dataBlockComposite == dataBlockComposite); + } + + void test_that_data_block_composites_are_not_equal() + { + // Arrange + std::vector<std::pair<int64_t, int64_t>> intervals + = {std::make_pair(5, 16), std::make_pair(20, 26)}; + auto dataBlockComposite = getSampleDataBlockComposite(intervals); + std::vector<std::pair<int64_t, int64_t>> intervals2 + = {std::make_pair(5, 15), std::make_pair(20, 26)}; + auto dataBlockComposite2 = getSampleDataBlockComposite(intervals2); + + // Act + Assert + TSM_ASSERT("Should not be equal", + !(dataBlockComposite == dataBlockComposite2)); } - TSM_ASSERT_EQUALS("Should be equal", index, expected.size()); - } - - void test_that_getting_dataBlocks_returns_them_sorted() { - // Arrange - int64_t min1 = 2; - int64_t max1 = 8; - DataBlock dataBlock1; - dataBlock1.setMinSpectrumID(min1); - dataBlock1.setMaxSpectrumID(max1); - - int64_t min2 = 45; - int64_t max2 = 49; - DataBlock dataBlock2; - dataBlock2.setMinSpectrumID(min2); - dataBlock2.setMaxSpectrumID(max2); - - int64_t min3 = 23; - int64_t max3 = 27; - DataBlock dataBlock3; - dataBlock3.setMinSpectrumID(min3); - dataBlock3.setMaxSpectrumID(max3); - - DataBlockComposite dataBlockCompsite; - dataBlockCompsite.addDataBlock(dataBlock1); - dataBlockCompsite.addDataBlock(dataBlock2); - dataBlockCompsite.addDataBlock(dataBlock3); - - // Act - auto dataBlocks = dataBlockCompsite.getDataBlocks(); - - // Assert - TSM_ASSERT_EQUALS("There should be three data blocks", 3, - dataBlocks.size()); - TSM_ASSERT_EQUALS("The first min should be 2", min1, - dataBlocks[0].getMinSpectrumID()); - TSM_ASSERT_EQUALS("The first max should be 8", max1, - dataBlocks[0].getMaxSpectrumID()); - TSM_ASSERT_EQUALS("The second min should be 23", min3, - dataBlocks[1].getMinSpectrumID()); - TSM_ASSERT_EQUALS("The second max should be 27", max3, - dataBlocks[1].getMaxSpectrumID()); - TSM_ASSERT_EQUALS("The first min should be 45", min2, - dataBlocks[2].getMinSpectrumID()); - TSM_ASSERT_EQUALS("The first min should be 49", max2, - dataBlocks[2].getMaxSpectrumID()); - } - - void - test_that_add_number_of_spectra_is_returned_as_well_as_correct_min_and_max() { - // Arrange - int64_t min1 = 2; - int64_t max1 = 8; - DataBlock dataBlock1; - dataBlock1.setMinSpectrumID(min1); - dataBlock1.setMaxSpectrumID(max1); - - int64_t min2 = 45; - int64_t max2 = 49; - DataBlock dataBlock2; - dataBlock2.setMinSpectrumID(min2); - dataBlock2.setMaxSpectrumID(max2); - - int64_t min3 = 23; - int64_t max3 = 27; - DataBlock dataBlock3; - dataBlock3.setMinSpectrumID(min3); - dataBlock3.setMaxSpectrumID(max3); - - DataBlockComposite dataBlockCompsite; - dataBlockCompsite.addDataBlock(dataBlock1); - dataBlockCompsite.addDataBlock(dataBlock2); - dataBlockCompsite.addDataBlock(dataBlock3); - - // Act - auto numberOfSpectra = dataBlockCompsite.getNumberOfSpectra(); - auto min = dataBlockCompsite.getMinSpectrumID(); - auto max = dataBlockCompsite.getMaxSpectrumID(); - - // Assert - auto expectedNumberOfSpectra = dataBlock1.getNumberOfSpectra() + - dataBlock2.getNumberOfSpectra() + - dataBlock3.getNumberOfSpectra(); - TSM_ASSERT_EQUALS("The total number of spectra should be the sum of the " - "spectra of the sub datablocks", - expectedNumberOfSpectra, numberOfSpectra); - - TSM_ASSERT_EQUALS("The min should be the absolute min of 2", min1, min); - TSM_ASSERT_EQUALS("The max should be the aboslute max of 49", max2, max); - } - - void test_adding_composites_prouduces_correct_new_composite() { - // Arrange - int64_t min1 = 2; - int64_t max1 = 8; - DataBlock dataBlock1; - dataBlock1.setMinSpectrumID(min1); - dataBlock1.setMaxSpectrumID(max1); - - int64_t min2 = 45; - int64_t max2 = 49; - DataBlock dataBlock2; - dataBlock2.setMinSpectrumID(min2); - dataBlock2.setMaxSpectrumID(max2); - - int64_t min4 = 17; - int64_t max4 = 20; - DataBlock dataBlock4; - dataBlock4.setMinSpectrumID(min4); - dataBlock4.setMaxSpectrumID(max4); - - int64_t min3 = 23; - int64_t max3 = 27; - DataBlock dataBlock3; - dataBlock3.setMinSpectrumID(min3); - dataBlock3.setMaxSpectrumID(max3); - - DataBlockComposite dataBlockCompsite1; - dataBlockCompsite1.addDataBlock(dataBlock1); - dataBlockCompsite1.addDataBlock(dataBlock3); - - DataBlockComposite dataBlockCompsite2; - dataBlockCompsite2.addDataBlock(dataBlock2); - dataBlockCompsite2.addDataBlock(dataBlock4); - - // Act - auto dataBlockCompositeAdded = dataBlockCompsite1 + dataBlockCompsite2; - - // Assert - auto dataBlocks = dataBlockCompositeAdded.getDataBlocks(); - size_t expectedNumberOfDataBlocks = 4; - TSM_ASSERT_EQUALS("Should have 4 data blocks.", expectedNumberOfDataBlocks, - dataBlocks.size()); - - auto min = dataBlockCompositeAdded.getMinSpectrumID(); - TSM_ASSERT_EQUALS("Shouldd have a min value of 2", min1, min); - - auto max = dataBlockCompositeAdded.getMaxSpectrumID(); - TSM_ASSERT_EQUALS("Shouldd have a min value of 49", max2, max); - - auto numberOfSpectra = dataBlockCompositeAdded.getNumberOfSpectra(); - auto expectedNumberOfSpectra = - dataBlock1.getNumberOfSpectra() + dataBlock2.getNumberOfSpectra() + - dataBlock3.getNumberOfSpectra() + dataBlock4.getNumberOfSpectra(); - TSM_ASSERT_EQUALS("Should have full number of spectra", - expectedNumberOfSpectra, numberOfSpectra); - } - - void test_that_boost_array_can_be_loaded_into_composite() { - // Arrange - constexpr int64_t size = 11; - // Has intervals [1,1], [3,5], [8,11], [16, 16], [21,22] - boost::shared_array<int> indexArray( - new int[size]{1, 3, 4, 5, 8, 9, 10, 11, 16, 21, 22}); - DataBlockComposite composite; - int numberOfPeriods = 1; - size_t numberOfChannels = 100; - - // Act - Mantid::DataHandling::populateDataBlockCompositeWithContainer( - composite, indexArray, size, numberOfPeriods, numberOfChannels); - - // Assert - auto dataBlocks = composite.getDataBlocks(); - TSM_ASSERT_EQUALS("There should be 5 datablocks present", dataBlocks.size(), - 5); - - TSM_ASSERT_EQUALS("The min of the first data block should be 1", 1, - dataBlocks[0].getMinSpectrumID()); - TSM_ASSERT_EQUALS("The max of the first data block should be 1", 1, - dataBlocks[0].getMaxSpectrumID()); - TSM_ASSERT_EQUALS("The number of spectra should be 1", 1, - dataBlocks[0].getNumberOfSpectra()); - - TSM_ASSERT_EQUALS("The min of the second data block should be 3", 3, - dataBlocks[1].getMinSpectrumID()); - TSM_ASSERT_EQUALS("The max of the second data block should be 5", 5, - dataBlocks[1].getMaxSpectrumID()); - TSM_ASSERT_EQUALS("The number of spectra should be 3", 3, - dataBlocks[1].getNumberOfSpectra()); - - TSM_ASSERT_EQUALS("The min of the third data block should be 8", 8, - dataBlocks[2].getMinSpectrumID()); - TSM_ASSERT_EQUALS("The max of the third data block should be 11", 11, - dataBlocks[2].getMaxSpectrumID()); - TSM_ASSERT_EQUALS("The number of spectra should be 4", 4, - dataBlocks[2].getNumberOfSpectra()); - - TSM_ASSERT_EQUALS("The min of the fourth data block should be 16", 16, - dataBlocks[3].getMinSpectrumID()); - TSM_ASSERT_EQUALS("The max of the fourth data block should be 16", 16, - dataBlocks[3].getMaxSpectrumID()); - TSM_ASSERT_EQUALS("The number of spectra should be 1", 1, - dataBlocks[3].getNumberOfSpectra()); - - TSM_ASSERT_EQUALS("The min of the fifth data block should be 3", 21, - dataBlocks[4].getMinSpectrumID()); - TSM_ASSERT_EQUALS("The max of the fiffth data block should be 5", 22, - dataBlocks[4].getMaxSpectrumID()); - TSM_ASSERT_EQUALS("The number of spectra should be 2", 2, - dataBlocks[4].getNumberOfSpectra()); - } - - void - test_that_removing_data_blocks_which_dont_overlap_leave_the_composite_unaffected() { - // Arrange - std::vector<std::pair<int64_t, int64_t>> intervals = { - std::make_pair(2, 8), std::make_pair(10, 17), std::make_pair(34, 39)}; - auto dataBlockComposite = getSampleDataBlockComposite(intervals); - - auto copiedDataBlockComposite(dataBlockComposite); - - std::vector<std::pair<int64_t, int64_t>> removeIntervals = { - std::make_pair(9, 9), std::make_pair(21, 27), std::make_pair(100, 210)}; - auto dataBlockCompositeForRemoval = - getSampleDataBlockComposite(removeIntervals); - - // Act - dataBlockComposite.removeSpectra(dataBlockCompositeForRemoval); - - // Assert - auto original = copiedDataBlockComposite.getDataBlocks(); - auto newDataBlocks = dataBlockComposite.getDataBlocks(); - - TSM_ASSERT_EQUALS("SHould have the same number of data blocks", - original.size(), newDataBlocks.size()); - for (size_t index = 0; index < original.size(); ++index) { - TSM_ASSERT_EQUALS("Should have the same min spectrum", - original[index].getMinSpectrumID(), - newDataBlocks[index].getMinSpectrumID()); - - TSM_ASSERT_EQUALS("Should have the same max spectrum", - original[index].getMaxSpectrumID(), - newDataBlocks[index].getMaxSpectrumID()); - - TSM_ASSERT_EQUALS("Should have the same number of periods", - original[index].getNumberOfPeriods(), - newDataBlocks[index].getNumberOfPeriods()); - - TSM_ASSERT_EQUALS("Should have the same number of channels", - original[index].getNumberOfChannels(), - newDataBlocks[index].getNumberOfChannels()); - - TSM_ASSERT_EQUALS("Should have the same number of spectra", - original[index].getNumberOfSpectra(), - newDataBlocks[index].getNumberOfSpectra()); + void + test_that_data_block_composite_returns_collection_with_all_spectrum_numbers() + { + // Arrange + std::vector<std::pair<int64_t, int64_t>> intervals + = {std::make_pair(5, 16), std::make_pair(20, 26)}; + auto dataBlockComposite = getSampleDataBlockComposite(intervals); + + // Act + auto allSpectra = dataBlockComposite.getAllSpectrumNumbers(); + + // Assert + auto spectrumIsContained = [&allSpectra](int64_t spectrumNumber) { + return std::find(std::begin(allSpectra), std::end(allSpectra), + spectrumNumber) != std::end(allSpectra); + }; + + for (int64_t item = 2; item <= 4; ++item) { + TSM_ASSERT("Should not find the value.", + !spectrumIsContained(item)); + } + + for (int64_t item = 5; item <= 16; ++item) { + TSM_ASSERT("Should find the value.", spectrumIsContained(item)); + } + + for (int64_t item = 17; item <= 19; ++item) { + TSM_ASSERT("Should not find the value.", + !spectrumIsContained(item)); + } + + for (int64_t item = 20; item <= 26; ++item) { + TSM_ASSERT("Should find the value.", spectrumIsContained(item)); + } + + for (int64_t item = 27; item <= 30; ++item) { + TSM_ASSERT("Should not find the value.", + !spectrumIsContained(item)); + } } - } - - void test_that_exact_match_removes_everything() { - // Arrange - std::vector<std::pair<int64_t, int64_t>> intervals = { - std::make_pair(2, 8), std::make_pair(10, 17), std::make_pair(34, 39)}; - auto dataBlockComposite = getSampleDataBlockComposite(intervals); - - auto dataBlockCompositeForRemoval = getSampleDataBlockComposite(intervals); - // Act - dataBlockComposite.removeSpectra(dataBlockCompositeForRemoval); - // Assert - auto newDataBlocks = dataBlockComposite.getDataBlocks(); - - // TSM_ASSERT("There should be no data blocks.", newDataBlocks.empty()); - } - - void test_that_left_hand_overlap_is_handled_correctly_scenario1() { - // Arrange - // Scaneario: - // original: |------| - // removal: |------| - std::vector<std::pair<int64_t, int64_t>> intervals = { - std::make_pair(5, 10)}; - auto dataBlockComposite = getSampleDataBlockComposite(intervals); - std::vector<std::pair<int64_t, int64_t>> intervalsRemoval = { - std::make_pair(1, 7)}; - auto dataBlockCompositeRemoval = - getSampleDataBlockComposite(intervalsRemoval); - - // Act - dataBlockComposite.removeSpectra(dataBlockCompositeRemoval); - - // Assert - auto dataBlock = dataBlockComposite.getDataBlocks(); - TSM_ASSERT_EQUALS("Should have a single data block", 1, dataBlock.size()); - TSM_ASSERT_EQUALS("Should have a min of 8", 8, - dataBlock[0].getMinSpectrumID()); - TSM_ASSERT_EQUALS("Should have a max of 10", 10, - dataBlock[0].getMaxSpectrumID()); - } - - void test_that_left_hand_overlap_is_handled_correctly_scenario2() { - // Arrange - // Scaneario: - // original: |------| - // removal: |------| - std::vector<std::pair<int64_t, int64_t>> intervals = { - std::make_pair(5, 10)}; - auto dataBlockComposite = getSampleDataBlockComposite(intervals); - std::vector<std::pair<int64_t, int64_t>> intervalsRemoval = { - std::make_pair(1, 5)}; - auto dataBlockCompositeRemoval = - getSampleDataBlockComposite(intervalsRemoval); - - // Act - dataBlockComposite.removeSpectra(dataBlockCompositeRemoval); - - // Assert - auto dataBlock = dataBlockComposite.getDataBlocks(); - TSM_ASSERT_EQUALS("Should have a single data block", 1, dataBlock.size()); - TSM_ASSERT_EQUALS("Should have a min of 6", 6, - dataBlock[0].getMinSpectrumID()); - TSM_ASSERT_EQUALS("Should have a max of 10", 10, - dataBlock[0].getMaxSpectrumID()); - } - - void test_that_right_hand_overlap_is_handled_correctly_scenario1() { - // Arrange - // Scaneario: - // original: |------| - // removal: |------| - std::vector<std::pair<int64_t, int64_t>> intervals = { - std::make_pair(5, 10)}; - auto dataBlockComposite = getSampleDataBlockComposite(intervals); - std::vector<std::pair<int64_t, int64_t>> intervalsRemoval = { - std::make_pair(7, 12)}; - auto dataBlockCompositeRemoval = - getSampleDataBlockComposite(intervalsRemoval); - - // Act - dataBlockComposite.removeSpectra(dataBlockCompositeRemoval); - - // Assert - auto dataBlock = dataBlockComposite.getDataBlocks(); - TSM_ASSERT_EQUALS("Should have a single data block", 1, dataBlock.size()); - TSM_ASSERT_EQUALS("Should have a min of 5", 5, - dataBlock[0].getMinSpectrumID()); - TSM_ASSERT_EQUALS("Should have a max of 6", 6, - dataBlock[0].getMaxSpectrumID()); - } - - void test_that_right_hand_overlap_is_handled_correctly_scenario2() { - // Arrange - // Scaneario: - // original: |------| - // removal: |------| - std::vector<std::pair<int64_t, int64_t>> intervals = { - std::make_pair(5, 10)}; - auto dataBlockComposite = getSampleDataBlockComposite(intervals); - std::vector<std::pair<int64_t, int64_t>> intervalsRemoval = { - std::make_pair(10, 12)}; - auto dataBlockCompositeRemoval = - getSampleDataBlockComposite(intervalsRemoval); - - // Act - dataBlockComposite.removeSpectra(dataBlockCompositeRemoval); - - // Assert - auto dataBlock = dataBlockComposite.getDataBlocks(); - TSM_ASSERT_EQUALS("Should have a single data block", 1, dataBlock.size()); - TSM_ASSERT_EQUALS("Should have a min of 5", 5, - dataBlock[0].getMinSpectrumID()); - TSM_ASSERT_EQUALS("Should have a max of 9", 9, - dataBlock[0].getMaxSpectrumID()); - } - - void test_that_fully_contained_overlap_is_handled_correctly_scenario1() { - // Arrange - // Scaneario: - // original: |------| - // removal: |---| - std::vector<std::pair<int64_t, int64_t>> intervals = { - std::make_pair(5, 12)}; - auto dataBlockComposite = getSampleDataBlockComposite(intervals); - std::vector<std::pair<int64_t, int64_t>> intervalsRemoval = { - std::make_pair(7, 9)}; - auto dataBlockCompositeRemoval = - getSampleDataBlockComposite(intervalsRemoval); - - // Act - dataBlockComposite.removeSpectra(dataBlockCompositeRemoval); - - // Assert - auto dataBlock = dataBlockComposite.getDataBlocks(); - TSM_ASSERT_EQUALS("Should have two data block", 2, dataBlock.size()); - TSM_ASSERT_EQUALS("Should have a min of 5", 5, - dataBlock[0].getMinSpectrumID()); - TSM_ASSERT_EQUALS("Should have a max of 6", 6, - dataBlock[0].getMaxSpectrumID()); - TSM_ASSERT_EQUALS("Should have a min of 10", 10, - dataBlock[1].getMinSpectrumID()); - TSM_ASSERT_EQUALS("Should have a max of 12", 12, - dataBlock[1].getMaxSpectrumID()); - } - - void test_that_fully_contained_overlap_is_handled_correctly_scenario2() { - // Arrange - // Scaneario: - // original: |------| - // removal: |---| - std::vector<std::pair<int64_t, int64_t>> intervals = { - std::make_pair(5, 12)}; - auto dataBlockComposite = getSampleDataBlockComposite(intervals); - std::vector<std::pair<int64_t, int64_t>> intervalsRemoval = { - std::make_pair(5, 9)}; - auto dataBlockCompositeRemoval = - getSampleDataBlockComposite(intervalsRemoval); - - // Act - dataBlockComposite.removeSpectra(dataBlockCompositeRemoval); - - // Assert - auto dataBlock = dataBlockComposite.getDataBlocks(); - TSM_ASSERT_EQUALS("Should have a single data block", 1, dataBlock.size()); - TSM_ASSERT_EQUALS("Should have a min of 10", 10, - dataBlock[0].getMinSpectrumID()); - TSM_ASSERT_EQUALS("Should have a max of 12", 12, - dataBlock[0].getMaxSpectrumID()); - } - - void test_that_fully_contained_overlap_is_handled_correctly_scenario3() { - // Arrange - // Scaneario: - // original: |------| - // removal: |----| - std::vector<std::pair<int64_t, int64_t>> intervals = { - std::make_pair(5, 12)}; - auto dataBlockComposite = getSampleDataBlockComposite(intervals); - std::vector<std::pair<int64_t, int64_t>> intervalsRemoval = { - std::make_pair(8, 12)}; - auto dataBlockCompositeRemoval = - getSampleDataBlockComposite(intervalsRemoval); - - // Act - dataBlockComposite.removeSpectra(dataBlockCompositeRemoval); - - // Assert - auto dataBlock = dataBlockComposite.getDataBlocks(); - TSM_ASSERT_EQUALS("Should have a single data block", 1, dataBlock.size()); - TSM_ASSERT_EQUALS("Should have a min of 5", 5, - dataBlock[0].getMinSpectrumID()); - TSM_ASSERT_EQUALS("Should have a max of 7", 7, - dataBlock[0].getMaxSpectrumID()); - } - - void test_that_full_overlap_is_handled_correctly() { - // Arrange - // Scaneario: - // original: |------| - // removal: |--------| - std::vector<std::pair<int64_t, int64_t>> intervals = { - std::make_pair(5, 12)}; - auto dataBlockComposite = getSampleDataBlockComposite(intervals); - std::vector<std::pair<int64_t, int64_t>> intervalsRemoval = { - std::make_pair(4, 14)}; - auto dataBlockCompositeRemoval = - getSampleDataBlockComposite(intervalsRemoval); - - // Act - dataBlockComposite.removeSpectra(dataBlockCompositeRemoval); - - // Assert - auto dataBlock = dataBlockComposite.getDataBlocks(); - TSM_ASSERT("Should have no data blocks", dataBlock.empty()); - } - - void - test_that_multipiece_overlap_for_single_original_intervals_is_handled_correctly() { - // Arrange - // Scaneario: - // original: |------------------| - // removal: |-----| |--| |-| - std::vector<std::pair<int64_t, int64_t>> intervals = { - std::make_pair(5, 16)}; - auto dataBlockComposite = getSampleDataBlockComposite(intervals); - std::vector<std::pair<int64_t, int64_t>> intervalsRemoval = { - std::make_pair(4, 7), std::make_pair(9, 10), std::make_pair(13, 13)}; - auto dataBlockCompositeRemoval = - getSampleDataBlockComposite(intervalsRemoval); - - // Act - dataBlockComposite.removeSpectra(dataBlockCompositeRemoval); - - // Assert - auto dataBlock = dataBlockComposite.getDataBlocks(); - TSM_ASSERT_EQUALS("Should have three data blocks", 3, dataBlock.size()); - TSM_ASSERT_EQUALS("The min of the first ata block should be 8", 8, - dataBlock[0].getMinSpectrumID()); - TSM_ASSERT_EQUALS("The max of the first data block should be 8", 8, - dataBlock[0].getMaxSpectrumID()); - TSM_ASSERT_EQUALS("The min of the second ata block should be 11", 11, - dataBlock[1].getMinSpectrumID()); - TSM_ASSERT_EQUALS("The max of the second data block should be 12", 12, - dataBlock[1].getMaxSpectrumID()); - TSM_ASSERT_EQUALS("The min of the third ata block should be 14", 14, - dataBlock[2].getMinSpectrumID()); - TSM_ASSERT_EQUALS("The max of the third data block should be 16", 16, - dataBlock[2].getMaxSpectrumID()); - } - - void - test_that_multipiece_overlap_for_mulitple_original_intervals_is_handled_correctly() { - // Arrange - // Scaneario: - // original: |------------------| |-------| - // removal: |-----| |--| |-| |--| |--| - std::vector<std::pair<int64_t, int64_t>> intervals = { - std::make_pair(5, 16), std::make_pair(20, 26)}; - auto dataBlockComposite = getSampleDataBlockComposite(intervals); - std::vector<std::pair<int64_t, int64_t>> intervalsRemoval = { - std::make_pair(4, 7), std::make_pair(9, 10), std::make_pair(13, 13), - std::make_pair(21, 22), std::make_pair(25, 30)}; - auto dataBlockCompositeRemoval = - getSampleDataBlockComposite(intervalsRemoval); - - // Act - dataBlockComposite.removeSpectra(dataBlockCompositeRemoval); - - // Assert - auto dataBlock = dataBlockComposite.getDataBlocks(); - TSM_ASSERT_EQUALS("Should have three data blocks", 5, dataBlock.size()); - TSM_ASSERT_EQUALS("The min of the first ata block should be 8", 8, - dataBlock[0].getMinSpectrumID()); - TSM_ASSERT_EQUALS("The max of the first data block should be 8", 8, - dataBlock[0].getMaxSpectrumID()); - TSM_ASSERT_EQUALS("The min of the second ata block should be 11", 11, - dataBlock[1].getMinSpectrumID()); - TSM_ASSERT_EQUALS("The max of the second data block should be 12", 12, - dataBlock[1].getMaxSpectrumID()); - TSM_ASSERT_EQUALS("The min of the third ata block should be 14", 14, - dataBlock[2].getMinSpectrumID()); - TSM_ASSERT_EQUALS("The max of the third data block should be 16", 16, - dataBlock[2].getMaxSpectrumID()); - TSM_ASSERT_EQUALS("The min of the third ata block should be 20", 20, - dataBlock[3].getMinSpectrumID()); - TSM_ASSERT_EQUALS("The max of the third data block should be 20", 20, - dataBlock[3].getMaxSpectrumID()); - TSM_ASSERT_EQUALS("The min of the third ata block should be 23", 23, - dataBlock[4].getMinSpectrumID()); - TSM_ASSERT_EQUALS("The max of the third data block should be 24", 24, - dataBlock[4].getMaxSpectrumID()); - } - - void test_that_truncation_of_interval_handles_correctly_scenario1() { - // Arrange - // Scenario: - // original |------| |------| - // truncation | | - // result |----| |----| - std::vector<std::pair<int64_t, int64_t>> intervals = { - std::make_pair(5, 16), std::make_pair(20, 26)}; - auto dataBlockComposite = getSampleDataBlockComposite(intervals); - int64_t min = 8; - int64_t max = 22; - - // Act - dataBlockComposite.truncate(min, max); - - // Assert - auto dataBlocks = dataBlockComposite.getDataBlocks(); - TSM_ASSERT_EQUALS("Should have one datablock", 2, dataBlocks.size()); - TSM_ASSERT_EQUALS("Should have a minimum of 8", 8, - dataBlocks[0].getMinSpectrumID()); - TSM_ASSERT_EQUALS("Should have a maximum of 16", 16, - dataBlocks[0].getMaxSpectrumID()); - TSM_ASSERT_EQUALS("Should have a minimum of 20", 20, - dataBlocks[1].getMinSpectrumID()); - TSM_ASSERT_EQUALS("Should have a maximum of 22", 22, - dataBlocks[1].getMaxSpectrumID()); - } - - void test_that_truncation_of_interval_handles_correctly_scenario2() { - // Arrange - // Scenario: - // original |------| |------| - // truncation | | - // result |------| - std::vector<std::pair<int64_t, int64_t>> intervals = { - std::make_pair(5, 16), std::make_pair(20, 26)}; - auto dataBlockComposite = getSampleDataBlockComposite(intervals); - int64_t min = 5; - int64_t max = 18; - - // Act - dataBlockComposite.truncate(min, max); - - // Assert - auto dataBlocks = dataBlockComposite.getDataBlocks(); - TSM_ASSERT_EQUALS("Should have one datablock", 1, dataBlocks.size()); - TSM_ASSERT_EQUALS("Should have a minimum of 5", 5, - dataBlocks[0].getMinSpectrumID()); - TSM_ASSERT_EQUALS("Should have a maximum of 16", 16, - dataBlocks[0].getMaxSpectrumID()); - } - - void test_that_truncation_of_interval_handles_correctly_scenario3() { - // Arrange - // Scenario: - // original |------| |------| - // truncation | | - // result |------| |------| - std::vector<std::pair<int64_t, int64_t>> intervals = { - std::make_pair(5, 16), std::make_pair(20, 26)}; - auto dataBlockComposite = getSampleDataBlockComposite(intervals); - int64_t min = 4; - int64_t max = 34; - auto dataBlockCompositeCopy = dataBlockComposite; - - // Act - dataBlockComposite.truncate(min, max); - - // Assert - TSM_ASSERT("Should be equal", dataBlockComposite == dataBlockCompositeCopy); - } - - void test_that_data_block_composites_are_equal() { - // Arrange - std::vector<std::pair<int64_t, int64_t>> intervals = { - std::make_pair(5, 16), std::make_pair(20, 26)}; - auto dataBlockComposite = getSampleDataBlockComposite(intervals); - - // Act + Assert - TSM_ASSERT("Should be equal", dataBlockComposite == dataBlockComposite); - } - - void test_that_data_block_composites_are_not_equal() { - // Arrange - std::vector<std::pair<int64_t, int64_t>> intervals = { - std::make_pair(5, 16), std::make_pair(20, 26)}; - auto dataBlockComposite = getSampleDataBlockComposite(intervals); - std::vector<std::pair<int64_t, int64_t>> intervals2 = { - std::make_pair(5, 15), std::make_pair(20, 26)}; - auto dataBlockComposite2 = getSampleDataBlockComposite(intervals2); - - // Act + Assert - TSM_ASSERT("Should not be equal", - !(dataBlockComposite == dataBlockComposite2)); - } private: - DataBlockComposite getSampleDataBlockComposite( - const std::vector<std::pair<int64_t, int64_t>> &intervals) { - DataBlockComposite composite; - for (const auto &interval : intervals) { - DataBlock dataBlock(1, (interval.second - interval.first + 1), 120); - dataBlock.setMinSpectrumID(interval.first); - dataBlock.setMaxSpectrumID(interval.second); - composite.addDataBlock(dataBlock); + DataBlockComposite getSampleDataBlockComposite( + const std::vector<std::pair<int64_t, int64_t>> &intervals) + { + DataBlockComposite composite; + for (const auto &interval : intervals) { + DataBlock dataBlock(1, (interval.second - interval.first + 1), 120); + dataBlock.setMinSpectrumID(interval.first); + dataBlock.setMaxSpectrumID(interval.second); + composite.addDataBlock(dataBlock); + } + return composite; } - return composite; - } }; #endif /* MANTID_DATAHANDLING_DATABLOCKCOMPOSITETEST_H_ */ diff --git a/Framework/DataHandling/test/LoadISISNexusTest.h b/Framework/DataHandling/test/LoadISISNexusTest.h index 1fde063af14..ed21772915f 100644 --- a/Framework/DataHandling/test/LoadISISNexusTest.h +++ b/Framework/DataHandling/test/LoadISISNexusTest.h @@ -1071,6 +1071,14 @@ public: detIDtoWSIndexMap.count(detID) == 0); } + double delta = 1e-6; + // Make sure that the monitor data is correct (should be workspace index 26) + TS_ASSERT_DELTA(ws->readY(26)[0], 0.0, delta); + TS_ASSERT_DELTA(ws->readY(26)[1], 176660.0, delta); + TS_ASSERT_DELTA(ws->readY(26)[2], 57659.0, delta); + TS_ASSERT_DELTA(ws->readY(26)[17034], 4851.0, delta); + TS_ASSERT_DELTA(ws->readY(26)[17035], 4513.0, delta); + // Clean up AnalysisDataService::Instance().remove("outWS"); } -- GitLab