Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
40 commits
Select commit Hold shift + click to select a range
8ed0750
Implement FITS Compression algorithms in Codec classes
Cadair Oct 28, 2022
314f986
Add canonical compressed data from FITS site
Cadair Nov 14, 2022
992c03b
Fix up some tests and let gzip fail
Cadair Nov 14, 2022
17dce4e
Test against calls to fitsio
Cadair Nov 24, 2022
7d84890
Remove compressionmodule.c in favor of astropy.io.fits.tiled_compression
astrofrog Nov 24, 2022
f26913d
Use new Python compress_hdu and decompress_hdu functions
astrofrog Nov 24, 2022
b51be83
Various improvements to (de)compress_hdu
astrofrog Nov 24, 2022
c3575fc
Fix fitsio tests for all compression types
astrofrog Nov 28, 2022
1a283af
More fixes to compress_hdu
astrofrog Nov 28, 2022
03ee063
Improve the fitsio tests
Cadair Nov 25, 2022
625aba6
Support lossless GZIP decompression (with fitsio tests)
Cadair Nov 29, 2022
55a6839
Use cfitsio for quantization
astrofrog Nov 29, 2022
249cbe4
Starting adding support for de-quantization in decompress_hdu
astrofrog Nov 29, 2022
4e109a2
Finish implementing reading in of lossless GZIP fallback
astrofrog Dec 1, 2022
773b3f7
Enable lossy floating point tests for GZIP
astrofrog Dec 1, 2022
94a30b1
Remove unneeded tests and simplify canonical tests
astrofrog Dec 2, 2022
b0263b1
Renamed lossless to gzip_fallback and don't have Quantize inherit fro…
astrofrog Dec 3, 2022
444c20e
Split up tiled_compression.py
Cadair Dec 6, 2022
9e8b993
Fixed test_empty
astrofrog Dec 13, 2022
6018700
Fix tests related to PLIO compression (in which gzip fallback is used)
astrofrog Dec 13, 2022
e7a5a77
Include an exact zero in test data and make sure this is preserved ex…
astrofrog Dec 13, 2022
e302f8d
Added support for ZBLANK
astrofrog Dec 13, 2022
f58e55d
Attempt to fix the PLIO compression segfault
Cadair Dec 15, 2022
bfd4e2f
TMP: Remove some unused code from imcompress.c
Cadair Dec 14, 2022
2551958
Apply suggestions from code review
Cadair Dec 15, 2022
0949b41
Some docstring improvements
Cadair Dec 15, 2022
857337f
Guard against a segfault in HCOMPRESS
Cadair Dec 15, 2022
3b52ce4
i heard you like PLIO segfaults, so I made PLIO segfault again
Cadair Dec 15, 2022
7e1d659
TMP: Remove gate on initial_checks
Cadair Dec 16, 2022
e28e369
Actually test the tile shape we wanted to test
Cadair Dec 16, 2022
c76420f
Fix the segfault in the PLIO code for weird shaped tiles
Cadair Dec 16, 2022
d8fc152
Fix yet another PLIO segfault
Cadair Dec 16, 2022
5554f60
kill at least one segfault in HCOMPRESS
Cadair Dec 16, 2022
4317811
Hopefully turn the last of the hcompress segfaults into errors
Cadair Dec 16, 2022
6b23ab2
We now need error handlers on all the functions
Cadair Dec 16, 2022
7218270
Fix a lot of the rice errors
Cadair Dec 16, 2022
9b2eda8
I thought this might help HCOMPRESS, alas no
Cadair Dec 16, 2022
0b2c622
Fixed int -> long
astrofrog Dec 16, 2022
242f7d6
Generalize tile size check
astrofrog Dec 16, 2022
e0533e5
Generalize code that checks tile size for HCOMPRESS_1
astrofrog Dec 16, 2022
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
1 change: 1 addition & 0 deletions .gitattributes
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
*.fits -text
astropy/io/fits/tiled_compression/tests/data/*fits binary
13 changes: 9 additions & 4 deletions .github/workflows/ci_workflows.yml
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ jobs:
}

tests:
needs: [initial_checks]
# needs: [initial_checks]
uses: OpenAstronomy/github-actions-workflows/.github/workflows/tox.yml@v1
with:
submodules: false
Expand All @@ -65,7 +65,12 @@ jobs:
# leave open any files. This has a performance impact on running the
# tests, hence why it is not enabled by default.
- name: Python 3.9 with all optional dependencies
linux: py39-test-alldeps
linux: py39-test-alldeps-fitsio
libraries:
apt:
- language-pack-fr
- tzdata
- libcfitsio-dev
toxargs: -v --develop
posargs: --open-files --run-slow

Expand All @@ -82,7 +87,7 @@ jobs:
posargs: --durations=50 --run-slow

allowed_failures:
needs: [initial_checks]
# needs: [initial_checks]
uses: OpenAstronomy/github-actions-workflows/.github/workflows/tox.yml@v1
with:
submodules: false
Expand All @@ -101,7 +106,7 @@ jobs:
parallel_and_32bit:
name: 32-bit and parallel
runs-on: ubuntu-latest
needs: [initial_checks]
# needs: [initial_checks]
container:
image: quay.io/pypa/manylinux2014_i686:2022-04-03-da6ecb3
steps:
Expand Down
97 changes: 48 additions & 49 deletions astropy/io/fits/hdu/compressed.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
from astropy.io.fits.column import TDEF_RE, ColDefs, Column
from astropy.io.fits.fitsrec import FITS_rec
from astropy.io.fits.header import Header
from astropy.io.fits.tiled_compression import compress_hdu, decompress_hdu
from astropy.io.fits.util import (
_get_array_mmap,
_is_int,
Expand All @@ -30,13 +31,7 @@
from .image import ImageHDU
from .table import BinTableHDU

try:
from astropy.io.fits import compression

COMPRESSION_SUPPORTED = COMPRESSION_ENABLED = True
except ImportError:
COMPRESSION_SUPPORTED = COMPRESSION_ENABLED = False

COMPRESSION_ENABLED = True

# Quantization dithering method constants; these are right out of fitsio.h
NO_DITHER = -1
Expand Down Expand Up @@ -642,14 +637,6 @@ def __init__(
same image will always use the same seed.
"""

if not COMPRESSION_SUPPORTED:
# TODO: Raise a more specific Exception type
raise Exception(
"The astropy.io.fits.compression module is not "
"available. Creation of compressed image HDUs is "
"disabled."
)

compression_type = CMTYPE_ALIASES.get(compression_type, compression_type)

if data is DELAYED:
Expand Down Expand Up @@ -764,16 +751,8 @@ def match_header(cls, header):
if "ZIMAGE" not in header or not header["ZIMAGE"]:
return False

if COMPRESSION_SUPPORTED and COMPRESSION_ENABLED:
if COMPRESSION_ENABLED:
return True
elif not COMPRESSION_SUPPORTED:
warnings.warn(
"Failure matching header to a compressed image "
"HDU: The compression module is not available.\n"
"The HDU will be treated as a Binary Table HDU.",
AstropyUserWarning,
)
return False
else:
# Compression is supported but disabled; just pass silently (#92)
return False
Expand Down Expand Up @@ -1068,10 +1047,26 @@ def _update_header_data(
# Set default tile dimensions for HCOMPRESS_1

if compression_type == "HCOMPRESS_1":
if self._image_header["NAXIS1"] < 4 or self._image_header["NAXIS2"] < 4:

# HCOMPRESS_1 allows >2D tiles provided only two dimensions have
# non-1 values. We store the indices of those dimensions to use
# below.
keep_dims = []
for i in range(len(tile_size)):
if tile_size[i] > 1:
keep_dims.append(i)

if (
self._image_header[f"NAXIS{keep_dims[0] + 1}"] < 4
or self._image_header[f"NAXIS{keep_dims[1] + 1}"] < 4
):
raise ValueError("Hcompress minimum image dimension is 4 pixels")
elif tile_size:
if tile_size[0] < 4 or tile_size[1] < 4:
if len(keep_dims) != 2:
raise ValueError(
"Hcompress tile size should contain exactly two non-1 values"
)
if tile_size[keep_dims[0]] < 4 or tile_size[keep_dims[1]] < 4:
# user specified tile size is too small
raise ValueError("Hcompress minimum tile dimension is 4 pixels")
major_dims = len([ts for ts in tile_size if ts > 1])
Expand All @@ -1082,6 +1077,10 @@ def _update_header_data(
"to 1."
)

# TODO: is '0' a magic value that means all pixels along a certain
# dimension? If so we should perhaps check not the first two but
# the two dimensions that are not 1.

if tile_size and (tile_size[0] == 0 and tile_size[1] == 0):
# compress the whole image as a single tile
tile_size[0] = self._image_header["NAXIS1"]
Expand Down Expand Up @@ -1125,24 +1124,33 @@ def _update_header_data(
# check if requested tile size causes the last tile to have
# less than 4 pixels

remain = self._image_header["NAXIS1"] % tile_size[0] # 1st dimen
remain = (
self._image_header[f"NAXIS{keep_dims[0] + 1}"] % tile_size[keep_dims[0]]
) # 1st dimen

if remain > 0 and remain < 4:
tile_size[0] += 1 # try increasing tile size by 1

remain = self._image_header["NAXIS1"] % tile_size[0]
tile_size[keep_dims[0]] += 1 # try increasing tile size by 1
remain = (
self._image_header[f"NAXIS{keep_dims[0] + 1}"]
% tile_size[keep_dims[0]]
)

if remain > 0 and remain < 4:
raise ValueError(
"Last tile along 1st dimension has less than 4 pixels"
)

remain = self._image_header["NAXIS2"] % tile_size[1] # 2nd dimen
remain = (
self._image_header[f"NAXIS{keep_dims[1] + 1}"] % tile_size[keep_dims[1]]
) # 2nd dimen

if remain > 0 and remain < 4:
tile_size[1] += 1 # try increasing tile size by 1
tile_size[keep_dims[1]] += 1 # try increasing tile size by 1

remain = self._image_header["NAXIS2"] % tile_size[1]
remain = (
self._image_header[f"NAXIS{keep_dims[1] + 1}"]
% tile_size[keep_dims[1]]
)

if remain > 0 and remain < 4:
raise ValueError(
Expand Down Expand Up @@ -1495,7 +1503,7 @@ def _update_header_data(
@lazyproperty
def data(self):
# The data attribute is the image data (not the table data).
data = compression.decompress_hdu(self)
data = decompress_hdu(self)

if data is None:
return data
Expand All @@ -1505,6 +1513,11 @@ def data(self):
new_dtype = self._dtype_for_bitpix()
data = np.array(data, dtype=new_dtype)

# TODO: ZBLANK should not be dealt with here as it should apply
# to data before being unquantized, which has already happened in
# decompress_hdu, so we should remove references to ZBLANK here.
# However, it might be that we still need to handle BLANK.

zblank = None

if "ZBLANK" in self.compressed_data.columns.names:
Expand Down Expand Up @@ -1802,17 +1815,6 @@ def _update_compressed_data(self):
self.data - _pseudo_zero(self.data.dtype),
dtype=f"=i{self.data.dtype.itemsize}",
)
should_swap = False
else:
should_swap = not self.data.dtype.isnative

if should_swap:
if self.data.flags.writeable:
self.data.byteswap(True)
else:
# For read-only arrays, there is no way around making
# a byteswapped copy of the data.
self.data = self.data.byteswap(False)

try:
nrows = self._header["NAXIS2"]
Expand All @@ -1836,11 +1838,8 @@ def _update_compressed_data(self):
# self.compressed_data, and writes directly to it
# compress_hdu returns the size of the heap for the written
# compressed image table
heapsize, self.compressed_data = compression.compress_hdu(self)
heapsize, self.compressed_data = compress_hdu(self)
finally:
# if data was byteswapped return it to its original order
if should_swap:
self.data.byteswap(True)
self.data = old_data

# CFITSIO will write the compressed data in big-endian order
Expand Down
82 changes: 0 additions & 82 deletions astropy/io/fits/setup_package.py

This file was deleted.

Loading