From 008998753a49d1f8f54fdfea80c8084bd1632748 Mon Sep 17 00:00:00 2001 From: Thomas Robitaille Date: Fri, 17 Oct 2025 13:23:59 +0100 Subject: [PATCH 1/5] Fix syntax of hips_pixel_cut --- reproject/hips/high_level.py | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/reproject/hips/high_level.py b/reproject/hips/high_level.py index 9ff0b37b3..766be3055 100644 --- a/reproject/hips/high_level.py +++ b/reproject/hips/high_level.py @@ -470,7 +470,7 @@ def process(index): if tile_format == "fits": generated_properties["hips_pixel_bitpix"] = -64 if not np.isinf(pixel_min) and not np.isinf(pixel_max): - properties["hips_pixel_cut"] = (pixel_min, pixel_max) + properties["hips_pixel_cut"] = f"{pixel_min} {pixel_max}" generated_properties.update(properties) @@ -522,7 +522,6 @@ def compute_lower_resolution_tiles( output_directory, ndim, frame, - tile_dims, tile_format, tile_size, tile_depth, @@ -531,6 +530,11 @@ def compute_lower_resolution_tiles( indices=None, ): + if ndim == 3: + tile_dims = tile_size, tile_depth + else: + tile_dims = tile_size + # Iterate over higher levels and compute lower resolution tiles half_tile_size = tile_size // 2 @@ -569,7 +573,8 @@ def compute_lower_resolution_tiles( make_tile_folders(level=ilevel, indices=indices, output_directory=output_directory) - for index in indices: + from tqdm import tqdm + for index in tqdm(indices): header = tile_header(level=ilevel, index=index, frame=frame, tile_dims=tile_dims) @@ -599,7 +604,7 @@ def compute_lower_resolution_tiles( if tile_format == "fits": tile_data = fits.getdata(subtile_filename) - data = block_reduce(tile_data, 2, func=np.mean) + data = block_reduce(tile_data, 2, func=np.nanmean) else: data = block_reduce( np.array(Image.open(subtile_filename))[::-1], @@ -638,7 +643,7 @@ def compute_lower_resolution_tiles( subtile_filename, tile_size=tile_size, tile_depth=tile_depth ), 2, - func=np.mean, + func=np.nanmean, ) if subindex_spec == 0: From 91186b710bad7b973aec8a70eb14948f85258a86 Mon Sep 17 00:00:00 2001 From: Thomas Robitaille Date: Fri, 17 Oct 2025 13:24:29 +0100 Subject: [PATCH 2/5] Add a way to get the unrounded spectral index --- reproject/hips/utils.py | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/reproject/hips/utils.py b/reproject/hips/utils.py index 15e80c034..70f5dbd0f 100644 --- a/reproject/hips/utils.py +++ b/reproject/hips/utils.py @@ -50,14 +50,16 @@ def spectral_index_to_coord(level, index): ) -def spectral_coord_to_index(level, coord): - return ( - np.floor( - 2 ** (level + 1) - * np.log10(coord.to_value(u.Hz) / FREQ_MIN) - / np.log10(FREQ_MAX / FREQ_MIN) - ) - ).astype(int) +def spectral_coord_to_index(level, coord, rounded=True): + index = ( + 2 ** (level + 1) + * np.log10(coord.to_value(u.Hz) / FREQ_MIN) + / np.log10(FREQ_MAX / FREQ_MIN) + ) + if rounded: + return np.floor(index).astype(int) + else: + return index def map_header(*, level, frame, tile_dims): From 9a4dbc470f658ac08018ad88e9bc3f34dfd52f68 Mon Sep 17 00:00:00 2001 From: Thomas Robitaille Date: Fri, 17 Oct 2025 13:39:05 +0100 Subject: [PATCH 3/5] Strip trailing slashes from URL --- reproject/hips/_dask_array.py | 12 +++++++----- reproject/hips/high_level.py | 3 +-- reproject/hips/utils.py | 4 +--- 3 files changed, 9 insertions(+), 10 deletions(-) diff --git a/reproject/hips/_dask_array.py b/reproject/hips/_dask_array.py index 8449b659b..90b87f774 100644 --- a/reproject/hips/_dask_array.py +++ b/reproject/hips/_dask_array.py @@ -30,11 +30,13 @@ class HiPSArray: def __init__(self, directory_or_url, level=None, level_depth=None): - self._directory_or_url = directory_or_url + # We strip any trailing slashes since we then assume in the rest of the + # code that we need to add a slash (and double slashes cause issues for URLs) + self._directory_or_url = directory_or_url.rstrip("/") - self._is_url = is_url(directory_or_url) + self._is_url = is_url(self._directory_or_url) - self._properties = load_properties(directory_or_url) + self._properties = load_properties(self._directory_or_url) if self._properties["dataproduct_type"] == "image": self.ndim = 2 @@ -51,7 +53,7 @@ def __init__(self, directory_or_url, level=None, level_depth=None): else: if level > self._order_spatial: raise ValueError( - f"HiPS dataset at {directory_or_url} does not contain spatial level {level} data" + f"HiPS dataset at {self._directory_or_url} does not contain spatial level {level} data" ) elif level < 0: raise ValueError("level should be positive") @@ -70,7 +72,7 @@ def __init__(self, directory_or_url, level=None, level_depth=None): else: if level_depth > self._order_depth: raise ValueError( - f"HiPS dataset at {directory_or_url} does not contain spectral level {level_depth} data" + f"HiPS dataset at {self._directory_or_url} does not contain spectral level {level_depth} data" ) elif level_depth < 0: raise ValueError("level_depth should be positive") diff --git a/reproject/hips/high_level.py b/reproject/hips/high_level.py index 766be3055..55e693ee2 100644 --- a/reproject/hips/high_level.py +++ b/reproject/hips/high_level.py @@ -573,8 +573,7 @@ def compute_lower_resolution_tiles( make_tile_folders(level=ilevel, indices=indices, output_directory=output_directory) - from tqdm import tqdm - for index in tqdm(indices): + for index in indices: header = tile_header(level=ilevel, index=index, frame=frame, tile_dims=tile_dims) diff --git a/reproject/hips/utils.py b/reproject/hips/utils.py index 70f5dbd0f..2491496ce 100644 --- a/reproject/hips/utils.py +++ b/reproject/hips/utils.py @@ -52,9 +52,7 @@ def spectral_index_to_coord(level, index): def spectral_coord_to_index(level, coord, rounded=True): index = ( - 2 ** (level + 1) - * np.log10(coord.to_value(u.Hz) / FREQ_MIN) - / np.log10(FREQ_MAX / FREQ_MIN) + 2 ** (level + 1) * np.log10(coord.to_value(u.Hz) / FREQ_MIN) / np.log10(FREQ_MAX / FREQ_MIN) ) if rounded: return np.floor(index).astype(int) From 6fc6314ffe1668bb583855e94c26219f36ba4b0b Mon Sep 17 00:00:00 2001 From: Thomas Robitaille Date: Fri, 17 Oct 2025 15:16:05 +0100 Subject: [PATCH 4/5] Fix tests --- reproject/hips/_dask_array.py | 2 +- reproject/hips/high_level.py | 24 +++++++++++++++--------- 2 files changed, 16 insertions(+), 10 deletions(-) diff --git a/reproject/hips/_dask_array.py b/reproject/hips/_dask_array.py index 90b87f774..5e9348e33 100644 --- a/reproject/hips/_dask_array.py +++ b/reproject/hips/_dask_array.py @@ -32,7 +32,7 @@ def __init__(self, directory_or_url, level=None, level_depth=None): # We strip any trailing slashes since we then assume in the rest of the # code that we need to add a slash (and double slashes cause issues for URLs) - self._directory_or_url = directory_or_url.rstrip("/") + self._directory_or_url = str(directory_or_url).rstrip("/") self._is_url = is_url(self._directory_or_url) diff --git a/reproject/hips/high_level.py b/reproject/hips/high_level.py index 55e693ee2..e888556be 100644 --- a/reproject/hips/high_level.py +++ b/reproject/hips/high_level.py @@ -1,6 +1,7 @@ import os import shutil import uuid +import warnings from concurrent.futures import ThreadPoolExecutor from copy import deepcopy from datetime import datetime @@ -482,7 +483,6 @@ def process(index): output_directory=output_directory, ndim=ndim, frame=frame, - tile_dims=tile_dims, tile_format=tile_format, tile_size=tile_size, tile_depth=tile_depth, @@ -603,7 +603,10 @@ def compute_lower_resolution_tiles( if tile_format == "fits": tile_data = fits.getdata(subtile_filename) - data = block_reduce(tile_data, 2, func=np.nanmean) + # np.nanmean can emit warnings, so ignore these + with warnings.catch_warnings(): + warnings.simplefilter("ignore") + data = block_reduce(tile_data, 2, func=np.nanmean) else: data = block_reduce( np.array(Image.open(subtile_filename))[::-1], @@ -637,13 +640,16 @@ def compute_lower_resolution_tiles( if os.path.exists(subtile_filename): - data = block_reduce( - fits_getdata_untrimmed( - subtile_filename, tile_size=tile_size, tile_depth=tile_depth - ), - 2, - func=np.nanmean, - ) + # np.nanmean can emit warnings, so ignore these + with warnings.catch_warnings(): + warnings.simplefilter("ignore") + data = block_reduce( + fits_getdata_untrimmed( + subtile_filename, tile_size=tile_size, tile_depth=tile_depth + ), + 2, + func=np.nanmean, + ) if subindex_spec == 0: subtile_slice = [slice(None, half_tile_depth)] From 1c6048ec22f914cd28b7d91892f9f002d1448d05 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 20 Oct 2025 09:59:44 +0000 Subject: [PATCH 5/5] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- CHANGES.md | 66 +++++++++++++++++++++++++++--------------------------- 1 file changed, 33 insertions(+), 33 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index 4172e70cf..44e18aee7 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -296,9 +296,9 @@ ## 0.9 - 2022-09-02 - Drop support for Python 3.7. -- +- - Infrastructure and packaging updates. -- +- - Made many improvements, bug fixes, and significant speed-ups for the adaptive - resampling algorithm, `reproject_adaptive`. These bug fixes may cause - changes to the reprojected images, which are typically negligible. @@ -306,13 +306,13 @@ - Gaussian filter kernel, a menu of boundary-handling modes, and a - `center_jacobian` flag to trade speed for accuracy with rapidly-varying - transformations. -- +- - Added a `roundtrip_coords` argument to `reproject_adaptive` and - `reproject_interp`. By default, all coordinate transformations are run in - both directions to handle some situations where they are ambiguous. This can - be disabled by setting `roundtrip_coords=False` which may offer a - significant speed increase. -- +- ## 0.8 - 2021-08-11 @@ -321,34 +321,34 @@ - possible to solve for the optimal WCS for a set of images that couldn't fit - into memory all at once, since the actual data aren't needed for optimal WCS - determination. [#242] -- +- - Fix implementation of `hdu_weights` in `reproject_and_coadd`. [#249] -- +- ## 0.7.1 - 2020-05-29 - Fixed compatibility with Astropy 4.1. [#234] -- +- - Updated minimum requirement for SciPy. [#236] -- +- ## 0.7 - 2020-04-02 - Made C extension in overlapArea.c thread-safe by removing global - variables. [#211] -- +- - Made it possible to control whether to output debugging information - from overlapArea.c by setting DEBUG_OVERLAP_AREA=1 at build-time. [#211] -- +- - Fix compatibility with astropy v4.0.1. [#227] -- +- - Disable parallelization by default in `reproject_exact` - this can be - enabled with `parallel=True`. [#227] -- +- - Fixed a bug with `reproject_exact` with `parallel=False` and - `return_footprint=False`, which caused the footprint to be returned - anyway. [#227] -- +- - The infrastructure of the package has been updated in line with the - APE 17 roadmap (https://github.com/astropy/astropy-APEs/blob/main/APE17.rst). - The main changes are that the `python setup.py test` and @@ -357,7 +357,7 @@ - (https://tox.readthedocs.io) package and run `tox -e test` and - `tox -e build_docs`. It is also possible to run pytest and sphinx - directly. [#228] -- +- ## 0.6 - 2019-11-01 @@ -366,20 +366,20 @@ - `independent_celestial_slices=` argument to `reproject_interp` has - been deprecated since it is no longer needed, as transformations are - automatically done in the most efficient way possible. [#166] -- +- - Include a warning for high resolution images with `reproject_exact`, - since if the pixels are <0.05", precision issues can occur. [#200] -- +- - Added a new `reproject_and_coadd` function for doing mosaicking of - individual images, and added section in documentation about mosaicking. - [#186] -- +- - Added a new reproject.adaptive sub-package that implements the DeForest - (2004) algorithm for reprojection. [#52] -- +- - Fixed a bug that caused 'exact' reprojection results to have numerical - issues when doing identity transformations. [#190] -- +- ## 0.5.1 - 2019-09-01 @@ -390,33 +390,33 @@ - Improve parse_output_projection to make it so that the output projection - can be specified as a filename. [#150] -- +- - Fixed a bug that caused HEALPix maps in RING order to not be correctly - interpreted. [#163] -- +- - Make it possible to specify the output array for reprojection using the - `output_array=` keyword argument. [#115] -- +- ## 0.4 - 2018-01-29 - Refactored HEALPix reprojection code to use the astropy-healpix package - instead of healpy. [#139] -- +- - Added the ability to specify an output array in `reproject_interp`, which - permits the use of memory-mapped arrays and therefore provides the capability - to handle data cubes much larger than memory [#115] -- +- - Fix test 32-bit test failures. [#146] -- +- - Fix an issue with reprojecting images where there are two solutions along - the line of sight by forcing round-tripping of coordinate conversions [#129] -- +- - Explicitly define default HDU as 0 for normal reprojection and 1 for - HEALPix reprojection. [#119] -- +- - Added a function to find the optimal WCS for a set of images. [#136, #137] -- +- ## 0.3.2 - 2017-10-22 @@ -427,22 +427,22 @@ ## 0.3.1 - 2016-07-07 - Include missing license file in tarball. -- +- - Updated documentation to remove warnings about early versions. -- +- ## 0.3 - 2016-07-06 - Allow users to pass a `field=` option to `reproject_from_healpix` - to access different fields in a HEALPIX file. [#86] -- +- - Significant improvements to performance when the input data is a large - memory-mapped array. [#105] -- +- - Significant refactoring of interpolating reprojection to improve support for - n-dimensional arrays, optionally including two celestial axes (in which - case the coordinate transformation is taken into account). [#96, #102] -- +- ## 0.2 - 2015-10-29