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

Deal with integer FITS files with BLANK keywords #378

Merged
merged 6 commits into from
Dec 29, 2024
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
2 changes: 1 addition & 1 deletion ci/azure-build-and-test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ parameters:
PYTHON_SERIES: "3.10"

- name: macos_310
vmImage: macos-12
vmImage: macos-14
vars:
PYTHON_SERIES: "3.10"

Expand Down
13 changes: 8 additions & 5 deletions ci/azure-job-setup.yml
Original file line number Diff line number Diff line change
Expand Up @@ -79,17 +79,20 @@ steps:
- bash: |
set -euo pipefail

if [[ $AGENT_OS == Windows_NT ]] ; then
if [[ $AGENT_OS == Darwin ]] ; then
# As of macos-14, these no longer have Anaconda built in.
CONDA="$TMPDIR/conda"
curl -fsSL https://github.com/conda-forge/miniforge/releases/latest/download/Miniforge3-MacOSX-x86_64.sh >miniforge.sh
bash miniforge.sh -f -b -p "$CONDA"
rm -f miniforge.sh
condabin="$CONDA/bin"
elif [[ $AGENT_OS == Windows_NT ]] ; then
CONDA=$(echo "$CONDA" | sed -e 's|\\|\/|g' -e 's|^\([A-Za-z]\)\:/\(.*\)|/\L\1\E/\2|')
condabin="$CONDA/Scripts"
else
condabin="$CONDA/bin"
fi

if [[ $AGENT_OS == Darwin ]] ; then
sudo chown -R $USER $CONDA
fi

cat >activate-conda.sh <<EOF
eval "\$($condabin/conda shell.bash hook)"
conda activate
Expand Down
30 changes: 30 additions & 0 deletions docs/api/pywwt.BaseWWTWidget.rst
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ BaseWWTWidget

~BaseWWTWidget.actual_planet_scale
~BaseWWTWidget.alt_az_grid
~BaseWWTWidget.alt_az_grid_color
~BaseWWTWidget.alt_az_text
~BaseWWTWidget.available_hips_catalog_names
~BaseWWTWidget.available_layers
~BaseWWTWidget.available_views
Expand All @@ -20,18 +22,27 @@ BaseWWTWidget
~BaseWWTWidget.constellation_boundary_color
~BaseWWTWidget.constellation_figure_color
~BaseWWTWidget.constellation_figures
~BaseWWTWidget.constellation_labels
~BaseWWTWidget.constellation_pictures
~BaseWWTWidget.constellation_selection
~BaseWWTWidget.constellation_selection_color
~BaseWWTWidget.crosshairs
~BaseWWTWidget.crosshairs_color
~BaseWWTWidget.current_mode
~BaseWWTWidget.ecliptic
~BaseWWTWidget.ecliptic_color
~BaseWWTWidget.ecliptic_grid
~BaseWWTWidget.ecliptic_grid_color
~BaseWWTWidget.ecliptic_text
~BaseWWTWidget.foreground
~BaseWWTWidget.foreground_opacity
~BaseWWTWidget.galactic_grid
~BaseWWTWidget.galactic_grid_color
~BaseWWTWidget.galactic_mode
~BaseWWTWidget.galactic_text
~BaseWWTWidget.grid
~BaseWWTWidget.grid_color
~BaseWWTWidget.grid_text
~BaseWWTWidget.imagery
~BaseWWTWidget.instruments
~BaseWWTWidget.layers
Expand All @@ -40,6 +51,8 @@ BaseWWTWidget
~BaseWWTWidget.location_latitude
~BaseWWTWidget.location_longitude
~BaseWWTWidget.most_recent_source
~BaseWWTWidget.precession_chart
~BaseWWTWidget.precession_chart_color
~BaseWWTWidget.selected_sources
~BaseWWTWidget.solar_system

Expand All @@ -58,11 +71,13 @@ BaseWWTWidget
~BaseWWTWidget.get_center
~BaseWWTWidget.get_current_time
~BaseWWTWidget.get_fov
~BaseWWTWidget.get_roll
~BaseWWTWidget.load_image_collection
~BaseWWTWidget.load_tour
~BaseWWTWidget.pause_time
~BaseWWTWidget.pause_tour
~BaseWWTWidget.play_time
~BaseWWTWidget.refresh_tile_cache
~BaseWWTWidget.reset
~BaseWWTWidget.reset_view
~BaseWWTWidget.resume_tour
Expand All @@ -75,6 +90,8 @@ BaseWWTWidget

