From 026817b2cdf48cc2e076a56a3e7bef5047744979 Mon Sep 17 00:00:00 2001 From: "Adam Ginsburg (keflavich)" Date: Wed, 10 Jun 2026 07:37:33 +0200 Subject: [PATCH 1/4] MAINT: standardize spatial query parameter name to 'coordinates' Part of the API consolidation tracked in #2803: the first argument of the query_region/query_object/cone_search family is now uniformly named 'coordinates'. The old names ('coordinate' in alma, esa.euclid, esa.hsa, esa.jwst, gaia, ipac.irsa.ibe, noirlab; 'position' in esasky and heasarc; 'coord' in ogle) keep working via deprecated_renamed_argument shims (since 0.4.12) and now emit AstropyDeprecationWarning. In heasarc, the renamed parameter shadowed the 'from astropy import coordinates' module import, so that import was narrowed to the names actually used. Co-Authored-By: Claude Fable 5 --- CHANGES.rst | 58 +++++++++++++++++++ astroquery/alma/core.py | 6 +- astroquery/alma/tests/test_alma.py | 14 +++++ astroquery/alma/tests/test_alma_remote.py | 2 +- astroquery/esa/euclid/core.py | 32 +++++----- .../esa/euclid/tests/test_euclid_remote.py | 6 +- astroquery/esa/euclid/tests/test_euclidtap.py | 40 ++++++++----- astroquery/esa/hsa/core.py | 15 +++-- astroquery/esa/hsa/tests/test_hsa.py | 15 ++++- astroquery/esa/jwst/core.py | 19 +++--- astroquery/esa/jwst/tests/test_jwsttap.py | 27 ++++++++- astroquery/esasky/core.py | 28 +++++---- astroquery/esasky/tests/test_esasky.py | 36 ++++++++++++ astroquery/esasky/tests/test_esasky_remote.py | 6 +- astroquery/gaia/core.py | 40 +++++++------ astroquery/gaia/tests/test_gaia_remote.py | 6 +- astroquery/gaia/tests/test_gaiatap.py | 14 +++++ astroquery/heasarc/core.py | 27 ++++----- astroquery/heasarc/tests/test_heasarc.py | 24 +++++++- astroquery/ipac/irsa/ibe/core.py | 26 +++++---- astroquery/ipac/irsa/ibe/tests/test_ibe.py | 12 +++- .../ipac/irsa/ibe/tests/test_ibe_remote.py | 2 +- astroquery/noirlab/core.py | 8 ++- astroquery/noirlab/tests/test_noirlab.py | 13 ++++- .../noirlab/tests/test_noirlab_remote.py | 2 +- astroquery/ogle/core.py | 30 +++++----- astroquery/ogle/tests/test_ogle.py | 19 ++++-- astroquery/ogle/tests/test_ogle_remote.py | 4 +- docs/esa/euclid/euclid.rst | 6 +- docs/esa/jwst/jwst.rst | 4 +- docs/esasky/esasky.rst | 16 ++--- docs/gaia/gaia.rst | 6 +- docs/ogle/ogle.rst | 6 +- 33 files changed, 405 insertions(+), 164 deletions(-) create mode 100644 astroquery/esasky/tests/test_esasky.py diff --git a/CHANGES.rst b/CHANGES.rst index 6ebc35a201..bea6bcf64b 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -64,6 +64,8 @@ esa.euclid product_type parameters dynamically. [#3601] - In the method, ``get_scientific_product_list``, the ``dsr_part3`` parameter now supports the additional value ``latest``. [#3601] +- The ``coordinate`` keyword of ``query_object``, ``cone_search``, and ``get_cutout`` is deprecated in + favor of ``coordinates`` for consistency with the rest of astroquery. [#3609] vizier @@ -87,6 +89,62 @@ vo_conesearch PyVO Simple Cone Search interface instead. There is no direct replacement for server validation. [#3548] +alma +^^^^ + +- The ``coordinate`` keyword of ``query_region`` and ``query_region_async`` is deprecated in favor of + ``coordinates`` for consistency with the rest of astroquery. [#3609] + +esa.hsa +^^^^^^^ + +- The ``coordinate`` keyword of ``query_observations`` and ``query_region`` is deprecated in favor of + ``coordinates`` for consistency with the rest of astroquery. [#3609] + +esa.jwst +^^^^^^^^ + +- The ``coordinate`` keyword of ``query_region`` and ``cone_search`` is deprecated in favor of + ``coordinates`` for consistency with the rest of astroquery. [#3609] + +esasky +^^^^^^ + +- The ``position`` keyword of ``query_region_maps``, ``query_region_catalogs``, and + ``query_region_spectra`` is deprecated in favor of ``coordinates`` for consistency with the rest of + astroquery. [#3609] + +gaia +^^^^ + +- The ``coordinate`` keyword of ``query_object``, ``query_object_async``, ``cone_search``, and + ``cone_search_async`` is deprecated in favor of ``coordinates`` for consistency with the rest of + astroquery. [#3609] + +heasarc +^^^^^^^ + +- The ``position`` keyword of ``query_region`` is deprecated in favor of ``coordinates`` for + consistency with the rest of astroquery. [#3609] + +ipac.irsa.ibe +^^^^^^^^^^^^^ + +- The ``coordinate`` keyword of ``query_region``, ``query_region_sia``, and ``query_region_async`` is + deprecated in favor of ``coordinates`` for consistency with the rest of astroquery. [#3609] + +noirlab +^^^^^^^ + +- The ``coordinate`` keyword of ``query_region`` is deprecated in favor of ``coordinates`` for + consistency with the rest of astroquery. [#3609] + +ogle +^^^^ + +- The ``coord`` keyword of ``query_region`` and ``query_region_async`` is deprecated in favor of + ``coordinates`` for consistency with the rest of astroquery. [#3609] + Service fixes and enhancements ------------------------------ diff --git a/astroquery/alma/core.py b/astroquery/alma/core.py index 0a3ee5d1b0..279280eae6 100644 --- a/astroquery/alma/core.py +++ b/astroquery/alma/core.py @@ -20,6 +20,7 @@ from astropy import units as u from astropy.time import Time from astropy.coordinates import SkyCoord +from astropy.utils.decorators import deprecated_renamed_argument from pyvo.dal.sia2 import SIA2_PARAMETERS_DESC, SIA2Service @@ -506,7 +507,8 @@ def query_object_async(self, object_name, *, public=True, payload=payload, enhanced_results=enhanced_results, **kwargs) - def query_region_async(self, coordinate, radius, *, public=True, + @deprecated_renamed_argument("coordinate", "coordinates", since="0.4.12") + def query_region_async(self, coordinates, radius, *, public=True, science=True, payload=None, enhanced_results=False, **kwargs): """ @@ -533,7 +535,7 @@ def query_region_async(self, coordinate, radius, *, public=True, rad = radius if not isinstance(radius, u.Quantity): rad = radius*u.deg - obj_coord = commons.parse_coordinates(coordinate).icrs + obj_coord = commons.parse_coordinates(coordinates).icrs ra_dec = '{}, {}'.format(obj_coord.to_string(), rad.to(u.deg).value) if payload is None: payload = {} diff --git a/astroquery/alma/tests/test_alma.py b/astroquery/alma/tests/test_alma.py index 6bbdc50911..afe63b7c1c 100644 --- a/astroquery/alma/tests/test_alma.py +++ b/astroquery/alma/tests/test_alma.py @@ -12,6 +12,7 @@ from astropy.io import votable from astropy.coordinates import SkyCoord from astropy.time import Time +from astropy.utils.exceptions import AstropyDeprecationWarning import pyvo from astroquery.alma import Alma @@ -364,6 +365,19 @@ def test_query(): language='ADQL', maxrec=None, uploads=None) +def test_query_region_coordinate_deprecated(): + # the old ``coordinate`` keyword should still work but emit a + # deprecation warning (renamed to ``coordinates``, issue #2803) + alma = Alma() + alma._get_dataarchive_url = Mock() + new_payload = alma.query_region(coordinates='1 2', radius=1*u.deg, + get_query_payload=True) + with pytest.warns(AstropyDeprecationWarning): + old_payload = alma.query_region(coordinate='1 2', radius=1*u.deg, + get_query_payload=True) + assert old_payload == new_payload + + @pytest.mark.filterwarnings("ignore::astropy.utils.exceptions.AstropyUserWarning") def test_enhanced_table(): pytest.importorskip('regions') diff --git a/astroquery/alma/tests/test_alma_remote.py b/astroquery/alma/tests/test_alma_remote.py index 2a1535dc0e..4986a8f8ce 100644 --- a/astroquery/alma/tests/test_alma_remote.py +++ b/astroquery/alma/tests/test_alma_remote.py @@ -337,7 +337,7 @@ def test_query(self, tmp_path, alma): def test_misc(self, alma): # miscellaneous set of common tests # - # alma.query_region(coordinate=orionkl_coords, radius=4 * u.arcmin, + # alma.query_region(coordinates=orionkl_coords, radius=4 * u.arcmin, # public=False, science=False) result = alma.query_object('M83', public=True, science=True) diff --git a/astroquery/esa/euclid/core.py b/astroquery/esa/euclid/core.py index 917e99b020..0bf9e702dc 100644 --- a/astroquery/esa/euclid/core.py +++ b/astroquery/esa/euclid/core.py @@ -384,14 +384,15 @@ def launch_job_async(self, query, *, name=None, dump_to_file=False, output_file= except Exception as exx: log.error(f'Query failed: {query}, {str(exx)}') - def query_object(self, coordinate, *, radius=None, width=None, height=None, + @deprecated_renamed_argument("coordinate", "coordinates", since="0.4.12") + def query_object(self, coordinates, *, radius=None, width=None, height=None, async_job=False, verbose=False, columns=None): """ Searches for objects around a given position with the default catalog sascat_pvpr01.mer_final_cat_pvpr01 Parameters ---------- - coordinate : astropy.coordinate, mandatory + coordinates : astropy.coordinate, mandatory coordinates center point radius : astropy.units, required if no 'width' nor 'height' are provided radius (deg) @@ -411,7 +412,7 @@ def query_object(self, coordinate, *, radius=None, width=None, height=None, ------- The job results (astropy.table) """ - coord = commons.parse_coordinates(coordinate) + coord = commons.parse_coordinates(coordinates) if radius is not None: job = self.__cone_search(coord, radius, async_job=async_job, verbose=verbose, columns=columns) @@ -437,14 +438,14 @@ def query_object(self, coordinate, *, radius=None, width=None, height=None, job = super().launch_job(query, verbose=verbose, format_with_results_compressed=('votable_gzip',)) return job.get_results() - def __cone_search(self, coordinate, radius, *, table_name=None, ra_column_name=None, dec_column_name=None, + def __cone_search(self, coordinates, radius, *, table_name=None, ra_column_name=None, dec_column_name=None, async_job=False, verbose=False, columns=None): """Cone search sorted by distance TAP & TAP+ Parameters ---------- - coordinate : astropy.coordinate, mandatory + coordinates : astropy.coordinate, mandatory coordinates center point radius : astropy.units, mandatory radius @@ -478,7 +479,7 @@ def __cone_search(self, coordinate, radius, *, table_name=None, ra_column_name=N raise ValueError(f"Invalid ra or dec column names: ra, {ra_column_name}, dec, {dec_column_name}") radius_deg = None - coord = commons.parse_coordinates(coordinate) + coord = commons.parse_coordinates(coordinates) ra_hours, dec = commons.coord_to_radec(coord) ra = ra_hours * 15.0 # Converts to degrees if radius is not None: @@ -519,7 +520,8 @@ def __cone_search(self, coordinate, radius, *, table_name=None, ra_column_name=N return job - def cone_search(self, coordinate, radius, *, + @deprecated_renamed_argument("coordinate", "coordinates", since="0.4.12") + def cone_search(self, coordinates, radius, *, table_name=None, ra_column_name=None, dec_column_name=None, @@ -535,7 +537,7 @@ def cone_search(self, coordinate, radius, *, Parameters ---------- - coordinate : astropy.coordinate, mandatory + coordinates : astropy.coordinate, mandatory coordinates center point radius : astropy.units, mandatory radius @@ -570,7 +572,7 @@ def cone_search(self, coordinate, radius, *, """ radius_deg = None - coord = commons.parse_coordinates(coordinate) + coord = commons.parse_coordinates(coordinates) ra_hours, dec = commons.coord_to_radec(coord) ra = ra_hours * 15.0 # Converts to degrees if radius is not None: @@ -1453,9 +1455,9 @@ def __is_multiple(self, value): return not isinstance(value, int) and ((isinstance(value, (list, tuple)) and len(value) > 1) or ',' in value) - @deprecated_renamed_argument(('instrument', 'id'), (None, None), since='0.4.12') - def get_cutout(self, *, file_path=None, coordinate, radius, output_file=None, verbose=False, instrument=None, - id=None): + @deprecated_renamed_argument(('coordinate', 'instrument', 'id'), ('coordinates', None, None), since='0.4.12') + def get_cutout(self, *, file_path=None, coordinates=None, radius=None, output_file=None, verbose=False, + instrument=None, id=None): """ Downloads a cutout from a MER mosaic (background-subtracted image) for a given fits file path, centered on a coordinate and with a specified radius. @@ -1466,7 +1468,7 @@ def get_cutout(self, *, file_path=None, coordinate, radius, output_file=None, ve ---------- file_path : str, mandatory, default None file path for the product on the server (MER mosaic) - coordinate : astropy.coordinate or Simbad/VizieR/NED name (str), mandatory + coordinates : astropy.coordinate or Simbad/VizieR/NED name (str), mandatory coordinates center point radius : astropy.units, mandatory the radius of the cutout to generate @@ -1480,14 +1482,14 @@ def get_cutout(self, *, file_path=None, coordinate, radius, output_file=None, ve The fits file is downloaded, and the local path where the cutout is saved is returned """ - if file_path is None or coordinate is None or radius is None: + if file_path is None or coordinates is None or radius is None: raise ValueError(self.__ERROR_MSG_REQUESTED_GENERIC) # Parse POS radius_deg = Angle(self.__get_quantity_input(radius, "radius")).to_value(u.deg) if radius_deg > 0.5: raise ValueError(self.__ERROR_MSG_REQUESTED_RADIUS) - coord = commons.parse_coordinates(coordinate) + coord = commons.parse_coordinates(coordinates) ra_hours, dec = commons.coord_to_radec(coord) ra = ra_hours * 15.0 # Converts to degrees pos = """CIRCLE,{ra},{dec},{radius}""".format(**{'ra': ra, 'dec': dec, 'radius': radius_deg}) diff --git a/astroquery/esa/euclid/tests/test_euclid_remote.py b/astroquery/esa/euclid/tests/test_euclid_remote.py index 68826b37de..7aebbdf167 100644 --- a/astroquery/esa/euclid/tests/test_euclid_remote.py +++ b/astroquery/esa/euclid/tests/test_euclid_remote.py @@ -21,17 +21,17 @@ def test_query_object_row_limit(): coord = SkyCoord(ra=265.8, dec=64.1, unit=(u.degree, u.degree), frame='icrs') width = u.Quantity(0.1, u.deg) height = u.Quantity(0.1, u.deg) - r = euclid.query_object(coordinate=coord, width=width, height=height, async_job=True, verbose=True) + r = euclid.query_object(coordinates=coord, width=width, height=height, async_job=True, verbose=True) assert len(r) == 50 euclid.ROW_LIMIT = 10 - r = euclid.query_object(coordinate=coord, width=width, height=height, async_job=True) + r = euclid.query_object(coordinates=coord, width=width, height=height, async_job=True) assert len(r) == 10 == euclid.ROW_LIMIT euclid.ROW_LIMIT = -1 - r = euclid.query_object(coordinate=coord, width=width, height=height, async_job=True, verbose=True) + r = euclid.query_object(coordinates=coord, width=width, height=height, async_job=True, verbose=True) assert len(r) == 1948 diff --git a/astroquery/esa/euclid/tests/test_euclidtap.py b/astroquery/esa/euclid/tests/test_euclidtap.py index ad543ca057..510d32f6e0 100644 --- a/astroquery/esa/euclid/tests/test_euclidtap.py +++ b/astroquery/esa/euclid/tests/test_euclidtap.py @@ -22,6 +22,7 @@ from astropy.table import Column, Table from astropy.units import Quantity from astropy.utils.data import get_pkg_data_filename +from astropy.utils.exceptions import AstropyDeprecationWarning from requests import HTTPError from astroquery.esa.euclid.core import EuclidClass @@ -198,7 +199,7 @@ def test_load_environments(): def test_query_async_object(column_attrs, mock_querier_async): coord = SkyCoord(ra=60.3372780005097, dec=-49.93184727724773, unit=(u.degree, u.degree), frame='icrs') - table = mock_querier_async.query_object(coordinate=coord, width=u.Quantity(0.1, u.deg), + table = mock_querier_async.query_object(coordinates=coord, width=u.Quantity(0.1, u.deg), height=u.Quantity(0.1, u.deg), async_job=True) assert table is not None @@ -210,7 +211,7 @@ def test_query_async_object(column_attrs, mock_querier_async): def test_query_async_object_columns(column_attrs, mock_querier_async): coord = SkyCoord(ra=60.3372780005097, dec=-49.93184727724773, unit=(u.degree, u.degree), frame='icrs') - table = mock_querier_async.query_object(coordinate=coord, width=u.Quantity(0.1, u.deg), + table = mock_querier_async.query_object(coordinates=coord, width=u.Quantity(0.1, u.deg), height=u.Quantity(0.1, u.deg), columns=("alpha",), async_job=True) assert table is not None @@ -222,7 +223,7 @@ def test_query_async_object_columns(column_attrs, mock_querier_async): def test_query_object(column_attrs, mock_querier): coord = SkyCoord(ra=60.3372780005097, dec=-49.93184727724773, unit=(u.degree, u.degree), frame='icrs') - table = mock_querier.query_object(coordinate=coord, width=u.Quantity(0.1, u.deg), + table = mock_querier.query_object(coordinates=coord, width=u.Quantity(0.1, u.deg), height=u.Quantity(0.1, u.deg)) assert table is not None @@ -234,7 +235,7 @@ def test_query_object(column_attrs, mock_querier): def test_query_object_columns(column_attrs, mock_querier): coord = SkyCoord(ra=60.3372780005097, dec=-49.93184727724773, unit=(u.degree, u.degree), frame='icrs') - table = mock_querier.query_object(coordinate=coord, width=u.Quantity(0.1, u.deg), + table = mock_querier.query_object(coordinates=coord, width=u.Quantity(0.1, u.deg), height=u.Quantity(0.1, u.deg), columns=("alpha",)) assert table is not None @@ -245,7 +246,7 @@ def test_query_object_columns(column_attrs, mock_querier): def test_query_object_async_radius(column_attrs, mock_querier_async): coord = SkyCoord(ra=60.3372780005097, dec=-49.93184727724773, unit=(u.degree, u.degree), frame='icrs') - table = mock_querier_async.query_object(coordinate=coord, radius=RADIUS, async_job=True) + table = mock_querier_async.query_object(coordinates=coord, radius=RADIUS, async_job=True) assert table is not None @@ -256,7 +257,7 @@ def test_query_object_async_radius(column_attrs, mock_querier_async): def test_query_object_radius(column_attrs, mock_querier): coord = SkyCoord(ra=60.3372780005097, dec=-49.93184727724773, unit=(u.degree, u.degree), frame='icrs') - table = mock_querier.query_object(coordinate=coord, radius=RADIUS) + table = mock_querier.query_object(coordinates=coord, radius=RADIUS) assert table is not None @@ -265,9 +266,18 @@ def test_query_object_radius(column_attrs, mock_querier): assert table[colname].attrs_equal(attrs) +def test_query_object_deprecated_coordinate_keyword(mock_querier): + coord = SkyCoord(ra=60.3372780005097, dec=-49.93184727724773, unit=(u.degree, u.degree), frame='icrs') + with pytest.warns(AstropyDeprecationWarning, match='"coordinate" was deprecated'): + table = mock_querier.query_object(coordinate=coord, radius=RADIUS) + + assert table is not None + assert len(table) == 3 + + def test_query_object_async_radius_columns(column_attrs, mock_querier_async): coord = SkyCoord(ra=60.3372780005097, dec=-49.93184727724773, unit=(u.degree, u.degree), frame='icrs') - table = mock_querier_async.query_object(coordinate=coord, radius=RADIUS, columns=("alpha",), async_job=True) + table = mock_querier_async.query_object(coordinates=coord, radius=RADIUS, columns=("alpha",), async_job=True) assert table is not None @@ -277,7 +287,7 @@ def test_query_object_async_radius_columns(column_attrs, mock_querier_async): def test_query_object_radius_columns(column_attrs, mock_querier): coord = SkyCoord(ra=60.3372780005097, dec=-49.93184727724773, unit=(u.degree, u.degree), frame='icrs') - table = mock_querier.query_object(coordinate=coord, radius=RADIUS, columns=("alpha",)) + table = mock_querier.query_object(coordinates=coord, radius=RADIUS, columns=("alpha",)) assert table is not None @@ -1205,7 +1215,7 @@ def test_get_cutout(capsys): result = tap.get_cutout( file_path='/data/repository/NIR/19704/EUC_NIR_W-STACK_NIR-J-19704_20190718T001858.5Z_00.00.fits', - coordinate=c, radius=r, output_file=None, verbose=True) + coordinates=c, radius=r, output_file=None, verbose=True) assert result is not None @@ -1239,17 +1249,17 @@ def test_get_cutout_exception(): show_server_messages=False) with pytest.raises(ValueError, match="Radius cannot be greater than 30 arcminutes"): - tap.get_cutout(file_path=file_path, coordinate=c, radius=100 * u.arcmin, + tap.get_cutout(file_path=file_path, coordinates=c, radius=100 * u.arcmin, output_file=None) with pytest.raises(ValueError, match="Missing required argument"): - tap.get_cutout(file_path=None, coordinate=c, radius=r, output_file=None) + tap.get_cutout(file_path=None, coordinates=c, radius=r, output_file=None) with pytest.raises(ValueError, match="Missing required argument"): - tap.get_cutout(file_path=file_path, coordinate=None, radius=r, output_file=None) + tap.get_cutout(file_path=file_path, coordinates=None, radius=r, output_file=None) with pytest.raises(ValueError, match="Missing required argument"): - tap.get_cutout(file_path=file_path, coordinate=c, radius=None, output_file=None) + tap.get_cutout(file_path=file_path, coordinates=c, radius=None, output_file=None) @patch.object(TapPlus, 'load_data') @@ -1272,7 +1282,7 @@ def test_get_cutout_exceptions_2(mock_load_data, caplog): mock_load_data.side_effect = HTTPError("launch_job_async HTTPError") - tap.get_cutout(file_path='hola.fits', coordinate=SKYCOORD, radius=1 * u.arcmin, + tap.get_cutout(file_path='hola.fits', coordinates=SKYCOORD, radius=1 * u.arcmin, output_file=None) mssg = ("Cannot retrieve the product for file_path hola.fits. HTTP error: " @@ -1281,7 +1291,7 @@ def test_get_cutout_exceptions_2(mock_load_data, caplog): mock_load_data.side_effect = Exception("launch_job_async Exception") - tap.get_cutout(file_path='hola.fits', coordinate=SKYCOORD, radius=1 * u.arcmin, + tap.get_cutout(file_path='hola.fits', coordinates=SKYCOORD, radius=1 * u.arcmin, output_file=None) mssg = ("Cannot retrieve the product for file_path hola.fits: launch_job_async " diff --git a/astroquery/esa/hsa/core.py b/astroquery/esa/hsa/core.py index c9c655321c..b433e7997d 100644 --- a/astroquery/esa/hsa/core.py +++ b/astroquery/esa/hsa/core.py @@ -7,6 +7,7 @@ from pathlib import Path from astropy import units as u +from astropy.utils.decorators import deprecated_renamed_argument from astroquery.utils import commons from astroquery import log from astroquery.exceptions import LoginError @@ -380,13 +381,14 @@ def get_columns(self, table_name, *, only_names=True, verbose=False): else: return columns - def query_observations(self, coordinate, radius, *, n_obs=10, **kwargs): + @deprecated_renamed_argument("coordinate", "coordinates", since="0.4.12") + def query_observations(self, coordinates, radius, *, n_obs=10, **kwargs): """ Get the observation IDs from a given region Parameters ---------- - coordinate : string / `astropy.coordinates` + coordinates : string / `astropy.coordinates` the identifier or coordinates around which to query radius : int / `~astropy.units.Quantity` the radius of the region @@ -399,15 +401,16 @@ def query_observations(self, coordinate, radius, *, n_obs=10, **kwargs): ------- A table object with the list of observations in the region """ - return self.query_region(coordinate, radius, n_obs=n_obs, columns="observation_id", **kwargs) + return self.query_region(coordinates, radius, n_obs=n_obs, columns="observation_id", **kwargs) - def query_region(self, coordinate, radius, *, n_obs=10, columns='*', **kwargs): + @deprecated_renamed_argument("coordinate", "coordinates", since="0.4.12") + def query_region(self, coordinates, radius, *, n_obs=10, columns='*', **kwargs): """ Get the observation metadata from a given region Parameters ---------- - coordinate : string / `astropy.coordinates` + coordinates : string / `astropy.coordinates` the identifier or coordinates around which to query radius : int / `~astropy.units.Quantity` the radius of the region @@ -425,7 +428,7 @@ def query_region(self, coordinate, radius, *, n_obs=10, columns='*', **kwargs): r = radius if not isinstance(radius, u.Quantity): r = radius*u.deg - coord = commons.parse_coordinates(coordinate).icrs + coord = commons.parse_coordinates(coordinates).icrs query = (f"select top {n_obs} {columns} from hsa.v_active_observation " f"where contains(" diff --git a/astroquery/esa/hsa/tests/test_hsa.py b/astroquery/esa/hsa/tests/test_hsa.py index 82d35bfc16..fd2d09897a 100644 --- a/astroquery/esa/hsa/tests/test_hsa.py +++ b/astroquery/esa/hsa/tests/test_hsa.py @@ -1,8 +1,11 @@ # Licensed under a 3-clause BSD style license - see LICENSE.rst import os +import pytest + from astropy import units as u from astropy.coordinates import SkyCoord +from astropy.utils.exceptions import AstropyDeprecationWarning from ..core import HSAClass from ..tests.dummy_tap_handler import DummyHSATapHandler @@ -50,7 +53,7 @@ def test_get_columns(self): def test_query_observations(self): c = SkyCoord(ra=100.2417*u.degree, dec=9.895*u.degree, frame='icrs') - parameters = {'coordinate': c, + parameters = {'coordinates': c, 'radius': 0.5} dummyTapHandler = DummyHSATapHandler("query_observations", parameters) hsa = HSAClass(self.get_dummy_tap_handler()) @@ -59,9 +62,17 @@ def test_query_observations(self): def test_query_region(self): c = SkyCoord(ra=100.2417*u.degree, dec=9.895*u.degree, frame='icrs') - parameters = {'coordinate': c, + parameters = {'coordinates': c, 'radius': 0.5} dummyTapHandler = DummyHSATapHandler("query_region", parameters) hsa = HSAClass(self.get_dummy_tap_handler()) hsa.query_region(**parameters) dummyTapHandler.check_call("query_region", parameters) + + def test_query_region_deprecated_coordinate(self): + c = SkyCoord(ra=100.2417*u.degree, dec=9.895*u.degree, frame='icrs') + hsa = HSAClass(self.get_dummy_tap_handler()) + with pytest.warns(AstropyDeprecationWarning, match="coordinate"): + hsa.query_region(coordinate=c, radius=0.5) + with pytest.warns(AstropyDeprecationWarning, match="coordinate"): + hsa.query_observations(coordinate=c, radius=0.5) diff --git a/astroquery/esa/jwst/core.py b/astroquery/esa/jwst/core.py index b9347e5f4d..f28e10dd30 100644 --- a/astroquery/esa/jwst/core.py +++ b/astroquery/esa/jwst/core.py @@ -25,6 +25,7 @@ from astropy.coordinates import Angle, SkyCoord from astropy.table import vstack from astropy.units import Quantity +from astropy.utils.decorators import deprecated_renamed_argument from requests.exceptions import ConnectionError from astroquery.exceptions import RemoteServiceError @@ -233,7 +234,8 @@ def list_async_jobs(self, *, verbose=False): """ return self.__jwsttap.list_async_jobs(verbose=verbose) - def query_region(self, coordinate, *, + @deprecated_renamed_argument("coordinate", "coordinates", since="0.4.12") + def query_region(self, coordinates, *, radius=None, width=None, height=None, @@ -251,7 +253,7 @@ def query_region(self, coordinate, *, Parameters ---------- - coordinate : astropy.coordinate, mandatory + coordinates : astropy.coordinates, mandatory coordinates center point radius : astropy.units, required if no 'width' nor 'height' are provided @@ -294,10 +296,10 @@ def query_region(self, coordinate, *, ------- The job results (astropy.table). """ - coord = self.__get_coord_input(value=coordinate, msg="coordinate") + coord = self.__get_coord_input(value=coordinates, msg="coordinates") job = None if radius is not None: - job = self.cone_search(coordinate=coord, + job = self.cone_search(coordinates=coord, radius=radius, only_public=only_public, observation_id=observation_id, @@ -357,7 +359,8 @@ def query_region(self, coordinate, *, job = self.__jwsttap.launch_job(query=query, verbose=verbose) return job.get_results() - def cone_search(self, coordinate, radius, *, + @deprecated_renamed_argument("coordinate", "coordinates", since="0.4.12") + def cone_search(self, coordinates, radius, *, observation_id=None, cal_level="Top", prod_type=None, @@ -377,7 +380,7 @@ def cone_search(self, coordinate, radius, *, Parameters ---------- - coordinate : astropy.coordinate, mandatory + coordinates : astropy.coordinates, mandatory coordinates center point radius : astropy.units, mandatory radius @@ -428,7 +431,7 @@ def cone_search(self, coordinate, radius, *, ------- A Job object """ - coord = self.__get_coord_input(value=coordinate, msg="coordinate") + coord = self.__get_coord_input(value=coordinates, msg="coordinates") ra_hours, dec = commons.coord_to_radec(coord) ra = ra_hours * 15.0 # Converts to degrees @@ -548,7 +551,7 @@ def query_target(self, target_name, *, target_resolver="ALL", """ coordinates = self.resolve_target_coordinates(target_name=target_name, target_resolver=target_resolver) - return self.query_region(coordinate=coordinates, + return self.query_region(coordinates=coordinates, radius=radius, width=width, height=height, diff --git a/astroquery/esa/jwst/tests/test_jwsttap.py b/astroquery/esa/jwst/tests/test_jwsttap.py index d627c7b8e2..07f43510d7 100644 --- a/astroquery/esa/jwst/tests/test_jwsttap.py +++ b/astroquery/esa/jwst/tests/test_jwsttap.py @@ -24,6 +24,7 @@ from astropy.io.votable import parse_single_table from astropy.table import Table from astropy.units import Quantity +from astropy.utils.exceptions import AstropyDeprecationWarning from astroquery.exceptions import TableParseError from astroquery.esa.jwst import JwstClass @@ -239,11 +240,11 @@ def test_query_region(self): tap = JwstClass(tap_plus_handler=tapplus, show_messages=False) with pytest.raises(ValueError) as err: - tap.query_region(coordinate=123) - assert "coordinate must be either a string or astropy.coordinates" in err.value.args[0] + tap.query_region(coordinates=123) + assert "coordinates must be either a string or astropy.coordinates" in err.value.args[0] with pytest.raises(NameResolveError) as err: - tap.query_region(coordinate='test') + tap.query_region(coordinates='test') assert ("Unable to find coordinates for name 'test'" in err.value.args[0] or "Unable to retrieve " "coordinates" in err.value.args[0]) @@ -537,6 +538,26 @@ def test_cone_search_sync(self): tap.cone_search(sc, radius, proposal_id=123) assert "proposal_id must be string" in err.value.args[0] + def test_coordinate_deprecated_keyword(self): + connHandler = DummyConnHandler() + tapplus = TapPlus(url="http://test:1111/tap", connhandler=connHandler) + tap = JwstClass(tap_plus_handler=tapplus, show_messages=False) + responseLaunchJob = DummyResponse(200) + responseLaunchJob.set_data(method='POST', body=JOB_DATA) + connHandler.set_default_response(responseLaunchJob) + sc = SkyCoord(ra=19.0, dec=20.0, unit=(u.degree, u.degree), frame='icrs') + radius = Quantity(1.0, u.deg) + + with pytest.warns(AstropyDeprecationWarning, + match='"coordinate" was deprecated in version 0.4.12'): + job = tap.cone_search(coordinate=sc, radius=radius) + assert job is not None + + with pytest.warns(AstropyDeprecationWarning, + match='"coordinate" was deprecated in version 0.4.12'): + results = tap.query_region(coordinate=sc, radius=radius) + assert results is not None + def test_cone_search_async(self): connHandler = DummyConnHandler() tapplus = TapPlus(url="http://test:1111/tap", connhandler=connHandler) diff --git a/astroquery/esasky/core.py b/astroquery/esasky/core.py index 34755789b3..8caace0ffb 100644 --- a/astroquery/esasky/core.py +++ b/astroquery/esasky/core.py @@ -14,6 +14,7 @@ from astropy.coordinates import Angle from astropy.io import fits from astropy.utils.console import ProgressBar +from astropy.utils.decorators import deprecated_renamed_argument from astroquery import log from requests import HTTPError from requests import ConnectionError @@ -265,7 +266,7 @@ def query_object_maps(self, position, missions=__ALL_STRING, get_query_payload=F query_object_maps("265.05, 69.0", "Herschel") query_object_maps("265.05, 69.0", ["Herschel", "HST-OPTICAL"]) """ - return self.query_region_maps(position=position, + return self.query_region_maps(coordinates=position, radius=self.__ZERO_ARCMIN_STRING, missions=missions, get_query_payload=get_query_payload, @@ -322,7 +323,7 @@ def query_object_catalogs(self, position, catalogs=__ALL_STRING, row_limit=DEFAU query_object_catalogs("202.469, 47.195", "HSC") query_object_catalogs("202.469, 47.195", ["HSC", "XMM-OM"]) """ - return self.query_region_catalogs(position=position, + return self.query_region_catalogs(coordinates=position, radius=self.__ZERO_ARCMIN_STRING, catalogs=catalogs, row_limit=row_limit, @@ -378,7 +379,7 @@ def query_object_spectra(self, position, missions=__ALL_STRING, get_query_payloa query_object_spectra("202.469, 47.195", "Herschel") query_object_spectra("202.469, 47.195", ["Herschel", "HST-OPTICAL"]) """ - return self.query_region_spectra(position=position, + return self.query_region_spectra(coordinates=position, radius=self.__ZERO_ARCMIN_STRING, missions=missions, get_query_payload=get_query_payload, @@ -643,7 +644,8 @@ def get_images_sso(self, *, sso_name=None, sso_type="ALL", table_list=None, miss log.info("No maps found.") return maps - def query_region_maps(self, position, radius, missions=__ALL_STRING, get_query_payload=False, cache=True, + @deprecated_renamed_argument("position", "coordinates", since="0.4.12") + def query_region_maps(self, coordinates, radius, missions=__ALL_STRING, get_query_payload=False, cache=True, row_limit=DEFAULT_ROW_LIMIT, verbose=False): """ This method queries a chosen region for all available maps and returns a @@ -652,7 +654,7 @@ def query_region_maps(self, position, radius, missions=__ALL_STRING, get_query_p Parameters ---------- - position : str or `astropy.coordinates` object + coordinates : str or `astropy.coordinates` object Can either be a string of the location, eg 'M51', or the coordinates of the object. radius : str or `~astropy.units.Quantity` @@ -700,7 +702,7 @@ def query_region_maps(self, position, radius, missions=__ALL_STRING, get_query_p query_result = {} sesame_database.set('simbad') - coordinates = commons.parse_coordinates(position) + coordinates = commons.parse_coordinates(coordinates) self._store_query_result(query_result=query_result, names=sanitized_missions, descriptors=self._get_observation_info(), coordinates=coordinates, @@ -711,7 +713,8 @@ def query_region_maps(self, position, radius, missions=__ALL_STRING, get_query_p return commons.TableList(query_result) - def query_region_catalogs(self, position, radius, catalogs=__ALL_STRING, row_limit=DEFAULT_ROW_LIMIT, + @deprecated_renamed_argument("position", "coordinates", since="0.4.12") + def query_region_catalogs(self, coordinates, radius, catalogs=__ALL_STRING, row_limit=DEFAULT_ROW_LIMIT, get_query_payload=False, cache=True, verbose=False): """ This method queries a chosen region for all available catalogs and @@ -720,7 +723,7 @@ def query_region_catalogs(self, position, radius, catalogs=__ALL_STRING, row_lim Parameters ---------- - position : str or `astropy.coordinates` object + coordinates : str or `astropy.coordinates` object Can either be a string of the location, eg 'M51', or the coordinates of the object. radius : str or `~astropy.units.Quantity` @@ -766,7 +769,7 @@ def query_region_catalogs(self, position, radius, catalogs=__ALL_STRING, row_lim sanitized_row_limit = self._sanitize_input_row_limit(row_limit) sesame_database.set('simbad') - coordinates = commons.parse_coordinates(position) + coordinates = commons.parse_coordinates(coordinates) query_result = {} @@ -780,7 +783,8 @@ def query_region_catalogs(self, position, radius, catalogs=__ALL_STRING, row_lim return commons.TableList(query_result) - def query_region_spectra(self, position, radius, missions=__ALL_STRING, row_limit=DEFAULT_ROW_LIMIT, + @deprecated_renamed_argument("position", "coordinates", since="0.4.12") + def query_region_spectra(self, coordinates, radius, missions=__ALL_STRING, row_limit=DEFAULT_ROW_LIMIT, get_query_payload=False, cache=True, verbose=False): """ This method queries a chosen region for all available spectra and returns a @@ -789,7 +793,7 @@ def query_region_spectra(self, position, radius, missions=__ALL_STRING, row_limi Parameters ---------- - position : str or `astropy.coordinates` object + coordinates : str or `astropy.coordinates` object Can either be a string of the location, eg 'M51', or the coordinates of the object. radius : str or `~astropy.units.Quantity` @@ -837,7 +841,7 @@ def query_region_spectra(self, position, radius, missions=__ALL_STRING, row_limi query_result = {} sesame_database.set('simbad') - coordinates = commons.parse_coordinates(position) + coordinates = commons.parse_coordinates(coordinates) self._store_query_result(query_result=query_result, names=sanitized_missions, descriptors=self._get_spectra_info(), coordinates=coordinates, diff --git a/astroquery/esasky/tests/test_esasky.py b/astroquery/esasky/tests/test_esasky.py new file mode 100644 index 0000000000..0cb7d83113 --- /dev/null +++ b/astroquery/esasky/tests/test_esasky.py @@ -0,0 +1,36 @@ +# Licensed under a 3-clause BSD style license - see LICENSE.rst +import pytest + +from astropy.coordinates import SkyCoord +from astropy.utils.exceptions import AstropyDeprecationWarning + +from astroquery.esasky import ESASky + +# Fake mission descriptors so that no network access is needed to build the query payload. +FAKE_DESCRIPTORS = {"XMM": {"mission": "XMM", + "table_name": "observations.mv_v_esasky_xmm_om_optical_fdw", + "ra": "ra_deg", "dec": "dec_deg", + "intersect_polygon_query": True}} + + +@pytest.mark.parametrize("method_name, descriptor_getter", + [("query_region_maps", "_get_observation_info"), + ("query_region_catalogs", "_get_catalogs_info"), + ("query_region_spectra", "_get_spectra_info")]) +def test_query_region_deprecated_position(monkeypatch, method_name, descriptor_getter): + # The 'position' keyword was renamed to 'coordinates'; the old keyword + # should still work but emit an AstropyDeprecationWarning. + monkeypatch.setattr(ESASky, descriptor_getter, lambda: FAKE_DESCRIPTORS) + coordinates = SkyCoord(ra=202.469, dec=47.195, unit="deg") + method = getattr(ESASky, method_name) + kwargs = {("catalogs" if method_name == "query_region_catalogs" else "missions"): ["XMM"]} + + expected = method(coordinates=coordinates, radius="5 arcmin", + get_query_payload=True, **kwargs) + + with pytest.warns(AstropyDeprecationWarning): + result = method(position=coordinates, radius="5 arcmin", + get_query_payload=True, **kwargs) + + assert result == expected + assert "QUERY" in result["XMM"] diff --git a/astroquery/esasky/tests/test_esasky_remote.py b/astroquery/esasky/tests/test_esasky_remote.py index 9f43ed294e..40cec9b905 100755 --- a/astroquery/esasky/tests/test_esasky_remote.py +++ b/astroquery/esasky/tests/test_esasky_remote.py @@ -106,7 +106,7 @@ def test_esasky_get_spectra_obs_id(self, tmp_path, mission, observation_id): result[mission.upper()][0].close() def test_esasky_query_region_maps(self): - result = ESASky.query_region_maps(position="M51", radius="5 arcmin") + result = ESASky.query_region_maps(coordinates="M51", radius="5 arcmin") assert isinstance(result, TableList) def test_esasky_query_object_maps(self): @@ -150,7 +150,7 @@ def test_esasky_get_images_hst(self, tmp_path): assert Path(tmp_path, "HST-UV").exists() def test_esasky_query_region_catalogs(self): - result = ESASky.query_region_catalogs(position="M51", radius="5 arcmin") + result = ESASky.query_region_catalogs(coordinates="M51", radius="5 arcmin") assert isinstance(result, TableList) def test_esasky_query_object_catalogs(self): @@ -177,7 +177,7 @@ def test_esasky_get_maps(self, tmp_path): hdu_list.close() def test_esasky_query_region_spectra(self): - result = ESASky.query_region_spectra(position="M51", radius="5 arcmin") + result = ESASky.query_region_spectra(coordinates="M51", radius="5 arcmin") assert isinstance(result, TableList) def test_esasky_query_object_spectra(self): diff --git a/astroquery/gaia/core.py b/astroquery/gaia/core.py index a0be6d5354..3a7eca24ab 100644 --- a/astroquery/gaia/core.py +++ b/astroquery/gaia/core.py @@ -469,14 +469,14 @@ def get_datalinks(self, ids, *, linking_parameter='SOURCE_ID', verbose=False): return self.__gaiadata.get_datalinks(ids=ids, linking_parameter=final_linking_parameter, verbose=verbose) - def __query_object(self, coordinate, *, radius=None, width=None, height=None, + def __query_object(self, coordinates, *, radius=None, width=None, height=None, async_job=False, verbose=False, columns=(), get_query_payload=False): """Launches a job TAP & TAP+ Parameters ---------- - coordinate : str or astropy.coordinate, mandatory + coordinates : str or astropy.coordinate, mandatory coordinates center point radius : str or astropy.units if no 'width' nor 'height' are provided radius (deg) @@ -499,7 +499,7 @@ def __query_object(self, coordinate, *, radius=None, width=None, height=None, ------- The job results (astropy.table). """ - coord = self.__getCoordInput(coordinate, "coordinate") + coord = self.__getCoordInput(coordinates, "coordinates") if radius is not None: job = self.__cone_search(coord, radius, async_job=async_job, verbose=verbose, columns=columns) @@ -554,7 +554,8 @@ def __query_object(self, coordinate, *, radius=None, width=None, height=None, job = self.launch_job(query, verbose=verbose) return job.get_results() - def query_object(self, coordinate, *, radius=None, width=None, height=None, verbose=False, columns=(), + @deprecated_renamed_argument("coordinate", "coordinates", since="0.4.12") + def query_object(self, coordinates, *, radius=None, width=None, height=None, verbose=False, columns=(), get_query_payload=False): """Launches a synchronous cone search for the input search radius or the box on the sky, sorted by angular separation @@ -562,7 +563,7 @@ def query_object(self, coordinate, *, radius=None, width=None, height=None, verb Parameters ---------- - coordinate : str or astropy.coordinates, mandatory + coordinates : str or astropy.coordinates, mandatory coordinates center point radius : str or astropy.units if no 'width'/'height' are provided radius (deg) @@ -582,17 +583,18 @@ def query_object(self, coordinate, *, radius=None, width=None, height=None, verb ------- The job results (astropy.table). """ - return self.__query_object(coordinate, radius=radius, width=width, height=height, async_job=False, + return self.__query_object(coordinates, radius=radius, width=width, height=height, async_job=False, verbose=verbose, columns=columns, get_query_payload=get_query_payload) - def query_object_async(self, coordinate, *, radius=None, width=None, height=None, verbose=False, columns=()): + @deprecated_renamed_argument("coordinate", "coordinates", since="0.4.12") + def query_object_async(self, coordinates, *, radius=None, width=None, height=None, verbose=False, columns=()): """Launches an asynchronous cone search for the input search radius or the box on the sky, sorted by angular separation TAP & TAP+ Parameters ---------- - coordinate : str or astropy.coordinates, mandatory + coordinates : str or astropy.coordinates, mandatory coordinates center point radius : str or astropy.units if no 'width'/'height' are provided radius @@ -609,10 +611,10 @@ def query_object_async(self, coordinate, *, radius=None, width=None, height=None ------- The job results (astropy.table). """ - return self.__query_object(coordinate, radius=radius, width=width, height=height, async_job=True, + return self.__query_object(coordinates, radius=radius, width=width, height=height, async_job=True, verbose=verbose, columns=columns) - def __cone_search(self, coordinate, radius, *, table_name=None, + def __cone_search(self, coordinates, radius, *, table_name=None, ra_column_name=MAIN_GAIA_TABLE_RA, dec_column_name=MAIN_GAIA_TABLE_DEC, async_job=False, @@ -626,7 +628,7 @@ def __cone_search(self, coordinate, radius, *, table_name=None, Parameters ---------- - coordinate : astropy.coordinate, mandatory + coordinates : astropy.coordinate, mandatory coordinates center point radius : astropy.units, mandatory radius @@ -662,7 +664,7 @@ def __cone_search(self, coordinate, radius, *, table_name=None, A Job object """ radiusDeg = None - coord = self.__getCoordInput(coordinate, "coordinate") + coord = self.__getCoordInput(coordinates, "coordinates") raHours, dec = commons.coord_to_radec(coord) ra = raHours * 15.0 # Converts to degrees if radius is not None: @@ -706,7 +708,8 @@ def __cone_search(self, coordinate, radius, *, table_name=None, return self.launch_job(query=query, output_file=output_file, output_format=output_format, verbose=verbose, dump_to_file=dump_to_file) - def cone_search(self, coordinate, *, radius=None, + @deprecated_renamed_argument("coordinate", "coordinates", since="0.4.12") + def cone_search(self, coordinates, *, radius=None, table_name=None, ra_column_name=MAIN_GAIA_TABLE_RA, dec_column_name=MAIN_GAIA_TABLE_DEC, @@ -720,7 +723,7 @@ def cone_search(self, coordinate, *, radius=None, Parameters ---------- - coordinate : str or astropy.coordinate, mandatory + coordinates : str or astropy.coordinate, mandatory coordinates center point radius : str or astropy.units, mandatory radius @@ -749,7 +752,7 @@ def cone_search(self, coordinate, *, radius=None, ------- A Job object """ - return self.__cone_search(coordinate, + return self.__cone_search(coordinates, radius=radius, table_name=table_name, ra_column_name=ra_column_name, @@ -762,7 +765,8 @@ def cone_search(self, coordinate, *, radius=None, dump_to_file=dump_to_file, columns=columns, get_query_payload=get_query_payload) - def cone_search_async(self, coordinate, *, radius=None, + @deprecated_renamed_argument("coordinate", "coordinates", since="0.4.12") + def cone_search_async(self, coordinates, *, radius=None, table_name=None, ra_column_name=MAIN_GAIA_TABLE_RA, dec_column_name=MAIN_GAIA_TABLE_DEC, @@ -774,7 +778,7 @@ def cone_search_async(self, coordinate, *, radius=None, Parameters ---------- - coordinate : str or astropy.coordinate, mandatory + coordinates : str or astropy.coordinate, mandatory coordinates center point radius : str or astropy.units, mandatory radius @@ -804,7 +808,7 @@ def cone_search_async(self, coordinate, *, radius=None, ------- A Job object """ - return self.__cone_search(coordinate, + return self.__cone_search(coordinates, radius=radius, table_name=table_name, ra_column_name=ra_column_name, diff --git a/astroquery/gaia/tests/test_gaia_remote.py b/astroquery/gaia/tests/test_gaia_remote.py index 2fd6e4b8e2..ddb51be938 100644 --- a/astroquery/gaia/tests/test_gaia_remote.py +++ b/astroquery/gaia/tests/test_gaia_remote.py @@ -21,17 +21,17 @@ def test_query_object_row_limit(): coord = SkyCoord(ra=280, dec=-60, unit=(u.degree, u.degree), frame='icrs') width = u.Quantity(0.1, u.deg) height = u.Quantity(0.1, u.deg) - r = gaia.query_object_async(coordinate=coord, width=width, height=height) + r = gaia.query_object_async(coordinates=coord, width=width, height=height) assert len(r) == gaia.ROW_LIMIT gaia.ROW_LIMIT = 10 - r = gaia.query_object_async(coordinate=coord, width=width, height=height) + r = gaia.query_object_async(coordinates=coord, width=width, height=height) assert len(r) == 10 == gaia.ROW_LIMIT gaia.ROW_LIMIT = -1 - r = gaia.query_object_async(coordinate=coord, width=width, height=height) + r = gaia.query_object_async(coordinates=coord, width=width, height=height) assert len(r) == 184 diff --git a/astroquery/gaia/tests/test_gaiatap.py b/astroquery/gaia/tests/test_gaiatap.py index 2fc5b48d72..034d31da18 100644 --- a/astroquery/gaia/tests/test_gaiatap.py +++ b/astroquery/gaia/tests/test_gaiatap.py @@ -518,6 +518,20 @@ def test_query_object_async(column_attrs, mock_querier_async, kwargs): assert table[colname].attrs_equal(attrs) +def test_query_object_deprecated_coordinate_keyword(mock_querier): + with pytest.warns(AstropyDeprecationWarning, match='"coordinate" was deprecated'): + deprecated_query = mock_querier.query_object( + coordinate=SKYCOORD, width=12 * u.deg, height=10 * u.deg, get_query_payload=True) + assert deprecated_query == mock_querier.query_object( + coordinates=SKYCOORD, width=12 * u.deg, height=10 * u.deg, get_query_payload=True) + + with pytest.warns(AstropyDeprecationWarning, match='"coordinate" was deprecated'): + deprecated_query = mock_querier.cone_search( + coordinate=SKYCOORD, radius=RADIUS, get_query_payload=True) + assert deprecated_query == mock_querier.cone_search( + coordinates=SKYCOORD, radius=RADIUS, get_query_payload=True) + + def test_query_object_precision(mock_querier): """ Verifies that query_object() produces a query where RA, DEC, width and height diff --git a/astroquery/heasarc/core.py b/astroquery/heasarc/core.py index 2406e274a9..4eff64a28b 100644 --- a/astroquery/heasarc/core.py +++ b/astroquery/heasarc/core.py @@ -5,7 +5,7 @@ import warnings import numpy as np from astropy.table import Table, Row -from astropy import coordinates +from astropy.coordinates import Angle, SkyCoord from astropy import units as u from astropy.utils.decorators import deprecated, deprecated_renamed_argument @@ -422,7 +422,8 @@ def _parse_constraints(self, column_filters): arg_in_kwargs=(False, True, True, True, True, True, True, True, True, False) ) - def query_region(self, position=None, catalog=None, radius=None, *, + @deprecated_renamed_argument("position", "coordinates", since="0.4.12") + def query_region(self, coordinates=None, catalog=None, radius=None, *, spatial='cone', width=None, polygon=None, column_filters=None, add_offset=False, get_query_payload=False, columns=None, cache=False, verbose=False, maxrec=None, @@ -432,7 +433,7 @@ def query_region(self, position=None, catalog=None, radius=None, *, Parameters ---------- - position : str, `astropy.coordinates` object + coordinates : str, `astropy.coordinates` object Gives the position of the center of the cone or box if performing a cone or box search. Required if spatial is ``'cone'`` or ``'box'``. Ignored if spatial is ``'polygon'`` or ``'all-sky'``. @@ -499,8 +500,8 @@ def query_region(self, position=None, catalog=None, radius=None, *, table : A `~astropy.table.Table` object. """ - # if we have column_filters and no position, assume all-sky search - if position is None and column_filters is not None: + # if we have column_filters and no coordinates, assume all-sky search + if coordinates is None and column_filters is not None: spatial = 'all-sky' if spatial.lower() == 'all-sky': @@ -511,14 +512,14 @@ def query_region(self, position=None, catalog=None, radius=None, *, for coord in polygon] except TypeError: try: - coords_list = [coordinates.SkyCoord(*coord).icrs + coords_list = [SkyCoord(*coord).icrs for coord in polygon] except u.UnitTypeError: warnings.warn("Polygon endpoints are being interpreted as " "RA/Dec pairs specified in decimal degree " "units.") coords_list = [ - coordinates.SkyCoord(*coord, unit='deg').icrs + SkyCoord(*coord, unit='deg').icrs for coord in polygon ] @@ -527,19 +528,19 @@ def query_region(self, position=None, catalog=None, radius=None, *, where = ("WHERE CONTAINS(POINT('ICRS',ra,dec)," f"POLYGON('ICRS',{','.join(coords_str)}))=1") else: - if position is None: + if coordinates is None: raise InvalidQueryError( - "position is required to for spatial='cone' (default). " + "coordinates is required for spatial='cone' (default). " "Use spatial='all-sky' For all-sky searches." ) - coords_icrs = parse_coordinates(position).icrs + coords_icrs = parse_coordinates(coordinates).icrs ra, dec = coords_icrs.ra.deg, coords_icrs.dec.deg if spatial.lower() == 'cone': if radius is None: radius = self.get_default_radius(catalog) elif isinstance(radius, str): - radius = coordinates.Angle(radius) + radius = Angle(radius) where = ("WHERE CONTAINS(POINT('ICRS',ra,dec),CIRCLE(" f"'ICRS',{ra},{dec},{radius.to(u.deg).value}))=1") # add search_offset for the case of cone @@ -548,7 +549,7 @@ def query_region(self, position=None, catalog=None, radius=None, *, f"POINT('ICRS',{ra},{dec})) as search_offset") elif spatial.lower() == 'box': if isinstance(width, str): - width = coordinates.Angle(width) + width = Angle(width) where = ("WHERE CONTAINS(POINT('ICRS',ra,dec)," f"BOX('ICRS',{ra},{dec},{width.to(u.deg).value}," f"{width.to(u.deg).value}))=1") @@ -608,7 +609,7 @@ def query_object(self, object_name, mission, *, of additional parameters that can be used to refine search query. """ - pos = coordinates.SkyCoord.from_name(object_name) + pos = SkyCoord.from_name(object_name) return self.query_region(pos, catalog=mission, spatial='cone', get_query_payload=get_query_payload) diff --git a/astroquery/heasarc/tests/test_heasarc.py b/astroquery/heasarc/tests/test_heasarc.py index 3831c9083d..4e5118b82f 100644 --- a/astroquery/heasarc/tests/test_heasarc.py +++ b/astroquery/heasarc/tests/test_heasarc.py @@ -7,6 +7,7 @@ from astropy.coordinates import SkyCoord from astropy.table import Table from astropy.io import votable +from astropy.utils.exceptions import AstropyDeprecationWarning from pyvo.dal import TAPResults import astropy.units as u @@ -158,7 +159,7 @@ def test_query_region_box(coordinates, width): @pytest.mark.parametrize("polygon", [poly1, poly2]) def test_query_region_polygon(polygon): - # position is not used for polygon + # coordinates is not used for polygon query1 = Heasarc.query_region( catalog="suzamaster", spatial="polygon", @@ -184,7 +185,7 @@ def test_query_region_polygon(polygon): def test_query_region_polygon_no_unit(): - # position is not used for polygon + # coordinates is not used for polygon poly = [ (10.1, 10.1), (10.0, 10.1), @@ -230,11 +231,28 @@ def test_spatial_invalid(spatial): ) -def test_spatial_cone_no_position(): +def test_spatial_cone_no_coordinates(): with pytest.raises(InvalidQueryError): Heasarc.query_region(catalog="xmmmaster", columns="*", spatial="cone") +def test_query_region_position_deprecated(): + # the old `position` keyword still works but emits a deprecation warning + with pytest.warns(AstropyDeprecationWarning): + query = Heasarc.query_region( + position=OBJ_LIST[0], + catalog="suzamaster", + spatial="cone", + radius=2 * u.arcmin, + columns="*", + get_query_payload=True, + ) + assert ( + "FROM suzamaster WHERE CONTAINS(POINT('ICRS',ra,dec)," + "CIRCLE('ICRS',182.63" in query + ) + + def test_no_catalog(): with pytest.raises(InvalidQueryError): # OBJ_LIST[0] and radius added to avoid a remote call diff --git a/astroquery/ipac/irsa/ibe/core.py b/astroquery/ipac/irsa/ibe/core.py index 3d46410cd7..f1b0b0cf33 100644 --- a/astroquery/ipac/irsa/ibe/core.py +++ b/astroquery/ipac/irsa/ibe/core.py @@ -14,6 +14,7 @@ import astropy.coordinates as coord from astropy.table import Table +from astropy.utils.decorators import deprecated_renamed_argument from astroquery.exceptions import InvalidQueryError from astroquery.query import BaseQuery @@ -30,7 +31,8 @@ class IbeClass(BaseQuery): TABLE = conf.table TIMEOUT = conf.timeout - def query_region(self, *, coordinate=None, where=None, mission=None, + @deprecated_renamed_argument("coordinate", "coordinates", since="0.4.12") + def query_region(self, *, coordinates=None, where=None, mission=None, dataset=None, table=None, columns=None, width=None, height=None, intersect='OVERLAPS', most_centered=False): """ @@ -47,7 +49,7 @@ def query_region(self, *, coordinate=None, where=None, mission=None, Parameters ---------- - coordinate : str, `astropy.coordinates` object + coordinates : str, `astropy.coordinates` object Gives the position of the center of the box if performing a box search. If it is a string, then it must be a valid argument to `~astropy.coordinates.SkyCoord`. Required if ``where`` is absent. @@ -97,7 +99,7 @@ def query_region(self, *, coordinate=None, where=None, mission=None, A table containing the results of the query """ response = self.query_region_async( - coordinate=coordinate, where=where, mission=mission, + coordinates=coordinates, where=where, mission=mission, dataset=dataset, table=table, columns=columns, width=width, height=height, intersect=intersect, most_centered=most_centered) @@ -106,7 +108,8 @@ def query_region(self, *, coordinate=None, where=None, mission=None, return Table.read(response.text, format='ipac', guess=False) - def query_region_sia(self, *, coordinate=None, mission=None, + @deprecated_renamed_argument("coordinate", "coordinates", since="0.4.12") + def query_region_sia(self, *, coordinates=None, mission=None, dataset=None, table=None, width=None, height=None, intersect='OVERLAPS', most_centered=False): @@ -115,7 +118,7 @@ def query_region_sia(self, *, coordinate=None, mission=None, details. The returned table will include a list of URLs. """ response = self.query_region_async( - coordinate=coordinate, mission=mission, + coordinates=coordinates, mission=mission, dataset=dataset, table=table, width=width, height=height, intersect=intersect, most_centered=most_centered, action='sia') @@ -126,7 +129,8 @@ def query_region_sia(self, *, coordinate=None, mission=None, return commons.parse_votable( response.text).get_first_table().to_table() - def query_region_async(self, *, coordinate=None, where=None, mission=None, dataset=None, + @deprecated_renamed_argument("coordinate", "coordinates", since="0.4.12") + def query_region_async(self, *, coordinates=None, where=None, mission=None, dataset=None, table=None, columns=None, width=None, height=None, action='search', intersect='OVERLAPS', most_centered=False): """ @@ -143,7 +147,7 @@ def query_region_async(self, *, coordinate=None, where=None, mission=None, datas Parameters ---------- - coordinate : str, `astropy.coordinates` object + coordinates : str, `astropy.coordinates` object Gives the position of the center of the box if performing a box search. If it is a string, then it must be a valid argument to `~astropy.coordinates.SkyCoord`. Required if ``where`` is absent. @@ -198,9 +202,9 @@ def query_region_async(self, *, coordinate=None, where=None, mission=None, datas The HTTP response returned from the service """ - if coordinate is None and where is None: + if coordinates is None and where is None: raise InvalidQueryError( - 'At least one of `coordinate` or `where` is required') + 'At least one of `coordinates` or `where` is required') intersect = intersect.upper() if intersect not in ('COVERS', 'ENCLOSED', 'CENTER', 'OVERLAPS'): @@ -224,8 +228,8 @@ def query_region_async(self, *, coordinate=None, where=None, mission=None, datas if most_centered: args['mcen'] = '1' - if coordinate is not None: - c = commons.parse_coordinates(coordinate).transform_to(coord.ICRS) + if coordinates is not None: + c = commons.parse_coordinates(coordinates).transform_to(coord.ICRS) args['POS'] = '{0},{1}'.format(c.ra.deg, c.dec.deg) if width and height: args['SIZE'] = '{0},{1}'.format( diff --git a/astroquery/ipac/irsa/ibe/tests/test_ibe.py b/astroquery/ipac/irsa/ibe/tests/test_ibe.py index c5051b4a28..c535b92613 100644 --- a/astroquery/ipac/irsa/ibe/tests/test_ibe.py +++ b/astroquery/ipac/irsa/ibe/tests/test_ibe.py @@ -6,6 +6,7 @@ import pytest from astropy.table import Table from astropy.coordinates import SkyCoord +from astropy.utils.exceptions import AstropyDeprecationWarning import astropy.units as u from astroquery.utils.mocks import MockResponse @@ -82,12 +83,21 @@ def test_get_columns(patch_get): def test_ibe_pos(patch_get): table = Ibe.query_region( - coordinate=SkyCoord(148.969687 * u.deg, 69.679383 * u.deg), + coordinates=SkyCoord(148.969687 * u.deg, 69.679383 * u.deg), where='expid <= 43010') assert isinstance(table, Table) assert len(table) == 21 +def test_ibe_pos_deprecated_coordinate(patch_get): + with pytest.warns(AstropyDeprecationWarning): + table = Ibe.query_region( + coordinate=SkyCoord(148.969687 * u.deg, 69.679383 * u.deg), + where='expid <= 43010') + assert isinstance(table, Table) + assert len(table) == 21 + + def test_ibe_field_id(patch_get): table = Ibe.query_region( where="ptffield = 4808 and filter='R'") diff --git a/astroquery/ipac/irsa/ibe/tests/test_ibe_remote.py b/astroquery/ipac/irsa/ibe/tests/test_ibe_remote.py index 8bb919e9f1..fc3a0d28c5 100644 --- a/astroquery/ipac/irsa/ibe/tests/test_ibe_remote.py +++ b/astroquery/ipac/irsa/ibe/tests/test_ibe_remote.py @@ -13,7 +13,7 @@ @pytest.mark.remote_data def test_ibe_pos(): table = ibe.Ibe.query_region( - coordinate=SkyCoord(148.969687 * u.deg, 69.679383 * u.deg), + coordinates=SkyCoord(148.969687 * u.deg, 69.679383 * u.deg), where='expid <= 43010') assert isinstance(table, Table) assert len(table) == 21 diff --git a/astroquery/noirlab/core.py b/astroquery/noirlab/core.py index a52744067b..7d33be5ec3 100644 --- a/astroquery/noirlab/core.py +++ b/astroquery/noirlab/core.py @@ -6,6 +6,7 @@ """ import astropy.io.fits as fits import astropy.table +from astropy.utils.decorators import deprecated_renamed_argument from ..query import BaseQuery from ..exceptions import RemoteServiceError from . import conf @@ -144,7 +145,8 @@ def _service_metadata(self, hdu=False, cache=True): response = self._request('GET', url, timeout=self.TIMEOUT, cache=cache) return response.json() - def query_region(self, coordinate, *, radius=0.1, hdu=False, cache=True, async_=False): + @deprecated_renamed_argument("coordinate", "coordinates", since="0.4.12") + def query_region(self, coordinates, *, radius=0.1, hdu=False, cache=True, async_=False): """Query for NOIRLab observations by region of the sky. Given a sky coordinate and radius, returns a `~astropy.table.Table` @@ -152,7 +154,7 @@ def query_region(self, coordinate, *, radius=0.1, hdu=False, cache=True, async_= Parameters ---------- - coordinate : :class:`str` or `~astropy.coordinates` object + coordinates : :class:`str` or `~astropy.coordinates` object The target region which to search. It may be specified as a string or as the appropriate `~astropy.coordinates` object. radius : :class:`float` or :class:`str` or `~astropy.units.Quantity` object, optional @@ -173,7 +175,7 @@ def query_region(self, coordinate, *, radius=0.1, hdu=False, cache=True, async_= A table containing the results. """ self._validate_version() - ra, dec = coordinate.to_string('decimal').split() + ra, dec = coordinates.to_string('decimal').split() url = f'{self.sia_url(hdu=hdu)}?POS={ra},{dec}&SIZE={radius}&VERB=3&format=json' response = self._request('GET', url, timeout=self.TIMEOUT, cache=cache) if async_: diff --git a/astroquery/noirlab/tests/test_noirlab.py b/astroquery/noirlab/tests/test_noirlab.py index 05c50ecd4a..c85a963952 100644 --- a/astroquery/noirlab/tests/test_noirlab.py +++ b/astroquery/noirlab/tests/test_noirlab.py @@ -6,6 +6,7 @@ import pytest from astropy import units as u from astropy.coordinates import SkyCoord +from astropy.utils.exceptions import AstropyDeprecationWarning from ...utils.mocks import MockResponse from ...exceptions import RemoteServiceError from .. import NOIRLab @@ -68,7 +69,7 @@ def test_query_region(patch_request, hdu, radius): It is OK if more files have been added to the remote Archive. """ c = SkyCoord(ra=10.625*u.degree, dec=41.2*u.degree, frame='icrs') - r = NOIRLab.query_region(c, radius=radius, hdu=hdu) + r = NOIRLab.query_region(coordinates=c, radius=radius, hdu=hdu) actual = set(r['md5sum'].tolist()) if hdu: expected = exp.query_region_2 @@ -77,6 +78,16 @@ def test_query_region(patch_request, hdu, radius): assert expected.issubset(actual) +def test_query_region_deprecated_coordinate(patch_request): + """The old ``coordinate`` keyword should still work but emit a deprecation warning. + """ + c = SkyCoord(ra=10.625*u.degree, dec=41.2*u.degree, frame='icrs') + with pytest.warns(AstropyDeprecationWarning): + r = NOIRLab.query_region(coordinate=c, radius='0.1') + actual = set(r['md5sum'].tolist()) + assert exp.query_region_1.issubset(actual) + + @pytest.mark.parametrize('hdu', [(False,), (True,)]) def test_core_fields(patch_request, hdu): """List the available CORE fields. diff --git a/astroquery/noirlab/tests/test_noirlab_remote.py b/astroquery/noirlab/tests/test_noirlab_remote.py index 2bda39bc66..cc1b6e4349 100644 --- a/astroquery/noirlab/tests/test_noirlab_remote.py +++ b/astroquery/noirlab/tests/test_noirlab_remote.py @@ -36,7 +36,7 @@ def test_query_region(hdu, radius): """ conf.timeout = 300 c = SkyCoord(ra=10.625*u.degree, dec=41.2*u.degree, frame='icrs') - r = NOIRLab().query_region(c, radius=radius, hdu=hdu) + r = NOIRLab().query_region(coordinates=c, radius=radius, hdu=hdu) actual = set(r['md5sum'].tolist()) if hdu: expected = exp.query_region_2 diff --git a/astroquery/ogle/core.py b/astroquery/ogle/core.py index 96a22ef04f..9c2db3b70a 100644 --- a/astroquery/ogle/core.py +++ b/astroquery/ogle/core.py @@ -4,6 +4,7 @@ import functools import numpy as np from astropy.table import Table +from astropy.utils.decorators import deprecated_renamed_argument from ..query import BaseQuery from ..utils import commons, async_to_sync @@ -37,7 +38,7 @@ def wrapper(*args, **kwargs): class CoordParseError(ValueError): - def __init__(self, message='Could not parse `coord` argument.', **kwargs): + def __init__(self, message='Could not parse `coordinates` argument.', **kwargs): super().__init__(message, **kwargs) @@ -52,14 +53,15 @@ class OgleClass(BaseQuery): coord_systems = ['RD', 'LB'] @_validate_params - def query_region_async(self, *, coord=None, algorithm='NG', quality='GOOD', + @deprecated_renamed_argument("coord", "coordinates", since="0.4.12") + def query_region_async(self, *, coordinates=None, algorithm='NG', quality='GOOD', coord_sys='RD', get_query_payload=False): """ Query the OGLE-III interstellar extinction calculator. Parameters ---------- - coord : list-like + coordinates : list-like Pointings to evaluate interstellar extinction. Three forms of coordinates may be passed:: @@ -80,7 +82,7 @@ def query_region_async(self, *, coord=None, algorithm='NG', quality='GOOD', * 'GOOD': QF=0 as described in Nataf et al. (2012). coord_sys : string - Coordinate system if using lists of RA/Decs in ``coord``. + Coordinate system if using lists of RA/Decs in ``coordinates``. Valid options:: * 'RD': equatorial coordinates @@ -109,14 +111,14 @@ def query_region_async(self, *, coord=None, algorithm='NG', quality='GOOD', >>> co = SkyCoord(0.0, 3.0, unit=(u.degree, u.degree), ... frame='galactic') >>> from astroquery.ogle import Ogle - >>> t = Ogle.query_region(coord=co) + >>> t = Ogle.query_region(coordinates=co) >>> t.pprint() RA/LON Dec/Lat A_I E(V-I) S_E(V-I) R_JKVI mu S_mu --------- ---------- ----- ------ -------- ------ ------ ----- ... 17.568157 -27.342475 3.126 2.597 0.126 0.3337 14.581 0.212 """ - # Determine the coord object type and generate list of coordinates - lon, lat = self._parse_coords(coord, coord_sys) + # Determine the coordinates object type and generate list of coordinates + lon, lat = self._parse_coords(coordinates, coord_sys) # Generate payload query_header = '# {0} {1} {2}\n'.format(coord_sys, algorithm, quality) sources = '\n'.join(['{0} {1}'.format(lo, la) for lo, la in @@ -138,14 +140,14 @@ def _parse_result(self, response, *, verbose=False): t = Table.read(response.text.split('\n'), format='ascii') return t - def _parse_coords(self, coord, coord_sys): + def _parse_coords(self, coordinates, coord_sys): """ Parse single astropy.coordinates instance, list of astropy.coordinate instances, or 2xN list of coordinate values. Parameters ---------- - coord : list-like + coordinates : list-like coord_sys : string Returns @@ -155,21 +157,21 @@ def _parse_coords(self, coord, coord_sys): lat : list Latitude coordinate values """ - if not isinstance(coord, list): + if not isinstance(coordinates, list): # single astropy coordinate try: - ra, dec = commons.coord_to_radec(coord) + ra, dec = commons.coord_to_radec(coordinates) lon = [ra] lat = [dec] return lon, lat except ValueError: raise CoordParseError() - elif isinstance(coord, list): - shape = np.shape(coord) + elif isinstance(coordinates, list): + shape = np.shape(coordinates) # list of astropy coordinates if len(shape) == 1: try: - radec = [commons.coord_to_radec(co) for co in coord] + radec = [commons.coord_to_radec(co) for co in coordinates] lon, lat = list(zip(*radec)) return lon, lat except ValueError: diff --git a/astroquery/ogle/tests/test_ogle.py b/astroquery/ogle/tests/test_ogle.py index 7c02a7e7c3..8d7ffe9015 100644 --- a/astroquery/ogle/tests/test_ogle.py +++ b/astroquery/ogle/tests/test_ogle.py @@ -5,6 +5,7 @@ import pytest from astropy.coordinates import SkyCoord from astropy import units as u +from astropy.utils.exceptions import AstropyDeprecationWarning from astroquery.utils.mocks import MockResponse @@ -40,7 +41,7 @@ def test_ogle_single(patch_post): Test a single pointing using an astropy coordinate instance """ co = SkyCoord(0, 3, unit=(u.degree, u.degree), frame='galactic') - ogle.core.Ogle.query_region(coord=co) + ogle.core.Ogle.query_region(coordinates=co) def test_ogle_list(patch_post): @@ -49,7 +50,17 @@ def test_ogle_list(patch_post): """ co = SkyCoord(0, 3, unit=(u.degree, u.degree), frame='galactic') co_list = [co, co, co] - ogle.core.Ogle.query_region(coord=co_list) + ogle.core.Ogle.query_region(coordinates=co_list) + + +def test_ogle_deprecated_coord_keyword(patch_post): + """ + Test that the deprecated ``coord`` keyword still works and emits a + deprecation warning + """ + co = SkyCoord(0, 3, unit=(u.degree, u.degree), frame='galactic') + with pytest.warns(AstropyDeprecationWarning): + ogle.core.Ogle.query_region(coord=co) def test_ogle_single_payload(): @@ -57,7 +68,7 @@ def test_ogle_single_payload(): Test single pointing payload """ co = SkyCoord(0*u.deg, 3*u.deg, frame='galactic') - payload = ogle.core.Ogle.query_region(coord=co, get_query_payload=True) + payload = ogle.core.Ogle.query_region(coordinates=co, get_query_payload=True) fk5 = co.transform_to('fk5') ra = fk5.ra.hour dec = fk5.dec.degree @@ -74,7 +85,7 @@ def test_ogle_multipointing_payload(): co2 = SkyCoord(4*u.deg, 5*u.deg, frame='galactic') pointings = [co1, co2] payload = ogle.core.Ogle.query_region( - coord=pointings, + coordinates=pointings, get_query_payload=True ) conversions = [] diff --git a/astroquery/ogle/tests/test_ogle_remote.py b/astroquery/ogle/tests/test_ogle_remote.py index 23365a7af9..ebee61cad3 100644 --- a/astroquery/ogle/tests/test_ogle_remote.py +++ b/astroquery/ogle/tests/test_ogle_remote.py @@ -9,7 +9,7 @@ @pytest.mark.remote_data def test_ogle_single(): co = SkyCoord(0, 3, unit=(u.degree, u.degree), frame='galactic') - response = Ogle.query_region(coord=co) + response = Ogle.query_region(coordinates=co) assert len(response) == 1 @@ -17,6 +17,6 @@ def test_ogle_single(): def test_ogle_list(): co = SkyCoord(0, 3, unit=(u.degree, u.degree), frame='galactic') co_list = [co, co, co] - response = Ogle.query_region(coord=co_list) + response = Ogle.query_region(coordinates=co_list) assert len(response) == 3 assert response['RA[hr]'][0] == response['RA[hr]'][1] == response['RA[hr]'][2] diff --git a/docs/esa/euclid/euclid.rst b/docs/esa/euclid/euclid.rst index cad80ee9c4..a52f11304f 100644 --- a/docs/esa/euclid/euclid.rst +++ b/docs/esa/euclid/euclid.rst @@ -143,7 +143,7 @@ the "mer_catalogue" and its outcome is restricted to 50 rows. >>> import astropy.units as u >>> coord = SkyCoord("17h51m07.4s +65d31m50.8s", frame='icrs') >>> radius = u.Quantity(0.5, u.deg) - >>> job = Euclid.cone_search(coordinate=coord, radius=radius, columns="*", async_job=True) # doctest: +IGNORE_WARNINGS + >>> job = Euclid.cone_search(coordinates=coord, radius=radius, columns="*", async_job=True) # doctest: +IGNORE_WARNINGS INFO: Query finished. [astroquery.utils.tap.core] >>> cone_results = job.get_results() >>> print(f"Found {len(cone_results)} results") @@ -163,7 +163,7 @@ that the name is recognised by the Simbad, VizieR, or NED services. >>> radius = u.Quantity(0.2, u.deg) >>> Euclid.ROW_LIMIT = -1 - >>> job = Euclid.cone_search(coordinate='NGC 6505', radius=radius, table_name="sedm.calibrated_frame", ra_column_name="ra", dec_column_name="dec", async_job=True, columns = ['ra', 'dec', 'datalabs_path', 'file_path', 'file_name', 'observation_id', 'instrument_name']) + >>> job = Euclid.cone_search(coordinates='NGC 6505', radius=radius, table_name="sedm.calibrated_frame", ra_column_name="ra", dec_column_name="dec", async_job=True, columns = ['ra', 'dec', 'datalabs_path', 'file_path', 'file_name', 'observation_id', 'instrument_name']) INFO: Query finished. [astroquery.utils.tap.core] >>> res = job.get_results() >>> print(f"* Found {len(res)} results") @@ -375,7 +375,7 @@ Download the cutout... .. doctest-skip:: >>> file_path = f"{res['file_path'][0]}/{res['file_name'][0]}" - >>> cutout_out = Euclid.get_cutout(file_path=file_path, coordinate='NGC 6505', radius= 0.1 * u.arcmin, output_file='ngc6505_cutout_mer.fits') + >>> cutout_out = Euclid.get_cutout(file_path=file_path, coordinates='NGC 6505', radius= 0.1 * u.arcmin, output_file='ngc6505_cutout_mer.fits') >>> cutout_out = cutout_out[0] ... and inspect its content: diff --git a/docs/esa/jwst/jwst.rst b/docs/esa/jwst/jwst.rst index 8e6535aa15..377b678a28 100644 --- a/docs/esa/jwst/jwst.rst +++ b/docs/esa/jwst/jwst.rst @@ -101,7 +101,7 @@ service degradation. >>> coord = SkyCoord(ra=53, dec=-27, unit=(u.degree, u.degree), frame='icrs') >>> width = u.Quantity(5, u.deg) >>> height = u.Quantity(5, u.deg) - >>> result = Jwst.query_region(coordinate=coord, width=width, height=height) + >>> result = Jwst.query_region(coordinates=coord, width=width, height=height) >>> result # doctest: +IGNORE_OUTPUT dist observationid ... ------------------ ------------------------------ ... @@ -129,7 +129,7 @@ service degradation. >>> >>> coord = SkyCoord(ra=53, dec=-27, unit=(u.degree, u.degree), frame='icrs') >>> radius = u.Quantity(5.0, u.deg) - >>> j = Jwst.cone_search(coordinate=coord, radius=radius, async_job=True) + >>> j = Jwst.cone_search(coordinates=coord, radius=radius, async_job=True) INFO: Query finished. [astroquery.utils.tap.core] >>> result = j.get_results() >>> result # doctest: +IGNORE_OUTPUT diff --git a/docs/esasky/esasky.rst b/docs/esasky/esasky.rst index 13d2cfa021..37a49e5717 100644 --- a/docs/esasky/esasky.rst +++ b/docs/esasky/esasky.rst @@ -182,7 +182,7 @@ value for the radius of the region. For instance to query region around M51 in t >>> from astroquery.esasky import ESASky >>> import astropy.units as u - >>> result = ESASky.query_region_catalogs(position="M51", radius=10 * u.arcmin, catalogs=["HSC", "XMM-OM"]) + >>> result = ESASky.query_region_catalogs(coordinates="M51", radius=10 * u.arcmin, catalogs=["HSC", "XMM-OM"]) To search in all available catalogs you can write ``"all"`` instead of a catalog name. The same thing will happen if you don't write any catalog name. @@ -190,8 +190,8 @@ In the same manner, the radius can be specified with either a string or any `~as .. doctest-remote-data:: - >>> result = ESASky.query_region_catalogs(position="M51", radius=10 * u.arcmin, catalogs="all") - >>> result = ESASky.query_region_catalogs(position="M51", radius="10 arcmin") + >>> result = ESASky.query_region_catalogs(coordinates="M51", radius=10 * u.arcmin, catalogs="all") + >>> result = ESASky.query_region_catalogs(coordinates="M51", radius="10 arcmin") To see the result: @@ -228,8 +228,8 @@ you write this: .. doctest-remote-data:: - >>> result = ESASky.query_region_maps(position="M51", radius=10 * u.arcmin, missions="all") - >>> result = ESASky.query_region_spectra(position="M51", radius=10 * u.arcmin, missions="all") + >>> result = ESASky.query_region_maps(coordinates="M51", radius=10 * u.arcmin, missions="all") + >>> result = ESASky.query_region_spectra(coordinates="M51", radius=10 * u.arcmin, missions="all") The parameters are interchangeable in the same way as in :meth:`~astroquery.esasky.ESASkyClass.query_region_catalogs`. @@ -306,7 +306,7 @@ position, radius and missions. .. Skip testing examples with with hard-wired download dir values .. doctest-remote-data:: - >>> table_list = ESASky.query_region_maps(position="V* HT Aqr", radius="15 arcmin", missions=['Herschel', 'ISO-IR']) + >>> table_list = ESASky.query_region_maps(coordinates="V* HT Aqr", radius="15 arcmin", missions=['Herschel', 'ISO-IR']) >>> images = ESASky.get_maps(query_table_list=table_list, download_dir="/home/user/esasky") # doctest: +SKIP This example is equivalent to: @@ -341,7 +341,7 @@ or .. doctest-remote-data:: - >>> table_list = ESASky.query_region_spectra(position="Gaia DR3 4512810408088819712", radius="6.52 arcmin", + >>> table_list = ESASky.query_region_spectra(coordinates="Gaia DR3 4512810408088819712", radius="6.52 arcmin", ... missions=['Herschel', 'XMM-NEWTON']) >>> spectra = ESASky.get_spectra_from_table(query_table_list=table_list, download_dir="/home/user/esasky") # doctest: +SKIP dict: { @@ -357,7 +357,7 @@ Here is another example for Herschel, since it is a bit special: .. doctest-remote-data:: >>> from astroquery.esasky import ESASky - >>> result = ESASky.query_region_spectra(position='[SMB88] 6327', radius='1 arcmin', missions=['HERSCHEL']) + >>> result = ESASky.query_region_spectra(coordinates='[SMB88] 6327', radius='1 arcmin', missions=['HERSCHEL']) >>> herschel_result = result['HERSCHEL'] >>> herschel_result['observation_id', 'target_name', 'instrument', 'observing_mode_name', 'band', 'duration'].pprint() observation_id target_name instrument ... band duration diff --git a/docs/gaia/gaia.rst b/docs/gaia/gaia.rst index 6066b6aefd..f2bbd37be4 100644 --- a/docs/gaia/gaia.rst +++ b/docs/gaia/gaia.rst @@ -102,7 +102,7 @@ degrees around an specific point in RA/Dec coordinates. The results are sorted b >>> coord = SkyCoord(ra=280, dec=-60, unit=(u.degree, u.degree), frame='icrs') >>> width = u.Quantity(0.1, u.deg) >>> height = u.Quantity(0.1, u.deg) - >>> r = Gaia.query_object_async(coordinate=coord, width=width, height=height) + >>> r = Gaia.query_object_async(coordinates=coord, width=width, height=height) INFO: Query finished. [astroquery.utils.tap.core] >>> r.pprint(max_lines=12, max_width=130) dist solution_id designation ... ebpminrp_gspphot_upper libname_gspphot @@ -123,7 +123,7 @@ Queries return a limited number of rows controlled by ``Gaia.ROW_LIMIT``. To cha .. doctest-remote-data:: >>> Gaia.ROW_LIMIT = 8 - >>> r = Gaia.query_object_async(coordinate=coord, width=width, height=height) + >>> r = Gaia.query_object_async(coordinates=coord, width=width, height=height) INFO: Query finished. [astroquery.utils.tap.core] >>> r.pprint(max_width=140) dist solution_id designation ... ebpminrp_gspphot_lower ebpminrp_gspphot_upper libname_gspphot @@ -143,7 +143,7 @@ To return an unlimited number of rows set ``Gaia.ROW_LIMIT`` to -1. .. doctest-remote-data:: >>> Gaia.ROW_LIMIT = -1 - >>> r = Gaia.query_object_async(coordinate=coord, width=width, height=height) + >>> r = Gaia.query_object_async(coordinates=coord, width=width, height=height) INFO: Query finished. [astroquery.utils.tap.core] >>> r.pprint(max_lines=12, max_width=140) dist solution_id designation ... ebpminrp_gspphot_lower ebpminrp_gspphot_upper libname_gspphot diff --git a/docs/ogle/ogle.rst b/docs/ogle/ogle.rst index e099f163f3..d63970173b 100644 --- a/docs/ogle/ogle.rst +++ b/docs/ogle/ogle.rst @@ -19,7 +19,7 @@ using an `astropy.coordinates` instance use: >>> from astropy import units as u >>> from astroquery.ogle import Ogle >>> co = SkyCoord(0*u.deg, 3*u.deg, frame='galactic') - >>> t = Ogle.query_region(coord=co) + >>> t = Ogle.query_region(coordinates=co) Arguments can be passed to choose the interpolation algorithm, quality factor, and coordinate system. Multiple coordinates may be queried simultaneously by @@ -30,10 +30,10 @@ to FK5. >>> # list of coordinate instances >>> co_list = [co, co, co] - >>> t1 = Ogle.query_region(coord=co_list) + >>> t1 = Ogle.query_region(coordinates=co_list) >>> # (2 x N) list of values >>> co_list_values = SkyCoord([0, 1, 2], [3, 3, 3], unit=u.deg, frame='galactic') - >>> t2 = Ogle.query_region(coord=co_list_values, coord_sys='LB') + >>> t2 = Ogle.query_region(coordinates=co_list_values, coord_sys='LB') Note that non-Astropy coordinates may not be supported in a future version. From 930d67c6b8c95a884a424d5e74a2c3c0065786b5 Mon Sep 17 00:00:00 2001 From: "Adam Ginsburg (keflavich)" Date: Wed, 10 Jun 2026 13:08:27 +0200 Subject: [PATCH 2/4] Use singular 'coordinate' where only one position is accepted Audit of all renamed methods per review feedback: the parameter should be plural 'coordinates' only where the method genuinely accepts multiple positions, singular 'coordinate' otherwise. Of the renamed modules, only ogle supports multiple positions (a list of coordinates produces a valid multi-line query), so its rename to 'coordinates' stays. heasarc and esasky are single-position cone/box searches, so their 'position' keyword is now deprecated in favor of singular 'coordinate' instead. The seven modules that already used 'coordinate' for single-position queries (alma, esa.euclid, esa.hsa, esa.jwst, gaia, ipac.irsa.ibe, noirlab) were named correctly all along and are reverted to their original state. All deprecations use deprecated_renamed_argument (since 0.4.12), so the old keywords keep working with a warning. Co-Authored-By: Claude Fable 5 --- CHANGES.rst | 49 ++----------------- astroquery/alma/core.py | 6 +-- astroquery/alma/tests/test_alma.py | 14 ------ astroquery/alma/tests/test_alma_remote.py | 2 +- astroquery/esa/euclid/core.py | 32 ++++++------ .../esa/euclid/tests/test_euclid_remote.py | 6 +-- astroquery/esa/euclid/tests/test_euclidtap.py | 40 ++++++--------- astroquery/esa/hsa/core.py | 15 +++--- astroquery/esa/hsa/tests/test_hsa.py | 15 +----- astroquery/esa/jwst/core.py | 19 +++---- astroquery/esa/jwst/tests/test_jwsttap.py | 27 ++-------- astroquery/esasky/core.py | 30 ++++++------ astroquery/esasky/tests/test_esasky.py | 4 +- astroquery/esasky/tests/test_esasky_remote.py | 6 +-- astroquery/gaia/core.py | 40 +++++++-------- astroquery/gaia/tests/test_gaia_remote.py | 6 +-- astroquery/gaia/tests/test_gaiatap.py | 14 ------ astroquery/heasarc/core.py | 16 +++--- astroquery/heasarc/tests/test_heasarc.py | 2 +- astroquery/ipac/irsa/ibe/core.py | 26 +++++----- astroquery/ipac/irsa/ibe/tests/test_ibe.py | 12 +---- .../ipac/irsa/ibe/tests/test_ibe_remote.py | 2 +- astroquery/noirlab/core.py | 8 ++- astroquery/noirlab/tests/test_noirlab.py | 13 +---- .../noirlab/tests/test_noirlab_remote.py | 2 +- docs/esa/euclid/euclid.rst | 6 +-- docs/esa/jwst/jwst.rst | 4 +- docs/esasky/esasky.rst | 16 +++--- docs/gaia/gaia.rst | 6 +-- 29 files changed, 144 insertions(+), 294 deletions(-) diff --git a/CHANGES.rst b/CHANGES.rst index bea6bcf64b..4f262ee0bc 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -64,8 +64,6 @@ esa.euclid product_type parameters dynamically. [#3601] - In the method, ``get_scientific_product_list``, the ``dsr_part3`` parameter now supports the additional value ``latest``. [#3601] -- The ``coordinate`` keyword of ``query_object``, ``cone_search``, and ``get_cutout`` is deprecated in - favor of ``coordinates`` for consistency with the rest of astroquery. [#3609] vizier @@ -89,61 +87,24 @@ vo_conesearch PyVO Simple Cone Search interface instead. There is no direct replacement for server validation. [#3548] -alma -^^^^ - -- The ``coordinate`` keyword of ``query_region`` and ``query_region_async`` is deprecated in favor of - ``coordinates`` for consistency with the rest of astroquery. [#3609] - -esa.hsa -^^^^^^^ - -- The ``coordinate`` keyword of ``query_observations`` and ``query_region`` is deprecated in favor of - ``coordinates`` for consistency with the rest of astroquery. [#3609] - -esa.jwst -^^^^^^^^ - -- The ``coordinate`` keyword of ``query_region`` and ``cone_search`` is deprecated in favor of - ``coordinates`` for consistency with the rest of astroquery. [#3609] - esasky ^^^^^^ - The ``position`` keyword of ``query_region_maps``, ``query_region_catalogs``, and - ``query_region_spectra`` is deprecated in favor of ``coordinates`` for consistency with the rest of - astroquery. [#3609] - -gaia -^^^^ - -- The ``coordinate`` keyword of ``query_object``, ``query_object_async``, ``cone_search``, and - ``cone_search_async`` is deprecated in favor of ``coordinates`` for consistency with the rest of - astroquery. [#3609] + ``query_region_spectra`` is deprecated in favor of ``coordinate``; these methods accept a + single sky position. [#3609] heasarc ^^^^^^^ -- The ``position`` keyword of ``query_region`` is deprecated in favor of ``coordinates`` for - consistency with the rest of astroquery. [#3609] - -ipac.irsa.ibe -^^^^^^^^^^^^^ - -- The ``coordinate`` keyword of ``query_region``, ``query_region_sia``, and ``query_region_async`` is - deprecated in favor of ``coordinates`` for consistency with the rest of astroquery. [#3609] - -noirlab -^^^^^^^ - -- The ``coordinate`` keyword of ``query_region`` is deprecated in favor of ``coordinates`` for - consistency with the rest of astroquery. [#3609] +- The ``position`` keyword of ``query_region`` is deprecated in favor of ``coordinate``; the + method accepts a single sky position. [#3609] ogle ^^^^ - The ``coord`` keyword of ``query_region`` and ``query_region_async`` is deprecated in favor of - ``coordinates`` for consistency with the rest of astroquery. [#3609] + ``coordinates``; the method accepts one or more positions (as a list of coordinates). [#3609] Service fixes and enhancements ------------------------------ diff --git a/astroquery/alma/core.py b/astroquery/alma/core.py index 279280eae6..0a3ee5d1b0 100644 --- a/astroquery/alma/core.py +++ b/astroquery/alma/core.py @@ -20,7 +20,6 @@ from astropy import units as u from astropy.time import Time from astropy.coordinates import SkyCoord -from astropy.utils.decorators import deprecated_renamed_argument from pyvo.dal.sia2 import SIA2_PARAMETERS_DESC, SIA2Service @@ -507,8 +506,7 @@ def query_object_async(self, object_name, *, public=True, payload=payload, enhanced_results=enhanced_results, **kwargs) - @deprecated_renamed_argument("coordinate", "coordinates", since="0.4.12") - def query_region_async(self, coordinates, radius, *, public=True, + def query_region_async(self, coordinate, radius, *, public=True, science=True, payload=None, enhanced_results=False, **kwargs): """ @@ -535,7 +533,7 @@ def query_region_async(self, coordinates, radius, *, public=True, rad = radius if not isinstance(radius, u.Quantity): rad = radius*u.deg - obj_coord = commons.parse_coordinates(coordinates).icrs + obj_coord = commons.parse_coordinates(coordinate).icrs ra_dec = '{}, {}'.format(obj_coord.to_string(), rad.to(u.deg).value) if payload is None: payload = {} diff --git a/astroquery/alma/tests/test_alma.py b/astroquery/alma/tests/test_alma.py index afe63b7c1c..6bbdc50911 100644 --- a/astroquery/alma/tests/test_alma.py +++ b/astroquery/alma/tests/test_alma.py @@ -12,7 +12,6 @@ from astropy.io import votable from astropy.coordinates import SkyCoord from astropy.time import Time -from astropy.utils.exceptions import AstropyDeprecationWarning import pyvo from astroquery.alma import Alma @@ -365,19 +364,6 @@ def test_query(): language='ADQL', maxrec=None, uploads=None) -def test_query_region_coordinate_deprecated(): - # the old ``coordinate`` keyword should still work but emit a - # deprecation warning (renamed to ``coordinates``, issue #2803) - alma = Alma() - alma._get_dataarchive_url = Mock() - new_payload = alma.query_region(coordinates='1 2', radius=1*u.deg, - get_query_payload=True) - with pytest.warns(AstropyDeprecationWarning): - old_payload = alma.query_region(coordinate='1 2', radius=1*u.deg, - get_query_payload=True) - assert old_payload == new_payload - - @pytest.mark.filterwarnings("ignore::astropy.utils.exceptions.AstropyUserWarning") def test_enhanced_table(): pytest.importorskip('regions') diff --git a/astroquery/alma/tests/test_alma_remote.py b/astroquery/alma/tests/test_alma_remote.py index 4986a8f8ce..2a1535dc0e 100644 --- a/astroquery/alma/tests/test_alma_remote.py +++ b/astroquery/alma/tests/test_alma_remote.py @@ -337,7 +337,7 @@ def test_query(self, tmp_path, alma): def test_misc(self, alma): # miscellaneous set of common tests # - # alma.query_region(coordinates=orionkl_coords, radius=4 * u.arcmin, + # alma.query_region(coordinate=orionkl_coords, radius=4 * u.arcmin, # public=False, science=False) result = alma.query_object('M83', public=True, science=True) diff --git a/astroquery/esa/euclid/core.py b/astroquery/esa/euclid/core.py index 0bf9e702dc..917e99b020 100644 --- a/astroquery/esa/euclid/core.py +++ b/astroquery/esa/euclid/core.py @@ -384,15 +384,14 @@ def launch_job_async(self, query, *, name=None, dump_to_file=False, output_file= except Exception as exx: log.error(f'Query failed: {query}, {str(exx)}') - @deprecated_renamed_argument("coordinate", "coordinates", since="0.4.12") - def query_object(self, coordinates, *, radius=None, width=None, height=None, + def query_object(self, coordinate, *, radius=None, width=None, height=None, async_job=False, verbose=False, columns=None): """ Searches for objects around a given position with the default catalog sascat_pvpr01.mer_final_cat_pvpr01 Parameters ---------- - coordinates : astropy.coordinate, mandatory + coordinate : astropy.coordinate, mandatory coordinates center point radius : astropy.units, required if no 'width' nor 'height' are provided radius (deg) @@ -412,7 +411,7 @@ def query_object(self, coordinates, *, radius=None, width=None, height=None, ------- The job results (astropy.table) """ - coord = commons.parse_coordinates(coordinates) + coord = commons.parse_coordinates(coordinate) if radius is not None: job = self.__cone_search(coord, radius, async_job=async_job, verbose=verbose, columns=columns) @@ -438,14 +437,14 @@ def query_object(self, coordinates, *, radius=None, width=None, height=None, job = super().launch_job(query, verbose=verbose, format_with_results_compressed=('votable_gzip',)) return job.get_results() - def __cone_search(self, coordinates, radius, *, table_name=None, ra_column_name=None, dec_column_name=None, + def __cone_search(self, coordinate, radius, *, table_name=None, ra_column_name=None, dec_column_name=None, async_job=False, verbose=False, columns=None): """Cone search sorted by distance TAP & TAP+ Parameters ---------- - coordinates : astropy.coordinate, mandatory + coordinate : astropy.coordinate, mandatory coordinates center point radius : astropy.units, mandatory radius @@ -479,7 +478,7 @@ def __cone_search(self, coordinates, radius, *, table_name=None, ra_column_name= raise ValueError(f"Invalid ra or dec column names: ra, {ra_column_name}, dec, {dec_column_name}") radius_deg = None - coord = commons.parse_coordinates(coordinates) + coord = commons.parse_coordinates(coordinate) ra_hours, dec = commons.coord_to_radec(coord) ra = ra_hours * 15.0 # Converts to degrees if radius is not None: @@ -520,8 +519,7 @@ def __cone_search(self, coordinates, radius, *, table_name=None, ra_column_name= return job - @deprecated_renamed_argument("coordinate", "coordinates", since="0.4.12") - def cone_search(self, coordinates, radius, *, + def cone_search(self, coordinate, radius, *, table_name=None, ra_column_name=None, dec_column_name=None, @@ -537,7 +535,7 @@ def cone_search(self, coordinates, radius, *, Parameters ---------- - coordinates : astropy.coordinate, mandatory + coordinate : astropy.coordinate, mandatory coordinates center point radius : astropy.units, mandatory radius @@ -572,7 +570,7 @@ def cone_search(self, coordinates, radius, *, """ radius_deg = None - coord = commons.parse_coordinates(coordinates) + coord = commons.parse_coordinates(coordinate) ra_hours, dec = commons.coord_to_radec(coord) ra = ra_hours * 15.0 # Converts to degrees if radius is not None: @@ -1455,9 +1453,9 @@ def __is_multiple(self, value): return not isinstance(value, int) and ((isinstance(value, (list, tuple)) and len(value) > 1) or ',' in value) - @deprecated_renamed_argument(('coordinate', 'instrument', 'id'), ('coordinates', None, None), since='0.4.12') - def get_cutout(self, *, file_path=None, coordinates=None, radius=None, output_file=None, verbose=False, - instrument=None, id=None): + @deprecated_renamed_argument(('instrument', 'id'), (None, None), since='0.4.12') + def get_cutout(self, *, file_path=None, coordinate, radius, output_file=None, verbose=False, instrument=None, + id=None): """ Downloads a cutout from a MER mosaic (background-subtracted image) for a given fits file path, centered on a coordinate and with a specified radius. @@ -1468,7 +1466,7 @@ def get_cutout(self, *, file_path=None, coordinates=None, radius=None, output_fi ---------- file_path : str, mandatory, default None file path for the product on the server (MER mosaic) - coordinates : astropy.coordinate or Simbad/VizieR/NED name (str), mandatory + coordinate : astropy.coordinate or Simbad/VizieR/NED name (str), mandatory coordinates center point radius : astropy.units, mandatory the radius of the cutout to generate @@ -1482,14 +1480,14 @@ def get_cutout(self, *, file_path=None, coordinates=None, radius=None, output_fi The fits file is downloaded, and the local path where the cutout is saved is returned """ - if file_path is None or coordinates is None or radius is None: + if file_path is None or coordinate is None or radius is None: raise ValueError(self.__ERROR_MSG_REQUESTED_GENERIC) # Parse POS radius_deg = Angle(self.__get_quantity_input(radius, "radius")).to_value(u.deg) if radius_deg > 0.5: raise ValueError(self.__ERROR_MSG_REQUESTED_RADIUS) - coord = commons.parse_coordinates(coordinates) + coord = commons.parse_coordinates(coordinate) ra_hours, dec = commons.coord_to_radec(coord) ra = ra_hours * 15.0 # Converts to degrees pos = """CIRCLE,{ra},{dec},{radius}""".format(**{'ra': ra, 'dec': dec, 'radius': radius_deg}) diff --git a/astroquery/esa/euclid/tests/test_euclid_remote.py b/astroquery/esa/euclid/tests/test_euclid_remote.py index 7aebbdf167..68826b37de 100644 --- a/astroquery/esa/euclid/tests/test_euclid_remote.py +++ b/astroquery/esa/euclid/tests/test_euclid_remote.py @@ -21,17 +21,17 @@ def test_query_object_row_limit(): coord = SkyCoord(ra=265.8, dec=64.1, unit=(u.degree, u.degree), frame='icrs') width = u.Quantity(0.1, u.deg) height = u.Quantity(0.1, u.deg) - r = euclid.query_object(coordinates=coord, width=width, height=height, async_job=True, verbose=True) + r = euclid.query_object(coordinate=coord, width=width, height=height, async_job=True, verbose=True) assert len(r) == 50 euclid.ROW_LIMIT = 10 - r = euclid.query_object(coordinates=coord, width=width, height=height, async_job=True) + r = euclid.query_object(coordinate=coord, width=width, height=height, async_job=True) assert len(r) == 10 == euclid.ROW_LIMIT euclid.ROW_LIMIT = -1 - r = euclid.query_object(coordinates=coord, width=width, height=height, async_job=True, verbose=True) + r = euclid.query_object(coordinate=coord, width=width, height=height, async_job=True, verbose=True) assert len(r) == 1948 diff --git a/astroquery/esa/euclid/tests/test_euclidtap.py b/astroquery/esa/euclid/tests/test_euclidtap.py index 510d32f6e0..ad543ca057 100644 --- a/astroquery/esa/euclid/tests/test_euclidtap.py +++ b/astroquery/esa/euclid/tests/test_euclidtap.py @@ -22,7 +22,6 @@ from astropy.table import Column, Table from astropy.units import Quantity from astropy.utils.data import get_pkg_data_filename -from astropy.utils.exceptions import AstropyDeprecationWarning from requests import HTTPError from astroquery.esa.euclid.core import EuclidClass @@ -199,7 +198,7 @@ def test_load_environments(): def test_query_async_object(column_attrs, mock_querier_async): coord = SkyCoord(ra=60.3372780005097, dec=-49.93184727724773, unit=(u.degree, u.degree), frame='icrs') - table = mock_querier_async.query_object(coordinates=coord, width=u.Quantity(0.1, u.deg), + table = mock_querier_async.query_object(coordinate=coord, width=u.Quantity(0.1, u.deg), height=u.Quantity(0.1, u.deg), async_job=True) assert table is not None @@ -211,7 +210,7 @@ def test_query_async_object(column_attrs, mock_querier_async): def test_query_async_object_columns(column_attrs, mock_querier_async): coord = SkyCoord(ra=60.3372780005097, dec=-49.93184727724773, unit=(u.degree, u.degree), frame='icrs') - table = mock_querier_async.query_object(coordinates=coord, width=u.Quantity(0.1, u.deg), + table = mock_querier_async.query_object(coordinate=coord, width=u.Quantity(0.1, u.deg), height=u.Quantity(0.1, u.deg), columns=("alpha",), async_job=True) assert table is not None @@ -223,7 +222,7 @@ def test_query_async_object_columns(column_attrs, mock_querier_async): def test_query_object(column_attrs, mock_querier): coord = SkyCoord(ra=60.3372780005097, dec=-49.93184727724773, unit=(u.degree, u.degree), frame='icrs') - table = mock_querier.query_object(coordinates=coord, width=u.Quantity(0.1, u.deg), + table = mock_querier.query_object(coordinate=coord, width=u.Quantity(0.1, u.deg), height=u.Quantity(0.1, u.deg)) assert table is not None @@ -235,7 +234,7 @@ def test_query_object(column_attrs, mock_querier): def test_query_object_columns(column_attrs, mock_querier): coord = SkyCoord(ra=60.3372780005097, dec=-49.93184727724773, unit=(u.degree, u.degree), frame='icrs') - table = mock_querier.query_object(coordinates=coord, width=u.Quantity(0.1, u.deg), + table = mock_querier.query_object(coordinate=coord, width=u.Quantity(0.1, u.deg), height=u.Quantity(0.1, u.deg), columns=("alpha",)) assert table is not None @@ -246,7 +245,7 @@ def test_query_object_columns(column_attrs, mock_querier): def test_query_object_async_radius(column_attrs, mock_querier_async): coord = SkyCoord(ra=60.3372780005097, dec=-49.93184727724773, unit=(u.degree, u.degree), frame='icrs') - table = mock_querier_async.query_object(coordinates=coord, radius=RADIUS, async_job=True) + table = mock_querier_async.query_object(coordinate=coord, radius=RADIUS, async_job=True) assert table is not None @@ -257,7 +256,7 @@ def test_query_object_async_radius(column_attrs, mock_querier_async): def test_query_object_radius(column_attrs, mock_querier): coord = SkyCoord(ra=60.3372780005097, dec=-49.93184727724773, unit=(u.degree, u.degree), frame='icrs') - table = mock_querier.query_object(coordinates=coord, radius=RADIUS) + table = mock_querier.query_object(coordinate=coord, radius=RADIUS) assert table is not None @@ -266,18 +265,9 @@ def test_query_object_radius(column_attrs, mock_querier): assert table[colname].attrs_equal(attrs) -def test_query_object_deprecated_coordinate_keyword(mock_querier): - coord = SkyCoord(ra=60.3372780005097, dec=-49.93184727724773, unit=(u.degree, u.degree), frame='icrs') - with pytest.warns(AstropyDeprecationWarning, match='"coordinate" was deprecated'): - table = mock_querier.query_object(coordinate=coord, radius=RADIUS) - - assert table is not None - assert len(table) == 3 - - def test_query_object_async_radius_columns(column_attrs, mock_querier_async): coord = SkyCoord(ra=60.3372780005097, dec=-49.93184727724773, unit=(u.degree, u.degree), frame='icrs') - table = mock_querier_async.query_object(coordinates=coord, radius=RADIUS, columns=("alpha",), async_job=True) + table = mock_querier_async.query_object(coordinate=coord, radius=RADIUS, columns=("alpha",), async_job=True) assert table is not None @@ -287,7 +277,7 @@ def test_query_object_async_radius_columns(column_attrs, mock_querier_async): def test_query_object_radius_columns(column_attrs, mock_querier): coord = SkyCoord(ra=60.3372780005097, dec=-49.93184727724773, unit=(u.degree, u.degree), frame='icrs') - table = mock_querier.query_object(coordinates=coord, radius=RADIUS, columns=("alpha",)) + table = mock_querier.query_object(coordinate=coord, radius=RADIUS, columns=("alpha",)) assert table is not None @@ -1215,7 +1205,7 @@ def test_get_cutout(capsys): result = tap.get_cutout( file_path='/data/repository/NIR/19704/EUC_NIR_W-STACK_NIR-J-19704_20190718T001858.5Z_00.00.fits', - coordinates=c, radius=r, output_file=None, verbose=True) + coordinate=c, radius=r, output_file=None, verbose=True) assert result is not None @@ -1249,17 +1239,17 @@ def test_get_cutout_exception(): show_server_messages=False) with pytest.raises(ValueError, match="Radius cannot be greater than 30 arcminutes"): - tap.get_cutout(file_path=file_path, coordinates=c, radius=100 * u.arcmin, + tap.get_cutout(file_path=file_path, coordinate=c, radius=100 * u.arcmin, output_file=None) with pytest.raises(ValueError, match="Missing required argument"): - tap.get_cutout(file_path=None, coordinates=c, radius=r, output_file=None) + tap.get_cutout(file_path=None, coordinate=c, radius=r, output_file=None) with pytest.raises(ValueError, match="Missing required argument"): - tap.get_cutout(file_path=file_path, coordinates=None, radius=r, output_file=None) + tap.get_cutout(file_path=file_path, coordinate=None, radius=r, output_file=None) with pytest.raises(ValueError, match="Missing required argument"): - tap.get_cutout(file_path=file_path, coordinates=c, radius=None, output_file=None) + tap.get_cutout(file_path=file_path, coordinate=c, radius=None, output_file=None) @patch.object(TapPlus, 'load_data') @@ -1282,7 +1272,7 @@ def test_get_cutout_exceptions_2(mock_load_data, caplog): mock_load_data.side_effect = HTTPError("launch_job_async HTTPError") - tap.get_cutout(file_path='hola.fits', coordinates=SKYCOORD, radius=1 * u.arcmin, + tap.get_cutout(file_path='hola.fits', coordinate=SKYCOORD, radius=1 * u.arcmin, output_file=None) mssg = ("Cannot retrieve the product for file_path hola.fits. HTTP error: " @@ -1291,7 +1281,7 @@ def test_get_cutout_exceptions_2(mock_load_data, caplog): mock_load_data.side_effect = Exception("launch_job_async Exception") - tap.get_cutout(file_path='hola.fits', coordinates=SKYCOORD, radius=1 * u.arcmin, + tap.get_cutout(file_path='hola.fits', coordinate=SKYCOORD, radius=1 * u.arcmin, output_file=None) mssg = ("Cannot retrieve the product for file_path hola.fits: launch_job_async " diff --git a/astroquery/esa/hsa/core.py b/astroquery/esa/hsa/core.py index b433e7997d..c9c655321c 100644 --- a/astroquery/esa/hsa/core.py +++ b/astroquery/esa/hsa/core.py @@ -7,7 +7,6 @@ from pathlib import Path from astropy import units as u -from astropy.utils.decorators import deprecated_renamed_argument from astroquery.utils import commons from astroquery import log from astroquery.exceptions import LoginError @@ -381,14 +380,13 @@ def get_columns(self, table_name, *, only_names=True, verbose=False): else: return columns - @deprecated_renamed_argument("coordinate", "coordinates", since="0.4.12") - def query_observations(self, coordinates, radius, *, n_obs=10, **kwargs): + def query_observations(self, coordinate, radius, *, n_obs=10, **kwargs): """ Get the observation IDs from a given region Parameters ---------- - coordinates : string / `astropy.coordinates` + coordinate : string / `astropy.coordinates` the identifier or coordinates around which to query radius : int / `~astropy.units.Quantity` the radius of the region @@ -401,16 +399,15 @@ def query_observations(self, coordinates, radius, *, n_obs=10, **kwargs): ------- A table object with the list of observations in the region """ - return self.query_region(coordinates, radius, n_obs=n_obs, columns="observation_id", **kwargs) + return self.query_region(coordinate, radius, n_obs=n_obs, columns="observation_id", **kwargs) - @deprecated_renamed_argument("coordinate", "coordinates", since="0.4.12") - def query_region(self, coordinates, radius, *, n_obs=10, columns='*', **kwargs): + def query_region(self, coordinate, radius, *, n_obs=10, columns='*', **kwargs): """ Get the observation metadata from a given region Parameters ---------- - coordinates : string / `astropy.coordinates` + coordinate : string / `astropy.coordinates` the identifier or coordinates around which to query radius : int / `~astropy.units.Quantity` the radius of the region @@ -428,7 +425,7 @@ def query_region(self, coordinates, radius, *, n_obs=10, columns='*', **kwargs): r = radius if not isinstance(radius, u.Quantity): r = radius*u.deg - coord = commons.parse_coordinates(coordinates).icrs + coord = commons.parse_coordinates(coordinate).icrs query = (f"select top {n_obs} {columns} from hsa.v_active_observation " f"where contains(" diff --git a/astroquery/esa/hsa/tests/test_hsa.py b/astroquery/esa/hsa/tests/test_hsa.py index fd2d09897a..82d35bfc16 100644 --- a/astroquery/esa/hsa/tests/test_hsa.py +++ b/astroquery/esa/hsa/tests/test_hsa.py @@ -1,11 +1,8 @@ # Licensed under a 3-clause BSD style license - see LICENSE.rst import os -import pytest - from astropy import units as u from astropy.coordinates import SkyCoord -from astropy.utils.exceptions import AstropyDeprecationWarning from ..core import HSAClass from ..tests.dummy_tap_handler import DummyHSATapHandler @@ -53,7 +50,7 @@ def test_get_columns(self): def test_query_observations(self): c = SkyCoord(ra=100.2417*u.degree, dec=9.895*u.degree, frame='icrs') - parameters = {'coordinates': c, + parameters = {'coordinate': c, 'radius': 0.5} dummyTapHandler = DummyHSATapHandler("query_observations", parameters) hsa = HSAClass(self.get_dummy_tap_handler()) @@ -62,17 +59,9 @@ def test_query_observations(self): def test_query_region(self): c = SkyCoord(ra=100.2417*u.degree, dec=9.895*u.degree, frame='icrs') - parameters = {'coordinates': c, + parameters = {'coordinate': c, 'radius': 0.5} dummyTapHandler = DummyHSATapHandler("query_region", parameters) hsa = HSAClass(self.get_dummy_tap_handler()) hsa.query_region(**parameters) dummyTapHandler.check_call("query_region", parameters) - - def test_query_region_deprecated_coordinate(self): - c = SkyCoord(ra=100.2417*u.degree, dec=9.895*u.degree, frame='icrs') - hsa = HSAClass(self.get_dummy_tap_handler()) - with pytest.warns(AstropyDeprecationWarning, match="coordinate"): - hsa.query_region(coordinate=c, radius=0.5) - with pytest.warns(AstropyDeprecationWarning, match="coordinate"): - hsa.query_observations(coordinate=c, radius=0.5) diff --git a/astroquery/esa/jwst/core.py b/astroquery/esa/jwst/core.py index f28e10dd30..b9347e5f4d 100644 --- a/astroquery/esa/jwst/core.py +++ b/astroquery/esa/jwst/core.py @@ -25,7 +25,6 @@ from astropy.coordinates import Angle, SkyCoord from astropy.table import vstack from astropy.units import Quantity -from astropy.utils.decorators import deprecated_renamed_argument from requests.exceptions import ConnectionError from astroquery.exceptions import RemoteServiceError @@ -234,8 +233,7 @@ def list_async_jobs(self, *, verbose=False): """ return self.__jwsttap.list_async_jobs(verbose=verbose) - @deprecated_renamed_argument("coordinate", "coordinates", since="0.4.12") - def query_region(self, coordinates, *, + def query_region(self, coordinate, *, radius=None, width=None, height=None, @@ -253,7 +251,7 @@ def query_region(self, coordinates, *, Parameters ---------- - coordinates : astropy.coordinates, mandatory + coordinate : astropy.coordinate, mandatory coordinates center point radius : astropy.units, required if no 'width' nor 'height' are provided @@ -296,10 +294,10 @@ def query_region(self, coordinates, *, ------- The job results (astropy.table). """ - coord = self.__get_coord_input(value=coordinates, msg="coordinates") + coord = self.__get_coord_input(value=coordinate, msg="coordinate") job = None if radius is not None: - job = self.cone_search(coordinates=coord, + job = self.cone_search(coordinate=coord, radius=radius, only_public=only_public, observation_id=observation_id, @@ -359,8 +357,7 @@ def query_region(self, coordinates, *, job = self.__jwsttap.launch_job(query=query, verbose=verbose) return job.get_results() - @deprecated_renamed_argument("coordinate", "coordinates", since="0.4.12") - def cone_search(self, coordinates, radius, *, + def cone_search(self, coordinate, radius, *, observation_id=None, cal_level="Top", prod_type=None, @@ -380,7 +377,7 @@ def cone_search(self, coordinates, radius, *, Parameters ---------- - coordinates : astropy.coordinates, mandatory + coordinate : astropy.coordinate, mandatory coordinates center point radius : astropy.units, mandatory radius @@ -431,7 +428,7 @@ def cone_search(self, coordinates, radius, *, ------- A Job object """ - coord = self.__get_coord_input(value=coordinates, msg="coordinates") + coord = self.__get_coord_input(value=coordinate, msg="coordinate") ra_hours, dec = commons.coord_to_radec(coord) ra = ra_hours * 15.0 # Converts to degrees @@ -551,7 +548,7 @@ def query_target(self, target_name, *, target_resolver="ALL", """ coordinates = self.resolve_target_coordinates(target_name=target_name, target_resolver=target_resolver) - return self.query_region(coordinates=coordinates, + return self.query_region(coordinate=coordinates, radius=radius, width=width, height=height, diff --git a/astroquery/esa/jwst/tests/test_jwsttap.py b/astroquery/esa/jwst/tests/test_jwsttap.py index 07f43510d7..d627c7b8e2 100644 --- a/astroquery/esa/jwst/tests/test_jwsttap.py +++ b/astroquery/esa/jwst/tests/test_jwsttap.py @@ -24,7 +24,6 @@ from astropy.io.votable import parse_single_table from astropy.table import Table from astropy.units import Quantity -from astropy.utils.exceptions import AstropyDeprecationWarning from astroquery.exceptions import TableParseError from astroquery.esa.jwst import JwstClass @@ -240,11 +239,11 @@ def test_query_region(self): tap = JwstClass(tap_plus_handler=tapplus, show_messages=False) with pytest.raises(ValueError) as err: - tap.query_region(coordinates=123) - assert "coordinates must be either a string or astropy.coordinates" in err.value.args[0] + tap.query_region(coordinate=123) + assert "coordinate must be either a string or astropy.coordinates" in err.value.args[0] with pytest.raises(NameResolveError) as err: - tap.query_region(coordinates='test') + tap.query_region(coordinate='test') assert ("Unable to find coordinates for name 'test'" in err.value.args[0] or "Unable to retrieve " "coordinates" in err.value.args[0]) @@ -538,26 +537,6 @@ def test_cone_search_sync(self): tap.cone_search(sc, radius, proposal_id=123) assert "proposal_id must be string" in err.value.args[0] - def test_coordinate_deprecated_keyword(self): - connHandler = DummyConnHandler() - tapplus = TapPlus(url="http://test:1111/tap", connhandler=connHandler) - tap = JwstClass(tap_plus_handler=tapplus, show_messages=False) - responseLaunchJob = DummyResponse(200) - responseLaunchJob.set_data(method='POST', body=JOB_DATA) - connHandler.set_default_response(responseLaunchJob) - sc = SkyCoord(ra=19.0, dec=20.0, unit=(u.degree, u.degree), frame='icrs') - radius = Quantity(1.0, u.deg) - - with pytest.warns(AstropyDeprecationWarning, - match='"coordinate" was deprecated in version 0.4.12'): - job = tap.cone_search(coordinate=sc, radius=radius) - assert job is not None - - with pytest.warns(AstropyDeprecationWarning, - match='"coordinate" was deprecated in version 0.4.12'): - results = tap.query_region(coordinate=sc, radius=radius) - assert results is not None - def test_cone_search_async(self): connHandler = DummyConnHandler() tapplus = TapPlus(url="http://test:1111/tap", connhandler=connHandler) diff --git a/astroquery/esasky/core.py b/astroquery/esasky/core.py index 8caace0ffb..4019252bb6 100644 --- a/astroquery/esasky/core.py +++ b/astroquery/esasky/core.py @@ -266,7 +266,7 @@ def query_object_maps(self, position, missions=__ALL_STRING, get_query_payload=F query_object_maps("265.05, 69.0", "Herschel") query_object_maps("265.05, 69.0", ["Herschel", "HST-OPTICAL"]) """ - return self.query_region_maps(coordinates=position, + return self.query_region_maps(coordinate=position, radius=self.__ZERO_ARCMIN_STRING, missions=missions, get_query_payload=get_query_payload, @@ -323,7 +323,7 @@ def query_object_catalogs(self, position, catalogs=__ALL_STRING, row_limit=DEFAU query_object_catalogs("202.469, 47.195", "HSC") query_object_catalogs("202.469, 47.195", ["HSC", "XMM-OM"]) """ - return self.query_region_catalogs(coordinates=position, + return self.query_region_catalogs(coordinate=position, radius=self.__ZERO_ARCMIN_STRING, catalogs=catalogs, row_limit=row_limit, @@ -379,7 +379,7 @@ def query_object_spectra(self, position, missions=__ALL_STRING, get_query_payloa query_object_spectra("202.469, 47.195", "Herschel") query_object_spectra("202.469, 47.195", ["Herschel", "HST-OPTICAL"]) """ - return self.query_region_spectra(coordinates=position, + return self.query_region_spectra(coordinate=position, radius=self.__ZERO_ARCMIN_STRING, missions=missions, get_query_payload=get_query_payload, @@ -644,8 +644,8 @@ def get_images_sso(self, *, sso_name=None, sso_type="ALL", table_list=None, miss log.info("No maps found.") return maps - @deprecated_renamed_argument("position", "coordinates", since="0.4.12") - def query_region_maps(self, coordinates, radius, missions=__ALL_STRING, get_query_payload=False, cache=True, + @deprecated_renamed_argument("position", "coordinate", since="0.4.12") + def query_region_maps(self, coordinate, radius, missions=__ALL_STRING, get_query_payload=False, cache=True, row_limit=DEFAULT_ROW_LIMIT, verbose=False): """ This method queries a chosen region for all available maps and returns a @@ -654,7 +654,7 @@ def query_region_maps(self, coordinates, radius, missions=__ALL_STRING, get_quer Parameters ---------- - coordinates : str or `astropy.coordinates` object + coordinate : str or `astropy.coordinates` object Can either be a string of the location, eg 'M51', or the coordinates of the object. radius : str or `~astropy.units.Quantity` @@ -702,7 +702,7 @@ def query_region_maps(self, coordinates, radius, missions=__ALL_STRING, get_quer query_result = {} sesame_database.set('simbad') - coordinates = commons.parse_coordinates(coordinates) + coordinates = commons.parse_coordinates(coordinate) self._store_query_result(query_result=query_result, names=sanitized_missions, descriptors=self._get_observation_info(), coordinates=coordinates, @@ -713,8 +713,8 @@ def query_region_maps(self, coordinates, radius, missions=__ALL_STRING, get_quer return commons.TableList(query_result) - @deprecated_renamed_argument("position", "coordinates", since="0.4.12") - def query_region_catalogs(self, coordinates, radius, catalogs=__ALL_STRING, row_limit=DEFAULT_ROW_LIMIT, + @deprecated_renamed_argument("position", "coordinate", since="0.4.12") + def query_region_catalogs(self, coordinate, radius, catalogs=__ALL_STRING, row_limit=DEFAULT_ROW_LIMIT, get_query_payload=False, cache=True, verbose=False): """ This method queries a chosen region for all available catalogs and @@ -723,7 +723,7 @@ def query_region_catalogs(self, coordinates, radius, catalogs=__ALL_STRING, row_ Parameters ---------- - coordinates : str or `astropy.coordinates` object + coordinate : str or `astropy.coordinates` object Can either be a string of the location, eg 'M51', or the coordinates of the object. radius : str or `~astropy.units.Quantity` @@ -769,7 +769,7 @@ def query_region_catalogs(self, coordinates, radius, catalogs=__ALL_STRING, row_ sanitized_row_limit = self._sanitize_input_row_limit(row_limit) sesame_database.set('simbad') - coordinates = commons.parse_coordinates(coordinates) + coordinates = commons.parse_coordinates(coordinate) query_result = {} @@ -783,8 +783,8 @@ def query_region_catalogs(self, coordinates, radius, catalogs=__ALL_STRING, row_ return commons.TableList(query_result) - @deprecated_renamed_argument("position", "coordinates", since="0.4.12") - def query_region_spectra(self, coordinates, radius, missions=__ALL_STRING, row_limit=DEFAULT_ROW_LIMIT, + @deprecated_renamed_argument("position", "coordinate", since="0.4.12") + def query_region_spectra(self, coordinate, radius, missions=__ALL_STRING, row_limit=DEFAULT_ROW_LIMIT, get_query_payload=False, cache=True, verbose=False): """ This method queries a chosen region for all available spectra and returns a @@ -793,7 +793,7 @@ def query_region_spectra(self, coordinates, radius, missions=__ALL_STRING, row_l Parameters ---------- - coordinates : str or `astropy.coordinates` object + coordinate : str or `astropy.coordinates` object Can either be a string of the location, eg 'M51', or the coordinates of the object. radius : str or `~astropy.units.Quantity` @@ -841,7 +841,7 @@ def query_region_spectra(self, coordinates, radius, missions=__ALL_STRING, row_l query_result = {} sesame_database.set('simbad') - coordinates = commons.parse_coordinates(coordinates) + coordinates = commons.parse_coordinates(coordinate) self._store_query_result(query_result=query_result, names=sanitized_missions, descriptors=self._get_spectra_info(), coordinates=coordinates, diff --git a/astroquery/esasky/tests/test_esasky.py b/astroquery/esasky/tests/test_esasky.py index 0cb7d83113..89ef64ae17 100644 --- a/astroquery/esasky/tests/test_esasky.py +++ b/astroquery/esasky/tests/test_esasky.py @@ -18,14 +18,14 @@ ("query_region_catalogs", "_get_catalogs_info"), ("query_region_spectra", "_get_spectra_info")]) def test_query_region_deprecated_position(monkeypatch, method_name, descriptor_getter): - # The 'position' keyword was renamed to 'coordinates'; the old keyword + # The 'position' keyword was renamed to 'coordinate'; the old keyword # should still work but emit an AstropyDeprecationWarning. monkeypatch.setattr(ESASky, descriptor_getter, lambda: FAKE_DESCRIPTORS) coordinates = SkyCoord(ra=202.469, dec=47.195, unit="deg") method = getattr(ESASky, method_name) kwargs = {("catalogs" if method_name == "query_region_catalogs" else "missions"): ["XMM"]} - expected = method(coordinates=coordinates, radius="5 arcmin", + expected = method(coordinate=coordinates, radius="5 arcmin", get_query_payload=True, **kwargs) with pytest.warns(AstropyDeprecationWarning): diff --git a/astroquery/esasky/tests/test_esasky_remote.py b/astroquery/esasky/tests/test_esasky_remote.py index 40cec9b905..815fefd4ab 100755 --- a/astroquery/esasky/tests/test_esasky_remote.py +++ b/astroquery/esasky/tests/test_esasky_remote.py @@ -106,7 +106,7 @@ def test_esasky_get_spectra_obs_id(self, tmp_path, mission, observation_id): result[mission.upper()][0].close() def test_esasky_query_region_maps(self): - result = ESASky.query_region_maps(coordinates="M51", radius="5 arcmin") + result = ESASky.query_region_maps(coordinate="M51", radius="5 arcmin") assert isinstance(result, TableList) def test_esasky_query_object_maps(self): @@ -150,7 +150,7 @@ def test_esasky_get_images_hst(self, tmp_path): assert Path(tmp_path, "HST-UV").exists() def test_esasky_query_region_catalogs(self): - result = ESASky.query_region_catalogs(coordinates="M51", radius="5 arcmin") + result = ESASky.query_region_catalogs(coordinate="M51", radius="5 arcmin") assert isinstance(result, TableList) def test_esasky_query_object_catalogs(self): @@ -177,7 +177,7 @@ def test_esasky_get_maps(self, tmp_path): hdu_list.close() def test_esasky_query_region_spectra(self): - result = ESASky.query_region_spectra(coordinates="M51", radius="5 arcmin") + result = ESASky.query_region_spectra(coordinate="M51", radius="5 arcmin") assert isinstance(result, TableList) def test_esasky_query_object_spectra(self): diff --git a/astroquery/gaia/core.py b/astroquery/gaia/core.py index 3a7eca24ab..a0be6d5354 100644 --- a/astroquery/gaia/core.py +++ b/astroquery/gaia/core.py @@ -469,14 +469,14 @@ def get_datalinks(self, ids, *, linking_parameter='SOURCE_ID', verbose=False): return self.__gaiadata.get_datalinks(ids=ids, linking_parameter=final_linking_parameter, verbose=verbose) - def __query_object(self, coordinates, *, radius=None, width=None, height=None, + def __query_object(self, coordinate, *, radius=None, width=None, height=None, async_job=False, verbose=False, columns=(), get_query_payload=False): """Launches a job TAP & TAP+ Parameters ---------- - coordinates : str or astropy.coordinate, mandatory + coordinate : str or astropy.coordinate, mandatory coordinates center point radius : str or astropy.units if no 'width' nor 'height' are provided radius (deg) @@ -499,7 +499,7 @@ def __query_object(self, coordinates, *, radius=None, width=None, height=None, ------- The job results (astropy.table). """ - coord = self.__getCoordInput(coordinates, "coordinates") + coord = self.__getCoordInput(coordinate, "coordinate") if radius is not None: job = self.__cone_search(coord, radius, async_job=async_job, verbose=verbose, columns=columns) @@ -554,8 +554,7 @@ def __query_object(self, coordinates, *, radius=None, width=None, height=None, job = self.launch_job(query, verbose=verbose) return job.get_results() - @deprecated_renamed_argument("coordinate", "coordinates", since="0.4.12") - def query_object(self, coordinates, *, radius=None, width=None, height=None, verbose=False, columns=(), + def query_object(self, coordinate, *, radius=None, width=None, height=None, verbose=False, columns=(), get_query_payload=False): """Launches a synchronous cone search for the input search radius or the box on the sky, sorted by angular separation @@ -563,7 +562,7 @@ def query_object(self, coordinates, *, radius=None, width=None, height=None, ver Parameters ---------- - coordinates : str or astropy.coordinates, mandatory + coordinate : str or astropy.coordinates, mandatory coordinates center point radius : str or astropy.units if no 'width'/'height' are provided radius (deg) @@ -583,18 +582,17 @@ def query_object(self, coordinates, *, radius=None, width=None, height=None, ver ------- The job results (astropy.table). """ - return self.__query_object(coordinates, radius=radius, width=width, height=height, async_job=False, + return self.__query_object(coordinate, radius=radius, width=width, height=height, async_job=False, verbose=verbose, columns=columns, get_query_payload=get_query_payload) - @deprecated_renamed_argument("coordinate", "coordinates", since="0.4.12") - def query_object_async(self, coordinates, *, radius=None, width=None, height=None, verbose=False, columns=()): + def query_object_async(self, coordinate, *, radius=None, width=None, height=None, verbose=False, columns=()): """Launches an asynchronous cone search for the input search radius or the box on the sky, sorted by angular separation TAP & TAP+ Parameters ---------- - coordinates : str or astropy.coordinates, mandatory + coordinate : str or astropy.coordinates, mandatory coordinates center point radius : str or astropy.units if no 'width'/'height' are provided radius @@ -611,10 +609,10 @@ def query_object_async(self, coordinates, *, radius=None, width=None, height=Non ------- The job results (astropy.table). """ - return self.__query_object(coordinates, radius=radius, width=width, height=height, async_job=True, + return self.__query_object(coordinate, radius=radius, width=width, height=height, async_job=True, verbose=verbose, columns=columns) - def __cone_search(self, coordinates, radius, *, table_name=None, + def __cone_search(self, coordinate, radius, *, table_name=None, ra_column_name=MAIN_GAIA_TABLE_RA, dec_column_name=MAIN_GAIA_TABLE_DEC, async_job=False, @@ -628,7 +626,7 @@ def __cone_search(self, coordinates, radius, *, table_name=None, Parameters ---------- - coordinates : astropy.coordinate, mandatory + coordinate : astropy.coordinate, mandatory coordinates center point radius : astropy.units, mandatory radius @@ -664,7 +662,7 @@ def __cone_search(self, coordinates, radius, *, table_name=None, A Job object """ radiusDeg = None - coord = self.__getCoordInput(coordinates, "coordinates") + coord = self.__getCoordInput(coordinate, "coordinate") raHours, dec = commons.coord_to_radec(coord) ra = raHours * 15.0 # Converts to degrees if radius is not None: @@ -708,8 +706,7 @@ def __cone_search(self, coordinates, radius, *, table_name=None, return self.launch_job(query=query, output_file=output_file, output_format=output_format, verbose=verbose, dump_to_file=dump_to_file) - @deprecated_renamed_argument("coordinate", "coordinates", since="0.4.12") - def cone_search(self, coordinates, *, radius=None, + def cone_search(self, coordinate, *, radius=None, table_name=None, ra_column_name=MAIN_GAIA_TABLE_RA, dec_column_name=MAIN_GAIA_TABLE_DEC, @@ -723,7 +720,7 @@ def cone_search(self, coordinates, *, radius=None, Parameters ---------- - coordinates : str or astropy.coordinate, mandatory + coordinate : str or astropy.coordinate, mandatory coordinates center point radius : str or astropy.units, mandatory radius @@ -752,7 +749,7 @@ def cone_search(self, coordinates, *, radius=None, ------- A Job object """ - return self.__cone_search(coordinates, + return self.__cone_search(coordinate, radius=radius, table_name=table_name, ra_column_name=ra_column_name, @@ -765,8 +762,7 @@ def cone_search(self, coordinates, *, radius=None, dump_to_file=dump_to_file, columns=columns, get_query_payload=get_query_payload) - @deprecated_renamed_argument("coordinate", "coordinates", since="0.4.12") - def cone_search_async(self, coordinates, *, radius=None, + def cone_search_async(self, coordinate, *, radius=None, table_name=None, ra_column_name=MAIN_GAIA_TABLE_RA, dec_column_name=MAIN_GAIA_TABLE_DEC, @@ -778,7 +774,7 @@ def cone_search_async(self, coordinates, *, radius=None, Parameters ---------- - coordinates : str or astropy.coordinate, mandatory + coordinate : str or astropy.coordinate, mandatory coordinates center point radius : str or astropy.units, mandatory radius @@ -808,7 +804,7 @@ def cone_search_async(self, coordinates, *, radius=None, ------- A Job object """ - return self.__cone_search(coordinates, + return self.__cone_search(coordinate, radius=radius, table_name=table_name, ra_column_name=ra_column_name, diff --git a/astroquery/gaia/tests/test_gaia_remote.py b/astroquery/gaia/tests/test_gaia_remote.py index ddb51be938..2fd6e4b8e2 100644 --- a/astroquery/gaia/tests/test_gaia_remote.py +++ b/astroquery/gaia/tests/test_gaia_remote.py @@ -21,17 +21,17 @@ def test_query_object_row_limit(): coord = SkyCoord(ra=280, dec=-60, unit=(u.degree, u.degree), frame='icrs') width = u.Quantity(0.1, u.deg) height = u.Quantity(0.1, u.deg) - r = gaia.query_object_async(coordinates=coord, width=width, height=height) + r = gaia.query_object_async(coordinate=coord, width=width, height=height) assert len(r) == gaia.ROW_LIMIT gaia.ROW_LIMIT = 10 - r = gaia.query_object_async(coordinates=coord, width=width, height=height) + r = gaia.query_object_async(coordinate=coord, width=width, height=height) assert len(r) == 10 == gaia.ROW_LIMIT gaia.ROW_LIMIT = -1 - r = gaia.query_object_async(coordinates=coord, width=width, height=height) + r = gaia.query_object_async(coordinate=coord, width=width, height=height) assert len(r) == 184 diff --git a/astroquery/gaia/tests/test_gaiatap.py b/astroquery/gaia/tests/test_gaiatap.py index 034d31da18..2fc5b48d72 100644 --- a/astroquery/gaia/tests/test_gaiatap.py +++ b/astroquery/gaia/tests/test_gaiatap.py @@ -518,20 +518,6 @@ def test_query_object_async(column_attrs, mock_querier_async, kwargs): assert table[colname].attrs_equal(attrs) -def test_query_object_deprecated_coordinate_keyword(mock_querier): - with pytest.warns(AstropyDeprecationWarning, match='"coordinate" was deprecated'): - deprecated_query = mock_querier.query_object( - coordinate=SKYCOORD, width=12 * u.deg, height=10 * u.deg, get_query_payload=True) - assert deprecated_query == mock_querier.query_object( - coordinates=SKYCOORD, width=12 * u.deg, height=10 * u.deg, get_query_payload=True) - - with pytest.warns(AstropyDeprecationWarning, match='"coordinate" was deprecated'): - deprecated_query = mock_querier.cone_search( - coordinate=SKYCOORD, radius=RADIUS, get_query_payload=True) - assert deprecated_query == mock_querier.cone_search( - coordinates=SKYCOORD, radius=RADIUS, get_query_payload=True) - - def test_query_object_precision(mock_querier): """ Verifies that query_object() produces a query where RA, DEC, width and height diff --git a/astroquery/heasarc/core.py b/astroquery/heasarc/core.py index 4eff64a28b..9cf703a3f7 100644 --- a/astroquery/heasarc/core.py +++ b/astroquery/heasarc/core.py @@ -422,8 +422,8 @@ def _parse_constraints(self, column_filters): arg_in_kwargs=(False, True, True, True, True, True, True, True, True, False) ) - @deprecated_renamed_argument("position", "coordinates", since="0.4.12") - def query_region(self, coordinates=None, catalog=None, radius=None, *, + @deprecated_renamed_argument("position", "coordinate", since="0.4.12") + def query_region(self, coordinate=None, catalog=None, radius=None, *, spatial='cone', width=None, polygon=None, column_filters=None, add_offset=False, get_query_payload=False, columns=None, cache=False, verbose=False, maxrec=None, @@ -433,7 +433,7 @@ def query_region(self, coordinates=None, catalog=None, radius=None, *, Parameters ---------- - coordinates : str, `astropy.coordinates` object + coordinate : str, `astropy.coordinates` object Gives the position of the center of the cone or box if performing a cone or box search. Required if spatial is ``'cone'`` or ``'box'``. Ignored if spatial is ``'polygon'`` or ``'all-sky'``. @@ -500,8 +500,8 @@ def query_region(self, coordinates=None, catalog=None, radius=None, *, table : A `~astropy.table.Table` object. """ - # if we have column_filters and no coordinates, assume all-sky search - if coordinates is None and column_filters is not None: + # if we have column_filters and no coordinate, assume all-sky search + if coordinate is None and column_filters is not None: spatial = 'all-sky' if spatial.lower() == 'all-sky': @@ -528,12 +528,12 @@ def query_region(self, coordinates=None, catalog=None, radius=None, *, where = ("WHERE CONTAINS(POINT('ICRS',ra,dec)," f"POLYGON('ICRS',{','.join(coords_str)}))=1") else: - if coordinates is None: + if coordinate is None: raise InvalidQueryError( - "coordinates is required for spatial='cone' (default). " + "coordinate is required for spatial='cone' (default). " "Use spatial='all-sky' For all-sky searches." ) - coords_icrs = parse_coordinates(coordinates).icrs + coords_icrs = parse_coordinates(coordinate).icrs ra, dec = coords_icrs.ra.deg, coords_icrs.dec.deg if spatial.lower() == 'cone': diff --git a/astroquery/heasarc/tests/test_heasarc.py b/astroquery/heasarc/tests/test_heasarc.py index 4e5118b82f..c607ca7428 100644 --- a/astroquery/heasarc/tests/test_heasarc.py +++ b/astroquery/heasarc/tests/test_heasarc.py @@ -231,7 +231,7 @@ def test_spatial_invalid(spatial): ) -def test_spatial_cone_no_coordinates(): +def test_spatial_cone_no_coordinate(): with pytest.raises(InvalidQueryError): Heasarc.query_region(catalog="xmmmaster", columns="*", spatial="cone") diff --git a/astroquery/ipac/irsa/ibe/core.py b/astroquery/ipac/irsa/ibe/core.py index f1b0b0cf33..3d46410cd7 100644 --- a/astroquery/ipac/irsa/ibe/core.py +++ b/astroquery/ipac/irsa/ibe/core.py @@ -14,7 +14,6 @@ import astropy.coordinates as coord from astropy.table import Table -from astropy.utils.decorators import deprecated_renamed_argument from astroquery.exceptions import InvalidQueryError from astroquery.query import BaseQuery @@ -31,8 +30,7 @@ class IbeClass(BaseQuery): TABLE = conf.table TIMEOUT = conf.timeout - @deprecated_renamed_argument("coordinate", "coordinates", since="0.4.12") - def query_region(self, *, coordinates=None, where=None, mission=None, + def query_region(self, *, coordinate=None, where=None, mission=None, dataset=None, table=None, columns=None, width=None, height=None, intersect='OVERLAPS', most_centered=False): """ @@ -49,7 +47,7 @@ def query_region(self, *, coordinates=None, where=None, mission=None, Parameters ---------- - coordinates : str, `astropy.coordinates` object + coordinate : str, `astropy.coordinates` object Gives the position of the center of the box if performing a box search. If it is a string, then it must be a valid argument to `~astropy.coordinates.SkyCoord`. Required if ``where`` is absent. @@ -99,7 +97,7 @@ def query_region(self, *, coordinates=None, where=None, mission=None, A table containing the results of the query """ response = self.query_region_async( - coordinates=coordinates, where=where, mission=mission, + coordinate=coordinate, where=where, mission=mission, dataset=dataset, table=table, columns=columns, width=width, height=height, intersect=intersect, most_centered=most_centered) @@ -108,8 +106,7 @@ def query_region(self, *, coordinates=None, where=None, mission=None, return Table.read(response.text, format='ipac', guess=False) - @deprecated_renamed_argument("coordinate", "coordinates", since="0.4.12") - def query_region_sia(self, *, coordinates=None, mission=None, + def query_region_sia(self, *, coordinate=None, mission=None, dataset=None, table=None, width=None, height=None, intersect='OVERLAPS', most_centered=False): @@ -118,7 +115,7 @@ def query_region_sia(self, *, coordinates=None, mission=None, details. The returned table will include a list of URLs. """ response = self.query_region_async( - coordinates=coordinates, mission=mission, + coordinate=coordinate, mission=mission, dataset=dataset, table=table, width=width, height=height, intersect=intersect, most_centered=most_centered, action='sia') @@ -129,8 +126,7 @@ def query_region_sia(self, *, coordinates=None, mission=None, return commons.parse_votable( response.text).get_first_table().to_table() - @deprecated_renamed_argument("coordinate", "coordinates", since="0.4.12") - def query_region_async(self, *, coordinates=None, where=None, mission=None, dataset=None, + def query_region_async(self, *, coordinate=None, where=None, mission=None, dataset=None, table=None, columns=None, width=None, height=None, action='search', intersect='OVERLAPS', most_centered=False): """ @@ -147,7 +143,7 @@ def query_region_async(self, *, coordinates=None, where=None, mission=None, data Parameters ---------- - coordinates : str, `astropy.coordinates` object + coordinate : str, `astropy.coordinates` object Gives the position of the center of the box if performing a box search. If it is a string, then it must be a valid argument to `~astropy.coordinates.SkyCoord`. Required if ``where`` is absent. @@ -202,9 +198,9 @@ def query_region_async(self, *, coordinates=None, where=None, mission=None, data The HTTP response returned from the service """ - if coordinates is None and where is None: + if coordinate is None and where is None: raise InvalidQueryError( - 'At least one of `coordinates` or `where` is required') + 'At least one of `coordinate` or `where` is required') intersect = intersect.upper() if intersect not in ('COVERS', 'ENCLOSED', 'CENTER', 'OVERLAPS'): @@ -228,8 +224,8 @@ def query_region_async(self, *, coordinates=None, where=None, mission=None, data if most_centered: args['mcen'] = '1' - if coordinates is not None: - c = commons.parse_coordinates(coordinates).transform_to(coord.ICRS) + if coordinate is not None: + c = commons.parse_coordinates(coordinate).transform_to(coord.ICRS) args['POS'] = '{0},{1}'.format(c.ra.deg, c.dec.deg) if width and height: args['SIZE'] = '{0},{1}'.format( diff --git a/astroquery/ipac/irsa/ibe/tests/test_ibe.py b/astroquery/ipac/irsa/ibe/tests/test_ibe.py index c535b92613..c5051b4a28 100644 --- a/astroquery/ipac/irsa/ibe/tests/test_ibe.py +++ b/astroquery/ipac/irsa/ibe/tests/test_ibe.py @@ -6,7 +6,6 @@ import pytest from astropy.table import Table from astropy.coordinates import SkyCoord -from astropy.utils.exceptions import AstropyDeprecationWarning import astropy.units as u from astroquery.utils.mocks import MockResponse @@ -83,21 +82,12 @@ def test_get_columns(patch_get): def test_ibe_pos(patch_get): table = Ibe.query_region( - coordinates=SkyCoord(148.969687 * u.deg, 69.679383 * u.deg), + coordinate=SkyCoord(148.969687 * u.deg, 69.679383 * u.deg), where='expid <= 43010') assert isinstance(table, Table) assert len(table) == 21 -def test_ibe_pos_deprecated_coordinate(patch_get): - with pytest.warns(AstropyDeprecationWarning): - table = Ibe.query_region( - coordinate=SkyCoord(148.969687 * u.deg, 69.679383 * u.deg), - where='expid <= 43010') - assert isinstance(table, Table) - assert len(table) == 21 - - def test_ibe_field_id(patch_get): table = Ibe.query_region( where="ptffield = 4808 and filter='R'") diff --git a/astroquery/ipac/irsa/ibe/tests/test_ibe_remote.py b/astroquery/ipac/irsa/ibe/tests/test_ibe_remote.py index fc3a0d28c5..8bb919e9f1 100644 --- a/astroquery/ipac/irsa/ibe/tests/test_ibe_remote.py +++ b/astroquery/ipac/irsa/ibe/tests/test_ibe_remote.py @@ -13,7 +13,7 @@ @pytest.mark.remote_data def test_ibe_pos(): table = ibe.Ibe.query_region( - coordinates=SkyCoord(148.969687 * u.deg, 69.679383 * u.deg), + coordinate=SkyCoord(148.969687 * u.deg, 69.679383 * u.deg), where='expid <= 43010') assert isinstance(table, Table) assert len(table) == 21 diff --git a/astroquery/noirlab/core.py b/astroquery/noirlab/core.py index 7d33be5ec3..a52744067b 100644 --- a/astroquery/noirlab/core.py +++ b/astroquery/noirlab/core.py @@ -6,7 +6,6 @@ """ import astropy.io.fits as fits import astropy.table -from astropy.utils.decorators import deprecated_renamed_argument from ..query import BaseQuery from ..exceptions import RemoteServiceError from . import conf @@ -145,8 +144,7 @@ def _service_metadata(self, hdu=False, cache=True): response = self._request('GET', url, timeout=self.TIMEOUT, cache=cache) return response.json() - @deprecated_renamed_argument("coordinate", "coordinates", since="0.4.12") - def query_region(self, coordinates, *, radius=0.1, hdu=False, cache=True, async_=False): + def query_region(self, coordinate, *, radius=0.1, hdu=False, cache=True, async_=False): """Query for NOIRLab observations by region of the sky. Given a sky coordinate and radius, returns a `~astropy.table.Table` @@ -154,7 +152,7 @@ def query_region(self, coordinates, *, radius=0.1, hdu=False, cache=True, async_ Parameters ---------- - coordinates : :class:`str` or `~astropy.coordinates` object + coordinate : :class:`str` or `~astropy.coordinates` object The target region which to search. It may be specified as a string or as the appropriate `~astropy.coordinates` object. radius : :class:`float` or :class:`str` or `~astropy.units.Quantity` object, optional @@ -175,7 +173,7 @@ def query_region(self, coordinates, *, radius=0.1, hdu=False, cache=True, async_ A table containing the results. """ self._validate_version() - ra, dec = coordinates.to_string('decimal').split() + ra, dec = coordinate.to_string('decimal').split() url = f'{self.sia_url(hdu=hdu)}?POS={ra},{dec}&SIZE={radius}&VERB=3&format=json' response = self._request('GET', url, timeout=self.TIMEOUT, cache=cache) if async_: diff --git a/astroquery/noirlab/tests/test_noirlab.py b/astroquery/noirlab/tests/test_noirlab.py index c85a963952..05c50ecd4a 100644 --- a/astroquery/noirlab/tests/test_noirlab.py +++ b/astroquery/noirlab/tests/test_noirlab.py @@ -6,7 +6,6 @@ import pytest from astropy import units as u from astropy.coordinates import SkyCoord -from astropy.utils.exceptions import AstropyDeprecationWarning from ...utils.mocks import MockResponse from ...exceptions import RemoteServiceError from .. import NOIRLab @@ -69,7 +68,7 @@ def test_query_region(patch_request, hdu, radius): It is OK if more files have been added to the remote Archive. """ c = SkyCoord(ra=10.625*u.degree, dec=41.2*u.degree, frame='icrs') - r = NOIRLab.query_region(coordinates=c, radius=radius, hdu=hdu) + r = NOIRLab.query_region(c, radius=radius, hdu=hdu) actual = set(r['md5sum'].tolist()) if hdu: expected = exp.query_region_2 @@ -78,16 +77,6 @@ def test_query_region(patch_request, hdu, radius): assert expected.issubset(actual) -def test_query_region_deprecated_coordinate(patch_request): - """The old ``coordinate`` keyword should still work but emit a deprecation warning. - """ - c = SkyCoord(ra=10.625*u.degree, dec=41.2*u.degree, frame='icrs') - with pytest.warns(AstropyDeprecationWarning): - r = NOIRLab.query_region(coordinate=c, radius='0.1') - actual = set(r['md5sum'].tolist()) - assert exp.query_region_1.issubset(actual) - - @pytest.mark.parametrize('hdu', [(False,), (True,)]) def test_core_fields(patch_request, hdu): """List the available CORE fields. diff --git a/astroquery/noirlab/tests/test_noirlab_remote.py b/astroquery/noirlab/tests/test_noirlab_remote.py index cc1b6e4349..2bda39bc66 100644 --- a/astroquery/noirlab/tests/test_noirlab_remote.py +++ b/astroquery/noirlab/tests/test_noirlab_remote.py @@ -36,7 +36,7 @@ def test_query_region(hdu, radius): """ conf.timeout = 300 c = SkyCoord(ra=10.625*u.degree, dec=41.2*u.degree, frame='icrs') - r = NOIRLab().query_region(coordinates=c, radius=radius, hdu=hdu) + r = NOIRLab().query_region(c, radius=radius, hdu=hdu) actual = set(r['md5sum'].tolist()) if hdu: expected = exp.query_region_2 diff --git a/docs/esa/euclid/euclid.rst b/docs/esa/euclid/euclid.rst index a52f11304f..cad80ee9c4 100644 --- a/docs/esa/euclid/euclid.rst +++ b/docs/esa/euclid/euclid.rst @@ -143,7 +143,7 @@ the "mer_catalogue" and its outcome is restricted to 50 rows. >>> import astropy.units as u >>> coord = SkyCoord("17h51m07.4s +65d31m50.8s", frame='icrs') >>> radius = u.Quantity(0.5, u.deg) - >>> job = Euclid.cone_search(coordinates=coord, radius=radius, columns="*", async_job=True) # doctest: +IGNORE_WARNINGS + >>> job = Euclid.cone_search(coordinate=coord, radius=radius, columns="*", async_job=True) # doctest: +IGNORE_WARNINGS INFO: Query finished. [astroquery.utils.tap.core] >>> cone_results = job.get_results() >>> print(f"Found {len(cone_results)} results") @@ -163,7 +163,7 @@ that the name is recognised by the Simbad, VizieR, or NED services. >>> radius = u.Quantity(0.2, u.deg) >>> Euclid.ROW_LIMIT = -1 - >>> job = Euclid.cone_search(coordinates='NGC 6505', radius=radius, table_name="sedm.calibrated_frame", ra_column_name="ra", dec_column_name="dec", async_job=True, columns = ['ra', 'dec', 'datalabs_path', 'file_path', 'file_name', 'observation_id', 'instrument_name']) + >>> job = Euclid.cone_search(coordinate='NGC 6505', radius=radius, table_name="sedm.calibrated_frame", ra_column_name="ra", dec_column_name="dec", async_job=True, columns = ['ra', 'dec', 'datalabs_path', 'file_path', 'file_name', 'observation_id', 'instrument_name']) INFO: Query finished. [astroquery.utils.tap.core] >>> res = job.get_results() >>> print(f"* Found {len(res)} results") @@ -375,7 +375,7 @@ Download the cutout... .. doctest-skip:: >>> file_path = f"{res['file_path'][0]}/{res['file_name'][0]}" - >>> cutout_out = Euclid.get_cutout(file_path=file_path, coordinates='NGC 6505', radius= 0.1 * u.arcmin, output_file='ngc6505_cutout_mer.fits') + >>> cutout_out = Euclid.get_cutout(file_path=file_path, coordinate='NGC 6505', radius= 0.1 * u.arcmin, output_file='ngc6505_cutout_mer.fits') >>> cutout_out = cutout_out[0] ... and inspect its content: diff --git a/docs/esa/jwst/jwst.rst b/docs/esa/jwst/jwst.rst index 377b678a28..8e6535aa15 100644 --- a/docs/esa/jwst/jwst.rst +++ b/docs/esa/jwst/jwst.rst @@ -101,7 +101,7 @@ service degradation. >>> coord = SkyCoord(ra=53, dec=-27, unit=(u.degree, u.degree), frame='icrs') >>> width = u.Quantity(5, u.deg) >>> height = u.Quantity(5, u.deg) - >>> result = Jwst.query_region(coordinates=coord, width=width, height=height) + >>> result = Jwst.query_region(coordinate=coord, width=width, height=height) >>> result # doctest: +IGNORE_OUTPUT dist observationid ... ------------------ ------------------------------ ... @@ -129,7 +129,7 @@ service degradation. >>> >>> coord = SkyCoord(ra=53, dec=-27, unit=(u.degree, u.degree), frame='icrs') >>> radius = u.Quantity(5.0, u.deg) - >>> j = Jwst.cone_search(coordinates=coord, radius=radius, async_job=True) + >>> j = Jwst.cone_search(coordinate=coord, radius=radius, async_job=True) INFO: Query finished. [astroquery.utils.tap.core] >>> result = j.get_results() >>> result # doctest: +IGNORE_OUTPUT diff --git a/docs/esasky/esasky.rst b/docs/esasky/esasky.rst index 37a49e5717..04fc06c597 100644 --- a/docs/esasky/esasky.rst +++ b/docs/esasky/esasky.rst @@ -182,7 +182,7 @@ value for the radius of the region. For instance to query region around M51 in t >>> from astroquery.esasky import ESASky >>> import astropy.units as u - >>> result = ESASky.query_region_catalogs(coordinates="M51", radius=10 * u.arcmin, catalogs=["HSC", "XMM-OM"]) + >>> result = ESASky.query_region_catalogs(coordinate="M51", radius=10 * u.arcmin, catalogs=["HSC", "XMM-OM"]) To search in all available catalogs you can write ``"all"`` instead of a catalog name. The same thing will happen if you don't write any catalog name. @@ -190,8 +190,8 @@ In the same manner, the radius can be specified with either a string or any `~as .. doctest-remote-data:: - >>> result = ESASky.query_region_catalogs(coordinates="M51", radius=10 * u.arcmin, catalogs="all") - >>> result = ESASky.query_region_catalogs(coordinates="M51", radius="10 arcmin") + >>> result = ESASky.query_region_catalogs(coordinate="M51", radius=10 * u.arcmin, catalogs="all") + >>> result = ESASky.query_region_catalogs(coordinate="M51", radius="10 arcmin") To see the result: @@ -228,8 +228,8 @@ you write this: .. doctest-remote-data:: - >>> result = ESASky.query_region_maps(coordinates="M51", radius=10 * u.arcmin, missions="all") - >>> result = ESASky.query_region_spectra(coordinates="M51", radius=10 * u.arcmin, missions="all") + >>> result = ESASky.query_region_maps(coordinate="M51", radius=10 * u.arcmin, missions="all") + >>> result = ESASky.query_region_spectra(coordinate="M51", radius=10 * u.arcmin, missions="all") The parameters are interchangeable in the same way as in :meth:`~astroquery.esasky.ESASkyClass.query_region_catalogs`. @@ -306,7 +306,7 @@ position, radius and missions. .. Skip testing examples with with hard-wired download dir values .. doctest-remote-data:: - >>> table_list = ESASky.query_region_maps(coordinates="V* HT Aqr", radius="15 arcmin", missions=['Herschel', 'ISO-IR']) + >>> table_list = ESASky.query_region_maps(coordinate="V* HT Aqr", radius="15 arcmin", missions=['Herschel', 'ISO-IR']) >>> images = ESASky.get_maps(query_table_list=table_list, download_dir="/home/user/esasky") # doctest: +SKIP This example is equivalent to: @@ -341,7 +341,7 @@ or .. doctest-remote-data:: - >>> table_list = ESASky.query_region_spectra(coordinates="Gaia DR3 4512810408088819712", radius="6.52 arcmin", + >>> table_list = ESASky.query_region_spectra(coordinate="Gaia DR3 4512810408088819712", radius="6.52 arcmin", ... missions=['Herschel', 'XMM-NEWTON']) >>> spectra = ESASky.get_spectra_from_table(query_table_list=table_list, download_dir="/home/user/esasky") # doctest: +SKIP dict: { @@ -357,7 +357,7 @@ Here is another example for Herschel, since it is a bit special: .. doctest-remote-data:: >>> from astroquery.esasky import ESASky - >>> result = ESASky.query_region_spectra(coordinates='[SMB88] 6327', radius='1 arcmin', missions=['HERSCHEL']) + >>> result = ESASky.query_region_spectra(coordinate='[SMB88] 6327', radius='1 arcmin', missions=['HERSCHEL']) >>> herschel_result = result['HERSCHEL'] >>> herschel_result['observation_id', 'target_name', 'instrument', 'observing_mode_name', 'band', 'duration'].pprint() observation_id target_name instrument ... band duration diff --git a/docs/gaia/gaia.rst b/docs/gaia/gaia.rst index f2bbd37be4..6066b6aefd 100644 --- a/docs/gaia/gaia.rst +++ b/docs/gaia/gaia.rst @@ -102,7 +102,7 @@ degrees around an specific point in RA/Dec coordinates. The results are sorted b >>> coord = SkyCoord(ra=280, dec=-60, unit=(u.degree, u.degree), frame='icrs') >>> width = u.Quantity(0.1, u.deg) >>> height = u.Quantity(0.1, u.deg) - >>> r = Gaia.query_object_async(coordinates=coord, width=width, height=height) + >>> r = Gaia.query_object_async(coordinate=coord, width=width, height=height) INFO: Query finished. [astroquery.utils.tap.core] >>> r.pprint(max_lines=12, max_width=130) dist solution_id designation ... ebpminrp_gspphot_upper libname_gspphot @@ -123,7 +123,7 @@ Queries return a limited number of rows controlled by ``Gaia.ROW_LIMIT``. To cha .. doctest-remote-data:: >>> Gaia.ROW_LIMIT = 8 - >>> r = Gaia.query_object_async(coordinates=coord, width=width, height=height) + >>> r = Gaia.query_object_async(coordinate=coord, width=width, height=height) INFO: Query finished. [astroquery.utils.tap.core] >>> r.pprint(max_width=140) dist solution_id designation ... ebpminrp_gspphot_lower ebpminrp_gspphot_upper libname_gspphot @@ -143,7 +143,7 @@ To return an unlimited number of rows set ``Gaia.ROW_LIMIT`` to -1. .. doctest-remote-data:: >>> Gaia.ROW_LIMIT = -1 - >>> r = Gaia.query_object_async(coordinates=coord, width=width, height=height) + >>> r = Gaia.query_object_async(coordinate=coord, width=width, height=height) INFO: Query finished. [astroquery.utils.tap.core] >>> r.pprint(max_lines=12, max_width=140) dist solution_id designation ... ebpminrp_gspphot_lower ebpminrp_gspphot_upper libname_gspphot From d189966e4f86b33a90c7a1722ff655412621c45b Mon Sep 17 00:00:00 2001 From: "Adam Ginsburg (keflavich)" Date: Wed, 10 Jun 2026 17:02:23 +0200 Subject: [PATCH 3/4] Revert "Use singular 'coordinate' where only one position is accepted" This reverts commit 930d67c6b8c95a884a424d5e74a2c3c0065786b5. --- CHANGES.rst | 49 +++++++++++++++++-- astroquery/alma/core.py | 6 ++- astroquery/alma/tests/test_alma.py | 14 ++++++ astroquery/alma/tests/test_alma_remote.py | 2 +- astroquery/esa/euclid/core.py | 32 ++++++------ .../esa/euclid/tests/test_euclid_remote.py | 6 +-- astroquery/esa/euclid/tests/test_euclidtap.py | 40 +++++++++------ astroquery/esa/hsa/core.py | 15 +++--- astroquery/esa/hsa/tests/test_hsa.py | 15 +++++- astroquery/esa/jwst/core.py | 19 ++++--- astroquery/esa/jwst/tests/test_jwsttap.py | 27 ++++++++-- astroquery/esasky/core.py | 30 ++++++------ astroquery/esasky/tests/test_esasky.py | 4 +- astroquery/esasky/tests/test_esasky_remote.py | 6 +-- astroquery/gaia/core.py | 40 ++++++++------- astroquery/gaia/tests/test_gaia_remote.py | 6 +-- astroquery/gaia/tests/test_gaiatap.py | 14 ++++++ astroquery/heasarc/core.py | 16 +++--- astroquery/heasarc/tests/test_heasarc.py | 2 +- astroquery/ipac/irsa/ibe/core.py | 26 +++++----- astroquery/ipac/irsa/ibe/tests/test_ibe.py | 12 ++++- .../ipac/irsa/ibe/tests/test_ibe_remote.py | 2 +- astroquery/noirlab/core.py | 8 +-- astroquery/noirlab/tests/test_noirlab.py | 13 ++++- .../noirlab/tests/test_noirlab_remote.py | 2 +- docs/esa/euclid/euclid.rst | 6 +-- docs/esa/jwst/jwst.rst | 4 +- docs/esasky/esasky.rst | 16 +++--- docs/gaia/gaia.rst | 6 +-- 29 files changed, 294 insertions(+), 144 deletions(-) diff --git a/CHANGES.rst b/CHANGES.rst index 4f262ee0bc..bea6bcf64b 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -64,6 +64,8 @@ esa.euclid product_type parameters dynamically. [#3601] - In the method, ``get_scientific_product_list``, the ``dsr_part3`` parameter now supports the additional value ``latest``. [#3601] +- The ``coordinate`` keyword of ``query_object``, ``cone_search``, and ``get_cutout`` is deprecated in + favor of ``coordinates`` for consistency with the rest of astroquery. [#3609] vizier @@ -87,24 +89,61 @@ vo_conesearch PyVO Simple Cone Search interface instead. There is no direct replacement for server validation. [#3548] +alma +^^^^ + +- The ``coordinate`` keyword of ``query_region`` and ``query_region_async`` is deprecated in favor of + ``coordinates`` for consistency with the rest of astroquery. [#3609] + +esa.hsa +^^^^^^^ + +- The ``coordinate`` keyword of ``query_observations`` and ``query_region`` is deprecated in favor of + ``coordinates`` for consistency with the rest of astroquery. [#3609] + +esa.jwst +^^^^^^^^ + +- The ``coordinate`` keyword of ``query_region`` and ``cone_search`` is deprecated in favor of + ``coordinates`` for consistency with the rest of astroquery. [#3609] + esasky ^^^^^^ - The ``position`` keyword of ``query_region_maps``, ``query_region_catalogs``, and - ``query_region_spectra`` is deprecated in favor of ``coordinate``; these methods accept a - single sky position. [#3609] + ``query_region_spectra`` is deprecated in favor of ``coordinates`` for consistency with the rest of + astroquery. [#3609] + +gaia +^^^^ + +- The ``coordinate`` keyword of ``query_object``, ``query_object_async``, ``cone_search``, and + ``cone_search_async`` is deprecated in favor of ``coordinates`` for consistency with the rest of + astroquery. [#3609] heasarc ^^^^^^^ -- The ``position`` keyword of ``query_region`` is deprecated in favor of ``coordinate``; the - method accepts a single sky position. [#3609] +- The ``position`` keyword of ``query_region`` is deprecated in favor of ``coordinates`` for + consistency with the rest of astroquery. [#3609] + +ipac.irsa.ibe +^^^^^^^^^^^^^ + +- The ``coordinate`` keyword of ``query_region``, ``query_region_sia``, and ``query_region_async`` is + deprecated in favor of ``coordinates`` for consistency with the rest of astroquery. [#3609] + +noirlab +^^^^^^^ + +- The ``coordinate`` keyword of ``query_region`` is deprecated in favor of ``coordinates`` for + consistency with the rest of astroquery. [#3609] ogle ^^^^ - The ``coord`` keyword of ``query_region`` and ``query_region_async`` is deprecated in favor of - ``coordinates``; the method accepts one or more positions (as a list of coordinates). [#3609] + ``coordinates`` for consistency with the rest of astroquery. [#3609] Service fixes and enhancements ------------------------------ diff --git a/astroquery/alma/core.py b/astroquery/alma/core.py index 0a3ee5d1b0..279280eae6 100644 --- a/astroquery/alma/core.py +++ b/astroquery/alma/core.py @@ -20,6 +20,7 @@ from astropy import units as u from astropy.time import Time from astropy.coordinates import SkyCoord +from astropy.utils.decorators import deprecated_renamed_argument from pyvo.dal.sia2 import SIA2_PARAMETERS_DESC, SIA2Service @@ -506,7 +507,8 @@ def query_object_async(self, object_name, *, public=True, payload=payload, enhanced_results=enhanced_results, **kwargs) - def query_region_async(self, coordinate, radius, *, public=True, + @deprecated_renamed_argument("coordinate", "coordinates", since="0.4.12") + def query_region_async(self, coordinates, radius, *, public=True, science=True, payload=None, enhanced_results=False, **kwargs): """ @@ -533,7 +535,7 @@ def query_region_async(self, coordinate, radius, *, public=True, rad = radius if not isinstance(radius, u.Quantity): rad = radius*u.deg - obj_coord = commons.parse_coordinates(coordinate).icrs + obj_coord = commons.parse_coordinates(coordinates).icrs ra_dec = '{}, {}'.format(obj_coord.to_string(), rad.to(u.deg).value) if payload is None: payload = {} diff --git a/astroquery/alma/tests/test_alma.py b/astroquery/alma/tests/test_alma.py index 6bbdc50911..afe63b7c1c 100644 --- a/astroquery/alma/tests/test_alma.py +++ b/astroquery/alma/tests/test_alma.py @@ -12,6 +12,7 @@ from astropy.io import votable from astropy.coordinates import SkyCoord from astropy.time import Time +from astropy.utils.exceptions import AstropyDeprecationWarning import pyvo from astroquery.alma import Alma @@ -364,6 +365,19 @@ def test_query(): language='ADQL', maxrec=None, uploads=None) +def test_query_region_coordinate_deprecated(): + # the old ``coordinate`` keyword should still work but emit a + # deprecation warning (renamed to ``coordinates``, issue #2803) + alma = Alma() + alma._get_dataarchive_url = Mock() + new_payload = alma.query_region(coordinates='1 2', radius=1*u.deg, + get_query_payload=True) + with pytest.warns(AstropyDeprecationWarning): + old_payload = alma.query_region(coordinate='1 2', radius=1*u.deg, + get_query_payload=True) + assert old_payload == new_payload + + @pytest.mark.filterwarnings("ignore::astropy.utils.exceptions.AstropyUserWarning") def test_enhanced_table(): pytest.importorskip('regions') diff --git a/astroquery/alma/tests/test_alma_remote.py b/astroquery/alma/tests/test_alma_remote.py index 2a1535dc0e..4986a8f8ce 100644 --- a/astroquery/alma/tests/test_alma_remote.py +++ b/astroquery/alma/tests/test_alma_remote.py @@ -337,7 +337,7 @@ def test_query(self, tmp_path, alma): def test_misc(self, alma): # miscellaneous set of common tests # - # alma.query_region(coordinate=orionkl_coords, radius=4 * u.arcmin, + # alma.query_region(coordinates=orionkl_coords, radius=4 * u.arcmin, # public=False, science=False) result = alma.query_object('M83', public=True, science=True) diff --git a/astroquery/esa/euclid/core.py b/astroquery/esa/euclid/core.py index 917e99b020..0bf9e702dc 100644 --- a/astroquery/esa/euclid/core.py +++ b/astroquery/esa/euclid/core.py @@ -384,14 +384,15 @@ def launch_job_async(self, query, *, name=None, dump_to_file=False, output_file= except Exception as exx: log.error(f'Query failed: {query}, {str(exx)}') - def query_object(self, coordinate, *, radius=None, width=None, height=None, + @deprecated_renamed_argument("coordinate", "coordinates", since="0.4.12") + def query_object(self, coordinates, *, radius=None, width=None, height=None, async_job=False, verbose=False, columns=None): """ Searches for objects around a given position with the default catalog sascat_pvpr01.mer_final_cat_pvpr01 Parameters ---------- - coordinate : astropy.coordinate, mandatory + coordinates : astropy.coordinate, mandatory coordinates center point radius : astropy.units, required if no 'width' nor 'height' are provided radius (deg) @@ -411,7 +412,7 @@ def query_object(self, coordinate, *, radius=None, width=None, height=None, ------- The job results (astropy.table) """ - coord = commons.parse_coordinates(coordinate) + coord = commons.parse_coordinates(coordinates) if radius is not None: job = self.__cone_search(coord, radius, async_job=async_job, verbose=verbose, columns=columns) @@ -437,14 +438,14 @@ def query_object(self, coordinate, *, radius=None, width=None, height=None, job = super().launch_job(query, verbose=verbose, format_with_results_compressed=('votable_gzip',)) return job.get_results() - def __cone_search(self, coordinate, radius, *, table_name=None, ra_column_name=None, dec_column_name=None, + def __cone_search(self, coordinates, radius, *, table_name=None, ra_column_name=None, dec_column_name=None, async_job=False, verbose=False, columns=None): """Cone search sorted by distance TAP & TAP+ Parameters ---------- - coordinate : astropy.coordinate, mandatory + coordinates : astropy.coordinate, mandatory coordinates center point radius : astropy.units, mandatory radius @@ -478,7 +479,7 @@ def __cone_search(self, coordinate, radius, *, table_name=None, ra_column_name=N raise ValueError(f"Invalid ra or dec column names: ra, {ra_column_name}, dec, {dec_column_name}") radius_deg = None - coord = commons.parse_coordinates(coordinate) + coord = commons.parse_coordinates(coordinates) ra_hours, dec = commons.coord_to_radec(coord) ra = ra_hours * 15.0 # Converts to degrees if radius is not None: @@ -519,7 +520,8 @@ def __cone_search(self, coordinate, radius, *, table_name=None, ra_column_name=N return job - def cone_search(self, coordinate, radius, *, + @deprecated_renamed_argument("coordinate", "coordinates", since="0.4.12") + def cone_search(self, coordinates, radius, *, table_name=None, ra_column_name=None, dec_column_name=None, @@ -535,7 +537,7 @@ def cone_search(self, coordinate, radius, *, Parameters ---------- - coordinate : astropy.coordinate, mandatory + coordinates : astropy.coordinate, mandatory coordinates center point radius : astropy.units, mandatory radius @@ -570,7 +572,7 @@ def cone_search(self, coordinate, radius, *, """ radius_deg = None - coord = commons.parse_coordinates(coordinate) + coord = commons.parse_coordinates(coordinates) ra_hours, dec = commons.coord_to_radec(coord) ra = ra_hours * 15.0 # Converts to degrees if radius is not None: @@ -1453,9 +1455,9 @@ def __is_multiple(self, value): return not isinstance(value, int) and ((isinstance(value, (list, tuple)) and len(value) > 1) or ',' in value) - @deprecated_renamed_argument(('instrument', 'id'), (None, None), since='0.4.12') - def get_cutout(self, *, file_path=None, coordinate, radius, output_file=None, verbose=False, instrument=None, - id=None): + @deprecated_renamed_argument(('coordinate', 'instrument', 'id'), ('coordinates', None, None), since='0.4.12') + def get_cutout(self, *, file_path=None, coordinates=None, radius=None, output_file=None, verbose=False, + instrument=None, id=None): """ Downloads a cutout from a MER mosaic (background-subtracted image) for a given fits file path, centered on a coordinate and with a specified radius. @@ -1466,7 +1468,7 @@ def get_cutout(self, *, file_path=None, coordinate, radius, output_file=None, ve ---------- file_path : str, mandatory, default None file path for the product on the server (MER mosaic) - coordinate : astropy.coordinate or Simbad/VizieR/NED name (str), mandatory + coordinates : astropy.coordinate or Simbad/VizieR/NED name (str), mandatory coordinates center point radius : astropy.units, mandatory the radius of the cutout to generate @@ -1480,14 +1482,14 @@ def get_cutout(self, *, file_path=None, coordinate, radius, output_file=None, ve The fits file is downloaded, and the local path where the cutout is saved is returned """ - if file_path is None or coordinate is None or radius is None: + if file_path is None or coordinates is None or radius is None: raise ValueError(self.__ERROR_MSG_REQUESTED_GENERIC) # Parse POS radius_deg = Angle(self.__get_quantity_input(radius, "radius")).to_value(u.deg) if radius_deg > 0.5: raise ValueError(self.__ERROR_MSG_REQUESTED_RADIUS) - coord = commons.parse_coordinates(coordinate) + coord = commons.parse_coordinates(coordinates) ra_hours, dec = commons.coord_to_radec(coord) ra = ra_hours * 15.0 # Converts to degrees pos = """CIRCLE,{ra},{dec},{radius}""".format(**{'ra': ra, 'dec': dec, 'radius': radius_deg}) diff --git a/astroquery/esa/euclid/tests/test_euclid_remote.py b/astroquery/esa/euclid/tests/test_euclid_remote.py index 68826b37de..7aebbdf167 100644 --- a/astroquery/esa/euclid/tests/test_euclid_remote.py +++ b/astroquery/esa/euclid/tests/test_euclid_remote.py @@ -21,17 +21,17 @@ def test_query_object_row_limit(): coord = SkyCoord(ra=265.8, dec=64.1, unit=(u.degree, u.degree), frame='icrs') width = u.Quantity(0.1, u.deg) height = u.Quantity(0.1, u.deg) - r = euclid.query_object(coordinate=coord, width=width, height=height, async_job=True, verbose=True) + r = euclid.query_object(coordinates=coord, width=width, height=height, async_job=True, verbose=True) assert len(r) == 50 euclid.ROW_LIMIT = 10 - r = euclid.query_object(coordinate=coord, width=width, height=height, async_job=True) + r = euclid.query_object(coordinates=coord, width=width, height=height, async_job=True) assert len(r) == 10 == euclid.ROW_LIMIT euclid.ROW_LIMIT = -1 - r = euclid.query_object(coordinate=coord, width=width, height=height, async_job=True, verbose=True) + r = euclid.query_object(coordinates=coord, width=width, height=height, async_job=True, verbose=True) assert len(r) == 1948 diff --git a/astroquery/esa/euclid/tests/test_euclidtap.py b/astroquery/esa/euclid/tests/test_euclidtap.py index ad543ca057..510d32f6e0 100644 --- a/astroquery/esa/euclid/tests/test_euclidtap.py +++ b/astroquery/esa/euclid/tests/test_euclidtap.py @@ -22,6 +22,7 @@ from astropy.table import Column, Table from astropy.units import Quantity from astropy.utils.data import get_pkg_data_filename +from astropy.utils.exceptions import AstropyDeprecationWarning from requests import HTTPError from astroquery.esa.euclid.core import EuclidClass @@ -198,7 +199,7 @@ def test_load_environments(): def test_query_async_object(column_attrs, mock_querier_async): coord = SkyCoord(ra=60.3372780005097, dec=-49.93184727724773, unit=(u.degree, u.degree), frame='icrs') - table = mock_querier_async.query_object(coordinate=coord, width=u.Quantity(0.1, u.deg), + table = mock_querier_async.query_object(coordinates=coord, width=u.Quantity(0.1, u.deg), height=u.Quantity(0.1, u.deg), async_job=True) assert table is not None @@ -210,7 +211,7 @@ def test_query_async_object(column_attrs, mock_querier_async): def test_query_async_object_columns(column_attrs, mock_querier_async): coord = SkyCoord(ra=60.3372780005097, dec=-49.93184727724773, unit=(u.degree, u.degree), frame='icrs') - table = mock_querier_async.query_object(coordinate=coord, width=u.Quantity(0.1, u.deg), + table = mock_querier_async.query_object(coordinates=coord, width=u.Quantity(0.1, u.deg), height=u.Quantity(0.1, u.deg), columns=("alpha",), async_job=True) assert table is not None @@ -222,7 +223,7 @@ def test_query_async_object_columns(column_attrs, mock_querier_async): def test_query_object(column_attrs, mock_querier): coord = SkyCoord(ra=60.3372780005097, dec=-49.93184727724773, unit=(u.degree, u.degree), frame='icrs') - table = mock_querier.query_object(coordinate=coord, width=u.Quantity(0.1, u.deg), + table = mock_querier.query_object(coordinates=coord, width=u.Quantity(0.1, u.deg), height=u.Quantity(0.1, u.deg)) assert table is not None @@ -234,7 +235,7 @@ def test_query_object(column_attrs, mock_querier): def test_query_object_columns(column_attrs, mock_querier): coord = SkyCoord(ra=60.3372780005097, dec=-49.93184727724773, unit=(u.degree, u.degree), frame='icrs') - table = mock_querier.query_object(coordinate=coord, width=u.Quantity(0.1, u.deg), + table = mock_querier.query_object(coordinates=coord, width=u.Quantity(0.1, u.deg), height=u.Quantity(0.1, u.deg), columns=("alpha",)) assert table is not None @@ -245,7 +246,7 @@ def test_query_object_columns(column_attrs, mock_querier): def test_query_object_async_radius(column_attrs, mock_querier_async): coord = SkyCoord(ra=60.3372780005097, dec=-49.93184727724773, unit=(u.degree, u.degree), frame='icrs') - table = mock_querier_async.query_object(coordinate=coord, radius=RADIUS, async_job=True) + table = mock_querier_async.query_object(coordinates=coord, radius=RADIUS, async_job=True) assert table is not None @@ -256,7 +257,7 @@ def test_query_object_async_radius(column_attrs, mock_querier_async): def test_query_object_radius(column_attrs, mock_querier): coord = SkyCoord(ra=60.3372780005097, dec=-49.93184727724773, unit=(u.degree, u.degree), frame='icrs') - table = mock_querier.query_object(coordinate=coord, radius=RADIUS) + table = mock_querier.query_object(coordinates=coord, radius=RADIUS) assert table is not None @@ -265,9 +266,18 @@ def test_query_object_radius(column_attrs, mock_querier): assert table[colname].attrs_equal(attrs) +def test_query_object_deprecated_coordinate_keyword(mock_querier): + coord = SkyCoord(ra=60.3372780005097, dec=-49.93184727724773, unit=(u.degree, u.degree), frame='icrs') + with pytest.warns(AstropyDeprecationWarning, match='"coordinate" was deprecated'): + table = mock_querier.query_object(coordinate=coord, radius=RADIUS) + + assert table is not None + assert len(table) == 3 + + def test_query_object_async_radius_columns(column_attrs, mock_querier_async): coord = SkyCoord(ra=60.3372780005097, dec=-49.93184727724773, unit=(u.degree, u.degree), frame='icrs') - table = mock_querier_async.query_object(coordinate=coord, radius=RADIUS, columns=("alpha",), async_job=True) + table = mock_querier_async.query_object(coordinates=coord, radius=RADIUS, columns=("alpha",), async_job=True) assert table is not None @@ -277,7 +287,7 @@ def test_query_object_async_radius_columns(column_attrs, mock_querier_async): def test_query_object_radius_columns(column_attrs, mock_querier): coord = SkyCoord(ra=60.3372780005097, dec=-49.93184727724773, unit=(u.degree, u.degree), frame='icrs') - table = mock_querier.query_object(coordinate=coord, radius=RADIUS, columns=("alpha",)) + table = mock_querier.query_object(coordinates=coord, radius=RADIUS, columns=("alpha",)) assert table is not None @@ -1205,7 +1215,7 @@ def test_get_cutout(capsys): result = tap.get_cutout( file_path='/data/repository/NIR/19704/EUC_NIR_W-STACK_NIR-J-19704_20190718T001858.5Z_00.00.fits', - coordinate=c, radius=r, output_file=None, verbose=True) + coordinates=c, radius=r, output_file=None, verbose=True) assert result is not None @@ -1239,17 +1249,17 @@ def test_get_cutout_exception(): show_server_messages=False) with pytest.raises(ValueError, match="Radius cannot be greater than 30 arcminutes"): - tap.get_cutout(file_path=file_path, coordinate=c, radius=100 * u.arcmin, + tap.get_cutout(file_path=file_path, coordinates=c, radius=100 * u.arcmin, output_file=None) with pytest.raises(ValueError, match="Missing required argument"): - tap.get_cutout(file_path=None, coordinate=c, radius=r, output_file=None) + tap.get_cutout(file_path=None, coordinates=c, radius=r, output_file=None) with pytest.raises(ValueError, match="Missing required argument"): - tap.get_cutout(file_path=file_path, coordinate=None, radius=r, output_file=None) + tap.get_cutout(file_path=file_path, coordinates=None, radius=r, output_file=None) with pytest.raises(ValueError, match="Missing required argument"): - tap.get_cutout(file_path=file_path, coordinate=c, radius=None, output_file=None) + tap.get_cutout(file_path=file_path, coordinates=c, radius=None, output_file=None) @patch.object(TapPlus, 'load_data') @@ -1272,7 +1282,7 @@ def test_get_cutout_exceptions_2(mock_load_data, caplog): mock_load_data.side_effect = HTTPError("launch_job_async HTTPError") - tap.get_cutout(file_path='hola.fits', coordinate=SKYCOORD, radius=1 * u.arcmin, + tap.get_cutout(file_path='hola.fits', coordinates=SKYCOORD, radius=1 * u.arcmin, output_file=None) mssg = ("Cannot retrieve the product for file_path hola.fits. HTTP error: " @@ -1281,7 +1291,7 @@ def test_get_cutout_exceptions_2(mock_load_data, caplog): mock_load_data.side_effect = Exception("launch_job_async Exception") - tap.get_cutout(file_path='hola.fits', coordinate=SKYCOORD, radius=1 * u.arcmin, + tap.get_cutout(file_path='hola.fits', coordinates=SKYCOORD, radius=1 * u.arcmin, output_file=None) mssg = ("Cannot retrieve the product for file_path hola.fits: launch_job_async " diff --git a/astroquery/esa/hsa/core.py b/astroquery/esa/hsa/core.py index c9c655321c..b433e7997d 100644 --- a/astroquery/esa/hsa/core.py +++ b/astroquery/esa/hsa/core.py @@ -7,6 +7,7 @@ from pathlib import Path from astropy import units as u +from astropy.utils.decorators import deprecated_renamed_argument from astroquery.utils import commons from astroquery import log from astroquery.exceptions import LoginError @@ -380,13 +381,14 @@ def get_columns(self, table_name, *, only_names=True, verbose=False): else: return columns - def query_observations(self, coordinate, radius, *, n_obs=10, **kwargs): + @deprecated_renamed_argument("coordinate", "coordinates", since="0.4.12") + def query_observations(self, coordinates, radius, *, n_obs=10, **kwargs): """ Get the observation IDs from a given region Parameters ---------- - coordinate : string / `astropy.coordinates` + coordinates : string / `astropy.coordinates` the identifier or coordinates around which to query radius : int / `~astropy.units.Quantity` the radius of the region @@ -399,15 +401,16 @@ def query_observations(self, coordinate, radius, *, n_obs=10, **kwargs): ------- A table object with the list of observations in the region """ - return self.query_region(coordinate, radius, n_obs=n_obs, columns="observation_id", **kwargs) + return self.query_region(coordinates, radius, n_obs=n_obs, columns="observation_id", **kwargs) - def query_region(self, coordinate, radius, *, n_obs=10, columns='*', **kwargs): + @deprecated_renamed_argument("coordinate", "coordinates", since="0.4.12") + def query_region(self, coordinates, radius, *, n_obs=10, columns='*', **kwargs): """ Get the observation metadata from a given region Parameters ---------- - coordinate : string / `astropy.coordinates` + coordinates : string / `astropy.coordinates` the identifier or coordinates around which to query radius : int / `~astropy.units.Quantity` the radius of the region @@ -425,7 +428,7 @@ def query_region(self, coordinate, radius, *, n_obs=10, columns='*', **kwargs): r = radius if not isinstance(radius, u.Quantity): r = radius*u.deg - coord = commons.parse_coordinates(coordinate).icrs + coord = commons.parse_coordinates(coordinates).icrs query = (f"select top {n_obs} {columns} from hsa.v_active_observation " f"where contains(" diff --git a/astroquery/esa/hsa/tests/test_hsa.py b/astroquery/esa/hsa/tests/test_hsa.py index 82d35bfc16..fd2d09897a 100644 --- a/astroquery/esa/hsa/tests/test_hsa.py +++ b/astroquery/esa/hsa/tests/test_hsa.py @@ -1,8 +1,11 @@ # Licensed under a 3-clause BSD style license - see LICENSE.rst import os +import pytest + from astropy import units as u from astropy.coordinates import SkyCoord +from astropy.utils.exceptions import AstropyDeprecationWarning from ..core import HSAClass from ..tests.dummy_tap_handler import DummyHSATapHandler @@ -50,7 +53,7 @@ def test_get_columns(self): def test_query_observations(self): c = SkyCoord(ra=100.2417*u.degree, dec=9.895*u.degree, frame='icrs') - parameters = {'coordinate': c, + parameters = {'coordinates': c, 'radius': 0.5} dummyTapHandler = DummyHSATapHandler("query_observations", parameters) hsa = HSAClass(self.get_dummy_tap_handler()) @@ -59,9 +62,17 @@ def test_query_observations(self): def test_query_region(self): c = SkyCoord(ra=100.2417*u.degree, dec=9.895*u.degree, frame='icrs') - parameters = {'coordinate': c, + parameters = {'coordinates': c, 'radius': 0.5} dummyTapHandler = DummyHSATapHandler("query_region", parameters) hsa = HSAClass(self.get_dummy_tap_handler()) hsa.query_region(**parameters) dummyTapHandler.check_call("query_region", parameters) + + def test_query_region_deprecated_coordinate(self): + c = SkyCoord(ra=100.2417*u.degree, dec=9.895*u.degree, frame='icrs') + hsa = HSAClass(self.get_dummy_tap_handler()) + with pytest.warns(AstropyDeprecationWarning, match="coordinate"): + hsa.query_region(coordinate=c, radius=0.5) + with pytest.warns(AstropyDeprecationWarning, match="coordinate"): + hsa.query_observations(coordinate=c, radius=0.5) diff --git a/astroquery/esa/jwst/core.py b/astroquery/esa/jwst/core.py index b9347e5f4d..f28e10dd30 100644 --- a/astroquery/esa/jwst/core.py +++ b/astroquery/esa/jwst/core.py @@ -25,6 +25,7 @@ from astropy.coordinates import Angle, SkyCoord from astropy.table import vstack from astropy.units import Quantity +from astropy.utils.decorators import deprecated_renamed_argument from requests.exceptions import ConnectionError from astroquery.exceptions import RemoteServiceError @@ -233,7 +234,8 @@ def list_async_jobs(self, *, verbose=False): """ return self.__jwsttap.list_async_jobs(verbose=verbose) - def query_region(self, coordinate, *, + @deprecated_renamed_argument("coordinate", "coordinates", since="0.4.12") + def query_region(self, coordinates, *, radius=None, width=None, height=None, @@ -251,7 +253,7 @@ def query_region(self, coordinate, *, Parameters ---------- - coordinate : astropy.coordinate, mandatory + coordinates : astropy.coordinates, mandatory coordinates center point radius : astropy.units, required if no 'width' nor 'height' are provided @@ -294,10 +296,10 @@ def query_region(self, coordinate, *, ------- The job results (astropy.table). """ - coord = self.__get_coord_input(value=coordinate, msg="coordinate") + coord = self.__get_coord_input(value=coordinates, msg="coordinates") job = None if radius is not None: - job = self.cone_search(coordinate=coord, + job = self.cone_search(coordinates=coord, radius=radius, only_public=only_public, observation_id=observation_id, @@ -357,7 +359,8 @@ def query_region(self, coordinate, *, job = self.__jwsttap.launch_job(query=query, verbose=verbose) return job.get_results() - def cone_search(self, coordinate, radius, *, + @deprecated_renamed_argument("coordinate", "coordinates", since="0.4.12") + def cone_search(self, coordinates, radius, *, observation_id=None, cal_level="Top", prod_type=None, @@ -377,7 +380,7 @@ def cone_search(self, coordinate, radius, *, Parameters ---------- - coordinate : astropy.coordinate, mandatory + coordinates : astropy.coordinates, mandatory coordinates center point radius : astropy.units, mandatory radius @@ -428,7 +431,7 @@ def cone_search(self, coordinate, radius, *, ------- A Job object """ - coord = self.__get_coord_input(value=coordinate, msg="coordinate") + coord = self.__get_coord_input(value=coordinates, msg="coordinates") ra_hours, dec = commons.coord_to_radec(coord) ra = ra_hours * 15.0 # Converts to degrees @@ -548,7 +551,7 @@ def query_target(self, target_name, *, target_resolver="ALL", """ coordinates = self.resolve_target_coordinates(target_name=target_name, target_resolver=target_resolver) - return self.query_region(coordinate=coordinates, + return self.query_region(coordinates=coordinates, radius=radius, width=width, height=height, diff --git a/astroquery/esa/jwst/tests/test_jwsttap.py b/astroquery/esa/jwst/tests/test_jwsttap.py index d627c7b8e2..07f43510d7 100644 --- a/astroquery/esa/jwst/tests/test_jwsttap.py +++ b/astroquery/esa/jwst/tests/test_jwsttap.py @@ -24,6 +24,7 @@ from astropy.io.votable import parse_single_table from astropy.table import Table from astropy.units import Quantity +from astropy.utils.exceptions import AstropyDeprecationWarning from astroquery.exceptions import TableParseError from astroquery.esa.jwst import JwstClass @@ -239,11 +240,11 @@ def test_query_region(self): tap = JwstClass(tap_plus_handler=tapplus, show_messages=False) with pytest.raises(ValueError) as err: - tap.query_region(coordinate=123) - assert "coordinate must be either a string or astropy.coordinates" in err.value.args[0] + tap.query_region(coordinates=123) + assert "coordinates must be either a string or astropy.coordinates" in err.value.args[0] with pytest.raises(NameResolveError) as err: - tap.query_region(coordinate='test') + tap.query_region(coordinates='test') assert ("Unable to find coordinates for name 'test'" in err.value.args[0] or "Unable to retrieve " "coordinates" in err.value.args[0]) @@ -537,6 +538,26 @@ def test_cone_search_sync(self): tap.cone_search(sc, radius, proposal_id=123) assert "proposal_id must be string" in err.value.args[0] + def test_coordinate_deprecated_keyword(self): + connHandler = DummyConnHandler() + tapplus = TapPlus(url="http://test:1111/tap", connhandler=connHandler) + tap = JwstClass(tap_plus_handler=tapplus, show_messages=False) + responseLaunchJob = DummyResponse(200) + responseLaunchJob.set_data(method='POST', body=JOB_DATA) + connHandler.set_default_response(responseLaunchJob) + sc = SkyCoord(ra=19.0, dec=20.0, unit=(u.degree, u.degree), frame='icrs') + radius = Quantity(1.0, u.deg) + + with pytest.warns(AstropyDeprecationWarning, + match='"coordinate" was deprecated in version 0.4.12'): + job = tap.cone_search(coordinate=sc, radius=radius) + assert job is not None + + with pytest.warns(AstropyDeprecationWarning, + match='"coordinate" was deprecated in version 0.4.12'): + results = tap.query_region(coordinate=sc, radius=radius) + assert results is not None + def test_cone_search_async(self): connHandler = DummyConnHandler() tapplus = TapPlus(url="http://test:1111/tap", connhandler=connHandler) diff --git a/astroquery/esasky/core.py b/astroquery/esasky/core.py index 4019252bb6..8caace0ffb 100644 --- a/astroquery/esasky/core.py +++ b/astroquery/esasky/core.py @@ -266,7 +266,7 @@ def query_object_maps(self, position, missions=__ALL_STRING, get_query_payload=F query_object_maps("265.05, 69.0", "Herschel") query_object_maps("265.05, 69.0", ["Herschel", "HST-OPTICAL"]) """ - return self.query_region_maps(coordinate=position, + return self.query_region_maps(coordinates=position, radius=self.__ZERO_ARCMIN_STRING, missions=missions, get_query_payload=get_query_payload, @@ -323,7 +323,7 @@ def query_object_catalogs(self, position, catalogs=__ALL_STRING, row_limit=DEFAU query_object_catalogs("202.469, 47.195", "HSC") query_object_catalogs("202.469, 47.195", ["HSC", "XMM-OM"]) """ - return self.query_region_catalogs(coordinate=position, + return self.query_region_catalogs(coordinates=position, radius=self.__ZERO_ARCMIN_STRING, catalogs=catalogs, row_limit=row_limit, @@ -379,7 +379,7 @@ def query_object_spectra(self, position, missions=__ALL_STRING, get_query_payloa query_object_spectra("202.469, 47.195", "Herschel") query_object_spectra("202.469, 47.195", ["Herschel", "HST-OPTICAL"]) """ - return self.query_region_spectra(coordinate=position, + return self.query_region_spectra(coordinates=position, radius=self.__ZERO_ARCMIN_STRING, missions=missions, get_query_payload=get_query_payload, @@ -644,8 +644,8 @@ def get_images_sso(self, *, sso_name=None, sso_type="ALL", table_list=None, miss log.info("No maps found.") return maps - @deprecated_renamed_argument("position", "coordinate", since="0.4.12") - def query_region_maps(self, coordinate, radius, missions=__ALL_STRING, get_query_payload=False, cache=True, + @deprecated_renamed_argument("position", "coordinates", since="0.4.12") + def query_region_maps(self, coordinates, radius, missions=__ALL_STRING, get_query_payload=False, cache=True, row_limit=DEFAULT_ROW_LIMIT, verbose=False): """ This method queries a chosen region for all available maps and returns a @@ -654,7 +654,7 @@ def query_region_maps(self, coordinate, radius, missions=__ALL_STRING, get_query Parameters ---------- - coordinate : str or `astropy.coordinates` object + coordinates : str or `astropy.coordinates` object Can either be a string of the location, eg 'M51', or the coordinates of the object. radius : str or `~astropy.units.Quantity` @@ -702,7 +702,7 @@ def query_region_maps(self, coordinate, radius, missions=__ALL_STRING, get_query query_result = {} sesame_database.set('simbad') - coordinates = commons.parse_coordinates(coordinate) + coordinates = commons.parse_coordinates(coordinates) self._store_query_result(query_result=query_result, names=sanitized_missions, descriptors=self._get_observation_info(), coordinates=coordinates, @@ -713,8 +713,8 @@ def query_region_maps(self, coordinate, radius, missions=__ALL_STRING, get_query return commons.TableList(query_result) - @deprecated_renamed_argument("position", "coordinate", since="0.4.12") - def query_region_catalogs(self, coordinate, radius, catalogs=__ALL_STRING, row_limit=DEFAULT_ROW_LIMIT, + @deprecated_renamed_argument("position", "coordinates", since="0.4.12") + def query_region_catalogs(self, coordinates, radius, catalogs=__ALL_STRING, row_limit=DEFAULT_ROW_LIMIT, get_query_payload=False, cache=True, verbose=False): """ This method queries a chosen region for all available catalogs and @@ -723,7 +723,7 @@ def query_region_catalogs(self, coordinate, radius, catalogs=__ALL_STRING, row_l Parameters ---------- - coordinate : str or `astropy.coordinates` object + coordinates : str or `astropy.coordinates` object Can either be a string of the location, eg 'M51', or the coordinates of the object. radius : str or `~astropy.units.Quantity` @@ -769,7 +769,7 @@ def query_region_catalogs(self, coordinate, radius, catalogs=__ALL_STRING, row_l sanitized_row_limit = self._sanitize_input_row_limit(row_limit) sesame_database.set('simbad') - coordinates = commons.parse_coordinates(coordinate) + coordinates = commons.parse_coordinates(coordinates) query_result = {} @@ -783,8 +783,8 @@ def query_region_catalogs(self, coordinate, radius, catalogs=__ALL_STRING, row_l return commons.TableList(query_result) - @deprecated_renamed_argument("position", "coordinate", since="0.4.12") - def query_region_spectra(self, coordinate, radius, missions=__ALL_STRING, row_limit=DEFAULT_ROW_LIMIT, + @deprecated_renamed_argument("position", "coordinates", since="0.4.12") + def query_region_spectra(self, coordinates, radius, missions=__ALL_STRING, row_limit=DEFAULT_ROW_LIMIT, get_query_payload=False, cache=True, verbose=False): """ This method queries a chosen region for all available spectra and returns a @@ -793,7 +793,7 @@ def query_region_spectra(self, coordinate, radius, missions=__ALL_STRING, row_li Parameters ---------- - coordinate : str or `astropy.coordinates` object + coordinates : str or `astropy.coordinates` object Can either be a string of the location, eg 'M51', or the coordinates of the object. radius : str or `~astropy.units.Quantity` @@ -841,7 +841,7 @@ def query_region_spectra(self, coordinate, radius, missions=__ALL_STRING, row_li query_result = {} sesame_database.set('simbad') - coordinates = commons.parse_coordinates(coordinate) + coordinates = commons.parse_coordinates(coordinates) self._store_query_result(query_result=query_result, names=sanitized_missions, descriptors=self._get_spectra_info(), coordinates=coordinates, diff --git a/astroquery/esasky/tests/test_esasky.py b/astroquery/esasky/tests/test_esasky.py index 89ef64ae17..0cb7d83113 100644 --- a/astroquery/esasky/tests/test_esasky.py +++ b/astroquery/esasky/tests/test_esasky.py @@ -18,14 +18,14 @@ ("query_region_catalogs", "_get_catalogs_info"), ("query_region_spectra", "_get_spectra_info")]) def test_query_region_deprecated_position(monkeypatch, method_name, descriptor_getter): - # The 'position' keyword was renamed to 'coordinate'; the old keyword + # The 'position' keyword was renamed to 'coordinates'; the old keyword # should still work but emit an AstropyDeprecationWarning. monkeypatch.setattr(ESASky, descriptor_getter, lambda: FAKE_DESCRIPTORS) coordinates = SkyCoord(ra=202.469, dec=47.195, unit="deg") method = getattr(ESASky, method_name) kwargs = {("catalogs" if method_name == "query_region_catalogs" else "missions"): ["XMM"]} - expected = method(coordinate=coordinates, radius="5 arcmin", + expected = method(coordinates=coordinates, radius="5 arcmin", get_query_payload=True, **kwargs) with pytest.warns(AstropyDeprecationWarning): diff --git a/astroquery/esasky/tests/test_esasky_remote.py b/astroquery/esasky/tests/test_esasky_remote.py index 815fefd4ab..40cec9b905 100755 --- a/astroquery/esasky/tests/test_esasky_remote.py +++ b/astroquery/esasky/tests/test_esasky_remote.py @@ -106,7 +106,7 @@ def test_esasky_get_spectra_obs_id(self, tmp_path, mission, observation_id): result[mission.upper()][0].close() def test_esasky_query_region_maps(self): - result = ESASky.query_region_maps(coordinate="M51", radius="5 arcmin") + result = ESASky.query_region_maps(coordinates="M51", radius="5 arcmin") assert isinstance(result, TableList) def test_esasky_query_object_maps(self): @@ -150,7 +150,7 @@ def test_esasky_get_images_hst(self, tmp_path): assert Path(tmp_path, "HST-UV").exists() def test_esasky_query_region_catalogs(self): - result = ESASky.query_region_catalogs(coordinate="M51", radius="5 arcmin") + result = ESASky.query_region_catalogs(coordinates="M51", radius="5 arcmin") assert isinstance(result, TableList) def test_esasky_query_object_catalogs(self): @@ -177,7 +177,7 @@ def test_esasky_get_maps(self, tmp_path): hdu_list.close() def test_esasky_query_region_spectra(self): - result = ESASky.query_region_spectra(coordinate="M51", radius="5 arcmin") + result = ESASky.query_region_spectra(coordinates="M51", radius="5 arcmin") assert isinstance(result, TableList) def test_esasky_query_object_spectra(self): diff --git a/astroquery/gaia/core.py b/astroquery/gaia/core.py index a0be6d5354..3a7eca24ab 100644 --- a/astroquery/gaia/core.py +++ b/astroquery/gaia/core.py @@ -469,14 +469,14 @@ def get_datalinks(self, ids, *, linking_parameter='SOURCE_ID', verbose=False): return self.__gaiadata.get_datalinks(ids=ids, linking_parameter=final_linking_parameter, verbose=verbose) - def __query_object(self, coordinate, *, radius=None, width=None, height=None, + def __query_object(self, coordinates, *, radius=None, width=None, height=None, async_job=False, verbose=False, columns=(), get_query_payload=False): """Launches a job TAP & TAP+ Parameters ---------- - coordinate : str or astropy.coordinate, mandatory + coordinates : str or astropy.coordinate, mandatory coordinates center point radius : str or astropy.units if no 'width' nor 'height' are provided radius (deg) @@ -499,7 +499,7 @@ def __query_object(self, coordinate, *, radius=None, width=None, height=None, ------- The job results (astropy.table). """ - coord = self.__getCoordInput(coordinate, "coordinate") + coord = self.__getCoordInput(coordinates, "coordinates") if radius is not None: job = self.__cone_search(coord, radius, async_job=async_job, verbose=verbose, columns=columns) @@ -554,7 +554,8 @@ def __query_object(self, coordinate, *, radius=None, width=None, height=None, job = self.launch_job(query, verbose=verbose) return job.get_results() - def query_object(self, coordinate, *, radius=None, width=None, height=None, verbose=False, columns=(), + @deprecated_renamed_argument("coordinate", "coordinates", since="0.4.12") + def query_object(self, coordinates, *, radius=None, width=None, height=None, verbose=False, columns=(), get_query_payload=False): """Launches a synchronous cone search for the input search radius or the box on the sky, sorted by angular separation @@ -562,7 +563,7 @@ def query_object(self, coordinate, *, radius=None, width=None, height=None, verb Parameters ---------- - coordinate : str or astropy.coordinates, mandatory + coordinates : str or astropy.coordinates, mandatory coordinates center point radius : str or astropy.units if no 'width'/'height' are provided radius (deg) @@ -582,17 +583,18 @@ def query_object(self, coordinate, *, radius=None, width=None, height=None, verb ------- The job results (astropy.table). """ - return self.__query_object(coordinate, radius=radius, width=width, height=height, async_job=False, + return self.__query_object(coordinates, radius=radius, width=width, height=height, async_job=False, verbose=verbose, columns=columns, get_query_payload=get_query_payload) - def query_object_async(self, coordinate, *, radius=None, width=None, height=None, verbose=False, columns=()): + @deprecated_renamed_argument("coordinate", "coordinates", since="0.4.12") + def query_object_async(self, coordinates, *, radius=None, width=None, height=None, verbose=False, columns=()): """Launches an asynchronous cone search for the input search radius or the box on the sky, sorted by angular separation TAP & TAP+ Parameters ---------- - coordinate : str or astropy.coordinates, mandatory + coordinates : str or astropy.coordinates, mandatory coordinates center point radius : str or astropy.units if no 'width'/'height' are provided radius @@ -609,10 +611,10 @@ def query_object_async(self, coordinate, *, radius=None, width=None, height=None ------- The job results (astropy.table). """ - return self.__query_object(coordinate, radius=radius, width=width, height=height, async_job=True, + return self.__query_object(coordinates, radius=radius, width=width, height=height, async_job=True, verbose=verbose, columns=columns) - def __cone_search(self, coordinate, radius, *, table_name=None, + def __cone_search(self, coordinates, radius, *, table_name=None, ra_column_name=MAIN_GAIA_TABLE_RA, dec_column_name=MAIN_GAIA_TABLE_DEC, async_job=False, @@ -626,7 +628,7 @@ def __cone_search(self, coordinate, radius, *, table_name=None, Parameters ---------- - coordinate : astropy.coordinate, mandatory + coordinates : astropy.coordinate, mandatory coordinates center point radius : astropy.units, mandatory radius @@ -662,7 +664,7 @@ def __cone_search(self, coordinate, radius, *, table_name=None, A Job object """ radiusDeg = None - coord = self.__getCoordInput(coordinate, "coordinate") + coord = self.__getCoordInput(coordinates, "coordinates") raHours, dec = commons.coord_to_radec(coord) ra = raHours * 15.0 # Converts to degrees if radius is not None: @@ -706,7 +708,8 @@ def __cone_search(self, coordinate, radius, *, table_name=None, return self.launch_job(query=query, output_file=output_file, output_format=output_format, verbose=verbose, dump_to_file=dump_to_file) - def cone_search(self, coordinate, *, radius=None, + @deprecated_renamed_argument("coordinate", "coordinates", since="0.4.12") + def cone_search(self, coordinates, *, radius=None, table_name=None, ra_column_name=MAIN_GAIA_TABLE_RA, dec_column_name=MAIN_GAIA_TABLE_DEC, @@ -720,7 +723,7 @@ def cone_search(self, coordinate, *, radius=None, Parameters ---------- - coordinate : str or astropy.coordinate, mandatory + coordinates : str or astropy.coordinate, mandatory coordinates center point radius : str or astropy.units, mandatory radius @@ -749,7 +752,7 @@ def cone_search(self, coordinate, *, radius=None, ------- A Job object """ - return self.__cone_search(coordinate, + return self.__cone_search(coordinates, radius=radius, table_name=table_name, ra_column_name=ra_column_name, @@ -762,7 +765,8 @@ def cone_search(self, coordinate, *, radius=None, dump_to_file=dump_to_file, columns=columns, get_query_payload=get_query_payload) - def cone_search_async(self, coordinate, *, radius=None, + @deprecated_renamed_argument("coordinate", "coordinates", since="0.4.12") + def cone_search_async(self, coordinates, *, radius=None, table_name=None, ra_column_name=MAIN_GAIA_TABLE_RA, dec_column_name=MAIN_GAIA_TABLE_DEC, @@ -774,7 +778,7 @@ def cone_search_async(self, coordinate, *, radius=None, Parameters ---------- - coordinate : str or astropy.coordinate, mandatory + coordinates : str or astropy.coordinate, mandatory coordinates center point radius : str or astropy.units, mandatory radius @@ -804,7 +808,7 @@ def cone_search_async(self, coordinate, *, radius=None, ------- A Job object """ - return self.__cone_search(coordinate, + return self.__cone_search(coordinates, radius=radius, table_name=table_name, ra_column_name=ra_column_name, diff --git a/astroquery/gaia/tests/test_gaia_remote.py b/astroquery/gaia/tests/test_gaia_remote.py index 2fd6e4b8e2..ddb51be938 100644 --- a/astroquery/gaia/tests/test_gaia_remote.py +++ b/astroquery/gaia/tests/test_gaia_remote.py @@ -21,17 +21,17 @@ def test_query_object_row_limit(): coord = SkyCoord(ra=280, dec=-60, unit=(u.degree, u.degree), frame='icrs') width = u.Quantity(0.1, u.deg) height = u.Quantity(0.1, u.deg) - r = gaia.query_object_async(coordinate=coord, width=width, height=height) + r = gaia.query_object_async(coordinates=coord, width=width, height=height) assert len(r) == gaia.ROW_LIMIT gaia.ROW_LIMIT = 10 - r = gaia.query_object_async(coordinate=coord, width=width, height=height) + r = gaia.query_object_async(coordinates=coord, width=width, height=height) assert len(r) == 10 == gaia.ROW_LIMIT gaia.ROW_LIMIT = -1 - r = gaia.query_object_async(coordinate=coord, width=width, height=height) + r = gaia.query_object_async(coordinates=coord, width=width, height=height) assert len(r) == 184 diff --git a/astroquery/gaia/tests/test_gaiatap.py b/astroquery/gaia/tests/test_gaiatap.py index 2fc5b48d72..034d31da18 100644 --- a/astroquery/gaia/tests/test_gaiatap.py +++ b/astroquery/gaia/tests/test_gaiatap.py @@ -518,6 +518,20 @@ def test_query_object_async(column_attrs, mock_querier_async, kwargs): assert table[colname].attrs_equal(attrs) +def test_query_object_deprecated_coordinate_keyword(mock_querier): + with pytest.warns(AstropyDeprecationWarning, match='"coordinate" was deprecated'): + deprecated_query = mock_querier.query_object( + coordinate=SKYCOORD, width=12 * u.deg, height=10 * u.deg, get_query_payload=True) + assert deprecated_query == mock_querier.query_object( + coordinates=SKYCOORD, width=12 * u.deg, height=10 * u.deg, get_query_payload=True) + + with pytest.warns(AstropyDeprecationWarning, match='"coordinate" was deprecated'): + deprecated_query = mock_querier.cone_search( + coordinate=SKYCOORD, radius=RADIUS, get_query_payload=True) + assert deprecated_query == mock_querier.cone_search( + coordinates=SKYCOORD, radius=RADIUS, get_query_payload=True) + + def test_query_object_precision(mock_querier): """ Verifies that query_object() produces a query where RA, DEC, width and height diff --git a/astroquery/heasarc/core.py b/astroquery/heasarc/core.py index 9cf703a3f7..4eff64a28b 100644 --- a/astroquery/heasarc/core.py +++ b/astroquery/heasarc/core.py @@ -422,8 +422,8 @@ def _parse_constraints(self, column_filters): arg_in_kwargs=(False, True, True, True, True, True, True, True, True, False) ) - @deprecated_renamed_argument("position", "coordinate", since="0.4.12") - def query_region(self, coordinate=None, catalog=None, radius=None, *, + @deprecated_renamed_argument("position", "coordinates", since="0.4.12") + def query_region(self, coordinates=None, catalog=None, radius=None, *, spatial='cone', width=None, polygon=None, column_filters=None, add_offset=False, get_query_payload=False, columns=None, cache=False, verbose=False, maxrec=None, @@ -433,7 +433,7 @@ def query_region(self, coordinate=None, catalog=None, radius=None, *, Parameters ---------- - coordinate : str, `astropy.coordinates` object + coordinates : str, `astropy.coordinates` object Gives the position of the center of the cone or box if performing a cone or box search. Required if spatial is ``'cone'`` or ``'box'``. Ignored if spatial is ``'polygon'`` or ``'all-sky'``. @@ -500,8 +500,8 @@ def query_region(self, coordinate=None, catalog=None, radius=None, *, table : A `~astropy.table.Table` object. """ - # if we have column_filters and no coordinate, assume all-sky search - if coordinate is None and column_filters is not None: + # if we have column_filters and no coordinates, assume all-sky search + if coordinates is None and column_filters is not None: spatial = 'all-sky' if spatial.lower() == 'all-sky': @@ -528,12 +528,12 @@ def query_region(self, coordinate=None, catalog=None, radius=None, *, where = ("WHERE CONTAINS(POINT('ICRS',ra,dec)," f"POLYGON('ICRS',{','.join(coords_str)}))=1") else: - if coordinate is None: + if coordinates is None: raise InvalidQueryError( - "coordinate is required for spatial='cone' (default). " + "coordinates is required for spatial='cone' (default). " "Use spatial='all-sky' For all-sky searches." ) - coords_icrs = parse_coordinates(coordinate).icrs + coords_icrs = parse_coordinates(coordinates).icrs ra, dec = coords_icrs.ra.deg, coords_icrs.dec.deg if spatial.lower() == 'cone': diff --git a/astroquery/heasarc/tests/test_heasarc.py b/astroquery/heasarc/tests/test_heasarc.py index c607ca7428..4e5118b82f 100644 --- a/astroquery/heasarc/tests/test_heasarc.py +++ b/astroquery/heasarc/tests/test_heasarc.py @@ -231,7 +231,7 @@ def test_spatial_invalid(spatial): ) -def test_spatial_cone_no_coordinate(): +def test_spatial_cone_no_coordinates(): with pytest.raises(InvalidQueryError): Heasarc.query_region(catalog="xmmmaster", columns="*", spatial="cone") diff --git a/astroquery/ipac/irsa/ibe/core.py b/astroquery/ipac/irsa/ibe/core.py index 3d46410cd7..f1b0b0cf33 100644 --- a/astroquery/ipac/irsa/ibe/core.py +++ b/astroquery/ipac/irsa/ibe/core.py @@ -14,6 +14,7 @@ import astropy.coordinates as coord from astropy.table import Table +from astropy.utils.decorators import deprecated_renamed_argument from astroquery.exceptions import InvalidQueryError from astroquery.query import BaseQuery @@ -30,7 +31,8 @@ class IbeClass(BaseQuery): TABLE = conf.table TIMEOUT = conf.timeout - def query_region(self, *, coordinate=None, where=None, mission=None, + @deprecated_renamed_argument("coordinate", "coordinates", since="0.4.12") + def query_region(self, *, coordinates=None, where=None, mission=None, dataset=None, table=None, columns=None, width=None, height=None, intersect='OVERLAPS', most_centered=False): """ @@ -47,7 +49,7 @@ def query_region(self, *, coordinate=None, where=None, mission=None, Parameters ---------- - coordinate : str, `astropy.coordinates` object + coordinates : str, `astropy.coordinates` object Gives the position of the center of the box if performing a box search. If it is a string, then it must be a valid argument to `~astropy.coordinates.SkyCoord`. Required if ``where`` is absent. @@ -97,7 +99,7 @@ def query_region(self, *, coordinate=None, where=None, mission=None, A table containing the results of the query """ response = self.query_region_async( - coordinate=coordinate, where=where, mission=mission, + coordinates=coordinates, where=where, mission=mission, dataset=dataset, table=table, columns=columns, width=width, height=height, intersect=intersect, most_centered=most_centered) @@ -106,7 +108,8 @@ def query_region(self, *, coordinate=None, where=None, mission=None, return Table.read(response.text, format='ipac', guess=False) - def query_region_sia(self, *, coordinate=None, mission=None, + @deprecated_renamed_argument("coordinate", "coordinates", since="0.4.12") + def query_region_sia(self, *, coordinates=None, mission=None, dataset=None, table=None, width=None, height=None, intersect='OVERLAPS', most_centered=False): @@ -115,7 +118,7 @@ def query_region_sia(self, *, coordinate=None, mission=None, details. The returned table will include a list of URLs. """ response = self.query_region_async( - coordinate=coordinate, mission=mission, + coordinates=coordinates, mission=mission, dataset=dataset, table=table, width=width, height=height, intersect=intersect, most_centered=most_centered, action='sia') @@ -126,7 +129,8 @@ def query_region_sia(self, *, coordinate=None, mission=None, return commons.parse_votable( response.text).get_first_table().to_table() - def query_region_async(self, *, coordinate=None, where=None, mission=None, dataset=None, + @deprecated_renamed_argument("coordinate", "coordinates", since="0.4.12") + def query_region_async(self, *, coordinates=None, where=None, mission=None, dataset=None, table=None, columns=None, width=None, height=None, action='search', intersect='OVERLAPS', most_centered=False): """ @@ -143,7 +147,7 @@ def query_region_async(self, *, coordinate=None, where=None, mission=None, datas Parameters ---------- - coordinate : str, `astropy.coordinates` object + coordinates : str, `astropy.coordinates` object Gives the position of the center of the box if performing a box search. If it is a string, then it must be a valid argument to `~astropy.coordinates.SkyCoord`. Required if ``where`` is absent. @@ -198,9 +202,9 @@ def query_region_async(self, *, coordinate=None, where=None, mission=None, datas The HTTP response returned from the service """ - if coordinate is None and where is None: + if coordinates is None and where is None: raise InvalidQueryError( - 'At least one of `coordinate` or `where` is required') + 'At least one of `coordinates` or `where` is required') intersect = intersect.upper() if intersect not in ('COVERS', 'ENCLOSED', 'CENTER', 'OVERLAPS'): @@ -224,8 +228,8 @@ def query_region_async(self, *, coordinate=None, where=None, mission=None, datas if most_centered: args['mcen'] = '1' - if coordinate is not None: - c = commons.parse_coordinates(coordinate).transform_to(coord.ICRS) + if coordinates is not None: + c = commons.parse_coordinates(coordinates).transform_to(coord.ICRS) args['POS'] = '{0},{1}'.format(c.ra.deg, c.dec.deg) if width and height: args['SIZE'] = '{0},{1}'.format( diff --git a/astroquery/ipac/irsa/ibe/tests/test_ibe.py b/astroquery/ipac/irsa/ibe/tests/test_ibe.py index c5051b4a28..c535b92613 100644 --- a/astroquery/ipac/irsa/ibe/tests/test_ibe.py +++ b/astroquery/ipac/irsa/ibe/tests/test_ibe.py @@ -6,6 +6,7 @@ import pytest from astropy.table import Table from astropy.coordinates import SkyCoord +from astropy.utils.exceptions import AstropyDeprecationWarning import astropy.units as u from astroquery.utils.mocks import MockResponse @@ -82,12 +83,21 @@ def test_get_columns(patch_get): def test_ibe_pos(patch_get): table = Ibe.query_region( - coordinate=SkyCoord(148.969687 * u.deg, 69.679383 * u.deg), + coordinates=SkyCoord(148.969687 * u.deg, 69.679383 * u.deg), where='expid <= 43010') assert isinstance(table, Table) assert len(table) == 21 +def test_ibe_pos_deprecated_coordinate(patch_get): + with pytest.warns(AstropyDeprecationWarning): + table = Ibe.query_region( + coordinate=SkyCoord(148.969687 * u.deg, 69.679383 * u.deg), + where='expid <= 43010') + assert isinstance(table, Table) + assert len(table) == 21 + + def test_ibe_field_id(patch_get): table = Ibe.query_region( where="ptffield = 4808 and filter='R'") diff --git a/astroquery/ipac/irsa/ibe/tests/test_ibe_remote.py b/astroquery/ipac/irsa/ibe/tests/test_ibe_remote.py index 8bb919e9f1..fc3a0d28c5 100644 --- a/astroquery/ipac/irsa/ibe/tests/test_ibe_remote.py +++ b/astroquery/ipac/irsa/ibe/tests/test_ibe_remote.py @@ -13,7 +13,7 @@ @pytest.mark.remote_data def test_ibe_pos(): table = ibe.Ibe.query_region( - coordinate=SkyCoord(148.969687 * u.deg, 69.679383 * u.deg), + coordinates=SkyCoord(148.969687 * u.deg, 69.679383 * u.deg), where='expid <= 43010') assert isinstance(table, Table) assert len(table) == 21 diff --git a/astroquery/noirlab/core.py b/astroquery/noirlab/core.py index a52744067b..7d33be5ec3 100644 --- a/astroquery/noirlab/core.py +++ b/astroquery/noirlab/core.py @@ -6,6 +6,7 @@ """ import astropy.io.fits as fits import astropy.table +from astropy.utils.decorators import deprecated_renamed_argument from ..query import BaseQuery from ..exceptions import RemoteServiceError from . import conf @@ -144,7 +145,8 @@ def _service_metadata(self, hdu=False, cache=True): response = self._request('GET', url, timeout=self.TIMEOUT, cache=cache) return response.json() - def query_region(self, coordinate, *, radius=0.1, hdu=False, cache=True, async_=False): + @deprecated_renamed_argument("coordinate", "coordinates", since="0.4.12") + def query_region(self, coordinates, *, radius=0.1, hdu=False, cache=True, async_=False): """Query for NOIRLab observations by region of the sky. Given a sky coordinate and radius, returns a `~astropy.table.Table` @@ -152,7 +154,7 @@ def query_region(self, coordinate, *, radius=0.1, hdu=False, cache=True, async_= Parameters ---------- - coordinate : :class:`str` or `~astropy.coordinates` object + coordinates : :class:`str` or `~astropy.coordinates` object The target region which to search. It may be specified as a string or as the appropriate `~astropy.coordinates` object. radius : :class:`float` or :class:`str` or `~astropy.units.Quantity` object, optional @@ -173,7 +175,7 @@ def query_region(self, coordinate, *, radius=0.1, hdu=False, cache=True, async_= A table containing the results. """ self._validate_version() - ra, dec = coordinate.to_string('decimal').split() + ra, dec = coordinates.to_string('decimal').split() url = f'{self.sia_url(hdu=hdu)}?POS={ra},{dec}&SIZE={radius}&VERB=3&format=json' response = self._request('GET', url, timeout=self.TIMEOUT, cache=cache) if async_: diff --git a/astroquery/noirlab/tests/test_noirlab.py b/astroquery/noirlab/tests/test_noirlab.py index 05c50ecd4a..c85a963952 100644 --- a/astroquery/noirlab/tests/test_noirlab.py +++ b/astroquery/noirlab/tests/test_noirlab.py @@ -6,6 +6,7 @@ import pytest from astropy import units as u from astropy.coordinates import SkyCoord +from astropy.utils.exceptions import AstropyDeprecationWarning from ...utils.mocks import MockResponse from ...exceptions import RemoteServiceError from .. import NOIRLab @@ -68,7 +69,7 @@ def test_query_region(patch_request, hdu, radius): It is OK if more files have been added to the remote Archive. """ c = SkyCoord(ra=10.625*u.degree, dec=41.2*u.degree, frame='icrs') - r = NOIRLab.query_region(c, radius=radius, hdu=hdu) + r = NOIRLab.query_region(coordinates=c, radius=radius, hdu=hdu) actual = set(r['md5sum'].tolist()) if hdu: expected = exp.query_region_2 @@ -77,6 +78,16 @@ def test_query_region(patch_request, hdu, radius): assert expected.issubset(actual) +def test_query_region_deprecated_coordinate(patch_request): + """The old ``coordinate`` keyword should still work but emit a deprecation warning. + """ + c = SkyCoord(ra=10.625*u.degree, dec=41.2*u.degree, frame='icrs') + with pytest.warns(AstropyDeprecationWarning): + r = NOIRLab.query_region(coordinate=c, radius='0.1') + actual = set(r['md5sum'].tolist()) + assert exp.query_region_1.issubset(actual) + + @pytest.mark.parametrize('hdu', [(False,), (True,)]) def test_core_fields(patch_request, hdu): """List the available CORE fields. diff --git a/astroquery/noirlab/tests/test_noirlab_remote.py b/astroquery/noirlab/tests/test_noirlab_remote.py index 2bda39bc66..cc1b6e4349 100644 --- a/astroquery/noirlab/tests/test_noirlab_remote.py +++ b/astroquery/noirlab/tests/test_noirlab_remote.py @@ -36,7 +36,7 @@ def test_query_region(hdu, radius): """ conf.timeout = 300 c = SkyCoord(ra=10.625*u.degree, dec=41.2*u.degree, frame='icrs') - r = NOIRLab().query_region(c, radius=radius, hdu=hdu) + r = NOIRLab().query_region(coordinates=c, radius=radius, hdu=hdu) actual = set(r['md5sum'].tolist()) if hdu: expected = exp.query_region_2 diff --git a/docs/esa/euclid/euclid.rst b/docs/esa/euclid/euclid.rst index cad80ee9c4..a52f11304f 100644 --- a/docs/esa/euclid/euclid.rst +++ b/docs/esa/euclid/euclid.rst @@ -143,7 +143,7 @@ the "mer_catalogue" and its outcome is restricted to 50 rows. >>> import astropy.units as u >>> coord = SkyCoord("17h51m07.4s +65d31m50.8s", frame='icrs') >>> radius = u.Quantity(0.5, u.deg) - >>> job = Euclid.cone_search(coordinate=coord, radius=radius, columns="*", async_job=True) # doctest: +IGNORE_WARNINGS + >>> job = Euclid.cone_search(coordinates=coord, radius=radius, columns="*", async_job=True) # doctest: +IGNORE_WARNINGS INFO: Query finished. [astroquery.utils.tap.core] >>> cone_results = job.get_results() >>> print(f"Found {len(cone_results)} results") @@ -163,7 +163,7 @@ that the name is recognised by the Simbad, VizieR, or NED services. >>> radius = u.Quantity(0.2, u.deg) >>> Euclid.ROW_LIMIT = -1 - >>> job = Euclid.cone_search(coordinate='NGC 6505', radius=radius, table_name="sedm.calibrated_frame", ra_column_name="ra", dec_column_name="dec", async_job=True, columns = ['ra', 'dec', 'datalabs_path', 'file_path', 'file_name', 'observation_id', 'instrument_name']) + >>> job = Euclid.cone_search(coordinates='NGC 6505', radius=radius, table_name="sedm.calibrated_frame", ra_column_name="ra", dec_column_name="dec", async_job=True, columns = ['ra', 'dec', 'datalabs_path', 'file_path', 'file_name', 'observation_id', 'instrument_name']) INFO: Query finished. [astroquery.utils.tap.core] >>> res = job.get_results() >>> print(f"* Found {len(res)} results") @@ -375,7 +375,7 @@ Download the cutout... .. doctest-skip:: >>> file_path = f"{res['file_path'][0]}/{res['file_name'][0]}" - >>> cutout_out = Euclid.get_cutout(file_path=file_path, coordinate='NGC 6505', radius= 0.1 * u.arcmin, output_file='ngc6505_cutout_mer.fits') + >>> cutout_out = Euclid.get_cutout(file_path=file_path, coordinates='NGC 6505', radius= 0.1 * u.arcmin, output_file='ngc6505_cutout_mer.fits') >>> cutout_out = cutout_out[0] ... and inspect its content: diff --git a/docs/esa/jwst/jwst.rst b/docs/esa/jwst/jwst.rst index 8e6535aa15..377b678a28 100644 --- a/docs/esa/jwst/jwst.rst +++ b/docs/esa/jwst/jwst.rst @@ -101,7 +101,7 @@ service degradation. >>> coord = SkyCoord(ra=53, dec=-27, unit=(u.degree, u.degree), frame='icrs') >>> width = u.Quantity(5, u.deg) >>> height = u.Quantity(5, u.deg) - >>> result = Jwst.query_region(coordinate=coord, width=width, height=height) + >>> result = Jwst.query_region(coordinates=coord, width=width, height=height) >>> result # doctest: +IGNORE_OUTPUT dist observationid ... ------------------ ------------------------------ ... @@ -129,7 +129,7 @@ service degradation. >>> >>> coord = SkyCoord(ra=53, dec=-27, unit=(u.degree, u.degree), frame='icrs') >>> radius = u.Quantity(5.0, u.deg) - >>> j = Jwst.cone_search(coordinate=coord, radius=radius, async_job=True) + >>> j = Jwst.cone_search(coordinates=coord, radius=radius, async_job=True) INFO: Query finished. [astroquery.utils.tap.core] >>> result = j.get_results() >>> result # doctest: +IGNORE_OUTPUT diff --git a/docs/esasky/esasky.rst b/docs/esasky/esasky.rst index 04fc06c597..37a49e5717 100644 --- a/docs/esasky/esasky.rst +++ b/docs/esasky/esasky.rst @@ -182,7 +182,7 @@ value for the radius of the region. For instance to query region around M51 in t >>> from astroquery.esasky import ESASky >>> import astropy.units as u - >>> result = ESASky.query_region_catalogs(coordinate="M51", radius=10 * u.arcmin, catalogs=["HSC", "XMM-OM"]) + >>> result = ESASky.query_region_catalogs(coordinates="M51", radius=10 * u.arcmin, catalogs=["HSC", "XMM-OM"]) To search in all available catalogs you can write ``"all"`` instead of a catalog name. The same thing will happen if you don't write any catalog name. @@ -190,8 +190,8 @@ In the same manner, the radius can be specified with either a string or any `~as .. doctest-remote-data:: - >>> result = ESASky.query_region_catalogs(coordinate="M51", radius=10 * u.arcmin, catalogs="all") - >>> result = ESASky.query_region_catalogs(coordinate="M51", radius="10 arcmin") + >>> result = ESASky.query_region_catalogs(coordinates="M51", radius=10 * u.arcmin, catalogs="all") + >>> result = ESASky.query_region_catalogs(coordinates="M51", radius="10 arcmin") To see the result: @@ -228,8 +228,8 @@ you write this: .. doctest-remote-data:: - >>> result = ESASky.query_region_maps(coordinate="M51", radius=10 * u.arcmin, missions="all") - >>> result = ESASky.query_region_spectra(coordinate="M51", radius=10 * u.arcmin, missions="all") + >>> result = ESASky.query_region_maps(coordinates="M51", radius=10 * u.arcmin, missions="all") + >>> result = ESASky.query_region_spectra(coordinates="M51", radius=10 * u.arcmin, missions="all") The parameters are interchangeable in the same way as in :meth:`~astroquery.esasky.ESASkyClass.query_region_catalogs`. @@ -306,7 +306,7 @@ position, radius and missions. .. Skip testing examples with with hard-wired download dir values .. doctest-remote-data:: - >>> table_list = ESASky.query_region_maps(coordinate="V* HT Aqr", radius="15 arcmin", missions=['Herschel', 'ISO-IR']) + >>> table_list = ESASky.query_region_maps(coordinates="V* HT Aqr", radius="15 arcmin", missions=['Herschel', 'ISO-IR']) >>> images = ESASky.get_maps(query_table_list=table_list, download_dir="/home/user/esasky") # doctest: +SKIP This example is equivalent to: @@ -341,7 +341,7 @@ or .. doctest-remote-data:: - >>> table_list = ESASky.query_region_spectra(coordinate="Gaia DR3 4512810408088819712", radius="6.52 arcmin", + >>> table_list = ESASky.query_region_spectra(coordinates="Gaia DR3 4512810408088819712", radius="6.52 arcmin", ... missions=['Herschel', 'XMM-NEWTON']) >>> spectra = ESASky.get_spectra_from_table(query_table_list=table_list, download_dir="/home/user/esasky") # doctest: +SKIP dict: { @@ -357,7 +357,7 @@ Here is another example for Herschel, since it is a bit special: .. doctest-remote-data:: >>> from astroquery.esasky import ESASky - >>> result = ESASky.query_region_spectra(coordinate='[SMB88] 6327', radius='1 arcmin', missions=['HERSCHEL']) + >>> result = ESASky.query_region_spectra(coordinates='[SMB88] 6327', radius='1 arcmin', missions=['HERSCHEL']) >>> herschel_result = result['HERSCHEL'] >>> herschel_result['observation_id', 'target_name', 'instrument', 'observing_mode_name', 'band', 'duration'].pprint() observation_id target_name instrument ... band duration diff --git a/docs/gaia/gaia.rst b/docs/gaia/gaia.rst index 6066b6aefd..f2bbd37be4 100644 --- a/docs/gaia/gaia.rst +++ b/docs/gaia/gaia.rst @@ -102,7 +102,7 @@ degrees around an specific point in RA/Dec coordinates. The results are sorted b >>> coord = SkyCoord(ra=280, dec=-60, unit=(u.degree, u.degree), frame='icrs') >>> width = u.Quantity(0.1, u.deg) >>> height = u.Quantity(0.1, u.deg) - >>> r = Gaia.query_object_async(coordinate=coord, width=width, height=height) + >>> r = Gaia.query_object_async(coordinates=coord, width=width, height=height) INFO: Query finished. [astroquery.utils.tap.core] >>> r.pprint(max_lines=12, max_width=130) dist solution_id designation ... ebpminrp_gspphot_upper libname_gspphot @@ -123,7 +123,7 @@ Queries return a limited number of rows controlled by ``Gaia.ROW_LIMIT``. To cha .. doctest-remote-data:: >>> Gaia.ROW_LIMIT = 8 - >>> r = Gaia.query_object_async(coordinate=coord, width=width, height=height) + >>> r = Gaia.query_object_async(coordinates=coord, width=width, height=height) INFO: Query finished. [astroquery.utils.tap.core] >>> r.pprint(max_width=140) dist solution_id designation ... ebpminrp_gspphot_lower ebpminrp_gspphot_upper libname_gspphot @@ -143,7 +143,7 @@ To return an unlimited number of rows set ``Gaia.ROW_LIMIT`` to -1. .. doctest-remote-data:: >>> Gaia.ROW_LIMIT = -1 - >>> r = Gaia.query_object_async(coordinate=coord, width=width, height=height) + >>> r = Gaia.query_object_async(coordinates=coord, width=width, height=height) INFO: Query finished. [astroquery.utils.tap.core] >>> r.pprint(max_lines=12, max_width=140) dist solution_id designation ... ebpminrp_gspphot_lower ebpminrp_gspphot_upper libname_gspphot From 8c8b76717df6d8352f3080d8219f80bee2325bf2 Mon Sep 17 00:00:00 2001 From: "Adam Ginsburg (keflavich)" Date: Wed, 10 Jun 2026 17:17:48 +0200 Subject: [PATCH 4/4] Loop over multiple coordinates in single-position query methods Resolution of the singular/plural question for the 'coordinates' rename: instead of renaming scalar-only services back to singular, give them real multi-coordinate support. The new astroquery.utils.multicoord.support_multiple_coordinates decorator lets a single-position query method accept a list of coordinates or a non-scalar SkyCoord by running one query per position. Table results are stacked with a query_index column mapping rows to inputs; TableList results merge per key; anything else returns as a list in input order. Requests go through a bounded worker pool with a minimum spacing between submissions. A survey of the affected archives (ESA/ESAC, ALMA, IRSA, HEASARC, NOIRLab) found no published request-rate limits, so the defaults are set conservatively (3 parallel requests, >=0.3 s apart, i.e. ~3 requests/s aggregate) -- below every published limit elsewhere (e.g. MAST's 5 req/s, SIMBAD's 6-10 q/s ban threshold) and below the parallelism the archives' own tooling uses. Both knobs are configurable via astroquery.utils.multicoord.conf. Applied to gaia, esa.euclid, alma, esa.hsa, esa.jwst, esasky, heasarc, ipac.irsa.ibe, and noirlab. ogle already supported lists natively. For alma, an explicit sync query_region now exists (async_to_sync skips it), which also fixes in-place mutation of a user-supplied payload dict in repeated calls. Co-Authored-By: Claude Fable 5 --- CHANGES.rst | 32 +++ astroquery/alma/core.py | 56 ++++++ astroquery/alma/tests/test_alma.py | 13 ++ astroquery/esa/euclid/core.py | 13 +- astroquery/esa/euclid/tests/test_euclidtap.py | 17 ++ astroquery/esa/hsa/core.py | 15 +- astroquery/esa/hsa/tests/test_hsa.py | 12 ++ astroquery/esa/jwst/core.py | 14 +- astroquery/esa/jwst/tests/test_jwsttap.py | 25 +++ astroquery/esasky/core.py | 22 ++- astroquery/esasky/tests/test_esasky.py | 18 ++ astroquery/gaia/core.py | 27 ++- astroquery/gaia/tests/test_gaiatap.py | 21 ++ astroquery/heasarc/core.py | 7 + astroquery/heasarc/tests/test_heasarc.py | 22 +++ astroquery/ipac/irsa/ibe/core.py | 20 +- astroquery/ipac/irsa/ibe/tests/test_ibe.py | 10 + astroquery/noirlab/core.py | 7 + astroquery/noirlab/tests/test_noirlab.py | 12 ++ astroquery/utils/multicoord.py | 186 ++++++++++++++++++ astroquery/utils/tests/test_multicoord.py | 151 ++++++++++++++ docs/utils.rst | 43 ++++ 22 files changed, 729 insertions(+), 14 deletions(-) create mode 100644 astroquery/utils/multicoord.py create mode 100644 astroquery/utils/tests/test_multicoord.py diff --git a/CHANGES.rst b/CHANGES.rst index bea6bcf64b..b73e166f6b 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -66,6 +66,8 @@ esa.euclid ``latest``. [#3601] - The ``coordinate`` keyword of ``query_object``, ``cone_search``, and ``get_cutout`` is deprecated in favor of ``coordinates`` for consistency with the rest of astroquery. [#3609] +- ``query_object`` and ``cone_search`` now also accept multiple coordinates (a list, or a non-scalar + ``SkyCoord``); one query is run per position and the results are combined. [#3609] vizier @@ -94,18 +96,25 @@ alma - The ``coordinate`` keyword of ``query_region`` and ``query_region_async`` is deprecated in favor of ``coordinates`` for consistency with the rest of astroquery. [#3609] +- ``query_region`` now also accepts multiple coordinates (a list, or a non-scalar ``SkyCoord``); + one query is run per position and the results are stacked into a single table with a + ``query_index`` column. [#3609] esa.hsa ^^^^^^^ - The ``coordinate`` keyword of ``query_observations`` and ``query_region`` is deprecated in favor of ``coordinates`` for consistency with the rest of astroquery. [#3609] +- ``query_observations`` and ``query_region`` now also accept multiple coordinates (a list, or a + non-scalar ``SkyCoord``); one query is run per position and the results are combined. [#3609] esa.jwst ^^^^^^^^ - The ``coordinate`` keyword of ``query_region`` and ``cone_search`` is deprecated in favor of ``coordinates`` for consistency with the rest of astroquery. [#3609] +- ``query_region`` and ``cone_search`` now also accept multiple coordinates (a list, or a non-scalar + ``SkyCoord``); one query is run per position and the results are combined. [#3609] esasky ^^^^^^ @@ -113,6 +122,9 @@ esasky - The ``position`` keyword of ``query_region_maps``, ``query_region_catalogs``, and ``query_region_spectra`` is deprecated in favor of ``coordinates`` for consistency with the rest of astroquery. [#3609] +- ``query_region_maps``, ``query_region_catalogs``, and ``query_region_spectra`` now also accept + multiple coordinates (a list, or a non-scalar ``SkyCoord``); one query is run per position and the + per-mission tables are stacked with a ``query_index`` column. [#3609] gaia ^^^^ @@ -120,24 +132,37 @@ gaia - The ``coordinate`` keyword of ``query_object``, ``query_object_async``, ``cone_search``, and ``cone_search_async`` is deprecated in favor of ``coordinates`` for consistency with the rest of astroquery. [#3609] +- ``query_object``, ``query_object_async``, ``cone_search``, and ``cone_search_async`` now also + accept multiple coordinates (a list, or a non-scalar ``SkyCoord``); one query is run per position + and the results are combined (stacked tables, or a list of jobs for the cone-search methods). + [#3609] heasarc ^^^^^^^ - The ``position`` keyword of ``query_region`` is deprecated in favor of ``coordinates`` for consistency with the rest of astroquery. [#3609] +- ``query_region`` now also accepts multiple coordinates (a list, or a non-scalar ``SkyCoord``); + one query is run per position and the results are stacked into a single table with a + ``query_index`` column. [#3609] ipac.irsa.ibe ^^^^^^^^^^^^^ - The ``coordinate`` keyword of ``query_region``, ``query_region_sia``, and ``query_region_async`` is deprecated in favor of ``coordinates`` for consistency with the rest of astroquery. [#3609] +- ``query_region`` and ``query_region_sia`` now also accept multiple coordinates (a list, or a + non-scalar ``SkyCoord``); one query is run per position and the results are stacked into a single + table with a ``query_index`` column. [#3609] noirlab ^^^^^^^ - The ``coordinate`` keyword of ``query_region`` is deprecated in favor of ``coordinates`` for consistency with the rest of astroquery. [#3609] +- ``query_region`` now also accepts multiple coordinates (a list, or a non-scalar ``SkyCoord``); + one query is run per position and the results are stacked into a single table with a + ``query_index`` column. [#3609] ogle ^^^^ @@ -291,6 +316,13 @@ Infrastructure, Utility and Other Changes and Additions - Workaround upstream bug when caching a response using pyvo. [#3586] +- New ``astroquery.utils.multicoord.support_multiple_coordinates`` decorator: single-position + query methods decorated with it accept a list of coordinates or a non-scalar ``SkyCoord`` and + loop over the positions with bounded, rate-limited parallelism. The defaults (3 parallel + requests, at least 0.3 s between submissions) are deliberately conservative — none of the + affected archives publish request-rate limits — and are configurable via + ``astroquery.utils.multicoord.conf``. [#3609] + utils.tap ^^^^^^^^^ diff --git a/astroquery/alma/core.py b/astroquery/alma/core.py index 279280eae6..bff365082e 100644 --- a/astroquery/alma/core.py +++ b/astroquery/alma/core.py @@ -26,6 +26,7 @@ from ..exceptions import LoginError from ..utils import commons +from ..utils.multicoord import support_multiple_coordinates from ..utils.process_asyncs import async_to_sync from ..query import BaseQuery, QueryWithLogin, BaseVOQuery from .tapsql import (_gen_pos_sql, _gen_str_sql, _gen_numeric_sql, @@ -548,6 +549,61 @@ def query_region_async(self, coordinates, radius, *, public=True, payload=payload, enhanced_results=enhanced_results, **kwargs) + @deprecated_renamed_argument("coordinate", "coordinates", since="0.4.12") + @support_multiple_coordinates() + def query_region(self, coordinates, radius, *, public=True, + science=True, payload=None, enhanced_results=False, + verbose=False, **kwargs): + """ + Query the ALMA archive with a source name and radius. + + Multiple positions can be queried at once by passing a list of + coordinates (or coordinate strings) or a vector + `~astropy.coordinates.SkyCoord`: one query is run per position and + the results are stacked into a single table with a ``query_index`` + column mapping each row back to the input position. + + Parameters + ---------- + coordinates : str / `astropy.coordinates` + the identifier or coordinates around which to query. A list of + coordinates or a vector `~astropy.coordinates.SkyCoord` triggers + one query per position. + radius : str / `~astropy.units.Quantity`, optional + the radius of the region + public : bool + True to return only public datasets, False to return private only, + None to return both + science : bool + True to return only science datasets, False to return only + calibration, None to return both + payload : dict + Dictionary of additional keywords. See `help`. + enhanced_results : bool + True to return a table with quantities instead of just values. It + also returns the footprints as `regions` objects. + verbose : bool + Whether to show warnings when parsing the result. + + Returns + ------- + table : A `~astropy.table.Table` object. + """ + if payload is not None: + # do not mutate the caller's dict; query_region_async appends the + # position to payload['ra_dec'] in place, which would otherwise + # accumulate positions across the calls of a multi-coordinate query + payload = dict(payload) + response = self.query_region_async(coordinates, radius, public=public, + science=science, payload=payload, + enhanced_results=enhanced_results, + **kwargs) + if kwargs.get('get_query_payload'): + return response + result = self._parse_result(response, verbose=verbose) + self.table = result + return result + def query_async(self, payload, *, public=True, science=True, legacy_columns=False, get_query_payload=False, maxrec=None, enhanced_results=False, **kwargs): diff --git a/astroquery/alma/tests/test_alma.py b/astroquery/alma/tests/test_alma.py index afe63b7c1c..c2759fa0cd 100644 --- a/astroquery/alma/tests/test_alma.py +++ b/astroquery/alma/tests/test_alma.py @@ -378,6 +378,19 @@ def test_query_region_coordinate_deprecated(): assert old_payload == new_payload +def test_query_region_multiple_coordinates(): + # a list of coordinates runs one query per position; with + # ``get_query_payload`` a list of per-position payloads is returned + alma = Alma() + alma._get_dataarchive_url = Mock() + payloads = alma.query_region(['1 2', '3 4'], radius=1*u.deg, + get_query_payload=True) + assert isinstance(payloads, list) + assert len(payloads) == 2 + assert "CIRCLE('ICRS',1.0,2.0,1.0)" in payloads[0] + assert "CIRCLE('ICRS',3.0,4.0,1.0)" in payloads[1] + + @pytest.mark.filterwarnings("ignore::astropy.utils.exceptions.AstropyUserWarning") def test_enhanced_table(): pytest.importorskip('regions') diff --git a/astroquery/esa/euclid/core.py b/astroquery/esa/euclid/core.py index 0bf9e702dc..84df3be1b4 100644 --- a/astroquery/esa/euclid/core.py +++ b/astroquery/esa/euclid/core.py @@ -29,6 +29,7 @@ from astroquery.utils import commons from astroquery.utils.tap import TapPlus from astroquery.utils.tap import taputils +from ...utils.multicoord import support_multiple_coordinates from . import conf @@ -385,6 +386,7 @@ def launch_job_async(self, query, *, name=None, dump_to_file=False, output_file= log.error(f'Query failed: {query}, {str(exx)}') @deprecated_renamed_argument("coordinate", "coordinates", since="0.4.12") + @support_multiple_coordinates() def query_object(self, coordinates, *, radius=None, width=None, height=None, async_job=False, verbose=False, columns=None): """ @@ -393,7 +395,10 @@ def query_object(self, coordinates, *, radius=None, width=None, height=None, Parameters ---------- coordinates : astropy.coordinate, mandatory - coordinates center point + coordinates center point. A list of coordinates or a non-scalar + `~astropy.coordinates.SkyCoord` runs one query per position and + the resulting tables are stacked, with a ``query_index`` column + mapping each row back to the input position. radius : astropy.units, required if no 'width' nor 'height' are provided radius (deg) width : astropy.units, required if no 'radius' is provided @@ -521,6 +526,7 @@ def __cone_search(self, coordinates, radius, *, table_name=None, ra_column_name= return job @deprecated_renamed_argument("coordinate", "coordinates", since="0.4.12") + @support_multiple_coordinates() def cone_search(self, coordinates, radius, *, table_name=None, ra_column_name=None, @@ -538,7 +544,10 @@ def cone_search(self, coordinates, radius, *, Parameters ---------- coordinates : astropy.coordinate, mandatory - coordinates center point + coordinates center point. A list of coordinates or a non-scalar + `~astropy.coordinates.SkyCoord` runs one query per position; since + this method returns a job object, a list of jobs (one per position, + in input order) is returned when multiple positions are given. radius : astropy.units, mandatory radius table_name : str, optional, default the table defined for the selected environment diff --git a/astroquery/esa/euclid/tests/test_euclidtap.py b/astroquery/esa/euclid/tests/test_euclidtap.py index 510d32f6e0..e31a534b5e 100644 --- a/astroquery/esa/euclid/tests/test_euclidtap.py +++ b/astroquery/esa/euclid/tests/test_euclidtap.py @@ -28,6 +28,7 @@ from astroquery.esa.euclid.core import EuclidClass from astroquery.esa.euclid.core import conf from astroquery.utils.commons import ASTROPY_LT_7_1_1 +from astroquery.utils.multicoord import conf as multicoord_conf from astroquery.utils.tap.conn.tests.DummyConnHandler import DummyConnHandler from astroquery.utils.tap.conn.tests.DummyResponse import DummyResponse from astroquery.utils.tap.core import TapPlus, Tap @@ -266,6 +267,22 @@ def test_query_object_radius(column_attrs, mock_querier): assert table[colname].attrs_equal(attrs) +def test_query_object_multiple_coordinates(column_attrs, mock_querier): + coords = SkyCoord(ra=[60.3372780005097, 61.0], dec=[-49.93184727724773, -49.0], + unit=(u.degree, u.degree), frame='icrs') + # Serial execution: the dummy connection handler is not thread-safe. + with multicoord_conf.set_temp("max_parallel_queries", 1), \ + multicoord_conf.set_temp("min_request_interval", 0): + table = mock_querier.query_object(coordinates=coords, radius=RADIUS) + + assert table is not None + # One 3-row mock result per input position, stacked into a single table. + assert len(table) == 6 + assert list(table["query_index"]) == [0, 0, 0, 1, 1, 1] + for colname, attrs in column_attrs.items(): + assert table[colname].attrs_equal(attrs) + + def test_query_object_deprecated_coordinate_keyword(mock_querier): coord = SkyCoord(ra=60.3372780005097, dec=-49.93184727724773, unit=(u.degree, u.degree), frame='icrs') with pytest.warns(AstropyDeprecationWarning, match='"coordinate" was deprecated'): diff --git a/astroquery/esa/hsa/core.py b/astroquery/esa/hsa/core.py index b433e7997d..05783c731f 100644 --- a/astroquery/esa/hsa/core.py +++ b/astroquery/esa/hsa/core.py @@ -9,6 +9,7 @@ from astropy import units as u from astropy.utils.decorators import deprecated_renamed_argument from astroquery.utils import commons +from astroquery.utils.multicoord import support_multiple_coordinates from astroquery import log from astroquery.exceptions import LoginError from astroquery.query import BaseQuery @@ -382,6 +383,7 @@ def get_columns(self, table_name, *, only_names=True, verbose=False): return columns @deprecated_renamed_argument("coordinate", "coordinates", since="0.4.12") + @support_multiple_coordinates() def query_observations(self, coordinates, radius, *, n_obs=10, **kwargs): """ Get the observation IDs from a given region @@ -389,7 +391,11 @@ def query_observations(self, coordinates, radius, *, n_obs=10, **kwargs): Parameters ---------- coordinates : string / `astropy.coordinates` - the identifier or coordinates around which to query + the identifier or coordinates around which to query. + A list of coordinates or a vector `~astropy.coordinates.SkyCoord` + triggers one query per position; the resulting tables are stacked + into a single table with a ``query_index`` column mapping each row + back to the corresponding input position. radius : int / `~astropy.units.Quantity` the radius of the region n_obs : int, optional @@ -404,6 +410,7 @@ def query_observations(self, coordinates, radius, *, n_obs=10, **kwargs): return self.query_region(coordinates, radius, n_obs=n_obs, columns="observation_id", **kwargs) @deprecated_renamed_argument("coordinate", "coordinates", since="0.4.12") + @support_multiple_coordinates() def query_region(self, coordinates, radius, *, n_obs=10, columns='*', **kwargs): """ Get the observation metadata from a given region @@ -411,7 +418,11 @@ def query_region(self, coordinates, radius, *, n_obs=10, columns='*', **kwargs): Parameters ---------- coordinates : string / `astropy.coordinates` - the identifier or coordinates around which to query + the identifier or coordinates around which to query. + A list of coordinates or a vector `~astropy.coordinates.SkyCoord` + triggers one query per position; the resulting tables are stacked + into a single table with a ``query_index`` column mapping each row + back to the corresponding input position. radius : int / `~astropy.units.Quantity` the radius of the region n_obs : int, optional diff --git a/astroquery/esa/hsa/tests/test_hsa.py b/astroquery/esa/hsa/tests/test_hsa.py index fd2d09897a..5a0bba8c86 100644 --- a/astroquery/esa/hsa/tests/test_hsa.py +++ b/astroquery/esa/hsa/tests/test_hsa.py @@ -69,6 +69,18 @@ def test_query_region(self): hsa.query_region(**parameters) dummyTapHandler.check_call("query_region", parameters) + def test_query_region_multiple_coordinates(self): + coords = SkyCoord(ra=[100.2417, 101.2417]*u.degree, + dec=[9.895, 10.895]*u.degree, frame='icrs') + hsa = HSAClass(self.get_dummy_tap_handler()) + result = hsa.query_region(coordinates=coords, radius=0.5) + # The dummy TAP handler's launch_job returns a Job with no results + # and no output file, so each per-position query returns None and + # the combined result is a plain list with one entry per position. + assert isinstance(result, list) + assert len(result) == 2 + assert all(entry is None for entry in result) + def test_query_region_deprecated_coordinate(self): c = SkyCoord(ra=100.2417*u.degree, dec=9.895*u.degree, frame='icrs') hsa = HSAClass(self.get_dummy_tap_handler()) diff --git a/astroquery/esa/jwst/core.py b/astroquery/esa/jwst/core.py index f28e10dd30..8a4dd2b566 100644 --- a/astroquery/esa/jwst/core.py +++ b/astroquery/esa/jwst/core.py @@ -33,6 +33,7 @@ from astroquery.query import BaseQuery from astroquery.simbad import Simbad from astroquery.utils import commons +from astroquery.utils.multicoord import support_multiple_coordinates from astroquery.utils.tap import TapPlus from astroquery.vizier import Vizier from . import conf @@ -235,6 +236,7 @@ def list_async_jobs(self, *, verbose=False): return self.__jwsttap.list_async_jobs(verbose=verbose) @deprecated_renamed_argument("coordinate", "coordinates", since="0.4.12") + @support_multiple_coordinates() def query_region(self, coordinates, *, radius=None, width=None, @@ -254,7 +256,11 @@ def query_region(self, coordinates, *, Parameters ---------- coordinates : astropy.coordinates, mandatory - coordinates center point + coordinates center point. A list of coordinates or a vector + `~astropy.coordinates.SkyCoord` may also be provided, in which + case one query is run per position and the resulting tables are + stacked, with a ``query_index`` column mapping each row back to + the corresponding input position radius : astropy.units, required if no 'width' nor 'height' are provided radius (deg) @@ -360,6 +366,7 @@ def query_region(self, coordinates, *, return job.get_results() @deprecated_renamed_argument("coordinate", "coordinates", since="0.4.12") + @support_multiple_coordinates() def cone_search(self, coordinates, radius, *, observation_id=None, cal_level="Top", @@ -381,7 +388,10 @@ def cone_search(self, coordinates, radius, *, Parameters ---------- coordinates : astropy.coordinates, mandatory - coordinates center point + coordinates center point. A list of coordinates or a vector + `~astropy.coordinates.SkyCoord` may also be provided, in which + case one query is run per position; in that case a list of Job + objects is returned, in input order radius : astropy.units, mandatory radius observation_id : str, optional, default None diff --git a/astroquery/esa/jwst/tests/test_jwsttap.py b/astroquery/esa/jwst/tests/test_jwsttap.py index 07f43510d7..c5ed088c82 100644 --- a/astroquery/esa/jwst/tests/test_jwsttap.py +++ b/astroquery/esa/jwst/tests/test_jwsttap.py @@ -31,6 +31,7 @@ from astroquery.esa.jwst.tests.DummyTapHandler import DummyTapHandler from astroquery.ipac.ned import Ned from astroquery.simbad import SimbadClass +from astroquery.utils.multicoord import conf as multicoord_conf from astroquery.utils.tap.conn.tests.DummyConnHandler import DummyConnHandler from astroquery.utils.tap.conn.tests.DummyResponse import DummyResponse from astroquery.utils.tap.core import TapPlus @@ -381,6 +382,30 @@ def test_query_region(self): None, np.int32) + def test_query_region_multiple_coordinates(self): + connHandler = DummyConnHandler() + tapplus = TapPlus(url="http://test:1111/tap", connhandler=connHandler) + tap = JwstClass(tap_plus_handler=tapplus, show_messages=False) + + # The query contains decimals: force default response + responseLaunchJob = DummyResponse(200) + responseLaunchJob.set_data(method='POST', body=JOB_DATA) + connHandler.set_default_response(responseLaunchJob) + + sc = SkyCoord(ra=[29.0, 30.0], dec=[15.0, 16.0], + unit=(u.degree, u.degree), frame='icrs') + radius = Quantity(1, u.deg) + with multicoord_conf.set_temp('max_parallel_queries', 1), \ + multicoord_conf.set_temp('min_request_interval', 0): + table = tap.query_region(sc, radius=radius) + assert isinstance(table, Table) + # The dummy connection handler returns the same 3-row job data for + # each of the two per-position queries, so the rows are doubled. + assert len(table) == 6, f"Wrong job results (num rows). Expected: {6}, found {len(table)}" + assert 'query_index' in table.colnames + assert set(table['query_index']) == {0, 1} + assert list(table['query_index']) == [0, 0, 0, 1, 1, 1] + def test_query_region_async(self): connHandler = DummyConnHandler() tapplus = TapPlus(url="http://test:1111/tap", connhandler=connHandler) diff --git a/astroquery/esasky/core.py b/astroquery/esasky/core.py index 8caace0ffb..afdb30ea86 100644 --- a/astroquery/esasky/core.py +++ b/astroquery/esasky/core.py @@ -23,6 +23,7 @@ from ..utils.tap.core import TapPlus from ..utils import commons from ..utils import async_to_sync +from ..utils.multicoord import support_multiple_coordinates from . import conf from .. import version from astropy.coordinates.name_resolve import sesame_database @@ -645,6 +646,7 @@ def get_images_sso(self, *, sso_name=None, sso_type="ALL", table_list=None, miss return maps @deprecated_renamed_argument("position", "coordinates", since="0.4.12") + @support_multiple_coordinates() def query_region_maps(self, coordinates, radius, missions=__ALL_STRING, get_query_payload=False, cache=True, row_limit=DEFAULT_ROW_LIMIT, verbose=False): """ @@ -656,7 +658,11 @@ def query_region_maps(self, coordinates, radius, missions=__ALL_STRING, get_quer ---------- coordinates : str or `astropy.coordinates` object Can either be a string of the location, eg 'M51', or the coordinates - of the object. + of the object. A list of positions or a vector + `~astropy.coordinates.SkyCoord` may also be given, in which case one + query is run per position and the per-mission tables are stacked, + with a ``query_index`` column identifying the input position each + row came from. radius : str or `~astropy.units.Quantity` The radius of a region. missions : str or list, optional @@ -714,6 +720,7 @@ def query_region_maps(self, coordinates, radius, missions=__ALL_STRING, get_quer return commons.TableList(query_result) @deprecated_renamed_argument("position", "coordinates", since="0.4.12") + @support_multiple_coordinates() def query_region_catalogs(self, coordinates, radius, catalogs=__ALL_STRING, row_limit=DEFAULT_ROW_LIMIT, get_query_payload=False, cache=True, verbose=False): """ @@ -725,7 +732,11 @@ def query_region_catalogs(self, coordinates, radius, catalogs=__ALL_STRING, row_ ---------- coordinates : str or `astropy.coordinates` object Can either be a string of the location, eg 'M51', or the coordinates - of the object. + of the object. A list of positions or a vector + `~astropy.coordinates.SkyCoord` may also be given, in which case one + query is run per position and the per-mission tables are stacked, + with a ``query_index`` column identifying the input position each + row came from. radius : str or `~astropy.units.Quantity` The radius of a region. catalogs : str or list, optional @@ -784,6 +795,7 @@ def query_region_catalogs(self, coordinates, radius, catalogs=__ALL_STRING, row_ return commons.TableList(query_result) @deprecated_renamed_argument("position", "coordinates", since="0.4.12") + @support_multiple_coordinates() def query_region_spectra(self, coordinates, radius, missions=__ALL_STRING, row_limit=DEFAULT_ROW_LIMIT, get_query_payload=False, cache=True, verbose=False): """ @@ -795,7 +807,11 @@ def query_region_spectra(self, coordinates, radius, missions=__ALL_STRING, row_l ---------- coordinates : str or `astropy.coordinates` object Can either be a string of the location, eg 'M51', or the coordinates - of the object. + of the object. A list of positions or a vector + `~astropy.coordinates.SkyCoord` may also be given, in which case one + query is run per position and the per-mission tables are stacked, + with a ``query_index`` column identifying the input position each + row came from. radius : str or `~astropy.units.Quantity` The radius of a region. missions : str or list, optional diff --git a/astroquery/esasky/tests/test_esasky.py b/astroquery/esasky/tests/test_esasky.py index 0cb7d83113..a15f3defd3 100644 --- a/astroquery/esasky/tests/test_esasky.py +++ b/astroquery/esasky/tests/test_esasky.py @@ -34,3 +34,21 @@ def test_query_region_deprecated_position(monkeypatch, method_name, descriptor_g assert result == expected assert "QUERY" in result["XMM"] + + +def test_query_region_maps_multiple_coordinates(monkeypatch): + # A list of coordinates should run one query per position and, with + # get_query_payload=True, return a list of payloads in input order. + monkeypatch.setattr(ESASky, "_get_observation_info", lambda: FAKE_DESCRIPTORS) + coordinates = [SkyCoord(ra=202.469, dec=47.195, unit="deg"), + SkyCoord(ra=10.684, dec=41.269, unit="deg")] + + result = ESASky.query_region_maps(coordinates=coordinates, radius="5 arcmin", + missions=["XMM"], get_query_payload=True) + + assert isinstance(result, list) + assert len(result) == 2 + for payload, coord in zip(result, coordinates): + query = payload["XMM"]["QUERY"] + assert str(coord.ra.deg) in query + assert str(coord.dec.deg) in query diff --git a/astroquery/gaia/core.py b/astroquery/gaia/core.py index 3a7eca24ab..a73c84ecc5 100644 --- a/astroquery/gaia/core.py +++ b/astroquery/gaia/core.py @@ -28,6 +28,7 @@ from astroquery import log from astroquery.utils import commons +from astroquery.utils.multicoord import support_multiple_coordinates from astroquery.utils.tap import TapPlus from astroquery.utils.tap import taputils from . import conf @@ -555,6 +556,7 @@ def __query_object(self, coordinates, *, radius=None, width=None, height=None, return job.get_results() @deprecated_renamed_argument("coordinate", "coordinates", since="0.4.12") + @support_multiple_coordinates() def query_object(self, coordinates, *, radius=None, width=None, height=None, verbose=False, columns=(), get_query_payload=False): """Launches a synchronous cone search for the input search radius or the box on the sky, sorted by angular @@ -564,7 +566,11 @@ def query_object(self, coordinates, *, radius=None, width=None, height=None, ver Parameters ---------- coordinates : str or astropy.coordinates, mandatory - coordinates center point + coordinates center point. A list of coordinates or a non-scalar + `~astropy.coordinates.SkyCoord` is also accepted, in which case + one query is run per position and the results are stacked into a + single table with a ``query_index`` column mapping rows back to + the input positions. radius : str or astropy.units if no 'width'/'height' are provided radius (deg) width : str or astropy.units if no 'radius' is provided @@ -587,6 +593,7 @@ def query_object(self, coordinates, *, radius=None, width=None, height=None, ver verbose=verbose, columns=columns, get_query_payload=get_query_payload) @deprecated_renamed_argument("coordinate", "coordinates", since="0.4.12") + @support_multiple_coordinates() def query_object_async(self, coordinates, *, radius=None, width=None, height=None, verbose=False, columns=()): """Launches an asynchronous cone search for the input search radius or the box on the sky, sorted by angular separation @@ -595,7 +602,11 @@ def query_object_async(self, coordinates, *, radius=None, width=None, height=Non Parameters ---------- coordinates : str or astropy.coordinates, mandatory - coordinates center point + coordinates center point. A list of coordinates or a non-scalar + `~astropy.coordinates.SkyCoord` is also accepted, in which case + one query is run per position and the results are stacked into a + single table with a ``query_index`` column mapping rows back to + the input positions. radius : str or astropy.units if no 'width'/'height' are provided radius width : str or astropy.units if no 'radius' is provided @@ -709,6 +720,7 @@ def __cone_search(self, coordinates, radius, *, table_name=None, dump_to_file=dump_to_file) @deprecated_renamed_argument("coordinate", "coordinates", since="0.4.12") + @support_multiple_coordinates() def cone_search(self, coordinates, *, radius=None, table_name=None, ra_column_name=MAIN_GAIA_TABLE_RA, @@ -724,7 +736,10 @@ def cone_search(self, coordinates, *, radius=None, Parameters ---------- coordinates : str or astropy.coordinate, mandatory - coordinates center point + coordinates center point. A list of coordinates or a non-scalar + `~astropy.coordinates.SkyCoord` is also accepted, in which case + one query is run per position and a list of jobs is returned, in + input order. radius : str or astropy.units, mandatory radius table_name : str, optional, default main gaia table name doing the cone search against @@ -766,6 +781,7 @@ def cone_search(self, coordinates, *, radius=None, get_query_payload=get_query_payload) @deprecated_renamed_argument("coordinate", "coordinates", since="0.4.12") + @support_multiple_coordinates() def cone_search_async(self, coordinates, *, radius=None, table_name=None, ra_column_name=MAIN_GAIA_TABLE_RA, @@ -779,7 +795,10 @@ def cone_search_async(self, coordinates, *, radius=None, Parameters ---------- coordinates : str or astropy.coordinate, mandatory - coordinates center point + coordinates center point. A list of coordinates or a non-scalar + `~astropy.coordinates.SkyCoord` is also accepted, in which case + one query is run per position and a list of jobs is returned, in + input order. radius : str or astropy.units, mandatory radius table_name : str, optional, default main gaia table name doing the cone search against diff --git a/astroquery/gaia/tests/test_gaiatap.py b/astroquery/gaia/tests/test_gaiatap.py index 034d31da18..275edb050e 100644 --- a/astroquery/gaia/tests/test_gaiatap.py +++ b/astroquery/gaia/tests/test_gaiatap.py @@ -578,6 +578,27 @@ def test_cone_search_precision(mock_querier): ) +def test_query_object_multiple_coordinates(mock_querier): + coords = SkyCoord(ra=[19, 42] * u.deg, dec=[20, -5] * u.deg, frame="icrs") + queries = mock_querier.query_object(coords, width=12 * u.deg, height=10 * u.deg, get_query_payload=True) + assert isinstance(queries, list) + assert len(queries) == 2 + assert queries[0] != queries[1] + for query, coord in zip(queries, coords): + assert query == mock_querier.query_object(coord, width=12 * u.deg, height=10 * u.deg, + get_query_payload=True) + + +def test_cone_search_multiple_coordinates(mock_querier): + coords = SkyCoord(ra=[19, 42] * u.deg, dec=[20, -5] * u.deg, frame="icrs") + queries = mock_querier.cone_search(coords, radius=RADIUS, get_query_payload=True) + assert isinstance(queries, list) + assert len(queries) == 2 + assert queries[0] != queries[1] + for query, coord in zip(queries, coords): + assert query == mock_querier.cone_search(coord, radius=RADIUS, get_query_payload=True) + + def test_cone_search_sync(column_attrs, mock_querier): assert mock_querier.USE_NAMES_OVER_IDS is True diff --git a/astroquery/heasarc/core.py b/astroquery/heasarc/core.py index 4eff64a28b..f04541b81b 100644 --- a/astroquery/heasarc/core.py +++ b/astroquery/heasarc/core.py @@ -14,6 +14,7 @@ from astroquery import log from ..query import BaseQuery, BaseVOQuery from ..utils import commons, parse_coordinates +from ..utils.multicoord import support_multiple_coordinates from ..exceptions import InvalidQueryError, NoResultsWarning from . import conf @@ -423,6 +424,7 @@ def _parse_constraints(self, column_filters): True, True, True, False) ) @deprecated_renamed_argument("position", "coordinates", since="0.4.12") + @support_multiple_coordinates() def query_region(self, coordinates=None, catalog=None, radius=None, *, spatial='cone', width=None, polygon=None, column_filters=None, add_offset=False, get_query_payload=False, columns=None, cache=False, @@ -437,6 +439,11 @@ def query_region(self, coordinates=None, catalog=None, radius=None, *, Gives the position of the center of the cone or box if performing a cone or box search. Required if spatial is ``'cone'`` or ``'box'``. Ignored if spatial is ``'polygon'`` or ``'all-sky'``. + A list of coordinates or a vector `~astropy.coordinates.SkyCoord` + may also be given, in which case one query is run per position + and the results are stacked into a single table with a + ``query_index`` column mapping each row back to the input + position. catalog : str The catalog to query. To list the available catalogs, use :meth:`~astroquery.heasarc.HeasarcClass.list_catalogs`. diff --git a/astroquery/heasarc/tests/test_heasarc.py b/astroquery/heasarc/tests/test_heasarc.py index 4e5118b82f..8157977368 100644 --- a/astroquery/heasarc/tests/test_heasarc.py +++ b/astroquery/heasarc/tests/test_heasarc.py @@ -125,6 +125,28 @@ def test_query_region_cone(coordinates, radius, offset): assert ",0.0333" in query +def test_query_region_multiple_coordinates(): + coordinates = SkyCoord([182.63, 10.68] * u.deg, [39.40, 41.27] * u.deg) + queries = Heasarc.query_region( + coordinates, + catalog="suzamaster", + spatial="cone", + radius=2 * u.arcmin, + columns="*", + get_query_payload=True, + ) + + assert isinstance(queries, list) + assert len(queries) == 2 + assert "CIRCLE('ICRS',182.63" in queries[0] + assert ",39.4" in queries[0] + assert "CIRCLE('ICRS',10.68" in queries[1] + assert ",41.27" in queries[1] + for query in queries: + assert "SELECT * FROM suzamaster WHERE CONTAINS(POINT('ICRS',ra,dec)," in query + assert ",0.0333" in query + + @pytest.mark.parametrize("coordinates", OBJ_LIST) @pytest.mark.parametrize("width", SIZE_LIST) def test_query_region_box(coordinates, width): diff --git a/astroquery/ipac/irsa/ibe/core.py b/astroquery/ipac/irsa/ibe/core.py index f1b0b0cf33..8049f3ddae 100644 --- a/astroquery/ipac/irsa/ibe/core.py +++ b/astroquery/ipac/irsa/ibe/core.py @@ -21,6 +21,8 @@ from astroquery.utils import commons from astroquery.ipac.irsa.ibe import conf +from ....utils.multicoord import support_multiple_coordinates + __all__ = ['Ibe', 'IbeClass'] @@ -32,6 +34,7 @@ class IbeClass(BaseQuery): TIMEOUT = conf.timeout @deprecated_renamed_argument("coordinate", "coordinates", since="0.4.12") + @support_multiple_coordinates() def query_region(self, *, coordinates=None, where=None, mission=None, dataset=None, table=None, columns=None, width=None, height=None, intersect='OVERLAPS', most_centered=False): @@ -53,6 +56,11 @@ def query_region(self, *, coordinates=None, where=None, mission=None, Gives the position of the center of the box if performing a box search. If it is a string, then it must be a valid argument to `~astropy.coordinates.SkyCoord`. Required if ``where`` is absent. + A list of coordinates (or coordinate strings), or a vector + `~astropy.coordinates.SkyCoord`, may also be given, in which case + one query is run per position and the results are stacked into a + single table with a ``query_index`` column mapping each row back + to the corresponding input position. where : str SQL-like query string. Required if ``coordinates`` is absent. mission : str @@ -96,7 +104,10 @@ def query_region(self, *, coordinates=None, where=None, mission=None, Returns ------- table : `~astropy.table.Table` - A table containing the results of the query + A table containing the results of the query. If multiple + coordinates were given, the per-position tables are stacked and a + ``query_index`` column identifies the input position each row + corresponds to. """ response = self.query_region_async( coordinates=coordinates, where=where, mission=mission, @@ -109,6 +120,7 @@ def query_region(self, *, coordinates=None, where=None, mission=None, return Table.read(response.text, format='ipac', guess=False) @deprecated_renamed_argument("coordinate", "coordinates", since="0.4.12") + @support_multiple_coordinates() def query_region_sia(self, *, coordinates=None, mission=None, dataset=None, table=None, width=None, height=None, intersect='OVERLAPS', @@ -116,6 +128,12 @@ def query_region_sia(self, *, coordinates=None, mission=None, """ Query using simple image access protocol. See ``query_region`` for details. The returned table will include a list of URLs. + + As in ``query_region``, ``coordinates`` may be a list of coordinates + (or coordinate strings) or a vector `~astropy.coordinates.SkyCoord`, + in which case one query is run per position and the results are + stacked into a single table with a ``query_index`` column mapping + each row back to the corresponding input position. """ response = self.query_region_async( coordinates=coordinates, mission=mission, diff --git a/astroquery/ipac/irsa/ibe/tests/test_ibe.py b/astroquery/ipac/irsa/ibe/tests/test_ibe.py index c535b92613..a53bf88529 100644 --- a/astroquery/ipac/irsa/ibe/tests/test_ibe.py +++ b/astroquery/ipac/irsa/ibe/tests/test_ibe.py @@ -98,6 +98,16 @@ def test_ibe_pos_deprecated_coordinate(patch_get): assert len(table) == 21 +def test_ibe_pos_multiple_coordinates(patch_get): + coords = [SkyCoord(148.969687 * u.deg, 69.679383 * u.deg), + SkyCoord(148.969687 * u.deg, 69.679383 * u.deg)] + table = Ibe.query_region(coordinates=coords, where='expid <= 43010') + assert isinstance(table, Table) + assert 'query_index' in table.colnames + assert set(table['query_index']) == {0, 1} + assert len(table) == 42 + + def test_ibe_field_id(patch_get): table = Ibe.query_region( where="ptffield = 4808 and filter='R'") diff --git a/astroquery/noirlab/core.py b/astroquery/noirlab/core.py index 7d33be5ec3..2a89582d7d 100644 --- a/astroquery/noirlab/core.py +++ b/astroquery/noirlab/core.py @@ -9,6 +9,7 @@ from astropy.utils.decorators import deprecated_renamed_argument from ..query import BaseQuery from ..exceptions import RemoteServiceError +from ..utils.multicoord import support_multiple_coordinates from . import conf @@ -146,6 +147,7 @@ def _service_metadata(self, hdu=False, cache=True): return response.json() @deprecated_renamed_argument("coordinate", "coordinates", since="0.4.12") + @support_multiple_coordinates() def query_region(self, coordinates, *, radius=0.1, hdu=False, cache=True, async_=False): """Query for NOIRLab observations by region of the sky. @@ -157,6 +159,11 @@ def query_region(self, coordinates, *, radius=0.1, hdu=False, cache=True, async_ coordinates : :class:`str` or `~astropy.coordinates` object The target region which to search. It may be specified as a string or as the appropriate `~astropy.coordinates` object. + A list of coordinates or a vector `~astropy.coordinates.SkyCoord` + may also be given, in which case one query is run per position + and the results are stacked into a single table with a + ``query_index`` column identifying the input position each row + came from. radius : :class:`float` or :class:`str` or `~astropy.units.Quantity` object, optional Default 0.1 degrees. The string must be parsable by `~astropy.coordinates.Angle`. The diff --git a/astroquery/noirlab/tests/test_noirlab.py b/astroquery/noirlab/tests/test_noirlab.py index c85a963952..5d8fbf85ea 100644 --- a/astroquery/noirlab/tests/test_noirlab.py +++ b/astroquery/noirlab/tests/test_noirlab.py @@ -88,6 +88,18 @@ def test_query_region_deprecated_coordinate(patch_request): assert exp.query_region_1.issubset(actual) +def test_query_region_multiple_coordinates(patch_request): + """A vector SkyCoord should run one query per position and stack the results. + """ + c = SkyCoord(ra=[10.625, 20.5]*u.degree, dec=[41.2, -30.0]*u.degree, frame='icrs') + r = NOIRLab.query_region(coordinates=c, radius='0.1') + assert 'query_index' in r.colnames + assert set(r['query_index'].tolist()) == {0, 1} + assert len(r) == 2 * len(exp.query_region_1) + assert exp.query_region_1.issubset(set(r['md5sum'][r['query_index'] == 0].tolist())) + assert exp.query_region_1.issubset(set(r['md5sum'][r['query_index'] == 1].tolist())) + + @pytest.mark.parametrize('hdu', [(False,), (True,)]) def test_core_fields(patch_request, hdu): """List the available CORE fields. diff --git a/astroquery/utils/multicoord.py b/astroquery/utils/multicoord.py new file mode 100644 index 0000000000..2edda5b45e --- /dev/null +++ b/astroquery/utils/multicoord.py @@ -0,0 +1,186 @@ +# Licensed under a 3-clause BSD style license - see LICENSE.rst +""" +Support for looping single-position query methods over multiple coordinates. + +Most archive query methods accept a single sky position per request. The +`support_multiple_coordinates` decorator lets such a method transparently +accept a vector `~astropy.coordinates.SkyCoord` or a list of coordinates +(or coordinate strings): the method is called once per position, a few +requests at a time in parallel, and the per-position results are combined. + +The parallelism is deliberately conservative so that scripted use does not +overload archive servers; it can be tuned through +``astroquery.utils.multicoord.conf``. +""" +import functools +import inspect +import threading +import time +from concurrent.futures import ThreadPoolExecutor + +from astropy import config as _config +from astropy.coordinates import SkyCoord, BaseCoordinateFrame +from astropy.table import Table, vstack + +from .commons import TableList + +__all__ = ['support_multiple_coordinates', 'conf', 'Conf'] + + +class Conf(_config.ConfigNamespace): + """Configuration for queries looped over multiple coordinates.""" + + max_parallel_queries = _config.ConfigItem( + 3, + 'Maximum number of requests sent in parallel when a query method is ' + 'called with multiple coordinates. Keep this small: archive servers ' + 'are a shared resource, and aggressive parallelism can degrade the ' + 'service or get a client blocked. Do not raise this above what the ' + 'archive documentation explicitly allows.', + cfgtype='integer') + + min_request_interval = _config.ConfigItem( + 0.3, + 'Minimum delay (seconds) between submitting consecutive requests of ' + 'a multi-coordinate query, across all parallel workers. This bounds ' + 'the aggregate request rate at 1/min_request_interval regardless of ' + 'how many workers run in parallel. Set to 0 to disable.', + cfgtype='float') + + +conf = Conf() + + +class _Throttle: + """Enforce a minimum interval between request submissions (thread-safe).""" + + def __init__(self, interval): + self._interval = interval + self._lock = threading.Lock() + self._next_time = None + + def wait(self): + if self._interval <= 0: + return + with self._lock: + now = time.monotonic() + if self._next_time is None or now >= self._next_time: + delay = 0. + self._next_time = now + self._interval + else: + delay = self._next_time - now + self._next_time += self._interval + if delay > 0: + time.sleep(delay) + + +def _coordinate_list(value): + """Return a list of single positions if ``value`` holds several, else None. + + Lists and tuples are interpreted as one entry per position; a + non-scalar (vector) `~astropy.coordinates.SkyCoord` or coordinate frame + is split into its scalar elements. Anything else (a string, a scalar + coordinate, None) is treated as a single position. + """ + if isinstance(value, (list, tuple)): + if len(value) == 0: + raise ValueError("An empty list of coordinates was provided.") + return list(value) + if (isinstance(value, (SkyCoord, BaseCoordinateFrame)) + and not value.isscalar): + return list(value) + return None + + +def _stack_tables(tables): + if all('query_index' not in tbl.colnames for tbl in tables): + for index, tbl in enumerate(tables): + if len(tbl.colnames) > 0: + tbl['query_index'] = index + return vstack(tables, metadata_conflicts='silent') + + +def _combine_results(results): + """Combine per-coordinate results into a single object where possible. + + Tables are stacked (gaining a ``query_index`` column identifying which + input position each row came from, unless a column of that name already + exists). `~astroquery.utils.TableList` results are merged key by key. + Any other result type is returned as a plain list, in input order. + """ + if all(isinstance(result, Table) for result in results): + return _stack_tables(results) + if all(isinstance(result, TableList) for result in results): + keys = [] + for result in results: + keys.extend(key for key in result.keys() if key not in keys) + merged = {} + for key in keys: + for index, result in enumerate(results): + if (key in result.keys() + and 'query_index' not in result[key].colnames + and len(result[key].colnames) > 0): + result[key]['query_index'] = index + merged[key] = vstack([result[key] for result in results + if key in result.keys()], + metadata_conflicts='silent') + return TableList(merged) + return list(results) + + +def support_multiple_coordinates(coord_arg='coordinates', max_workers=None): + """Allow a single-position query method to accept multiple coordinates. + + When the decorated method receives a vector + `~astropy.coordinates.SkyCoord` or a list of coordinates (or coordinate + strings) in its ``coord_arg`` argument, it is called once per position + and the results are combined: tables are stacked into one table with an + added ``query_index`` column mapping rows back to the input positions; + other return types come back as a list in input order. + + A bounded worker pool (``conf.max_parallel_queries``, default 3) issues + the requests, and consecutive request submissions are spaced by at least + ``conf.min_request_interval`` seconds in aggregate, to stay well below + archive rate limits. An exception in any single request propagates and + aborts the combined result. + + Parameters + ---------- + coord_arg : str + Name of the coordinate parameter of the wrapped method. + max_workers : int, optional + Per-method cap on parallel requests, overriding + ``conf.max_parallel_queries`` (use for services with stricter + documented limits). + """ + def decorator(func): + signature = inspect.signature(func) + if coord_arg not in signature.parameters: + raise TypeError(f"'{func.__name__}' has no '{coord_arg}' parameter") + + @functools.wraps(func) + def wrapper(*args, **kwargs): + bound = signature.bind(*args, **kwargs) + coords = _coordinate_list(bound.arguments.get(coord_arg)) + if coords is None: + return func(*args, **kwargs) + + nworkers = max_workers if max_workers is not None else conf.max_parallel_queries + nworkers = max(1, min(int(nworkers), len(coords))) + throttle = _Throttle(conf.min_request_interval) + + def run_one(coord): + rebound = signature.bind(*args, **kwargs) + rebound.arguments[coord_arg] = coord + throttle.wait() + return func(*rebound.args, **rebound.kwargs) + + if nworkers == 1: + results = [run_one(coord) for coord in coords] + else: + with ThreadPoolExecutor(max_workers=nworkers) as executor: + results = list(executor.map(run_one, coords)) + return _combine_results(results) + + return wrapper + return decorator diff --git a/astroquery/utils/tests/test_multicoord.py b/astroquery/utils/tests/test_multicoord.py new file mode 100644 index 0000000000..2bc3438fb9 --- /dev/null +++ b/astroquery/utils/tests/test_multicoord.py @@ -0,0 +1,151 @@ +# Licensed under a 3-clause BSD style license - see LICENSE.rst +import threading + +import pytest + +import astropy.units as u +from astropy.coordinates import SkyCoord +from astropy.table import Table +from astropy.utils.decorators import deprecated_renamed_argument +from astropy.utils.exceptions import AstropyDeprecationWarning + +from astroquery.utils.commons import TableList +from astroquery.utils.multicoord import support_multiple_coordinates, conf + + +COORDS = SkyCoord([10, 20, 30] * u.deg, [-10, 0, 10] * u.deg) + + +class DummyQuery: + """Single-position query class for exercising the decorator.""" + + def __init__(self): + self.lock = threading.Lock() + self.active = 0 + self.max_active = 0 + + def _track(self): + with self.lock: + self.active += 1 + self.max_active = max(self.max_active, self.active) + + def _untrack(self): + with self.lock: + self.active -= 1 + + @support_multiple_coordinates() + def query_region(self, coordinates, radius=1 * u.deg): + if not (isinstance(coordinates, str) or coordinates.isscalar): + raise TypeError("scalar input required") + self._track() + try: + ra = (coordinates if isinstance(coordinates, str) + else str(coordinates.ra.deg)) + result = Table({'ra': [ra], 'radius': [str(radius)]}) + finally: + self._untrack() + return result + + @support_multiple_coordinates(coord_arg='coordinates', max_workers=1) + def query_serial(self, coordinates): + self._track() + try: + with self.lock: + concurrent = self.active + finally: + self._untrack() + return Table({'concurrent': [concurrent]}) + + @support_multiple_coordinates() + def query_payload(self, coordinates, get_query_payload=False): + return {'POS': str(coordinates)} + + @support_multiple_coordinates() + def query_tablelist(self, coordinates): + return TableList({'mission': Table({'ra': [str(coordinates)]})}) + + +def test_scalar_passthrough(): + result = DummyQuery().query_region(COORDS[0]) + assert isinstance(result, Table) + assert len(result) == 1 + assert 'query_index' not in result.colnames + + +def test_string_passthrough(): + result = DummyQuery().query_region("10 -10") + assert len(result) == 1 + + +def test_vector_skycoord_stacks_in_order(): + result = DummyQuery().query_region(COORDS, radius=2 * u.deg) + assert isinstance(result, Table) + assert len(result) == 3 + assert list(result['query_index']) == [0, 1, 2] + assert list(result['ra']) == [str(c.ra.deg) for c in COORDS] + assert all(result['radius'] == str(2 * u.deg)) + + +def test_list_of_coordinates(): + result = DummyQuery().query_region([COORDS[0], COORDS[1]]) + assert len(result) == 2 + assert list(result['query_index']) == [0, 1] + + +def test_list_of_strings(): + result = DummyQuery().query_region(["10 -10", "20 0"]) + assert list(result['ra']) == ["10 -10", "20 0"] + + +def test_empty_list_raises(): + with pytest.raises(ValueError, match="empty list"): + DummyQuery().query_region([]) + + +def test_max_workers_one_is_serial(): + dummy = DummyQuery() + result = dummy.query_serial(list(COORDS)) + assert dummy.max_active == 1 + assert len(result) == 3 + + +def test_parallelism_is_bounded(): + dummy = DummyQuery() + coords = SkyCoord(range(1, 21) * u.deg, range(1, 21) * u.deg) + with conf.set_temp('max_parallel_queries', 2), \ + conf.set_temp('min_request_interval', 0): + dummy.query_region(coords) + assert dummy.max_active <= 2 + + +def test_non_table_results_return_list(): + result = DummyQuery().query_payload(list(COORDS[:2]), get_query_payload=True) + assert isinstance(result, list) + assert len(result) == 2 + assert all('POS' in payload for payload in result) + + +def test_tablelist_results_merge(): + result = DummyQuery().query_tablelist(list(COORDS[:2])) + assert isinstance(result, TableList) + assert len(result['mission']) == 2 + assert list(result['mission']['query_index']) == [0, 1] + + +def test_missing_coord_arg_raises_at_definition(): + with pytest.raises(TypeError, match="no 'coordinates' parameter"): + @support_multiple_coordinates() + def query(self, position): + pass + + +def test_composes_with_deprecated_renamed_argument(): + class Legacy: + @deprecated_renamed_argument("coordinate", "coordinates", since="0.4.12") + @support_multiple_coordinates() + def query_region(self, coordinates=None): + return Table({'ra': [str(coordinates)]}) + + with pytest.warns(AstropyDeprecationWarning): + result = Legacy().query_region(coordinate=["10 -10", "20 0"]) + assert len(result) == 2 diff --git a/docs/utils.rst b/docs/utils.rst index 83e82eb69d..8fbdcabd35 100644 --- a/docs/utils.rst +++ b/docs/utils.rst @@ -6,12 +6,55 @@ Astroquery utils (`astroquery.utils`) ************************************* +Querying multiple coordinates +============================= + +Several query methods that accept a single sky position per request (for +example ``Gaia.query_object``, ``Heasarc.query_region``, +``Alma.query_region``) also accept a vector +`~astropy.coordinates.SkyCoord` or a list of coordinates (or coordinate +strings). In that case astroquery submits one request per position and +combines the results: methods returning a `~astropy.table.Table` return a +single stacked table with an added ``query_index`` column mapping each row +back to the input position, while other return types come back as a list +in input order. + +.. code-block:: python + + from astropy.coordinates import SkyCoord + import astropy.units as u + from astroquery.heasarc import Heasarc + + coords = SkyCoord([182.6, 10.7] * u.deg, [39.4, 41.3] * u.deg) + result = Heasarc.query_region(coords, catalog='suzamaster', radius=2 * u.arcmin) + +The requests are issued through a small worker pool with a minimum spacing +between submissions, so that looped queries stay well below request rates +that could degrade the archive services. None of the affected archives +publish a hard rate limit, so the defaults are deliberately conservative; +they can be tuned through ``astroquery.utils.multicoord.conf``: + +.. code-block:: python + + from astroquery.utils.multicoord import conf + + conf.max_parallel_queries = 2 # parallel requests (default 3) + conf.min_request_interval = 1. # seconds between submissions (default 0.3) + +Please be considerate: archive servers are a shared resource, raising these +values can get a client blocked, and where a service offers a native +multi-position interface (for example a TAP table upload), that is always +preferable to a long client-side loop. + Reference/API ============= .. automodapi:: astroquery.utils :no-inheritance-diagram: +.. automodapi:: astroquery.utils.multicoord + :no-inheritance-diagram: + .. automodapi:: astroquery.utils.timer :no-inheritance-diagram: