Skip to content
Closed
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 0 additions & 3 deletions .github/codecov.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,4 @@ coverage:
project: false

ignore:
- "setup.py"
- "torchio/external/due.py"
- "torchio/datasets"
- "torchio/download.py"
46 changes: 41 additions & 5 deletions .github/workflows/tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -46,21 +46,57 @@ jobs:
shell: bash

- name: Setup test suite
run: tox run -v --notest --skip-missing-interpreters false -e ${{ matrix.python }}
run: |
if [ "${{ matrix.os }}" == "ubuntu-latest" ] && [ "${{ matrix.python }}" == "3.14" ]; then
tox_env=coverage
else
tox_env=pytest
fi
tox run -v --notest --skip-missing-interpreters false -e "$tox_env"
shell: bash # this wouldn't work on Powershell

# Run all tests on schedule, but only non-slow tests on push
- name: Run pytest
# Run all tests on schedule, but only non-slow tests otherwise
- name: Run unit tests
run: |
if [ "${{ matrix.os }}" == "ubuntu-latest" ] && [ "${{ matrix.python }}" == "3.14" ]; then
tox_env=coverage
else
tox_env=pytest
fi

if [ "${{ github.event_name }}" == "schedule" ]; then
tox -e pytest
tox -e "$tox_env"
else
tox -e pytest -- -m "not slow"
tox -e "$tox_env" -- -m "not slow"
fi
shell: bash # this wouldn't work on Powershell

- name: Summarize coverage
if: ${{ matrix.os == 'ubuntu-latest' && matrix.python == '3.14' }}
run: |
python3 - <<'PY'
import os
import xml.etree.ElementTree as ET

root = ET.parse('coverage.xml').getroot()
line_rate = float(root.attrib['line-rate']) * 100
lines_covered = int(root.attrib['lines-covered'])
lines_valid = int(root.attrib['lines-valid'])

with open(os.environ['GITHUB_STEP_SUMMARY'], 'a', encoding='utf-8') as f:
f.write('## Coverage report\n\n')
f.write(
f'- Line coverage: **{line_rate:.2f}%** '
f'({lines_covered}/{lines_valid} lines)\n'
)
f.write('- Full coverage details are uploaded to Codecov.\n')
PY

Comment thread
fepegar marked this conversation as resolved.
Outdated
- name: Upload coverage reports to Codecov
if: ${{ matrix.os == 'ubuntu-latest' && matrix.python == '3.14' }}
uses: codecov/codecov-action@v5.5.2
with:
files: ./coverage.xml
env:
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}

Expand Down
9 changes: 9 additions & 0 deletions tests/data/inference/test_aggregator.py
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,10 @@ def test_overlap_hann(self):
)
self.aggregate('hann', fixture)

def test_bad_overlap_mode(self):
with pytest.raises(ValueError, match='Overlap mode must be'):
tio.data.GridAggregator._parse_overlap_mode('bad')

def run_sampler_aggregator(self, overlap_mode='crop'):
patch_size = 10
patch_overlap = 2
Expand All @@ -93,6 +97,11 @@ def test_warning_int64(self):
with pytest.warns(RuntimeWarning):
aggregator.get_output_tensor()

def test_overlap_hann_casts_int_tensors_to_float(self):
aggregator = self.run_sampler_aggregator(overlap_mode='hann')
output = aggregator.get_output_tensor()
assert output.dtype == torch.float32

def run_patch_crop_issue(self, *, padding_mode):
# https://github.com/TorchIO-project/torchio/issues/813
pao, pas, ims, bb1, bb2 = 4, 102, 320, 100, 120
Expand Down
7 changes: 7 additions & 0 deletions tests/data/inference/test_grid_sampler.py
Original file line number Diff line number Diff line change
Expand Up @@ -65,3 +65,10 @@ def test_subject_shape(self):
)
final_shape = self.sample_subject.shape
assert initial_shape == final_shape