.. autoattribute:: actual_planet_scale
.. autoattribute:: alt_az_grid
.. autoattribute:: alt_az_grid_color
.. autoattribute:: alt_az_text
.. autoattribute:: available_hips_catalog_names
.. autoattribute:: available_layers
.. autoattribute:: available_views
Expand All @@ -83,18 +100,27 @@ BaseWWTWidget
.. autoattribute:: constellation_boundary_color
.. autoattribute:: constellation_figure_color
.. autoattribute:: constellation_figures
.. autoattribute:: constellation_labels
.. autoattribute:: constellation_pictures
.. autoattribute:: constellation_selection
.. autoattribute:: constellation_selection_color
.. autoattribute:: crosshairs
.. autoattribute:: crosshairs_color
.. autoattribute:: current_mode
.. autoattribute:: ecliptic
.. autoattribute:: ecliptic_color
.. autoattribute:: ecliptic_grid
.. autoattribute:: ecliptic_grid_color
.. autoattribute:: ecliptic_text
.. autoattribute:: foreground
.. autoattribute:: foreground_opacity
.. autoattribute:: galactic_grid
.. autoattribute:: galactic_grid_color
.. autoattribute:: galactic_mode
.. autoattribute:: galactic_text
.. autoattribute:: grid
.. autoattribute:: grid_color
.. autoattribute:: grid_text
.. autoattribute:: imagery
.. autoattribute:: instruments
.. autoattribute:: layers
Expand All @@ -103,6 +129,8 @@ BaseWWTWidget
.. autoattribute:: location_latitude
.. autoattribute:: location_longitude
.. autoattribute:: most_recent_source
.. autoattribute:: precession_chart
.. autoattribute:: precession_chart_color
.. autoattribute:: selected_sources
.. autoattribute:: solar_system

Expand All @@ -119,11 +147,13 @@ BaseWWTWidget
.. automethod:: get_center
.. automethod:: get_current_time
.. automethod:: get_fov
.. automethod:: get_roll
.. automethod:: load_image_collection
.. automethod:: load_tour
.. automethod:: pause_time
.. automethod:: pause_tour
.. automethod:: play_time
.. automethod:: refresh_tile_cache
.. automethod:: reset
.. automethod:: reset_view
.. automethod:: resume_tour
Expand Down
2 changes: 2 additions & 0 deletions docs/api/pywwt.core.BaseWWTWidget.rst
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@ BaseWWTWidget
~BaseWWTWidget.pause_time
~BaseWWTWidget.pause_tour
~BaseWWTWidget.play_time
~BaseWWTWidget.refresh_tile_cache
~BaseWWTWidget.reset
~BaseWWTWidget.reset_view
~BaseWWTWidget.resume_tour
Expand Down Expand Up @@ -152,6 +153,7 @@ BaseWWTWidget
.. automethod:: pause_time
.. automethod:: pause_tour
.. automethod:: play_time
.. automethod:: refresh_tile_cache
.. automethod:: reset
.. automethod:: reset_view
.. automethod:: resume_tour
Expand Down
6 changes: 6 additions & 0 deletions docs/api/pywwt.traits.to_hex.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
to_hex
======

.. currentmodule:: pywwt.traits

.. autofunction:: to_hex
46 changes: 46 additions & 0 deletions docs/clear-automodapis.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
#! /bin/bash

# For URL structure reasons, our "api/" directory has a mixture of "root" files
# that must exist (the ones for each module) and other files that live in
# version control but are generated by the automodapi system. In order to
# refresh the latter files, they must be deleted before running a doc build.
# This script does that, while leaving the "root" files.

apidir=$(dirname $0)/api

cd "$apidir"

for f in *.rst; do
case "$f" in
pywwt.rst|\
pywwt.annotation_.rst|\
pywwt.app.rst|\
pywwt.core.rst|\
pywwt.data_server.rst|\
pywwt.imagery.rst|\
pywwt.instruments.rst|\
pywwt.jupyter_relay.rst|\
pywwt.jupyter.rst|\
pywwt.jupyter_server.rst|\
pywwt.layers.rst|\
pywwt.logger.rst|\
pywwt.qt.rst|\
pywwt.solar_system.rst|\
pywwt.traits.rst|\
pywwt.utils.rst|\
pywwt.windows.rst|\
pywwt.windows.client.rst|\
pywwt.windows.layer.rst|\
pywwt.windows.misc.rst|\
pywwt.windows.mods.rst|\
pywwt.windows.utils.rst) ;;

