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 9136850
Show file tree
Hide file tree
Showing 34 changed files with 439 additions and 345 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=False)):
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=False)):

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
4 changes: 2 additions & 2 deletions aiapy/calibrate/tests/test_prep.py
Original file line number Diff line number Diff line change
Expand Up @@ -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=False):
assert tc == degradation(94 * u.angstrom, o, correction_table=correction_table, calibration_version=8)


Expand Down
4 changes: 2 additions & 2 deletions aiapy/calibrate/tests/test_spikes.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,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=False):

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

View check run for this annotation

Codecov / codecov/patch

aiapy/calibrate/tests/test_spikes.py#L38

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


Expand Down Expand Up @@ -87,7 +87,7 @@ def test_exceptions(despiked_map, key, value, match):
@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 pytest.warns(AiapyUserWarning, match="DEF"):

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

View check run for this annotation

Codecov / codecov/patch

aiapy/calibrate/tests/test_spikes.py#L90

Added line #L90 was not covered by tests
respike(despiked_map_resample)


Expand Down
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
21 changes: 12 additions & 9 deletions aiapy/calibrate/util.py
Original file line number Diff line number Diff line change
Expand Up @@ -72,10 +72,11 @@ def get_correction_table(*, correction_table=None):
if isinstance(correction_table, astropy.table.QTable):
return correction_table
if correction_table is not None:
if isinstance(correction_table, (str, pathlib.Path)):
if isinstance(correction_table, str | pathlib.Path):
table = QTable(astropy.io.ascii.read(correction_table))
else:
raise ValueError("correction_table must be a file path, an existing table, or None.")
msg = "correction_table must be a file path, an existing table, or None."
raise ValueError(msg)
else:
# NOTE: the [!1=1!] disables the drms PrimeKey logic and enables
# the query to find records that are ordinarily considered
Expand Down Expand Up @@ -143,7 +144,8 @@ def _select_epoch_from_correction_table(channel: u.angstrom, obstime, table, *,
# Select the epoch for the given observation time
obstime_in_epoch = np.logical_and(obstime >= table["T_START"], obstime < table["T_STOP"])
if not obstime_in_epoch.any():
raise ValueError(f"No valid calibration epoch for {obstime}")
msg = f"No valid calibration epoch for {obstime}"
raise ValueError(msg)
# NOTE: In some cases, there may be multiple entries for a single epoch. We want to
# use the most up-to-date one.
i_epoch = np.where(obstime_in_epoch)[0]
Expand Down Expand Up @@ -199,7 +201,8 @@ def get_pointing_table(start, end):
# If there's no pointing information available between these times,
# JSOC will raise a cryptic KeyError
# (see https://github.com/LM-SAL/aiapy/issues/71)
raise RuntimeError(f"Could not find any pointing information between {start} and {end}")
msg = f"Could not find any pointing information between {start} and {end}"
raise RuntimeError(msg)

Check warning on line 205 in aiapy/calibrate/util.py

View check run for this annotation

Codecov / codecov/patch

aiapy/calibrate/util.py#L204-L205

Added lines #L204 - L205 were not covered by tests
table["T_START"] = Time(table["T_START"], scale="utc")
table["T_STOP"] = Time(table["T_STOP"], scale="utc")
for c in table.colnames:
Expand All @@ -211,9 +214,8 @@ def get_pointing_table(start, end):
table[c].unit = "degree"
# Remove masking on columns with pointing parameters
for c in table.colnames:
if any(n in c for n in ["X0", "Y0", "IMSCALE", "INSTROT"]):
if hasattr(table[c], "mask"):
table[c] = table[c].filled(np.nan)
if any(n in c for n in ["X0", "Y0", "IMSCALE", "INSTROT"]) and hasattr(table[c], "mask"):
table[c] = table[c].filled(np.nan)

Check warning on line 218 in aiapy/calibrate/util.py

View check run for this annotation

Codecov / codecov/patch

aiapy/calibrate/util.py#L217-L218

Added lines #L217 - L218 were not covered by tests
return table


Expand All @@ -224,12 +226,13 @@ def get_error_table(error_table=None):
os.environ["PARFIVE_DISABLE_RANGE"] = "1"
error_table = fetch_error_table()
os.environ.pop("PARFIVE_DISABLE_RANGE")
if isinstance(error_table, (str, pathlib.Path)):
if isinstance(error_table, str | pathlib.Path):
table = astropy.io.ascii.read(error_table)
elif isinstance(error_table, QTable):
table = error_table
else:
raise ValueError("error_table must be a file path, an existing table, or None.")
msg = f"error_table must be a file path, an existing table, or None, not {type(error_table)}"
raise TypeError(msg)
table = QTable(table)
table["DATE"] = Time(table["DATE"], scale="utc")
table["T_START"] = Time(table["T_START"], scale="utc")
Expand Down
8 changes: 4 additions & 4 deletions aiapy/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,9 @@

# Force MPL to use non-gui backends for testing.
with contextlib.suppress(ImportError):
import matplotlib
import matplotlib as mpl

matplotlib.use("Agg")
mpl.use("Agg")


@pytest.fixture()
Expand Down Expand Up @@ -45,8 +45,8 @@ def idl_available():
import hissw

Check warning on line 45 in aiapy/conftest.py

View check run for this annotation

Codecov / codecov/patch

aiapy/conftest.py#L44-L45

Added lines #L44 - L45 were not covered by tests

hissw.Environment().run("")
return True
except Exception as e: # NOQA
return True # NOQA: TRY300
except Exception as e: # NOQA: BLE001
log.warning(e)
return False

Check warning on line 51 in aiapy/conftest.py

View check run for this annotation

Codecov / codecov/patch

aiapy/conftest.py#L47-L51

Added lines #L47 - L51 were not covered by tests

Expand Down
Loading

0 comments on commit 9136850

Please sign in to comment.