def test_num_patches_not_supported(self):
sampler = tio.GridSampler(self.sample_subject, 5)
with pytest.raises(
ValueError, match='does not support limiting the number of patches'
):
next(sampler(num_patches=1))
16 changes: 16 additions & 0 deletions tests/data/sampler/test_label_sampler.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import numpy as np
import pytest
import torch

Expand Down Expand Up @@ -79,3 +80,18 @@ def test_empty_map(self):
sampler = tio.LabelSampler(4)
with pytest.raises(RuntimeError):
next(sampler(subject))

def test_missing_label_name(self):
subject = tio.Subject(image=tio.ScalarImage(tensor=torch.rand(1, 1, 1, 1)))
sampler = tio.LabelSampler(1, 'missing')
with pytest.raises(KeyError):
sampler.get_probability_map_image(subject)

def test_patch_size_larger_than_label_map(self):
label_map = torch.ones(1, 5, 5, 5)
with pytest.raises(RuntimeError, match='Patch size .*larger than label map'):
tio.LabelSampler.get_probabilities_from_label_map(
label_map,
{1: 1},
np.array((8, 8, 8)),
)
5 changes: 5 additions & 0 deletions tests/data/sampler/test_patch_sampler.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,3 +21,8 @@ def test_bad_patch_size(self):

def test_extract_patch(self):
PatchSampler(1).extract_patch(self.sample_subject, (3, 4, 5))

def test_patch_size_larger_than_image(self):
sampler = PatchSampler(100)
with pytest.raises(RuntimeError, match='cannot be larger than image size'):
sampler(self.sample_subject)
5 changes: 5 additions & 0 deletions tests/data/sampler/test_uniform_sampler.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,3 +24,8 @@ def test_incosistent_shape(self):
patch_size = 2
sampler = UniformSampler(patch_size)
next(sampler(subject))

def test_num_patches(self):
sampler = UniformSampler(5)
patches = list(sampler(self.sample_subject, num_patches=3))
assert len(patches) == 3
45 changes: 45 additions & 0 deletions tests/data/sampler/test_weighted_sampler.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
from unittest.mock import patch

import numpy as np
import pytest
import torch

import torchio as tio
Expand Down Expand Up @@ -37,3 +41,44 @@ def test_inconsistent_shape(self):
patch_size = 2
sampler = tio.data.WeightedSampler(patch_size, 'im1')
next(sampler(subject))

def test_missing_probability_map(self):
subject = self.get_sample((1, 7, 7, 7))
sampler = WeightedSampler(5, 'missing')
with pytest.raises(KeyError):
sampler.get_probability_map_image(subject)

def test_negative_probability_map(self):
subject = self.get_sample((1, 7, 7, 7))
subject.prob.set_data(subject.prob.data - 2)
sampler = WeightedSampler(5, 'prob')
with pytest.raises(ValueError, match='Negative values found'):
sampler.get_probability_map(subject)

def test_extract_patch_without_cdf(self):
subject = self.get_sample((1, 7, 7, 7))
sampler = WeightedSampler(5, 'prob')
patch = sampler.extract_patch(subject, np.array((1, 1, 1)))
assert patch.spatial_shape == (5, 5, 5)

def test_extract_patch_tuple_without_cdf(self):
subject = self.get_sample((1, 7, 7, 7))
sampler = WeightedSampler(5, 'prob')
patch = sampler.extract_patch(subject, (1, 1, 1))
assert patch.spatial_shape == (5, 5, 5)

def test_extract_patch_invalid_type_with_cdf(self):
subject = self.get_sample((1, 7, 7, 7))
sampler = WeightedSampler(5, 'prob')
with pytest.raises(TypeError, match='Probability map must be a NumPy array'):
sampler.extract_patch(subject, (1, 1, 1), cdf=np.array((1.0,)))

def test_probability_zero_raises(self):
probability_map = np.array(((0, 1), (1, 1)), dtype=np.float32)
cdf = WeightedSampler.get_cumulative_distribution_function(probability_map)

with (
patch('torchio.data.sampler.weighted.np.searchsorted', return_value=0),
pytest.raises(RuntimeError, match='Error retrieving probability'),
):
WeightedSampler.sample_probability_map(probability_map, cdf)
Loading
Loading