Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

MNT: NumPy 2.0 compatibility, other fixes #363

Merged
merged 4 commits into from
Sep 8, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
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
8 changes: 4 additions & 4 deletions .github/workflows/ci_workflows.yml
Original file line number Diff line number Diff line change
Expand Up @@ -82,8 +82,8 @@ jobs:

- name: Test with old dependencies
os: ubuntu-20.04
python: 3.8
toxenv: py38-test-oldestdeps
python: 3.9
toxenv: py39-test-oldestdeps

- name: Test in OSX
os: macos-latest
Expand All @@ -93,8 +93,8 @@ jobs:
# NOTE: If TRDS cannot take the hit, disable --remote-data
- name: Test in Windows with remote data
os: windows-latest
python: 3.9
toxenv: py39-test-alldeps
python: '3.11'
toxenv: py311-test-alldeps
toxposargs: --remote-data

steps:
Expand Down
4 changes: 2 additions & 2 deletions .readthedocs.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,11 @@
version: 2

build:
os: ubuntu-20.04
os: ubuntu-22.04
apt_packages:
- graphviz
tools:
python: "3.9"
python: "3.11"

sphinx:
builder: html
Expand Down
5 changes: 5 additions & 0 deletions CHANGES.rst
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
1.3.0 (unreleased)
==================

- Compatibility with ``numpy`` 2.0. [#363]

- Bumped minimum supported versions for Python to 3.9,
``numpy`` to 1.20, ``astropy`` to 5.0, and ``scipy`` to 1.6. [#363]

1.2.1 (2023-06-01)
==================

Expand Down
6 changes: 6 additions & 0 deletions conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,12 @@
except ImportError:
version = 'unknown'

from astropy.utils import minversion
NUMPY_LT_2_0 = not minversion("numpy", "2.0.dev")
if not NUMPY_LT_2_0:
import numpy as np
np.set_printoptions(legacy="1.25")

# Uncomment and customize the following lines to add/remove entries
# from the list of packages for which version numbers are displayed
# when running the tests.
Expand Down
6 changes: 2 additions & 4 deletions docs/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ reported) or contact `STScI Help Desk <https://hsthelp.stsci.edu>`_.
Installation and Setup
======================

**synphot** works for Python 3.8 or later only. It requires the following
**synphot** works for Python 3.9 or later only. It requires the following
packages:

* numpy
Expand Down Expand Up @@ -77,12 +77,10 @@ via HTTP, create a local directory where you plan to store the data files
>>> from synphot.utils import download_data
>>> file_list = download_data('/my/local/dir/trds') # doctest: +SKIP

With ``astropy`` 4.1 or later, you can generate a
With ``astropy``, you can generate a
``$HOME/.astropy/config/synphot.cfg`` file like this (otherwise, you can
manually create one from :ref:`synphot_config_file`):

.. doctest-requires:: astropy>=4.1

>>> from astropy.config import generate_config
>>> generate_config(pkgname='synphot')

Expand Down
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,5 @@
requires = ["setuptools>=30.3.0",
"setuptools_scm",
"wheel",
"oldest-supported-numpy"]
"numpy>=1.25,<2"]
build-backend = "setuptools.build_meta"
10 changes: 5 additions & 5 deletions setup.cfg
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
[tool:pytest]
minversion = 5
minversion = 6
testpaths = "synphot" "docs"
norecursedirs = build docs/_build synphot/src
astropy_header = true
Expand Down Expand Up @@ -48,10 +48,10 @@ zip_safe = False
setup_requires =
setuptools_scm
install_requires =
numpy>=1.18
astropy>=4.3
scipy>=1.3
python_requires = >=3.8
numpy>=1.20
astropy>=5
scipy>=1.6
python_requires = >=3.9

[options.extras_require]
all =
Expand Down
9 changes: 5 additions & 4 deletions synphot/observation.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@

# THIRD-PARTY
import numpy as np
from scipy.integrate import trapezoid

