Skip to content

Commit 3b2b9fc

Browse files
committed
Use array API in all cosmic ray tests
1 parent e03dbcb commit 3b2b9fc

3 files changed

Lines changed: 31 additions & 33 deletions

File tree

ccdproc/combiner.py

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -500,8 +500,7 @@ def median_combine(
500500
Parameters
501501
----------
502502
median_func : function, optional
503-
Function that calculates median of a `numpy.ma.MaskedArray`.
504-
Default is `numpy.ma.median`.
503+
Function that calculates median of an array.
505504
506505
scale_to : float or None, optional
507506
Scaling factor used in the average combined image. If given,
@@ -612,19 +611,18 @@ def average_combine(
612611
Parameters
613612
----------
614613
scale_func : function, optional
615-
Function to calculate the average. Defaults to
616-
`numpy.nanmean`.
614+
Function to calculate the average.
617615
618616
scale_to : float or None, optional
619617
Scaling factor used in the average combined image. If given,
620618
it overrides `scaling`. Defaults to ``None``.
621619
622620
uncertainty_func : function, optional
623-
Function to calculate uncertainty. Defaults to `numpy.ma.std`.
621+
Function to calculate uncertainty.
624622
625623
sum_func : function, optional
626624
Function used to calculate sums, including the one done to
627-
find the weighted average. Defaults to `numpy.nansum`.
625+
find the weighted average.
628626
629627
Returns
630628
-------
@@ -706,7 +704,7 @@ def sum_combine(
706704
it overrides `scaling`. Defaults to ``None``.
707705
708706
uncertainty_func : function, optional
709-
Function to calculate uncertainty. Defaults to `numpy.ma.std`.
707+
Function to calculate uncertainty.
710708
711709
Returns
712710
-------

ccdproc/core.py

Lines changed: 20 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
import warnings
99

1010
import array_api_compat
11+
import array_api_extra as xpx
1112
from astropy import nddata, stats
1213
from astropy import units as u
1314
from astropy.modeling import fitting
@@ -101,7 +102,7 @@ def _percentile_fallback(array, percentiles, xp=None): # pragma: no cover
101102
102103
Parameters
103104
----------
104-
array : array-like
105+
array : array_like
105106
Array from which to calculate the percentile.
106107
107108
percentiles : float or list-like
@@ -1205,7 +1206,7 @@ def setbox(x, y, mbox, xmax, ymax):
12051206
return x1, x2, y1, y2
12061207

12071208

1208-
def background_deviation_box(data, bbox):
1209+
def background_deviation_box(data, bbox, xp=None):
12091210
"""
12101211
Determine the background deviation with a box size of bbox. The algorithm
12111212
steps through the image and calculates the deviation within each box.
@@ -1214,34 +1215,43 @@ def background_deviation_box(data, bbox):
12141215
12151216
Parameters
12161217
----------
1217-
data : `numpy.ndarray` or `numpy.ma.MaskedArray`
1218+
data : `numpy.ndarray` or other array_like
12181219
Data to measure background deviation.
12191220
12201221
bbox : int
12211222
Box size for calculating background deviation.
12221223
1224+
xp : array namespace, optional
1225+
Array namespace to use for calculations. If not provided, the
1226+
namespace will be determined from the array.
1227+
12231228
Raises
12241229
------
12251230
ValueError
12261231
A value error is raised if bbox is less than 1.
12271232
12281233
Returns
12291234
-------
1230-
background : `numpy.ndarray` or `numpy.ma.MaskedArray`
1235+
background : array_like
12311236
An array with the measured background deviation in each pixel.
12321237
"""
12331238
# Check to make sure the background box is an appropriate size
12341239
# If it is too small, then insufficient statistics are generated
12351240
if bbox < 1:
12361241
raise ValueError("bbox must be greater than 1.")
12371242

1243+
if xp is None:
1244+
# Get the array namespace
1245+
xp = array_api_compat.array_namespace(data)
12381246
# make the background image
1239-
barr = data * 0.0 + data.std()
1247+
barr = data * 0.0 + xp.std(data)
12401248
ylen, xlen = data.shape
12411249
for i in range(int(0.5 * bbox), xlen, bbox):
12421250
for j in range(int(0.5 * bbox), ylen, bbox):
12431251
x1, x2, y1, y2 = setbox(i, j, bbox, xlen, ylen)
1244-
barr[y1:y2, x1:x2] = sigma_func(data[y1:y2, x1:x2])
1252+
xpx.at(barr)[y1:y2, x1:x2].set(
1253+
xp.astype(sigma_func(data[y1:y2, x1:x2]), data.dtype)
1254+
)
12451255

12461256
return barr
12471257

@@ -1266,7 +1276,7 @@ def background_deviation_filter(data, bbox):
12661276
12671277
Returns
12681278
-------
1269-
background : `numpy.ndarray` or `numpy.ma.MaskedArray`
1279+
background : `numpy.ndarray`
12701280
An array with the measured background deviation in each pixel.
12711281
"""
12721282
# Check to make sure the background box is an appropriate size
@@ -1861,7 +1871,7 @@ def cosmicray_median(ccd, error_image=None, thresh=5, mbox=11, gbox=0, rbox=0, x
18611871
18621872
Parameters
18631873
----------
1864-
ccd : `~astropy.nddata.CCDData`, `numpy.ndarray` or `numpy.ma.MaskedArray`
1874+
ccd : `~astropy.nddata.CCDData`, `numpy.ndarray` or other array_like
18651875
Data to have cosmic ray cleaned.
18661876
18671877
thresh : float, optional
@@ -2079,7 +2089,7 @@ def ccdmask(
20792089
-------
20802090
mask : `numpy.ndarray`
20812091
A boolean ndarray where the bad pixels have a value of 1 (True) and
2082-
valid pixels 0 (False), following the numpy.ma conventions.
2092+
valid pixels 0 (False), following the numpy convention for masking.
20832093
20842094
Notes
20852095
-----
@@ -2235,8 +2245,7 @@ def bitfield_to_boolean_mask(bitfield, ignore_bits=0, flip_bits=None):
22352245
Returns
22362246
-------
22372247
mask : `numpy.ndarray` of boolean dtype
2238-
The bitfield converted to a boolean mask that can be used for
2239-
`numpy.ma.MaskedArray` or `~astropy.nddata.CCDData`.
2248+
The bitfield converted to a boolean mask.
22402249
22412250
Examples
22422251
--------

ccdproc/tests/test_cosmicray.py

Lines changed: 6 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
# Licensed under a 3-clause BSD style license - see LICENSE.rst
22

3-
import array_api_compat
43
import pytest
54
from astropy import units as u
65
from astropy.utils.exceptions import AstropyDeprecationWarning
@@ -9,6 +8,8 @@
98
from numpy.random import default_rng
109
from numpy.testing import assert_allclose
1110

11+
# Set up the array library to be used in tests
12+
from ccdproc.conftest import testing_array_library as xp
1213
from ccdproc.core import (
1314
background_deviation_box,
1415
background_deviation_filter,
@@ -26,7 +27,6 @@
2627
def add_cosmicrays(data, scale, threshold, ncrays=NCRAYS):
2728
size = data.shape[0]
2829
rng = default_rng(99)
29-
xp = array_api_compat.array_namespace(data.data)
3030
crrays = xp.asarray(rng.integers(0, size, size=(ncrays, 2)))
3131
# use (threshold + 15) below to make sure cosmic ray is well above the
3232
# threshold no matter what the random number generator returns
@@ -58,7 +58,6 @@ def test_cosmicray_lacosmic():
5858

5959
def test_cosmicray_lacosmic_ccddata():
6060
ccd_data = ccd_data_func(data_scale=DATA_SCALE)
61-
xp = array_api_compat.array_namespace(ccd_data.data)
6261
threshold = 5
6362
add_cosmicrays(ccd_data, DATA_SCALE, threshold, ncrays=NCRAYS)
6463
noise = DATA_SCALE * xp.ones_like(ccd_data.data)
@@ -75,7 +74,6 @@ def test_cosmicray_lacosmic_ccddata():
7574

7675
def test_cosmicray_lacosmic_check_data():
7776
ccd_data = ccd_data_func(data_scale=DATA_SCALE)
78-
xp = array_api_compat.array_namespace(ccd_data.data)
7977
with pytest.raises(TypeError):
8078
noise = DATA_SCALE * xp.ones_like(ccd_data.data)
8179
cosmicray_lacosmic(10, noise)
@@ -90,7 +88,6 @@ def test_cosmicray_gain_correct(array_input, gain_correct_data):
9088
# data and returns that gain corrected data. That is not the
9189
# intent...
9290
ccd_data = ccd_data_func(data_scale=DATA_SCALE)
93-
xp = array_api_compat.array_namespace(ccd_data.data)
9491
threshold = 5
9592
add_cosmicrays(ccd_data, DATA_SCALE, threshold, ncrays=NCRAYS)
9693
noise = DATA_SCALE * xp.ones_like(ccd_data.data)
@@ -123,7 +120,6 @@ def test_cosmicray_gain_correct(array_input, gain_correct_data):
123120

124121
def test_cosmicray_lacosmic_accepts_quantity_gain():
125122
ccd_data = ccd_data_func(data_scale=DATA_SCALE)
126-
xp = array_api_compat.array_namespace(ccd_data.data)
127123
threshold = 5
128124
add_cosmicrays(ccd_data, DATA_SCALE, threshold, ncrays=NCRAYS)
129125
noise = DATA_SCALE * xp.ones_like(ccd_data.data)
@@ -138,7 +134,6 @@ def test_cosmicray_lacosmic_accepts_quantity_gain():
138134

139135
def test_cosmicray_lacosmic_accepts_quantity_readnoise():
140136
ccd_data = ccd_data_func(data_scale=DATA_SCALE)
141-
xp = array_api_compat.array_namespace(ccd_data.data)
142137
threshold = 5
143138
add_cosmicrays(ccd_data, DATA_SCALE, threshold, ncrays=NCRAYS)
144139
noise = DATA_SCALE * xp.ones_like(ccd_data.data)
@@ -156,7 +151,6 @@ def test_cosmicray_lacosmic_detects_inconsistent_units():
156151
# of adu, a readnoise in electrons and a gain in adu / electron.
157152
# That is not internally inconsistent.
158153
ccd_data = ccd_data_func(data_scale=DATA_SCALE)
159-
xp = array_api_compat.array_namespace(ccd_data.data)
160154
ccd_data.unit = "adu"
161155
threshold = 5
162156
add_cosmicrays(ccd_data, DATA_SCALE, threshold, ncrays=NCRAYS)
@@ -176,7 +170,6 @@ def test_cosmicray_lacosmic_detects_inconsistent_units():
176170
def test_cosmicray_lacosmic_warns_on_ccd_in_electrons():
177171
# Check that an input ccd in electrons raises a warning.
178172
ccd_data = ccd_data_func(data_scale=DATA_SCALE)
179-
xp = array_api_compat.array_namespace(ccd_data.data)
180173
# The unit below is important for the test; this unit on
181174
# input is supposed to raise an error.
182175
ccd_data.unit = u.electron
@@ -206,7 +199,6 @@ def test_cosmicray_lacosmic_invar_inbkg(new_args):
206199
# that calling with the new keyword arguments to astroscrappy
207200
# 1.1.0 raises no error.
208201
ccd_data = ccd_data_func(data_scale=DATA_SCALE)
209-
xp = array_api_compat.array_namespace(ccd_data.data)
210202
threshold = 5
211203
add_cosmicrays(ccd_data, DATA_SCALE, threshold, ncrays=NCRAYS)
212204
noise = DATA_SCALE * xp.ones_like(ccd_data.data)
@@ -304,28 +296,28 @@ def test_cosmicray_median_background_deviation():
304296

305297
def test_background_deviation_box():
306298
scale = 5.3
307-
cd = default_rng(seed=123).normal(loc=0, size=(100, 100), scale=scale)
299+
cd = xp.asarray(default_rng(seed=123).normal(loc=0, size=(100, 100), scale=scale))
308300
bd = background_deviation_box(cd, 25)
309301
assert abs(bd.mean() - scale) < 0.10
310302

311303

312304
def test_background_deviation_box_fail():
313305
scale = 5.3
314-
cd = default_rng(seed=123).normal(loc=0, size=(100, 100), scale=scale)
306+
cd = xp.asarray(default_rng(seed=123).normal(loc=0, size=(100, 100), scale=scale))
315307
with pytest.raises(ValueError):
316308
background_deviation_box(cd, 0.5)
317309

318310

319311
def test_background_deviation_filter():
320312
scale = 5.3
321-
cd = default_rng(seed=123).normal(loc=0, size=(100, 100), scale=scale)
313+
cd = xp.asarray(default_rng(seed=123).normal(loc=0, size=(100, 100), scale=scale))
322314
bd = background_deviation_filter(cd, 25)
323315
assert abs(bd.mean() - scale) < 0.10
324316

325317

326318
def test_background_deviation_filter_fail():
327319
scale = 5.3
328-
cd = default_rng(seed=123).normal(loc=0, size=(100, 100), scale=scale)
320+
cd = xp.asarray(default_rng(seed=123).normal(loc=0, size=(100, 100), scale=scale))
329321
with pytest.raises(ValueError):
330322
background_deviation_filter(cd, 0.5)
331323

@@ -356,7 +348,6 @@ def test_cosmicray_lacosmic_pssl_does_not_fail():
356348
# to make sure that passing in pssl does not lead to an error
357349
# since the new interface does not include pssl.
358350
ccd_data = ccd_data_func(data_scale=DATA_SCALE)
359-
xp = array_api_compat.array_namespace(ccd_data.data)
360351
threshold = 5
361352
add_cosmicrays(ccd_data, DATA_SCALE, threshold, ncrays=NCRAYS)
362353
noise = DATA_SCALE * xp.ones_like(ccd_data.data)

0 commit comments

Comments
 (0)