Skip to content

Commit

Permalink
MORE
Browse files Browse the repository at this point in the history
  • Loading branch information
nabobalis committed May 10, 2024
1 parent c3b5755 commit 601cb5b
Show file tree
Hide file tree
Showing 36 changed files with 454 additions and 361 deletions.
11 changes: 5 additions & 6 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ jobs:
toxdeps: tox-pypi-filter
posargs: -n auto
envs: |
- linux: py311
- linux: py312
secrets:
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}

Expand All @@ -42,15 +42,15 @@ jobs:
posargs: -n auto
envs: |
- windows: py310
- macos: py39
- macos: py311
secrets:
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}

docs:
needs: [core]
uses: OpenAstronomy/github-actions-workflows/.github/workflows/tox.yml@main
with:
default_python: "3.9"
default_python: "3.12"
submodules: false
pytest: false
toxdeps: tox-pypi-filter
Expand All @@ -69,13 +69,12 @@ jobs:
needs: [docs]
uses: OpenAstronomy/github-actions-workflows/.github/workflows/tox.yml@main
with:
default_python: "3.9"
submodules: false
coverage: codecov
toxdeps: tox-pypi-filter
posargs: -n auto --dist loadgroup
envs: |
- linux: py39-online
- linux: py312-online
secrets:
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}

Expand All @@ -95,7 +94,7 @@ jobs:
needs: [test]
uses: OpenAstronomy/github-actions-workflows/.github/workflows/publish_pure_python.yml@main
with:
python-version: "3.10"
python-version: "3.12"
test_extras: "all,tests"
test_command: 'pytest -p no:warnings --doctest-rst -m "not mpl_image_compare" --pyargs sunpy'
submodules: false
Expand Down
29 changes: 15 additions & 14 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
exclude: ".*(.fits|.fts|.fit|.txt|.csv)$"
repos:
- repo: https://github.com/myint/docformatter
rev: v1.7.5
hooks:
- id: docformatter
args: [--in-place, --pre-summary-newline, --make-summary-multi]
args: ["--in-place", "--pre-summary-newline", "--make-summary-multi"]
- repo: https://github.com/myint/autoflake
rev: v2.3.1
hooks:
Expand All @@ -21,25 +20,27 @@ repos:
hooks:
- id: ruff
args: ["--fix", "--unsafe-fixes"]
- repo: https://github.com/psf/black
rev: 24.4.2
hooks:
- id: black
- repo: https://github.com/PyCQA/isort
rev: 5.13.2
hooks:
- id: isort
- repo: https://github.com/pre-commit/mirrors-prettier
rev: v4.0.0-alpha.8
hooks:
- id: prettier
- id: ruff-format
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v4.6.0
hooks:
- id: check-ast
- id: check-case-conflict
- id: trailing-whitespace
exclude: ".*(.fits|.fts|.fit|.txt|.csv)$"
- id: mixed-line-ending
exclude: ".*(.fits|.fts|.fit|.txt|.csv)$"
- id: end-of-file-fixer
exclude: ".*(.fits|.fts|.fit|.txt|.csv)$"
- id: check-yaml
- id: debug-statements
- repo: https://github.com/codespell-project/codespell
rev: v2.2.6
hooks:
- id: codespell
additional_dependencies:
- tomli
- repo: https://github.com/pre-commit/mirrors-prettier
rev: v4.0.0-alpha.8
hooks:
- id: prettier
2 changes: 1 addition & 1 deletion CHANGELOG.rst
Original file line number Diff line number Diff line change
Expand Up @@ -235,7 +235,7 @@ Features
- :func:`aiapy.calibrate.degradation` can now accept `~astropy.time.Time` objects with length greater than 1.
This makes it easier to compute the channel degradation over long intervals. (`#80 <https://gitlab.com/LMSAL_HUB/aia_hub/aiapy/-/merge_requests/80>`__)
- Citation information for `aiapy` is now available from ``aiapy.__citation__``. (`#82 <https://gitlab.com/LMSAL_HUB/aia_hub/aiapy/-/merge_requests/82>`__)
- The pointing table can now be passsed in as a keyword argument to :func:`aiapy.calibrate.update_pointing`.
- The pointing table can now be passed in as a keyword argument to :func:`aiapy.calibrate.update_pointing`.
Added a :func:`aiapy.calibrate.util.get_pointing_table` to retrieve the 3-hour pointing table from JSOC over a given time interval. (`#84 <https://gitlab.com/LMSAL_HUB/aia_hub/aiapy/-/merge_requests/84>`__)

Bug Fixes
Expand Down
2 changes: 1 addition & 1 deletion aiapy/__init__.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
from pathlib import Path
from itertools import compress
from pathlib import Path

from .version import version as __version__

Expand Down
10 changes: 5 additions & 5 deletions aiapy/calibrate/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@
Subpackage for calibrating AIA imaging data.
"""

from .meta import * # NOQA
from .prep import * # NOQA
from .spikes import * # NOQA
from .transform import * # NOQA
from .uncertainty import * # NOQA
from .meta import * # NOQA: F403
from .prep import * # NOQA: F403
from .spikes import * # NOQA: F403
from .transform import * # NOQA: F403
from .uncertainty import * # NOQA: F403
19 changes: 12 additions & 7 deletions aiapy/calibrate/meta.py
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ def fix_observer_location(smap):
new_meta["hglt_obs"] = coord.lat.to(u.degree).value
new_meta["dsun_obs"] = coord.radius.to(u.m).value

return smap._new_instance(smap.data, new_meta, plot_settings=smap.plot_settings, mask=smap.mask)
return smap._new_instance(smap.data, new_meta, plot_settings=smap.plot_settings, mask=smap.mask) # NOQA: SLF001


def update_pointing(smap, *, pointing_table=None):
Expand Down Expand Up @@ -104,10 +104,12 @@ def update_pointing(smap, *, pointing_table=None):
`aiapy.calibrate.util.get_pointing_table`
"""
if not contains_full_disk(smap):
raise ValueError("Input must be a full disk image.")
msg = "Input must be a full disk image."
raise ValueError(msg)

Check warning on line 108 in aiapy/calibrate/meta.py

View check run for this annotation

Codecov / codecov/patch

aiapy/calibrate/meta.py#L107-L108

Added lines #L107 - L108 were not covered by tests
shape_full_frame = (4096, 4096)
if not all(d == (s * u.pixel) for d, s in zip(smap.dimensions, shape_full_frame)):
raise ValueError(f"Input must be at the full resolution of {shape_full_frame}")
if not all(d == (s * u.pixel) for d, s in zip(smap.dimensions, shape_full_frame, strict=True)):
msg = f"Input must be at the full resolution of {shape_full_frame}"
raise ValueError(msg)

Check warning on line 112 in aiapy/calibrate/meta.py

View check run for this annotation

Codecov / codecov/patch

aiapy/calibrate/meta.py#L111-L112

Added lines #L111 - L112 were not covered by tests
if pointing_table is None:
# Make range wide enough to get closest 3-hour pointing
pointing_table = get_pointing_table(smap.date - 12 * u.h, smap.date + 12 * u.h)
Expand All @@ -134,10 +136,13 @@ def update_pointing(smap, *, pointing_table=None):
t_obs = astropy.time.Time(t_obs)
t_obs_in_interval = np.logical_and(t_obs >= pointing_table["T_START"], t_obs < pointing_table["T_STOP"])
if not t_obs_in_interval.any():
raise IndexError(
msg = (

Check warning on line 139 in aiapy/calibrate/meta.py

View check run for this annotation

Codecov / codecov/patch

aiapy/calibrate/meta.py#L139

Added line #L139 was not covered by tests
f"No valid entries for {t_obs} in pointing table "
f'with first T_START date of {pointing_table[0]["T_START"]} '
f'and a last T_STOP date of {pointing_table[-1]["T_STOP"]}.',
f'and a last T_STOP date of {pointing_table[-1]["T_STOP"]}.'
)
raise IndexError(

Check warning on line 144 in aiapy/calibrate/meta.py

View check run for this annotation

Codecov / codecov/patch

aiapy/calibrate/meta.py#L144

Added line #L144 was not covered by tests
msg,
)
i_nearest = np.where(t_obs_in_interval)[0][0]
w_str = f"{smap.wavelength.to(u.angstrom).value:03.0f}"
Expand Down Expand Up @@ -185,4 +190,4 @@ def update_pointing(smap, *, pointing_table=None):
new_meta.pop("PC1_2")
new_meta.pop("PC2_1")
new_meta.pop("PC2_2")
return smap._new_instance(smap.data, new_meta, plot_settings=smap.plot_settings, mask=smap.mask)
return smap._new_instance(smap.data, new_meta, plot_settings=smap.plot_settings, mask=smap.mask) # NOQA: SLF001
8 changes: 5 additions & 3 deletions aiapy/calibrate/prep.py
Original file line number Diff line number Diff line change
Expand Up @@ -69,10 +69,12 @@ def register(smap, *, missing=None, order=3, method="scipy"):
# This implementation is taken directly from the `aiaprep` method in
# sunpy.instr.aia.aiaprep under the terms of the BSD 2 Clause license.
# See licenses/SUNPY.rst.
if not isinstance(smap, (AIAMap, HMIMap)):
raise ValueError("Input must be an AIAMap or HMIMap.")
if not isinstance(smap, AIAMap | HMIMap):
msg = "Input must be an AIAMap or HMIMap."
raise TypeError(msg)
if not contains_full_disk(smap):
raise ValueError("Input must be a full disk image.")
msg = "Input must be a full disk image."
raise ValueError(msg)
if smap.processing_level is None or smap.processing_level > 1:
warnings.warn(
"Image registration should only be applied to level 1 data",
Expand Down
13 changes: 8 additions & 5 deletions aiapy/calibrate/spikes.py
Original file line number Diff line number Diff line change
Expand Up @@ -63,9 +63,11 @@ def respike(smap, *, spikes=None):
`fetch_spikes`
"""
if not isinstance(smap, AIAMap):
raise ValueError("Input must be an AIAMap.")
msg = "Input must be an AIAMap."
raise TypeError(msg)

Check warning on line 67 in aiapy/calibrate/spikes.py

View check run for this annotation

Codecov / codecov/patch

aiapy/calibrate/spikes.py#L66-L67

Added lines #L66 - L67 were not covered by tests
if smap.meta["lvl_num"] != 1.0:
raise ValueError("Can only apply respike procedure to level 1 data")
msg = "Can only apply respike procedure to level 1 data"
raise ValueError(msg)

Check warning on line 70 in aiapy/calibrate/spikes.py

View check run for this annotation

Codecov / codecov/patch

aiapy/calibrate/spikes.py#L69-L70

Added lines #L69 - L70 were not covered by tests
# Approximate check to make sure the input map has not been interpolated
# in any way. Note that the level 1 plate scales are not exactly 0.6
# ''/pixel, but should not differ by more than 0.1%. This is only a
Expand All @@ -88,7 +90,8 @@ def respike(smap, *, spikes=None):
# Or better yet, why can't the logic below just handle the case of
# no spikes?
if smap.meta["nspikes"] == 0:
raise ValueError("No spikes were present in the level 0 data.")
msg = "No spikes were present in the level 0 data."
raise ValueError(msg)

Check warning on line 94 in aiapy/calibrate/spikes.py

View check run for this annotation

Codecov / codecov/patch

aiapy/calibrate/spikes.py#L93-L94

Added lines #L93 - L94 were not covered by tests
if spikes is None:
coords, values = fetch_spikes(smap, as_coords=False)
else:
Expand All @@ -102,7 +105,7 @@ def respike(smap, *, spikes=None):
new_meta["lvl_num"] = 0.5
new_meta["comments"] = f"Respike applied; {values.shape[0]} hot pixels reinserted."
new_meta["nspikes"] = 0
return smap._new_instance(
return smap._new_instance( # NOQA: SLF001

Check warning on line 108 in aiapy/calibrate/spikes.py

View check run for this annotation

Codecov / codecov/patch

aiapy/calibrate/spikes.py#L108

Added line #L108 was not covered by tests
new_data,
new_meta,
plot_settings=smap.plot_settings,
Expand Down Expand Up @@ -151,7 +154,7 @@ def fetch_spikes(smap, *, as_coords=False):
# If this is a cutout, need to transform the full-frame pixel
# coordinates into the cutout pixel coordinates and then only select
# those in the FOV of the cutout
if not all(d == (s * u.pixel) for d, s in zip(smap.dimensions, shape_full_frame)):
if not all(d == (s * u.pixel) for d, s in zip(smap.dimensions, shape_full_frame, strict=True)):

Check warning on line 157 in aiapy/calibrate/spikes.py

View check run for this annotation

Codecov / codecov/patch

aiapy/calibrate/spikes.py#L157

Added line #L157 was not covered by tests
# Construct WCS for full frame
wcs_full_frame = copy.deepcopy(smap.wcs)
wcs_full_frame.wcs.crval = np.array([0.0, 0.0])
Expand Down
6 changes: 3 additions & 3 deletions aiapy/calibrate/tests/test_prep.py
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ def test_register_unsupported_maps(aia_171_map, non_sdo_map):
with pytest.raises(ValueError, match="Input must be a full disk image."):
register(original_cutout)
# A Map besides AIA or HMI
with pytest.raises(ValueError, match="Input must be an AIAMap"):
with pytest.raises(TypeError, match="Input must be an AIAMap"):
register(non_sdo_map)


Expand All @@ -95,7 +95,7 @@ def test_register_level_15(lvl_15_map):
AiapyUserWarning,
match="Image registration should only be applied to level 1 data",
):
register(lvl_15_map._new_instance(lvl_15_map.data, new_meta))
register(lvl_15_map._new_instance(lvl_15_map.data, new_meta)) # NOQA: SLF001


@pytest.mark.parametrize(
Expand Down Expand Up @@ -256,7 +256,7 @@ def test_degradation_time_array():
calibration_version=8,
)
assert time_correction.shape == obstime.shape
for o, tc in zip(obstime, time_correction):
for o, tc in zip(obstime, time_correction, strict=True):
assert tc == degradation(94 * u.angstrom, o, correction_table=correction_table, calibration_version=8)


Expand Down
22 changes: 11 additions & 11 deletions aiapy/calibrate/tests/test_spikes.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@
from aiapy.util import AiapyUserWarning


@pytest.mark.remote_data()
@pytest.fixture()
def despiked_map():
# Need an actual 4K-by-4K map to do the spike replacement
Expand All @@ -20,13 +19,11 @@ def despiked_map():
)


@pytest.mark.remote_data()
@pytest.fixture()
def respiked_map(despiked_map):
return respike(despiked_map)


@pytest.mark.remote_data()
@pytest.fixture()
def spikes(despiked_map):
return fetch_spikes(despiked_map)
Expand All @@ -35,7 +32,7 @@ def spikes(despiked_map):
@pytest.mark.remote_data()
def test_respike(respiked_map, spikes):
coords, values = spikes
for x, y, v in zip(coords.x.value, coords.y.value, values):
for x, y, v in zip(coords.x.value, coords.y.value, values, strict=True):

Check warning on line 35 in aiapy/calibrate/tests/test_spikes.py

View check run for this annotation

Codecov / codecov/patch

aiapy/calibrate/tests/test_spikes.py#L35

Added line #L35 was not covered by tests
assert v == respiked_map.data[int(y), int(x)]


Expand Down Expand Up @@ -70,24 +67,27 @@ def test_cutout(respiked_map, despiked_map):

@pytest.mark.remote_data()
@pytest.mark.parametrize(
("key", "value", "match"),
("key", "value", "error", "match"),
[
("lvl_num", 1.5, "Can only apply respike procedure to level 1 data"),
("nspikes", 0, "No spikes were present in the level 0 data."),
("instrume", "not AIA", "Input must be an AIAMap."),
("lvl_num", 1.5, ValueError, "Can only apply respike procedure to level 1 data"),
("nspikes", 0, ValueError, "No spikes were present in the level 0 data."),
("instrume", "not AIA", TypeError, "Input must be an AIAMap."),
],
)
def test_exceptions(despiked_map, key, value, match):
def test_exceptions(despiked_map, key, value, error, match):
new_meta = copy.deepcopy(despiked_map.meta)
new_meta[key] = value
with pytest.raises(ValueError, match=match):
with pytest.raises(error, match=match):

Check warning on line 80 in aiapy/calibrate/tests/test_spikes.py

View check run for this annotation

Codecov / codecov/patch

aiapy/calibrate/tests/test_spikes.py#L80

Added line #L80 was not covered by tests
respike(sunpy.map.Map(despiked_map.data, new_meta))


@pytest.mark.remote_data()
def test_resample_warning(despiked_map):
despiked_map_resample = despiked_map.resample((512, 512) * u.pixel)
with pytest.warns(AiapyUserWarning):
with (

Check warning on line 87 in aiapy/calibrate/tests/test_spikes.py

View check run for this annotation

Codecov / codecov/patch

aiapy/calibrate/tests/test_spikes.py#L87

Added line #L87 was not covered by tests
pytest.warns(AiapyUserWarning, match="is significantly different from the expected level 1 plate scale"),
pytest.warns(ResourceWarning),
):
respike(despiked_map_resample)


Expand Down
2 changes: 1 addition & 1 deletion aiapy/calibrate/tests/test_util.py
Original file line number Diff line number Diff line change
Expand Up @@ -134,5 +134,5 @@ def test_error_table(error_table):


def test_invalid_error_table_input():
with pytest.raises(ValueError, match="error_table must be a file path, an existing table, or None."):
with pytest.raises(TypeError, match="error_table must be a file path, an existing table, or None"):
get_error_table(error_table=-1)
7 changes: 4 additions & 3 deletions aiapy/calibrate/transform.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,10 @@
handles_image_nans=False,
handles_nan_missing=True,
)
def _rotation_cupy(image, matrix, shift, order, missing, clip):
def _rotation_cupy(image, matrix, shift, order, missing, clip): # NOQA: ARG001
"""
* Rotates using `cupyx.scipy.ndimage.affine_transform` from `cupy <https://docs.cupy.dev/en/stable/index.html>`__
* Coverts from a numpy array to a cupy array and then back again.
* Converts from a numpy array to a cupy array and then back again.
* The ``order`` parameter is the order of the spline interpolation, and ranges
from 0 to 5.
* The ``mode`` parameter for :func:`~cupyx.scipy.ndimage.affine_transform` is fixed to
Expand All @@ -23,8 +23,9 @@ def _rotation_cupy(image, matrix, shift, order, missing, clip):
import cupy
import cupyx.scipy.ndimage
except ImportError as e:
msg = "cupy or cupy-cuda* (pre-compiled for each cuda version) is required to use this rotation method."

Check warning on line 26 in aiapy/calibrate/transform.py

View check run for this annotation

Codecov / codecov/patch

aiapy/calibrate/transform.py#L26

Added line #L26 was not covered by tests
raise ImportError(
"cupy or cupy-cuda* (pre-compiled for each cuda version) is required to use this rotation method.",
msg,
) from e
rotated_image = cupyx.scipy.ndimage.affine_transform(
cupy.array(image).T,
Expand Down
3 changes: 2 additions & 1 deletion aiapy/calibrate/uncertainty.py
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,8 @@ def estimate_error(

# Photometric calibration
if include_eve and include_preflight:
raise ValueError("Cannot include both EVE and pre-flight correction.")
msg = "Cannot include both EVE and pre-flight correction."
raise ValueError(msg)
calib = 0
if include_eve:
calib = error_table["EVEERR"]
Expand Down
Loading

0 comments on commit 601cb5b

Please sign in to comment.