# ASTROPY
from astropy import log
Expand Down Expand Up @@ -409,8 +410,8 @@ def effective_wavelength(self, binned=True, wavelengths=None,
x = self._validate_wavelengths(wavelengths).value
y = units.convert_flux(x, self(x), flux_unit).value

num = np.trapz(y * x ** 2, x=x)
den = np.trapz(y * x, x=x)
num = trapezoid(y * x ** 2, x=x)
den = trapezoid(y * x, x=x)

if den == 0.0: # pragma: no cover
eff_lam = 0.0
Expand Down Expand Up @@ -488,8 +489,8 @@ def effstim(self, flux_unit=None, wavelengths=None, area=None,
influx = units.convert_flux(inwave, self(inwave), units.FLAM).value

# Integrate
num = abs(np.trapz(inwave * influx, x=inwave))
den = abs(np.trapz(x_band * y_band, x=x_band))
num = abs(trapezoid(inwave * influx, x=inwave))
den = abs(trapezoid(x_band * y_band, x=x_band))
utils.validate_totalflux(num)
utils.validate_totalflux(den)
val = (num / den) * units.FLAM
Expand Down
27 changes: 14 additions & 13 deletions synphot/spectrum.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@

# THIRD-PARTY
import numpy as np
from scipy.integrate import trapezoid

# ASTROPY
from astropy import log
Expand Down Expand Up @@ -498,7 +499,7 @@ def integrate(self, wavelengths=None, integration_type=None, **kwargs):

if integration_type == 'trapezoid':
y = abs(self(x, **kwargs)) # Unsigned area
result = abs(np.trapz(y, x=x))
result = abs(trapezoid(y, x=x))

elif integration_type == 'analytical':
result = self.model.integrate(x)
Expand Down Expand Up @@ -553,8 +554,8 @@ def avgwave(self, wavelengths=None):
"""
x = self._validate_wavelengths(wavelengths).value
y = self(x).value
num = np.trapz(y * x, x=x)
den = np.trapz(y, x=x)
num = trapezoid(y * x, x=x)
den = trapezoid(y, x=x)

if den == 0: # pragma: no cover
avg_wave = 0.0
Expand All @@ -581,8 +582,8 @@ def barlam(self, wavelengths=None):
"""
x = self._validate_wavelengths(wavelengths).value
y = self(x).value
num = np.trapz(y * np.log(x) / x, x=x)
den = np.trapz(y / x, x=x)
num = trapezoid(y * np.log(x) / x, x=x)
den = trapezoid(y / x, x=x)

if num == 0 or den == 0: # pragma: no cover
bar_lam = 0.0
Expand All @@ -609,8 +610,8 @@ def pivot(self, wavelengths=None):
"""
x = self._validate_wavelengths(wavelengths).value
y = self(x).value
num = np.trapz(y * x, x=x)
den = np.trapz(y / x, x=x)
num = trapezoid(y * x, x=x)
den = trapezoid(y / x, x=x)

if den == 0: # pragma: no cover
pivwv = 0.0
Expand Down Expand Up @@ -1593,7 +1594,7 @@ def unit_response(self, area, wavelengths=None):
x = self._validate_wavelengths(wavelengths).to(u.AA)

y = self(x) * x
int_val = abs(np.trapz(y, x=x))
int_val = abs(trapezoid(y, x=x))
uresp = units.HC / (a.cgs * int_val)

return (uresp / u.s).to(units.FLAM)
Expand Down Expand Up @@ -1642,8 +1643,8 @@ def rmswidth(self, wavelengths=None, threshold=None):
thru = y[mask]

a = self.avgwave(wavelengths=wavelengths)
num = np.trapz((wave - a) ** 2 * thru, x=wave)
den = np.trapz(thru, x=wave)
num = trapezoid((wave - a) ** 2 * thru, x=wave)
den = trapezoid(thru, x=wave)

if den == 0: # pragma: no cover
rms_width = 0.0 * a.unit
Expand Down Expand Up @@ -1703,8 +1704,8 @@ def photbw(self, wavelengths=None, threshold=None):
if a == 0:
bandw = 0.0 * a.unit
else:
num = np.trapz(thru * np.log(wave / a) ** 2 / wave, x=wave)
den = np.trapz(thru / wave, x=wave)
num = trapezoid(thru * np.log(wave / a) ** 2 / wave, x=wave)
den = trapezoid(thru / wave, x=wave)

if den == 0: # pragma: no cover
bandw = 0.0 * a.unit
Expand Down Expand Up @@ -1849,7 +1850,7 @@ def efficiency(self, wavelengths=None):
"""
x = self._validate_wavelengths(wavelengths)
y = self(x)
return abs(np.trapz(y / x, x=x))
return abs(trapezoid(y / x, x=x))

def emflx(self, area, wavelengths=None):
"""Calculate
Expand Down
7 changes: 4 additions & 3 deletions synphot/tests/test_integrator.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
from astropy.modeling.models import Const1D
from astropy.tests.helper import assert_quantity_allclose
from numpy.testing import assert_allclose
from scipy.integrate import trapezoid

# LOCAL
from synphot import models, units
Expand Down Expand Up @@ -180,14 +181,14 @@ def test_bandpass_Trapezoid1D():
assert_quantity_allclose(bp.integrate(integration_type='analytical'), ans)


def test_trapz_box1d():
def test_trapezoid_box1d():
"""Test the underlying trapezoid integration."""
m = models.Box1D(amplitude=1, x_0=5000, width=10)

# Ascending.
x = m.sampleset()
assert_allclose(np.trapz(m(x), x=x), 10)
assert_allclose(trapezoid(m(x), x=x), 10)

# Descending.
x2 = x[::-1]
assert_allclose(abs(np.trapz(m(x2), x=x2)), 10)
assert_allclose(abs(trapezoid(m(x2), x=x2)), 10)
2 changes: 0 additions & 2 deletions synphot/tests/test_units.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,6 @@

.. note:: VEGAMAG conversion is tested in test_spectrum_source.py.

.. note:: spectral_density_integrated is tested in astropy>=4.1.

"""

# THIRD-PARTY
Expand Down
14 changes: 9 additions & 5 deletions tox.ini
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[tox]
envlist =
py{38,39,310,311}-test{,-alldeps,-oldestdeps,-devdeps,-predeps}{,-cov}
py{39,310,311}-test{,-alldeps,-oldestdeps,-devdeps,-predeps}{,-cov}
codestyle
twine
bandit
Expand All @@ -10,6 +10,8 @@ requires =
pip >= 19.3.1

[testenv]
setenv =
devdeps: PIP_EXTRA_INDEX_URL = https://pypi.anaconda.org/astropy/simple https://pypi.anaconda.org/scientific-python-nightly-wheels/simple

# Pass through the following environemnt variables which are needed for the CI
passenv = HOME,WINDIR,CC,CI
Expand Down Expand Up @@ -37,12 +39,15 @@ deps =

# The oldestdeps factor is intended to be used to install the oldest versions of all
# dependencies that have a minimum version.
oldestdeps: numpy==1.18.*
oldestdeps: scipy==1.3.*
oldestdeps: astropy==4.3.*
oldestdeps: numpy==1.20.*
oldestdeps: scipy==1.6.*
oldestdeps: astropy==5.0.*

# The devdeps factor is intended to be used to install the latest developer version
# or nightly wheel of key dependencies.
devdeps: numpy>=0.0.dev0
devdeps: scipy>=0.0.dev0
devdeps: astropy>=0.0.dev0
devdeps: git+https://github.com/astropy/specutils.git@main#egg=specutils

cov: pytest-cov
Expand All @@ -52,7 +57,6 @@ extras =
alldeps: all

commands =
devdeps: pip install -U -i https://pypi.anaconda.org/astropy/simple astropy --pre
pip freeze
!cov: pytest --pyargs synphot {toxinidir}/docs {posargs}
cov: pytest --pyargs synphot {toxinidir}/docs --cov synphot --cov-config={toxinidir}/setup.cfg {posargs}
Expand Down