Skip to content

Commit 16e1b1a

Browse files
committed
Fixed issue with PatchGenerator blocking when no patches are generated. It now throws an exception instead.
1 parent 1a27a35 commit 16e1b1a

File tree

4 files changed

+56
-12
lines changed

4 files changed

+56
-12
lines changed

source/FAST/Algorithms/ImagePatch/PatchGenerator.cpp

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -307,14 +307,23 @@ void PatchGenerator::generateStream() {
307307
throw Exception("Unsupported data object given to PatchGenerator");
308308
}
309309
// Add final patch, and mark it has last frame
310-
previousPatch->setLastFrame(getNameOfClass());
311-
previousPatch->setFrameData("streaming", "yes"); // Since we are not propagating frame data, we have to set this
312-
try {
313-
addOutputData(0, previousPatch, false, false);
314-
} catch(ThreadStopped &e) {
310+
if(!previousPatch) {
311+
// No patches have been created
312+
reportInfo() << "No patches were generated." << reportEnd();
313+
frameAdded(); // Unlock blocking execute()
314+
for(const auto& channel : mOutputConnections[0]) {
315+
channel.lock()->stop("No patches were created by the PatchGenerator");
316+
}
317+
} else {
318+
previousPatch->setLastFrame(getNameOfClass());
319+
previousPatch->setFrameData("streaming", "yes"); // Since we are not propagating frame data, we have to set this
320+
try {
321+
addOutputData(0, previousPatch, false, false);
322+
} catch(ThreadStopped &e) {
315323

324+
}
325+
reportInfo() << "Done generating patches" << reportEnd();
316326
}
317-
reportInfo() << "Done generating patches" << reportEnd();
318327
} catch(std::exception &e) {
319328
// Exception happened in thread. Stop pipeline, and propagate error message.
320329
for(auto item : mOutputConnections) {

source/FAST/Algorithms/ImagePatch/Tests.cpp

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,29 @@ TEST_CASE("Patch generator on 2D image", "[fast][PatchGenerator]") {
5959
REQUIRE(nrOfPatches == counter);
6060
}
6161

62+
63+
TEST_CASE("Patch generator with no patches", "[fast][PatchGenerator]") {
64+
auto importer = WholeSlideImageImporter::create(Config::getTestDataPath() + "/WSI/CMU-1.svs");
65+
auto wsi = importer->runAndGetOutputData<ImagePyramid>();
66+
67+
auto segmentation = TissueSegmentation::create(true)->connect(wsi)->runAndGetOutputData<Image>();
68+
segmentation->fill(0); // Empty segmentation will mean no patches
69+
const int width = 256;
70+
const int height = 256;
71+
auto generator = PatchGenerator::create(width, height, 1, 2)
72+
->connect(importer)
73+
->connect(1, segmentation);
74+
auto stream = DataStream(generator);
75+
int counter = 0;
76+
CHECK_THROWS(
77+
while(!stream.isDone()) {
78+
auto image = stream.getNextFrame<Image>();
79+
++counter;
80+
}
81+
);
82+
REQUIRE(counter == 0);
83+
}
84+
6285
TEST_CASE("Patch generator on 3D image", "[fast][PatchGenerator]") {
6386
auto importer = ImageFileImporter::create(Config::getTestDataPath() + "/CT/CT-Thorax.mhd");
6487
auto image = importer->runAndGetOutputData<Image>();

source/FAST/Exception.hpp

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
1-
#ifndef EXCEPTIONS_HPP_
2-
#define EXCEPTIONS_HPP_
1+
#pragma once
32

43
#include "FASTExport.hpp"
54
#include <exception>
@@ -129,7 +128,4 @@ class FAST_EXPORT ThreadStopped : public Exception {
129128
bool m_error = false; // Whether thread was stopped due to an error or not.
130129
};
131130

132-
} // end namespace fast
133-
134-
135-
#endif /* EXCEPTIONS_HPP_ */
131+
} // end namespace fast

source/FAST/Python/Tests/test_data_stream_object.py

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,21 @@
22
import numpy as np
33
import pytest
44

5+
6+
def test_data_stream_empty():
7+
importer = fast.WholeSlideImageImporter.create(fast.Config.getTestDataPath() + '/WSI/CMU-1.svs')
8+
9+
segmentation = fast.TissueSegmentation.create(False).connect(importer).runAndGetOutputData()
10+
segmentation.fill(0) # Empty segmentation, means no patches
11+
generator = fast.PatchGenerator.create(256, 256, level=2).connect(importer).connect(1, segmentation)
12+
13+
counter = 0
14+
with pytest.raises(RuntimeError):
15+
for image in fast.DataStream(generator):
16+
counter += 1
17+
assert(counter == 0)
18+
19+
520
def test_data_stream_single():
621
streamer = fast.ImageFileStreamer\
722
.create(fast.Config.getTestDataPath() + "/US/Heart/ApicalFourChamber/US-2D_#.mhd")
@@ -17,6 +32,7 @@ def test_data_stream_single():
1732
counter += 1
1833
assert counter == 100
1934

35+
2036
def test_data_stream_multiple():
2137
streamer1 = fast.ImageFileStreamer \
2238
.create(fast.Config.getTestDataPath() + "/US/Heart/ApicalFourChamber/US-2D_#.mhd")

0 commit comments

Comments
 (0)