19const specnum_t INVALIDINTERVALVALUE = std::numeric_limits<specnum_t>::min();
30std::vector<SpectrumPair>
31getRemovalIntervalsRelevantForTheCurrentOriginalInterval(
const SpectrumPair &original,
32 const std::vector<SpectrumPair> &removeIntervals) {
35 return ((original.first <= toRemove.first) && (toRemove.first <= original.second)) ||
36 ((original.first <= toRemove.second) && (toRemove.second <= original.second)) ||
37 ((toRemove.first <= original.first) && (original.first <= toRemove.second));
40 std::vector<SpectrumPair> overlaps;
41 for (
auto &removeInterval : removeIntervals) {
42 if (hasOverlap(original, removeInterval)) {
43 overlaps.emplace_back(removeInterval);
57void handleLeftHandSideOverlap(SpectrumPair &original,
const SpectrumPair &toRemove) {
58 original.first = toRemove.second + 1;
69SpectrumPair handleRightHandSideOverlap(SpectrumPair &original,
const SpectrumPair &toRemove) {
70 auto newInterval = std::make_pair(original.first, toRemove.first - 1);
71 original.first = INVALIDINTERVALVALUE;
72 original.second = INVALIDINTERVALVALUE;
84SpectrumPair handleFullyContained(SpectrumPair &original,
const SpectrumPair &toRemove) {
86 auto newPair = std::make_pair(original.first, toRemove.first - 1);
87 original.first = toRemove.second + 1;
91std::vector<SpectrumPair> getSlicedIntervals(SpectrumPair original,
const std::vector<SpectrumPair> &removeIntervals) {
93 if (removeIntervals.empty()) {
94 return std::vector<SpectrumPair>{original};
112 return (toRemove.first <= original.first) && (original.first <= toRemove.second) &&
113 (toRemove.first <= original.second) && (original.second <= toRemove.second);
117 return (toRemove.first <= original.first) && (original.first <= toRemove.second) &&
118 (toRemove.second < original.second);
122 return (original.first < toRemove.first) && (toRemove.first <= original.second) &&
123 (original.second <= toRemove.second);
127 return (original.first < toRemove.first) && (toRemove.first < original.second) &&
128 (original.first < toRemove.second) && (toRemove.second < original.second);
133 std::vector<SpectrumPair> newIntervals;
134 for (
auto &removeInterval : removeIntervals) {
136 if (isFullOverlap(original, removeInterval)) {
141 assert(newIntervals.empty() &&
"DataBlockComposite: The "
142 "newIntervals container should be "
147 original.first = INVALIDINTERVALVALUE;
148 original.second = INVALIDINTERVALVALUE;
150 }
else if (isRightHandSideOverlap(original, removeInterval)) {
151 auto newInterval = handleRightHandSideOverlap(original, removeInterval);
152 newIntervals.emplace_back(newInterval);
153 }
else if (isLeftHandSideOverlap(original, removeInterval)) {
154 handleLeftHandSideOverlap(original, removeInterval);
155 }
else if (isFullyContained(original, removeInterval)) {
156 auto newInterval = handleFullyContained(original, removeInterval);
157 newIntervals.emplace_back(newInterval);
159 throw std::runtime_error(
"DataBlockComposite: The intervals don't seem to overlap.");
167 if ((original.first != INVALIDINTERVALVALUE) && (original.second != INVALIDINTERVALVALUE)) {
168 newIntervals.emplace_back(original);
177template <
typename T>
void sortDataBlocks(T &dataBlcokCollection) {
183 std::sort(std::begin(dataBlcokCollection), std::end(dataBlcokCollection), comparison);
186std::vector<SpectrumPair> spectrumIDIntervals(
const std::vector<Mantid::DataHandling::DataBlock> &blocks) {
187 std::vector<SpectrumPair> intervals;
188 intervals.reserve(blocks.size());
190 std::transform(blocks.begin(), blocks.end(), std::back_inserter(intervals),
191 [](
const auto &block) { return std::make_pair(block.getMinSpectrumID(), block.getMaxSpectrumID()); });
199 specnum_t min = std::numeric_limits<specnum_t>::max();
201 auto temp = child.getMinSpectrumID();
214 specnum_t max = std::numeric_limits<specnum_t>::min();
216 auto temp = child.getMaxSpectrumID();
229 const auto intervals = spectrumIDIntervals(
m_dataBlocks);
230 return std::make_unique<DataBlockGenerator>(intervals);
245 [](
size_t sum,
const auto &element) { return sum + element.getNumberOfSpectra(); });
260 std::end(other.m_dataBlocks));
276 auto isNotCompletelyCutOffFromMin = [&specMin](
const DataBlock &block) {
277 return (specMin <= block.getMinSpectrumID()) || (specMin <= block.getMaxSpectrumID());
284 auto isNotCompletelyCutOffFromMax = [&specMax](
const DataBlock &block) {
285 return (block.getMinSpectrumID() <= specMax) || (block.getMaxSpectrumID() <= specMax);
291 auto lastDataBlockReverseIterator =
298 auto isFirstDataBlockAtEnd = firstDataBlock ==
m_dataBlocks.end();
299 auto isLastDataBlockReverseIteratorAtREnd = lastDataBlockReverseIterator ==
m_dataBlocks.rend();
301 if (isFirstDataBlockAtEnd || isLastDataBlockReverseIteratorAtREnd) {
302 std::vector<DataBlock> newDataBlocks;
308 auto isEmptyInterval = firstDataBlock->getMinSpectrumID() > lastDataBlockReverseIterator->getMaxSpectrumID();
310 if (isEmptyInterval) {
311 std::vector<DataBlock> newDataBlocks;
321 std::vector<DataBlock> newDataBlocks(firstDataBlock, lastDataBlock);
326 auto numberOfSpectra = newDataBlocks[0].getMaxSpectrumID() - specMin + 1;
330 newDataBlocks[0] = block;
333 auto lastIndex = newDataBlocks.size() - 1;
335 auto numberOfSpectra = specMax - newDataBlocks[lastIndex].
getMaxSpectrumID() + 1;
340 newDataBlocks[lastIndex] = block;
354 auto otherDataBlocks = other.m_dataBlocks;
356 sortDataBlocks(otherDataBlocks);
357 sortDataBlocks(thisDataBlocks);
360 auto itOther = otherDataBlocks.cbegin();
361 auto itThis = thisDataBlocks.cbegin();
362 for (; itOther != otherDataBlocks.cend(); ++itOther, ++itThis) {
363 isEqual = isEqual && *itOther == *itThis;
378 const auto originalIntervals = spectrumIDIntervals(
m_dataBlocks);
382 const auto toRemoveIntervals = spectrumIDIntervals(removeBlocks);
386 std::vector<SpectrumPair> newIntervals;
387 for (
const auto &originalInterval : originalIntervals) {
390 auto currentRemovalIntervals =
391 getRemovalIntervalsRelevantForTheCurrentOriginalInterval(originalInterval, toRemoveIntervals);
392 auto slicedIntervals = getSlicedIntervals(originalInterval, currentRemovalIntervals);
393 newIntervals.insert(std::end(newIntervals), std::begin(slicedIntervals), std::end(slicedIntervals));
397 auto numberOfPeriods =
m_dataBlocks[0].getNumberOfPeriods();
398 auto numberOfChannels =
m_dataBlocks[0].getNumberOfChannels();
401 for (
const auto &newInterval : newIntervals) {
402 DataBlock dataBlock(numberOfPeriods, newInterval.second - newInterval.first + 1, numberOfChannels);
415 std::vector<specnum_t> allSpectra;
417 for (; !generator->isDone(); generator->next()) {
418 allSpectra.emplace_back(generator->getValue());
DataBlockComposite: The DataBlockComposite handles a collection of DataBlocks.
bool operator==(const DataBlockComposite &other) const
void setMinSpectrumID(specnum_t) override
specnum_t getMinSpectrumID() const override
DataBlockComposite operator+(const DataBlockComposite &other)
void truncate(specnum_t specMin, specnum_t specMax)
std::vector< DataBlock > m_dataBlocks
std::vector< specnum_t > getAllSpectrumNumbers()
Provides a container with all spectrum numbers.
size_t getNumberOfSpectra() const override
void setMaxSpectrumID(specnum_t) override
std::unique_ptr< DataBlockGenerator > getGenerator() const override
size_t getNumberOfChannels() const override
size_t getNumberOfPeriods() const override
std::vector< DataBlock > getDataBlocks()
specnum_t getMaxSpectrumID() const override
void addDataBlock(const DataBlock &dataBlock)
void removeSpectra(DataBlockComposite &toRemove)
Removes the input data blocks from the current list of data blocks.
DataBlock: The DataBlock class holds information about a contiguous block of spectrum numbers.
virtual specnum_t getMaxSpectrumID() const
virtual size_t getNumberOfChannels() const
size_t m_numberOfChannels
virtual void setMaxSpectrumID(specnum_t minSpecID)
virtual size_t getNumberOfSpectra() const
virtual size_t getNumberOfPeriods() const
virtual specnum_t getMinSpectrumID() const
virtual void setMinSpectrumID(specnum_t minSpecID)
std::pair< specnum_t, specnum_t > SpectrumPair
int32_t specnum_t
Typedef for a spectrum Number.