Skip to content

Commit

Permalink
restore opencv-python to a hard dependency (#155)
Browse files Browse the repository at this point in the history
* restore `opencv-python` to a hard dependency

* add change log entry
  • Loading branch information
zacharyburnett authored Mar 29, 2023
1 parent 52beb28 commit 0b18533
Show file tree
Hide file tree
Showing 6 changed files with 14 additions and 48 deletions.
1 change: 0 additions & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,6 @@ jobs:
python-version: '3.11'
- macos: test-xdist
python-version: '3.11'
- linux: test-opencv-xdist
- linux: test-cov-xdist
coverage: 'codecov'
test_downstream:
Expand Down
2 changes: 2 additions & 0 deletions CHANGES.rst
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ Other

- update minimum version of ``numpy`` to ``1.20`` and add minimum dependency testing to CI [#153]

- restore ``opencv-python`` to a hard dependency [#155]

1.3.4 (2023-02-13)
==================

Expand Down
4 changes: 1 addition & 3 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ dependencies = [
'astropy >=5.0.4',
'scipy >=1.6.0',
'numpy >=1.20',
'opencv-python >=4.6.0.66',
]
dynamic = ['version']

Expand All @@ -35,9 +36,6 @@ test = [
'pytest-doctestplus',
'pytest-openfiles >=0.5.0',
]
opencv = [
'opencv-python >=4.6.0.66',
]

[project.urls]
'repository' = 'https://github.com/spacetelescope/stcal'
Expand Down
42 changes: 11 additions & 31 deletions src/stcal/jump/jump.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,19 +3,11 @@
import time

import numpy as np
import cv2 as cv

from . import constants
from . import twopoint_difference as twopt

ELLIPSE_PACKAGE = None
try:
import cv2 as cv

ELLIPSE_PACKAGE = 'opencv-python'
except (ImportError, ModuleNotFoundError):
ELLIPSE_PACKAGE_WARNING = '`opencv-python` must be installed (`pip install stcal[opencv]`) ' \
'in order to use ellipses'

log = logging.getLogger(__name__)
log.setLevel(logging.DEBUG)

Expand Down Expand Up @@ -400,10 +392,7 @@ def extend_snowballs(plane, snowballs, sat_flag, jump_flag, expansion=1.5):
center = (round(ceny), round(cenx))
extend_radius = round(jump_radius * expansion)
color = (0, 0, 4)
if ELLIPSE_PACKAGE == 'opencv-python':
image = cv.circle(image, center, extend_radius, color, -1)
else:
raise ModuleNotFoundError(ELLIPSE_PACKAGE_WARNING)
image = cv.circle(image, center, extend_radius, color, -1)
jump_circle = image[:, :, 2]
saty, satx = np.where(sat_pix == 2)
jump_circle[saty, satx] = 0
Expand Down Expand Up @@ -435,10 +424,7 @@ def extend_ellipses(plane, ellipses, sat_flag, jump_flag, expansion=1.1):
center = (round(ceny), round(cenx))
axes = (round(axis1 / 2), round(axis2 / 2))
color = (0, 0, 4)
if ELLIPSE_PACKAGE == 'opencv-python':
image = cv.ellipse(image, center, axes, alpha, 0, 360, color, -1)
else:
raise ModuleNotFoundError(ELLIPSE_PACKAGE_WARNING)
image = cv.ellipse(image, center, axes, alpha, 0, 360, color, -1)
jump_ellipse = image[:, :, 2]
saty, satx = np.where(sat_pix == 2)
jump_ellipse[saty, satx] = 0
Expand All @@ -450,27 +436,21 @@ def find_circles(dqplane, bitmask, min_area):
# Using an input DQ plane this routine will find the groups of pixels with at least the minimum
# area and return a list of the minimum enclosing circle parameters.
pixels = np.bitwise_and(dqplane, bitmask)
if ELLIPSE_PACKAGE == 'opencv-python':
contours, hierarchy = cv.findContours(pixels, cv.RETR_EXTERNAL, cv.CHAIN_APPROX_SIMPLE)
bigcontours = [con for con in contours if cv.contourArea(con) >= min_area]
circles = [cv.minEnclosingCircle(con) for con in bigcontours]
else:
raise ModuleNotFoundError(ELLIPSE_PACKAGE_WARNING)
contours, hierarchy = cv.findContours(pixels, cv.RETR_EXTERNAL, cv.CHAIN_APPROX_SIMPLE)
bigcontours = [con for con in contours if cv.contourArea(con) >= min_area]
circles = [cv.minEnclosingCircle(con) for con in bigcontours]
return circles


def find_ellipses(dqplane, bitmask, min_area):
# Using an input DQ plane this routine will find the groups of pixels with at least the minimum
# area and return a list of the minimum enclosing ellipse parameters.
pixels = np.bitwise_and(dqplane, bitmask)
if ELLIPSE_PACKAGE == 'opencv-python':
contours, hierarchy = cv.findContours(pixels, cv.RETR_EXTERNAL, cv.CHAIN_APPROX_SIMPLE)
bigcontours = [con for con in contours if cv.contourArea(con) > min_area]
# minAreaRect is used becuase fitEllipse requires 5 points and it is possible to have a contour
# with just 4 points.
ellipses = [cv.minAreaRect(con) for con in bigcontours]
else:
raise ModuleNotFoundError(ELLIPSE_PACKAGE_WARNING)
contours, hierarchy = cv.findContours(pixels, cv.RETR_EXTERNAL, cv.CHAIN_APPROX_SIMPLE)
bigcontours = [con for con in contours if cv.contourArea(con) > min_area]
# minAreaRect is used becuase fitEllipse requires 5 points and it is possible to have a contour
# with just 4 points.
ellipses = [cv.minAreaRect(con) for con in bigcontours]
return ellipses


Expand Down
10 changes: 0 additions & 10 deletions tests/test_jump.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,6 @@

DQFLAGS = {'JUMP_DET': 4, 'SATURATED': 2, 'DO_NOT_USE': 1}

try:
import cv2 as cv # noqa: F401

OPENCV_INSTALLED = True
except ImportError:
OPENCV_INSTALLED = False


@pytest.fixture(scope='function')
def setup_cube():
def _cube(ngroups, readnoise=10):
Expand All @@ -31,7 +23,6 @@ def _cube(ngroups, readnoise=10):
return _cube


@pytest.mark.xfail(not OPENCV_INSTALLED, reason="`opencv-python` not installed")
def test_find_simple_circle():
plane = np.zeros(shape=(5, 5), dtype=np.uint8)
plane[2, 2] = DQFLAGS['JUMP_DET']
Expand All @@ -43,7 +34,6 @@ def test_find_simple_circle():
assert circle[0][1] == pytest.approx(1.0, 1e-3)


@pytest.mark.xfail(not OPENCV_INSTALLED, reason="`opencv-python` not installed")
def test_find_simple_ellipse():
plane = np.zeros(shape=(5, 5), dtype=np.uint8)
plane[2, 2] = DQFLAGS['JUMP_DET']
Expand Down
3 changes: 0 additions & 3 deletions tox.ini
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,6 @@ commands =
[testenv]
description =
run tests
opencv: requiring opencv-python
jwst: of JWST pipeline
romancal: of Romancal pipeline
oldestdeps: with the oldest supported version of key dependencies
Expand All @@ -53,7 +52,6 @@ description =
xdist: using parallel processing
extras =
test
opencv: opencv
deps =
xdist: pytest-xdist
jwst: jwst[test] @ git+https://github.com/spacetelescope/jwst.git
Expand All @@ -78,7 +76,6 @@ commands =
jwst: --pyargs jwst --ignore-glob=timeconversion --ignore-glob=associations --ignore-glob=*/scripts/* \
romancal: --pyargs romancal \
cov: --cov=. --cov-config=pyproject.toml --cov-report=term-missing --cov-report=xml \
opencv: -- tests/test_jump.py \
{posargs}

[testenv:build-docs]
Expand Down

0 comments on commit 0b18533

Please sign in to comment.