Skip to content

Commit

Permalink
Merge pull request #43 from JacobBumgarner/feat/binary_warning
Browse files Browse the repository at this point in the history
Non-binary image spot check.
  • Loading branch information
JacobBumgarner authored May 30, 2022
2 parents 6e052d5 + 0224260 commit aed933b
Show file tree
Hide file tree
Showing 5 changed files with 108 additions and 15 deletions.
8 changes: 6 additions & 2 deletions VVTerminal.py
Original file line number Diff line number Diff line change
Expand Up @@ -158,10 +158,14 @@ def process_volume(
# region
volume, image_shape = ImProc.load_volume(volume_file, verbose=verbose)

if not ImProc.volume_check(volume, loading=True, verbose=verbose):
if volume is None: # make sure the image was loaded.
if verbose:
print("Error loading volume.")
break
elif not ImProc.binary_check(volume):
if verbose:
print("Error: Non-binary image loaded.")
break

# If there as an ROI, segment the ROI from the volume.
if roi_name:
Expand Down Expand Up @@ -194,7 +198,7 @@ def process_volume(
)

# Make sure the ROI is in the volume.
if not roi_volume or not ImProc.volume_check(volume, verbose=verbose):
if not roi_volume or not ImProc.segmentation_check(volume):
ResExp.cache_result(
[filename, roi_name, "ROI not in dataset."]
) # Cache results
Expand Down
42 changes: 36 additions & 6 deletions library/image_processing.py
Original file line number Diff line number Diff line change
Expand Up @@ -80,15 +80,45 @@ def reshape_2D(points, volume, verbose=False):
return points, volume, image_shape


# Confirm that the volume was either loaded or segmented properly
def volume_check(volume, loading=False, verbose=False):
def binary_check(volume: np.ndarray) -> bool:
"""Return a bool indicating if the loaded volume is binary or not.
Takes a slice from the volume and checks to confirm that only two unique
values are present.
Parameters:
volume : np.ndarray
Returns:
bool
True if the spot check of the volume only return two unique values,
False if more than two unique values were identified.
"""
middle = int(volume.shape[0] / 2)
unique = np.unique(volume[middle])

return unique.shape[0] < 3


def segmentation_check(volume: np.ndarray) -> bool:
"""Return a bool indicating if volume has vessels after the segmentation.
Some regions of interest may be present in the annotation, but there may
be no corresponding vasculature in the datasets. This function checks to see
if vessels are present.
Parameters:
volume : np.ndarray
Returns:
bool
True if vessels are present, False if not.
"""
if volume is None:
return False

elif not loading and not np.any(volume):
elif not np.any(volume):
return False
else:
return True
return True


# Returns file size in bytes
Expand Down
32 changes: 25 additions & 7 deletions library/qt_threading.py
Original file line number Diff line number Diff line change
Expand Up @@ -95,11 +95,17 @@ def run(self):

## Volume processing
volume, image_shape = ImProc.load_volume(volume_file)
if not ImProc.volume_check(volume, loading=True):

if volume is None:
file_size = helpers.get_file_size(volume_file, GB=True)
self.analysis_status.emit([i, "Error: Unable to read image."])
file_analyzed = False
break
elif not ImProc.binary_check(volume):
file_size = helpers.get_file_size(volume_file, GB=True)
self.analysis_status.emit([i, "Error: Non-binary image loaded."])
file_analyzed = False
break

if roi_name:
roi_id = j % 255
Expand Down Expand Up @@ -138,7 +144,7 @@ def run(self):
# point_minima += 1

# Make sure the volume is still present after ROI segmentation
if not roi_volume or not ImProc.volume_check(volume):
if not roi_volume or not ImProc.segmentation_check(volume):
self.analysis_status.emit([i, "ROI not in dataset..."])
# Cache results
ResExp.cache_result([filename, roi_name, "ROI not in dataset."])
Expand Down Expand Up @@ -428,6 +434,8 @@ def run(self):
progress = 0
step_weight = (70 / roi_count) / 8

error_present = False

# Iterate through the ROI's or single file and generate graphs
for i, roi_name in enumerate(annotation_data.keys()):
## File initialization
Expand All @@ -439,9 +447,16 @@ def run(self):

## Volume processing
volume, image_shape = ImProc.load_volume(volume_file)
if not ImProc.volume_check(volume, loading=True):
if volume is None:
self.analysis_status.emit(["Error: Unable to read image.", 0])
error_present = True
break
elif not ImProc.binary_check(volume):
file_size = helpers.get_file_size(volume_file, GB=True)
self.analysis_status.emit(["Error: Non-binary image loaded.", 0])
error_present = True
break

progress += step_weight

if roi_name:
Expand All @@ -460,6 +475,7 @@ def run(self):
self.failure_emit.emit(1)
self.running = False
self.complete = True
error_present = True
return

self.analysis_status.emit(["Labeling volume...", progress])
Expand All @@ -469,6 +485,7 @@ def run(self):
)
if roi_volumes is None:
self.analysis_status.emit(["Error labeling volume...", 0])
error_present = True
break

roi_volume = roi_volumes[roi_id]
Expand All @@ -479,7 +496,7 @@ def run(self):
point_minima, point_maxima, roi_id + 1
)

if not roi_volume or not ImProc.volume_check(volume):
if not roi_volume or not ImProc.segmentation_check(volume):
progress += step_weight * 7
self.analysis_status.emit(["ROI not in dataset...", progress])
continue
Expand Down Expand Up @@ -598,9 +615,10 @@ def run(self):
status_updater=self.analysis_status,
)
else:
self.analysis_status.emit(
["Visualization cancelled: Volume has no vessels.", 0]
)
if not error_present:
self.analysis_status.emit(
["Visualization cancelled: Volume has no vessels.", 0]
)
self.failure_emit.emit(1)
self.running = False

Expand Down
Binary file added tests/test_files/non_binary_volume.tiff
Binary file not shown.
41 changes: 41 additions & 0 deletions tests/test_image_processing.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import os
import sys

import pytest

sys.path.insert(1, "/Users/jacobbumgarner/Documents/GitHub/VesselVio")


import numpy as np
from library import image_processing

from skimage.io import imread


THIS_PATH = os.path.realpath(__file__)
TEST_FILES = os.path.join(os.path.dirname(THIS_PATH), "test_files")


@pytest.mark.datafiles(TEST_FILES)
def test_binary_check(datafiles):
volume = imread(os.path.join(datafiles, "non_binary_volume.tiff"))

# test 3D
assert image_processing.binary_check(volume) is False
assert image_processing.binary_check(volume > 0) is True

# test 2D
assert image_processing.binary_check(volume[0]) is False
assert image_processing.binary_check(volume[0] > 0) is True


@pytest.mark.datafiles(TEST_FILES)
def test_segmentation_check(datafiles):
# test None
assert image_processing.segmentation_check(None) is False

# test full
assert image_processing.segmentation_check(np.ones((5, 5, 5))) is True

# test empty
assert image_processing.segmentation_check(np.zeros((5, 5, 5))) is False

0 comments on commit aed933b

Please sign in to comment.