From d078f60b08692371e93c9f69a52597e0c570c80d Mon Sep 17 00:00:00 2001 From: Paul Adkisson Date: Wed, 1 May 2024 17:45:07 -0400 Subject: [PATCH] Update Workflows (#317) * downgrade mac-os to 13 * downgrade to macos-12 * removed setup-conda * added macos-13 to update testing data * removed conda * added 3.12 * added quotes to version numbers * added macos-latest * removed macos-latest * added dev testing * unpin xdist * condense tests into 1 line for better output * downgrade python setup for wheel support * added macos-latest with scanimage skips * continue on collection errors * added platform check for scanimage import * added platform check for scanimage import * switched to try-except * fixed ignores * fixed ignores * updated dev install * fixed ignores * added formatting * added macos-latest to update-testing-data * switched back to if-else import * updated changelog --- .github/workflows/dev-testing.yaml | 57 +++++++++++++++++++++ .github/workflows/run-tests.yml | 11 ++-- CHANGELOG.md | 2 + tests/test_io.py | 11 ++++ tests/test_scan_image_tiff.py | 14 +++-- tests/test_scanimage_utils.py | 8 +++ tests/test_scanimagetiffimagingextractor.py | 27 ++++++++-- 7 files changed, 120 insertions(+), 10 deletions(-) create mode 100644 .github/workflows/dev-testing.yaml diff --git a/.github/workflows/dev-testing.yaml b/.github/workflows/dev-testing.yaml new file mode 100644 index 00000000..fbe55627 --- /dev/null +++ b/.github/workflows/dev-testing.yaml @@ -0,0 +1,57 @@ +name: Dev Testing +on: + pull_request: + workflow_dispatch: + +concurrency: + group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }} + cancel-in-progress: true + +jobs: + run: + name: Ubuntu tests with Python ${{ matrix.python-version }} + runs-on: ubuntu-latest + strategy: + fail-fast: false + matrix: + python-version: ["3.8", "3.9", "3.10", "3.11", "3.12"] + steps: + - uses: actions/checkout@v2 + - run: git fetch --prune --unshallow --tags + - name: Setup Python ${{ matrix.python-version }} + uses: actions/setup-python@v2 + with: + python-version: ${{ matrix.python-version }} + + - name: Global Setup + run: | + pip install -U pip + pip install pytest-xdist + git config --global user.email "CI@example.com" + git config --global user.name "CI Almighty" + pip install wheel==0.41.2 # needed for scanimage + + - name: Install full requirements + run: | + pip install .[test] + pip install .[full] + + - name: Clone and Install NeuroConv + run: | + git clone https://github.com/catalystneuro/neuroconv.git + cd neuroconv + pip install --no-cache-dir .[full,test] + cd ../ + - name: Get ophys_testing_data current head hash + id: ophys + run: echo "::set-output name=HASH_OPHYS_DATASET::$(git ls-remote https://gin.g-node.org/CatalystNeuro/ophys_testing_data.git HEAD | cut -f1)" + - name: Cache ophys dataset - ${{ steps.ophys.outputs.HASH_OPHYS_DATASET }} + uses: actions/cache@v2 + id: cache-ophys-datasets + with: + path: ./ophys_testing_data + key: ophys-datasets-042023-ubuntu-latest-${{ steps.ophys.outputs.HASH_OPHYS_DATASET }} + + - name: Run NeuroConv tests + run: | + pytest -n auto --dist loadscope neuroconv/tests/test_ophys neuroconv/tests/test_on_data/test_imaging_interfaces.py neuroconv/tests/test_on_data/test_segmentation_interfaces.py diff --git a/.github/workflows/run-tests.yml b/.github/workflows/run-tests.yml index f3f2c071..ac903b3f 100644 --- a/.github/workflows/run-tests.yml +++ b/.github/workflows/run-tests.yml @@ -6,6 +6,10 @@ on: workflows: [update-testing-data] types: [completed] +concurrency: + group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }} + cancel-in-progress: true + jobs: on-failure: name: Notify on failure @@ -37,10 +41,9 @@ jobs: strategy: fail-fast: false matrix: - python-version: [3.8, 3.9, "3.10", 3.11] - os: [ubuntu-latest, windows-latest, macos-latest] + python-version: ["3.8", "3.9", "3.10", "3.11", "3.12"] + os: [ubuntu-latest, windows-latest, macos-latest, macos-13] # macos-13 is the latest version of macOS with Intel chip steps: - - uses: s-weigand/setup-conda@v1 - uses: actions/checkout@v2 - run: git fetch --prune --unshallow --tags - name: Setup Python ${{ matrix.python-version }} @@ -79,7 +82,7 @@ jobs: run: pytest -n auto --dist loadscope --cov=./ --cov-report xml:./codecov.xml - if: ${{ matrix.python-version == '3.9' && matrix.os == 'ubuntu-latest'}} name: Upload full coverage to Codecov - uses: codecov/codecov-action@v1 + uses: codecov/codecov-action@v4 with: token: ${{ secrets.CODECOV_TOKEN }} file: ./codecov.xml diff --git a/CHANGELOG.md b/CHANGELOG.md index 88fe901c..a38f716d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,8 @@ ### Features +* Updated testing workflows to include python 3.12, m1/intel macos, and dev tests to check neuroconv: [PR #317](https://github.com/catalystneuro/roiextractors/pull/317) + ### Fixes * Remove unecessary scipy import error handling [#315]((https://github.com/catalystneuro/roiextractors/pull/315) diff --git a/tests/test_io.py b/tests/test_io.py index 95e9937f..2f9186fb 100644 --- a/tests/test_io.py +++ b/tests/test_io.py @@ -25,6 +25,11 @@ from .setup_paths import OPHYS_DATA_PATH, OUTPUT_PATH +import platform + +# Remove this check once scanimage tiff reader is available on ARM -- see https://gitlab.com/vidriotech/scanimagetiffreader-python/-/issues/31 +is_m_series_mac = platform.system() == "Darwin" and platform.machine() == "arm64" + def custom_name_func(testcase_func, param_num, param): return ( @@ -68,6 +73,9 @@ class TestExtractors(TestCase): @parameterized.expand(imaging_extractor_list, name_func=custom_name_func) def test_imaging_extractors(self, extractor_class, extractor_kwargs): + if extractor_class == ScanImageTiffImagingExtractor and is_m_series_mac: + return + extractor = extractor_class(**extractor_kwargs) check_imaging_return_types(extractor) @@ -88,6 +96,9 @@ def test_imaging_extractors(self, extractor_class, extractor_kwargs): @parameterized.expand(imaging_extractor_list, name_func=custom_name_func) def test_imaging_extractors_canonical_shape(self, extractor_class, extractor_kwargs): """Test that get_video and get_frame methods for their shapes and types under different indexing scenarios""" + if extractor_class == ScanImageTiffImagingExtractor and is_m_series_mac: + return + extractor = extractor_class(**extractor_kwargs) image_size = extractor.get_image_size() num_channels = extractor.get_num_channels() diff --git a/tests/test_scan_image_tiff.py b/tests/test_scan_image_tiff.py index a0d7c25d..589f1811 100644 --- a/tests/test_scan_image_tiff.py +++ b/tests/test_scan_image_tiff.py @@ -2,15 +2,22 @@ from pathlib import Path from tempfile import mkdtemp from shutil import rmtree, copy - from hdmf.testing import TestCase from numpy.testing import assert_array_equal -from ScanImageTiffReader import ScanImageTiffReader +import pytest from roiextractors import TiffImagingExtractor, ScanImageTiffImagingExtractor - +from roiextractors.extractors.tiffimagingextractors.scanimagetiff_utils import _get_scanimage_reader from .setup_paths import OPHYS_DATA_PATH +import platform + +is_m_series_mac = platform.system() == "Darwin" and platform.machine() == "arm64" +if ( + is_m_series_mac +): # Remove this check once scanimage tiff reader is available on ARM -- see https://gitlab.com/vidriotech/scanimagetiffreader-python/-/issues/31 + pytest.skip("ScanImageTiffReader does not support M-series Macs", allow_module_level=True) + class TestScanImageTiffExtractor(TestCase): @classmethod @@ -18,6 +25,7 @@ def setUpClass(cls): cls.file_path = OPHYS_DATA_PATH / "imaging_datasets" / "Tif" / "sample_scanimage.tiff" cls.tmpdir = Path(mkdtemp()) cls.imaging_extractor = ScanImageTiffImagingExtractor(file_path=cls.file_path, sampling_frequency=30.0) + ScanImageTiffReader = _get_scanimage_reader() with ScanImageTiffReader(filename=str(cls.imaging_extractor.file_path)) as io: cls.data = io.data() diff --git a/tests/test_scanimage_utils.py b/tests/test_scanimage_utils.py index 619a2327..8429eba0 100644 --- a/tests/test_scanimage_utils.py +++ b/tests/test_scanimage_utils.py @@ -11,6 +11,14 @@ from .setup_paths import OPHYS_DATA_PATH +import platform + +is_m_series_mac = platform.system() == "Darwin" and platform.machine() == "arm64" +if ( + is_m_series_mac +): # Remove this check once scanimage tiff reader is available on ARM -- see https://gitlab.com/vidriotech/scanimagetiffreader-python/-/issues/31 + pytest.skip("ScanImageTiffReader does not support M-series Macs", allow_module_level=True) + def test_get_scanimage_reader(): ScanImageTiffReader = _get_scanimage_reader() diff --git a/tests/test_scanimagetiffimagingextractor.py b/tests/test_scanimagetiffimagingextractor.py index 92e943e1..55d9370c 100644 --- a/tests/test_scanimagetiffimagingextractor.py +++ b/tests/test_scanimagetiffimagingextractor.py @@ -1,16 +1,27 @@ import pytest from numpy.testing import assert_array_equal -from ScanImageTiffReader import ScanImageTiffReader + from roiextractors import ( ScanImageTiffSinglePlaneImagingExtractor, ScanImageTiffMultiPlaneImagingExtractor, ScanImageTiffSinglePlaneMultiFileImagingExtractor, ScanImageTiffMultiPlaneMultiFileImagingExtractor, ) -from roiextractors.extractors.tiffimagingextractors.scanimagetiff_utils import extract_extra_metadata, parse_metadata - +from roiextractors.extractors.tiffimagingextractors.scanimagetiff_utils import ( + extract_extra_metadata, + parse_metadata, + _get_scanimage_reader, +) from .setup_paths import OPHYS_DATA_PATH +import platform + +is_m_series_mac = platform.system() == "Darwin" and platform.machine() == "arm64" +if ( + is_m_series_mac +): # Remove this check once scanimage tiff reader is available on ARM -- see https://gitlab.com/vidriotech/scanimagetiffreader-python/-/issues/31 + pytest.skip("ScanImageTiffReader does not support M-series Macs", allow_module_level=True) + @pytest.fixture(scope="module") def file_path(): @@ -91,6 +102,8 @@ def test_ScanImageTiffSinglePlaneImagingExtractor__init__parsed_metadata_not_pro @pytest.mark.parametrize("frame_idxs", (0, [0, 1, 2], [0, 2, 5])) def test_get_frames(scan_image_tiff_single_plane_imaging_extractor, frame_idxs, expected_properties): + ScanImageTiffReader = _get_scanimage_reader() + frames = scan_image_tiff_single_plane_imaging_extractor.get_frames(frame_idxs=frame_idxs) file_path = str(scan_image_tiff_single_plane_imaging_extractor.file_path) plane = scan_image_tiff_single_plane_imaging_extractor.plane @@ -100,6 +113,7 @@ def test_get_frames(scan_image_tiff_single_plane_imaging_extractor, frame_idxs, frames_per_slice = expected_properties["frames_per_slice"] if isinstance(frame_idxs, int): frame_idxs = [frame_idxs] + raw_idxs = [] for idx in frame_idxs: cycle = idx // frames_per_slice @@ -111,6 +125,7 @@ def test_get_frames(scan_image_tiff_single_plane_imaging_extractor, frame_idxs, + channel ) raw_idxs.append(raw_idx) + with ScanImageTiffReader(file_path) as io: assert_array_equal(frames, io.data()[raw_idxs]) @@ -123,6 +138,8 @@ def test_get_frames_invalid(scan_image_tiff_single_plane_imaging_extractor, fram @pytest.mark.parametrize("frame_idx", (1, 3, 5)) def test_get_single_frame(scan_image_tiff_single_plane_imaging_extractor, expected_properties, frame_idx): + ScanImageTiffReader = _get_scanimage_reader() + frame = scan_image_tiff_single_plane_imaging_extractor._get_single_frame(frame=frame_idx) file_path = str(scan_image_tiff_single_plane_imaging_extractor.file_path) plane = scan_image_tiff_single_plane_imaging_extractor.plane @@ -155,6 +172,8 @@ def test_get_video( start_frame, end_frame, ): + ScanImageTiffReader = _get_scanimage_reader() + video = scan_image_tiff_single_plane_imaging_extractor.get_video(start_frame=start_frame, end_frame=end_frame) if start_frame is None: start_frame = 0 @@ -166,6 +185,7 @@ def test_get_video( num_planes = expected_properties["num_planes"] num_channels = expected_properties["num_channels"] frames_per_slice = expected_properties["frames_per_slice"] + raw_idxs = [] for idx in range(start_frame, end_frame): cycle = idx // frames_per_slice @@ -177,6 +197,7 @@ def test_get_video( + channel ) raw_idxs.append(raw_idx) + with ScanImageTiffReader(file_path) as io: assert_array_equal(video, io.data()[raw_idxs])