15const specnum_t INVALIDINTERVALVALUE = std::numeric_limits<specnum_t>::min();
26std::vector<SpectrumPair>
27getRemovalIntervalsRelevantForTheCurrentOriginalInterval(
const SpectrumPair &original,
28 const std::vector<SpectrumPair> &removeIntervals) {
31 return ((original.first <= toRemove.first) && (toRemove.first <= original.second)) ||
32 ((original.first <= toRemove.second) && (toRemove.second <= original.second)) ||
33 ((toRemove.first <= original.first) && (original.first <= toRemove.second));
36 std::vector<SpectrumPair> overlaps;
37 for (
auto &removeInterval : removeIntervals) {
38 if (hasOverlap(original, removeInterval)) {
39 overlaps.emplace_back(removeInterval);
53void handleLeftHandSideOverlap(SpectrumPair &original,
const SpectrumPair &toRemove) {
54 original.first = toRemove.second + 1;
65SpectrumPair handleRightHandSideOverlap(SpectrumPair &original,
const SpectrumPair &toRemove) {
66 auto newInterval = std::make_pair(original.first, toRemove.first - 1);
67 original.first = INVALIDINTERVALVALUE;
68 original.second = INVALIDINTERVALVALUE;
80SpectrumPair handleFullyContained(SpectrumPair &original,
const SpectrumPair &toRemove) {
82 auto newPair = std::make_pair(original.first, toRemove.first - 1);
83 original.first = toRemove.second + 1;
87std::vector<SpectrumPair> getSlicedIntervals(SpectrumPair original,
const std::vector<SpectrumPair> &removeIntervals) {
89 if (removeIntervals.empty()) {
90 return std::vector<SpectrumPair>{original};
108 return (toRemove.first <= original.first) && (original.first <= toRemove.second) &&
109 (toRemove.first <= original.second) && (original.second <= toRemove.second);
113 return (toRemove.first <= original.first) && (original.first <= toRemove.second) &&
114 (toRemove.second < original.second);
118 return (original.first < toRemove.first) && (toRemove.first <= original.second) &&
119 (original.second <= toRemove.second);
123 return (original.first < toRemove.first) && (toRemove.first < original.second) &&
124 (original.first < toRemove.second) && (toRemove.second < original.second);
129 std::vector<SpectrumPair> newIntervals;
130 for (
auto &removeInterval : removeIntervals) {
132 if (isFullOverlap(original, removeInterval)) {
137 assert(newIntervals.empty() &&
"DataBlockComposite: The "
138 "newIntervals container should be "
143 original.first = INVALIDINTERVALVALUE;
144 original.second = INVALIDINTERVALVALUE;
146 }
else if (isRightHandSideOverlap(original, removeInterval)) {
147 auto newInterval = handleRightHandSideOverlap(original, removeInterval);
148 newIntervals.emplace_back(newInterval);
149 }
else if (isLeftHandSideOverlap(original, removeInterval)) {
150 handleLeftHandSideOverlap(original, removeInterval);
151 }
else if (isFullyContained(original, removeInterval)) {
152 auto newInterval = handleFullyContained(original, removeInterval);
153 newIntervals.emplace_back(newInterval);
155 throw std::runtime_error(
"DataBlockComposite: The intervals don't seem to overlap.");
163 if ((original.first != INVALIDINTERVALVALUE) && (original.second != INVALIDINTERVALVALUE)) {
164 newIntervals.emplace_back(original);
173template <
typename T>
void sortDataBlocks(T &dataBlcokCollection) {
179 std::sort(std::begin(dataBlcokCollection), std::end(dataBlcokCollection), comparison);
182std::vector<SpectrumPair> spectrumIDIntervals(
const std::vector<Mantid::DataHandling::DataBlock> &blocks) {
183 std::vector<SpectrumPair> intervals;
184 intervals.reserve(blocks.size());
186 std::transform(blocks.begin(), blocks.end(), std::back_inserter(intervals),
187 [](
const auto &block) { return std::make_pair(block.getMinSpectrumID(), block.getMaxSpectrumID()); });
195 specnum_t min = std::numeric_limits<specnum_t>::max();
197 auto temp = child.getMinSpectrumID();
210 specnum_t max = std::numeric_limits<specnum_t>::min();
212 auto temp = child.getMaxSpectrumID();
225 const auto intervals = spectrumIDIntervals(
m_dataBlocks);
226 return std::make_unique<DataBlockGenerator>(intervals);
241 [](
size_t sum,
const auto &element) { return sum + element.getNumberOfSpectra(); });
256 std::end(other.m_dataBlocks));
272 auto isNotCompletelyCutOffFromMin = [&specMin](
const DataBlock &block) {
273 return (specMin <= block.getMinSpectrumID()) || (specMin <= block.getMaxSpectrumID());
280 auto isNotCompletelyCutOffFromMax = [&specMax](
const DataBlock &block) {
281 return (block.getMinSpectrumID() <= specMax) || (block.getMaxSpectrumID() <= specMax);
287 auto lastDataBlockReverseIterator =
294 auto isFirstDataBlockAtEnd = firstDataBlock ==
m_dataBlocks.end();
295 auto isLastDataBlockReverseIteratorAtREnd = lastDataBlockReverseIterator ==
m_dataBlocks.rend();
297 if (isFirstDataBlockAtEnd || isLastDataBlockReverseIteratorAtREnd) {
298 std::vector<DataBlock> newDataBlocks;
304 auto isEmptyInterval = firstDataBlock->getMinSpectrumID() > lastDataBlockReverseIterator->getMaxSpectrumID();
306 if (isEmptyInterval) {
307 std::vector<DataBlock> newDataBlocks;
317 std::vector<DataBlock> newDataBlocks(firstDataBlock, lastDataBlock);
322 auto numberOfSpectra = newDataBlocks[0].getMaxSpectrumID() - specMin + 1;
326 newDataBlocks[0] = block;
329 auto lastIndex = newDataBlocks.size() - 1;
331 auto numberOfSpectra = specMax - newDataBlocks[lastIndex].
getMaxSpectrumID() + 1;
336 newDataBlocks[lastIndex] = block;
350 auto otherDataBlocks = other.m_dataBlocks;
352 sortDataBlocks(otherDataBlocks);
353 sortDataBlocks(thisDataBlocks);
356 auto itOther = otherDataBlocks.cbegin();
357 auto itThis = thisDataBlocks.cbegin();
358 for (; itOther != otherDataBlocks.cend(); ++itOther, ++itThis) {
359 isEqual = isEqual && *itOther == *itThis;
374 const auto originalIntervals = spectrumIDIntervals(
m_dataBlocks);
378 const auto toRemoveIntervals = spectrumIDIntervals(removeBlocks);
382 std::vector<SpectrumPair> newIntervals;
383 for (
auto &originalInterval : originalIntervals) {
386 auto currentRemovalIntervals =
387 getRemovalIntervalsRelevantForTheCurrentOriginalInterval(originalInterval, toRemoveIntervals);
388 auto slicedIntervals = getSlicedIntervals(originalInterval, currentRemovalIntervals);
389 newIntervals.insert(std::end(newIntervals), std::begin(slicedIntervals), std::end(slicedIntervals));
393 auto numberOfPeriods =
m_dataBlocks[0].getNumberOfPeriods();
394 auto numberOfChannels =
m_dataBlocks[0].getNumberOfChannels();
397 for (
const auto &newInterval : newIntervals) {
398 DataBlock dataBlock(numberOfPeriods, newInterval.second - newInterval.first + 1, numberOfChannels);
411 std::vector<specnum_t> allSpectra;
413 for (; !generator->isDone(); generator->next()) {
414 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
int getNumberOfPeriods() const override
void setMaxSpectrumID(specnum_t) override
std::unique_ptr< DataBlockGenerator > getGenerator() const override
size_t getNumberOfChannels() 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 int getNumberOfPeriods() const
virtual size_t getNumberOfSpectra() 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.