Skip to content

Commit

Permalink
starfish.display: unpin napari version, add tests, view masks separat…
Browse files Browse the repository at this point in the history
…ely (#1570)

* display: unpin napari version, add tests, view masks separately

* Separate napari tests into its own category

1. Run them as part of the napari install test that's run on master branches.
2. Move the napari and pyqt imports inside test_display() so they don't trip up tests when napari isn't installed.
3. Upgrade pytest version.

Test plan: named this branch -alltest, so it should hit all the test cases.
  • Loading branch information
kne42 authored and ttung committed Sep 24, 2019
1 parent 089a758 commit 849058e
Show file tree
Hide file tree
Showing 6 changed files with 88 additions and 17 deletions.
14 changes: 12 additions & 2 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -47,9 +47,19 @@ jobs:
- make install-dev slow-test
after_success:
- bash <(curl -s https://codecov.io/bash)
- name: Install Napari
- name: Install Napari & Test napari
if: type = push and (branch = master or branch =~ /-alltest/)
script: pip install .[napari]
dist: xenial
before_install:
- sudo apt-get install -y libgl1-mesa-glx libqt5x11extras5 xvfb
- make install-dev
- pip install .[napari]
- export DISPLAY=:99
- Xvfb $DISPLAY -ac -screen 0 1024x768x24 &
- sleep 10
script:
- python -c "import vispy; print(vispy.sys_info())"
- make napari-test
- name: Docker
if: type = push and (branch = master or branch =~ /-alltest/)
script: make docker
Expand Down
12 changes: 9 additions & 3 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -39,14 +39,20 @@ lint-non-init:
lint-init:
flake8 --ignore 'E252, E301, E302, E305, E401, F401, W503, E731, F811' --filename='*__init__.py' $(MODULES)

# note that napari tests shouldn't be run in parallel because Qt seems to intermittently fail when multiple QApplications are spawned on threads.
test:
pytest -v -n 8 --cov starfish
pytest -v -n 8 --cov starfish -m 'not napari'
pytest -v --cov starfish -m 'napari'

fast-test:
pytest -v -n 8 --cov starfish -m 'not slow'
pytest -v -n 8 --cov starfish -m 'not (slow or napari)'

slow-test:
pytest -v -n 8 --cov starfish -m 'slow'
pytest -v -n 8 --cov starfish -m 'slow and (not napari)'

# note that this shouldn't be run in parallel because Qt seems to intermittently fail when multiple QApplications are spawned on threads.
napari-test:
pytest -v --cov starfish -m 'napari'

mypy:
mypy --ignore-missing-imports $(MODULES)
Expand Down
2 changes: 1 addition & 1 deletion REQUIREMENTS-CI.txt
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ mypy
numpydoc
nbencdec >= 0.0.5
pycodestyle==2.5.0
pytest>=3.6.3
pytest>=4.4.0
pytest-cov>=2.5.1
pytest-xdist
recommonmark
Expand Down
2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
packages=setuptools.find_packages(),
install_requires=install_requires,
extras_require={
'napari': [f"napari=={napari_version}"],
'napari': [f"napari>={napari_version}"],
},
entry_points={
'console_scripts': [
Expand Down
21 changes: 11 additions & 10 deletions starfish/core/_display.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
from typing import Iterable, List, Optional, Set, Tuple, Union

import numpy as np
from packaging.version import parse as parse_version

from starfish.core.imagestack.imagestack import ImageStack
from starfish.core.intensity_table.intensity_table import IntensityTable
Expand All @@ -16,7 +17,7 @@
Viewer = None


NAPARI_VERSION = "0.1.3" # when changing this, update docs in display
NAPARI_VERSION = "0.1.5" # when changing this, update docs in display
INTERACTIVE = not hasattr(__main__, "__file__")


Expand Down Expand Up @@ -127,7 +128,8 @@ def display(
z_multiplier: float = 1
):
"""
Displays an image stack and/or detected spots using napari (https://github.com/napari/napari).
Display an image stack, detected spots, and masks using
`napari <https://github.com/napari/napari>`.
Parameters
----------
Expand Down Expand Up @@ -193,20 +195,19 @@ def display(
Notes
-----
- To use in ipython, use the `%gui qt5` magic.
- To use in ipython, use the `%gui qt` magic.
- napari axes currently cannot be labeled. Until such a time that they can, this function will
order them by Round, Channel, and Z.
- Requires napari 0.1.3: install starfish using `pip install starfish[napari]` to install all
necessary requirements
- Requires at least napari 0.1.5: use `pip install starfish[napari]`
to install all necessary requirements
"""
if stack is None and spots is None:
# masks without stack or spots have no context so don't check for that
raise TypeError("expected a stack and/or spots; got nothing")
if stack is None and spots is None and masks is None:
raise TypeError("expected a stack, spots, or masks; got nothing")

try:
import napari
except ImportError:
raise ImportError(f"Requires napari {NAPARI_VERSION}. "
raise ImportError(f"Requires at least napari {NAPARI_VERSION}. "
"Run `pip install starfish[napari]` "
"to install the necessary requirements.")

Expand All @@ -215,7 +216,7 @@ def display(
except Exception as e:
raise RuntimeError("Could not identify napari version") from e

if version != NAPARI_VERSION:
if parse_version(version) < parse_version(NAPARI_VERSION):
raise ValueError(f"Incorrect version {version} of napari installed."
"Run `pip install starfish[napari]` "
"to install the necessary requirements.")
Expand Down
54 changes: 54 additions & 0 deletions starfish/core/test/test_display.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
import numpy as np
import pytest

from starfish import display, SegmentationMaskCollection
from starfish.core.test.factories import SyntheticData
from starfish.types import Coordinates


sd = SyntheticData(
n_ch=2,
n_round=3,
n_spots=1,
n_codes=4,
n_photons_background=0,
background_electrons=0,
camera_detection_efficiency=1.0,
gray_level=1,
ad_conversion_bits=16,
point_spread_function=(2, 2, 2),
)

stack = sd.spots()
spots = sd.intensities()
masks = SegmentationMaskCollection.from_label_image(
np.random.rand(128, 128).astype(np.uint8),
{Coordinates.Y: np.arange(128), Coordinates.X: np.arange(128)}
)


@pytest.mark.napari
@pytest.mark.parametrize('masks', [masks, None], ids=['masks', ' '])
@pytest.mark.parametrize('spots', [spots, None], ids=['spots', ' '])
@pytest.mark.parametrize('stack', [stack, None], ids=['stack', ' '])
def test_display(stack, spots, masks):
import napari
from qtpy.QtCore import QTimer
from qtpy.QtWidgets import QApplication

def run():
app = QApplication.instance() or QApplication([])
viewer = napari.Viewer()
timer = QTimer()
timer.setInterval(500)
timer.timeout.connect(viewer.window.close)
timer.timeout.connect(app.quit)
timer.start()
display(stack, spots, masks, viewer=viewer)
app.exec_()

if stack is None and spots is None and masks is None:
with pytest.raises(TypeError):
run()
else:
run()

0 comments on commit 849058e

Please sign in to comment.