*) rm -f "$f"
esac
done

echo "- Restoring files to work around issue with traitlets inherited members"

for c in AstropyQuantity Color ColorWithOpacity ; do
git restore pywwt.traits.$c.rst
done
12 changes: 11 additions & 1 deletion pywwt/layers.py
Original file line number Diff line number Diff line change
Expand Up @@ -243,6 +243,7 @@ def add_image_layer(
self,
image=None,
hdu_index=None,
wcs_key=" ",
verbose=True,
name=None,
tiling_method=TilingMethod.AUTO_DETECT,
Expand Down Expand Up @@ -270,6 +271,11 @@ def add_image_layer(
by using a list of integers like this: [0, 2, 1]. If hdu_index is
not set, toasty will use the first HDU with tilable content in each
FITS.
wcs_key : optional str or list of str, defaults to " "
Specify which set of WCS keywords to load from each input HDU. If
the *image* input is a list of FITS, you can specify the wcs_key of
each FITS by using a list of letters like this: [" ", "C", "A"]. If
If a scalar value is given, the same value will be used for all inputs.
verbose : optional boolean, defaults True
If true, progress messages will be printed as the FITS files are
being processed.
Expand Down Expand Up @@ -316,7 +322,8 @@ def add_image_layer(
image = [image]

if (
tiling_method == TilingMethod.TOAST
wcs_key != " "
or tiling_method == TilingMethod.TOAST
or tiling_method == TilingMethod.HIPS
or tiling_method == TilingMethod.TAN
) or (
Expand All @@ -329,6 +336,7 @@ def add_image_layer(
self._tile_and_serve(
fits_list=image,
hdu_index=hdu_index,
wcs_key=wcs_key,
cli_progress=verbose,
display_name=name,
tiling_method=tiling_method,
Expand Down Expand Up @@ -438,6 +446,7 @@ async def _tile_and_serve(
self,
fits_list,
hdu_index=None,
wcs_key=" ",
cli_progress=True,
display_name=None,
tiling_method=TilingMethod.AUTO_DETECT,
Expand All @@ -449,6 +458,7 @@ async def _tile_and_serve(
out_dir, builder = toasty.tile_fits(
fits_list,
hdu_index=hdu_index,
wcs_key=wcs_key,
cli_progress=cli_progress,
tiling_method=tiling_method,
**kwargs
Expand Down
20 changes: 20 additions & 0 deletions pywwt/utils.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import numpy as np
import pytz
from astropy.io import fits
from astropy.io.fits import CompImageHDU, ImageHDU, PrimaryHDU
from astropy.coordinates import ICRS
from astropy.time import Time
from datetime import datetime
Expand Down Expand Up @@ -49,8 +50,27 @@
with warnings.catch_warnings():
# Sorry, Astropy, no one cares if you fixed the FITS.
warnings.simplefilter("ignore")

# Inner workaround: as of October 2024, `reproject` will crash with
# integer-valued images that have the "BLANK" keyword set:
# https://github.com/astropy/reproject/issues/475 . This issue should of
# course be fixed upstream, but a fix will take a while to propagate
# through the ecosystem. In the meantime, fiddle with things to avoid
# the issue if it looks like it might be relevant.
do_blank_workaround = (
isinstance(image, (PrimaryHDU, ImageHDU, CompImageHDU))
and image.header.get("BLANK") is not None
and hasattr(image, "_data_replaced")
)
if do_blank_workaround:
old_data_replaced = image._data_replaced
image._data_replaced = True

Check warning on line 67 in pywwt/utils.py

View check run for this annotation

Codecov / codecov/patch

pywwt/utils.py#L66-L67

Added lines #L66 - L67 were not covered by tests

data, wcs = parse_input_data(image)

if do_blank_workaround:
image._data_replaced = old_data_replaced

Check warning on line 72 in pywwt/utils.py

View check run for this annotation

Codecov / codecov/patch

pywwt/utils.py#L72

Added line #L72 was not covered by tests

if wcs.naxis != 2:
if not wcs.has_celestial:
raise Exception(
Expand Down
2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,7 @@
"pytz",
"reproject>=0.8",
"requests",
"toasty>=0.18",
"toasty>=0.20",
"tornado",
"traitlets>=5",
"wwt_data_formats>=0.12",
Expand Down