Skip to content

Adopt the array api #885

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

Open
wants to merge 46 commits into
base: main
Choose a base branch
from
Open

Adopt the array api #885

wants to merge 46 commits into from

Conversation

mwcraig
Copy link
Member

@mwcraig mwcraig commented Mar 19, 2025

This PR makes the necessary changes to adopt the array API. There are still some things to sort out:

  • Run tests mostly against numpy, but do one run against jax (or some other non-numpy array library)
  • Check for remaining invocations of numpy in the code.
  • Check whether changing .data_arr.mask to .data_arr_mask constitutes an API change. If it does (and I think it does) then patch things up so that .data_arr.mask points to .data_arr_mask
  • Clean up any remaining handling of immutable arrays (array_api_extra makes handling those easy)

Once those are done the next step will be to find an outside reviewer for this...

@mwcraig mwcraig added this to the 2.5.0 milestone Mar 19, 2025
Copy link

codecov bot commented Mar 20, 2025

Codecov Report

Attention: Patch coverage is 98.91304% with 2 lines in your changes missing coverage. Please review.

Project coverage is 97.82%. Comparing base (aca218e) to head (c8f8da3).
Report is 15 commits behind head on main.

Files with missing lines Patch % Lines
ccdproc/core.py 97.70% 2 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main     #885      +/-   ##
==========================================
- Coverage   97.87%   97.82%   -0.05%     
==========================================
  Files           7        7              
  Lines        1271     1334      +63     
==========================================
+ Hits         1244     1305      +61     
- Misses         27       29       +2     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@mwcraig mwcraig force-pushed the explore-array-api branch from 85625f0 to 04293b7 Compare March 27, 2025 18:05
@mwcraig mwcraig marked this pull request as ready for review June 24, 2025 14:55
@mwcraig mwcraig changed the title WIP: Adopt the array api Adopt the array api Jun 24, 2025
@mwcraig mwcraig requested a review from Copilot June 24, 2025 16:42
Copy link

@Copilot Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

This PR transitions the codebase to use the Array API via array_api_compat and array_api_extra, updates CI and test environments to run against non-NumPy backends (JAX, Dask), and renames the combiner’s mask attribute from .data_arr.mask to .data_arr_mask.

  • Swap direct NumPy calls for array_api_compat calls and inject xp namespaces.
  • Extend tox.ini, CI workflows, and pyproject.toml to test with JAX, Dask, and bump supported Python/NumPy versions.
  • Rename .data_arr.mask to .data_arr_mask in code and documentation.

Reviewed Changes

Copilot reviewed 17 out of 18 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
tox.ini Added JAX/Dask CCDPROC_ARRAY_LIBRARY settings for array tests.
pyproject.toml Bumped requires-python and NumPy version; added Array API deps.
docs/image_combination.rst Updated examples to use .data_arr_mask instead of .mask.
ccdproc/combiner.py Introduced data_arr_mask, removed masked array, use Array API.
ccdproc/core.py Replaced NumPy calls with array_api_compat namespace calls.
Comments suppressed due to low confidence (2)

ccdproc/combiner.py:190

  • For backward compatibility with code expecting self.data_arr.mask, add an alias or property so that self.data_arr.mask returns self.data_arr_mask.
        self.data_arr_mask = xp.array(mask_list, dtype=bool)

docs/image_combination.rst:107

  • The documentation now references data_arr_mask instead of data_arr.mask. Ensure the API change is documented and consider providing a deprecation note or alias for data_arr.mask.
    >>> new_n_masked = combiner.data_arr_mask.sum()

crflux = 10 * scale * rng.random(NCRAYS) + (threshold + 15) * scale
crflux = xp.asarray(10 * scale * rng.random(ncrays) + (threshold + 15) * scale)

# Some array libraris (Dask) do not support setting individual elements,
Copy link
Preview

Copilot AI Jun 24, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fix typo in comment: "libraris" should be "libraries".

Suggested change
# Some array libraris (Dask) do not support setting individual elements,
# Some array libraries (Dask) do not support setting individual elements,

Copilot uses AI. Check for mistakes.

crflux = xp.asarray(10 * scale * rng.random(ncrays) + (threshold + 15) * scale)

# Some array libraris (Dask) do not support setting individual elements,
# so use nuympy.
Copy link
Preview

Copilot AI Jun 24, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fix typo in comment: "nuympy" should be "NumPy".

Suggested change
# so use nuympy.
# so use NumPy.

Copilot uses AI. Check for mistakes.

@eteq
Copy link
Member

eteq commented Jun 24, 2025

As a quick FYI I ran the test suite in this PR on a machine with a NVidia GPU with CCDPROC_ARRAY_LIBRARY=cupy and got a whole pile of errors (sent the log directly to @mwcraig but can also share snippets here if someone else wants to see them)

@@ -145,6 +148,7 @@ filterwarnings= [
"ignore:numpy\\.ufunc size changed:RuntimeWarning",
"ignore:numpy.ndarray size changed:RuntimeWarning",
"ignore:`np.bool` is a deprecated alias for the builtin `bool`:DeprecationWarning",
"ignore:invalid value encountered in sqrt:RuntimeWarning",
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd suggest adding a comment recording why the ignore is necessary, which helps figuring out when it isn't.

try:
import bottleneck as bn
except ImportError:
HAS_BOTTLENECK = False # pragma: no cover
else:
HAS_BOTTLENECK = True

import array_api_compat
import array_api_extra as xpx
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I like the alias.

Comment on lines +183 to +188
mask_list = []
for ccd in ccd_list:
if ccd.mask is not None:
self.data_arr.mask[i] = ccd.mask
mask_list.append(ccd.mask)
else:
self.data_arr.mask[i] = ma.zeros(default_shape)
mask_list.append(xp.zeros(default_shape))
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this can be sped up through list comprehension and made a one liner.
mask_list = [ccd.mask if ccd.mask is not None else xp.zeros(default_shape) for ccd in ccd_list]

@@ -8,17 +8,19 @@ dynamic = ["version"]
description = "Astropy affiliated package"
readme = "README.rst"
license = { text = "BSD-3-Clause" }
requires-python = ">=3.8"
requires-python = ">=3.11"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Adopt Spec 0? Has that been adopted?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants