Skip to content

Commit 9d659e7

Browse files
committed
Rename **kwargs, info to regenerate column file, parameter checking on collections
1 parent d3ecf0d commit 9d659e7

File tree

3 files changed

+71
-40
lines changed

3 files changed

+71
-40
lines changed

astroquery/mast/collections.py

Lines changed: 37 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
This module contains various methods for querying MAST collections such as catalogs.
77
"""
88

9+
import difflib
910
import warnings
1011
import os
1112
import time
@@ -60,7 +61,7 @@ def _parse_result(self, response, *, verbose=False):
6061

6162
@class_or_instance
6263
def query_region_async(self, coordinates, *, radius=0.2*u.deg, catalog="Hsc",
63-
version=None, pagesize=None, page=None, **kwargs):
64+
version=None, pagesize=None, page=None, **criteria):
6465
"""
6566
Given a sky position and radius, returns a list of catalog entries.
6667
See column documentation for specific catalogs `here <https://mast.stsci.edu/api/v0/pages.html>`__.
@@ -88,7 +89,7 @@ def query_region_async(self, coordinates, *, radius=0.2*u.deg, catalog="Hsc",
8889
Default None.
8990
Can be used to override the default behavior of all results being returned to obtain a
9091
specific page of results.
91-
**kwargs
92+
**criteria
9293
Other catalog-specific keyword args.
9394
These can be found in the (service documentation)[https://mast.stsci.edu/api/v0/_services.html]
9495
for specific catalogs. For example one can specify the magtype for an HSC search.
@@ -109,10 +110,18 @@ def query_region_async(self, coordinates, *, radius=0.2*u.deg, catalog="Hsc",
109110
'dec': coordinates.dec.deg,
110111
'radius': radius.deg}
111112

113+
# valid criteria keywords
114+
valid_criteria = []
115+
112116
# Determine API connection and service name
113117
if catalog.lower() in self._service_api_connection.SERVICES:
114118
self._current_connection = self._service_api_connection
115119
service = catalog
120+
121+
# adding additional user specified parameters
122+
for prop, value in criteria.items():
123+
params[prop] = value
124+
116125
else:
117126
self._current_connection = self._portal_api_connection
118127

@@ -125,19 +134,20 @@ def query_region_async(self, coordinates, *, radius=0.2*u.deg, catalog="Hsc",
125134
warnings.warn("Invalid HSC version number, defaulting to v3.", InputWarning)
126135
service = "Mast.Hsc.Db.v3"
127136

128-
self.catalog_limit = kwargs.get('nr', 50000)
129-
130137
# Hsc specific parameters (can be overridden by user)
131-
params['nr'] = 50000
132-
params['ni'] = 1
133-
params['magtype'] = 1
138+
self.catalog_limit = criteria.pop('nr', 50000)
139+
valid_criteria = ['nr', 'ni', 'magtype']
140+
params['nr'] = self.catalog_limit
141+
params['ni'] = criteria.pop('ni', 1)
142+
params['magtype'] = criteria.pop('magtype', 1)
134143

135144
elif catalog.lower() == "galex":
136145
service = "Mast.Galex.Catalog"
137-
self.catalog_limit = kwargs.get('maxrecords', 50000)
146+
self.catalog_limit = criteria.get('maxrecords', 50000)
138147

139148
# galex specific parameters (can be overridden by user)
140-
params['maxrecords'] = 50000
149+
valid_criteria = ['maxrecords']
150+
params['maxrecords'] = criteria.pop('maxrecords', 50000)
141151

142152
elif catalog.lower() == "gaia":
143153
if version == 1:
@@ -158,9 +168,16 @@ def query_region_async(self, coordinates, *, radius=0.2*u.deg, catalog="Hsc",
158168
service = "Mast.Catalogs." + catalog + ".Cone"
159169
self.catalog_limit = None
160170

161-
# adding additional user specified parameters
162-
for prop, value in kwargs.items():
163-
params[prop] = value
171+
# additional user-specified parameters are not valid
172+
if criteria:
173+
key = next(iter(criteria))
174+
closest_match = difflib.get_close_matches(key, valid_criteria, n=1)
175+
error_msg = (
176+
f"Filter '{key}' does not exist for catalog {catalog}. Did you mean '{closest_match[0]}'?"
177+
if closest_match
178+
else f"Filter '{key}' does not exist for catalog {catalog}."
179+
)
180+
raise InvalidQueryError(error_msg)
164181

165182
# Parameters will be passed as JSON objects only when accessing the PANSTARRS API
166183
use_json = catalog.lower() == 'panstarrs'
@@ -170,7 +187,7 @@ def query_region_async(self, coordinates, *, radius=0.2*u.deg, catalog="Hsc",
170187

171188
@class_or_instance
172189
def query_object_async(self, objectname, *, radius=0.2*u.deg, catalog="Hsc",
173-
pagesize=None, page=None, version=None, **kwargs):
190+
pagesize=None, page=None, version=None, **criteria):
174191
"""
175192
Given an object name, returns a list of catalog entries.
176193
See column documentation for specific catalogs `here <https://mast.stsci.edu/api/v0/pages.html>`__.
@@ -197,7 +214,7 @@ def query_object_async(self, objectname, *, radius=0.2*u.deg, catalog="Hsc",
197214
to obtain a specific page of results.
198215
version : int, optional
199216
Version number for catalogs that have versions. Default is highest version.
200-
**kwargs
217+
**criteria
201218
Catalog-specific keyword args.
202219
These can be found in the `service documentation <https://mast.stsci.edu/api/v0/_services.html>`__.
203220
for specific catalogs. For example one can specify the magtype for an HSC search.
@@ -215,7 +232,7 @@ def query_object_async(self, objectname, *, radius=0.2*u.deg, catalog="Hsc",
215232
version=version,
216233
pagesize=pagesize,
217234
page=page,
218-
**kwargs)
235+
**criteria)
219236

220237
@class_or_instance
221238
def query_criteria_async(self, catalog, *, pagesize=None, page=None, **criteria):
@@ -295,26 +312,25 @@ def query_criteria_async(self, catalog, *, pagesize=None, page=None, **criteria)
295312
if coordinates or objectname:
296313
service += ".Position"
297314
service += ".Rows" # Using the rowstore version of the query for speed
298-
filters = self._current_connection.build_filter_set("Mast.Catalogs.Tess.Cone",
299-
service, **criteria)
315+
column_config_name = "Mast.Catalogs.Tess.Cone"
300316
params["columns"] = "*"
301317
elif catalog.lower() == "ctl":
302318
service = "Mast.Catalogs.Filtered.Ctl"
303319
if coordinates or objectname:
304320
service += ".Position"
305321
service += ".Rows" # Using the rowstore version of the query for speed
306-
filters = self._current_connection.build_filter_set("Mast.Catalogs.Tess.Cone",
307-
service, **criteria)
322+
column_config_name = "Mast.Catalogs.Tess.Cone"
308323
params["columns"] = "*"
309324
elif catalog.lower() == "diskdetective":
310325
service = "Mast.Catalogs.Filtered.DiskDetective"
311326
if coordinates or objectname:
312327
service += ".Position"
313-
filters = self._current_connection.build_filter_set("Mast.Catalogs.Dd.Cone",
314-
service, **criteria)
328+
column_config_name = "Mast.Catalogs.Dd.Cone"
315329
else:
316330
raise InvalidQueryError("Criteria query not available for {}".format(catalog))
317331

332+
filters = self._current_connection.build_filter_set(column_config_name, service, **criteria)
333+
318334
if not filters:
319335
raise InvalidQueryError("At least one non-positional criterion must be supplied.")
320336
params["filters"] = filters

astroquery/mast/missions.py

Lines changed: 17 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ def _validate_criteria(self, **criteria):
7777
7878
Parameters
7979
----------
80-
**kwargs
80+
**criteria
8181
Keyword arguments representing criteria filters to apply.
8282
8383
Raises
@@ -102,7 +102,7 @@ def _validate_criteria(self, **criteria):
102102
raise InvalidQueryError(error_msg)
103103

104104
@class_or_instance
105-
def query_region_async(self, coordinates, *, radius=3*u.arcmin, limit=5000, offset=0, **kwargs):
105+
def query_region_async(self, coordinates, *, radius=3*u.arcmin, limit=5000, offset=0, **criteria):
106106
"""
107107
Given a sky position and radius, returns a list of matching dataset IDs.
108108
@@ -122,12 +122,11 @@ def query_region_async(self, coordinates, *, radius=3*u.arcmin, limit=5000, offs
122122
offset : int
123123
Optional and default is 0
124124
the number of records you wish to skip before selecting records.
125-
**kwargs
126-
Other mission-specific keyword args.
127-
Any invalid keys are ignored by the API.
128-
All valid key names can be found using `~astroquery.mast.missions.MastMissionsClass.get_column_list`
125+
**criteria
126+
Other mission-specific criteria arguments.
127+
All valid filters can be found using `~astroquery.mast.missions.MastMissionsClass.get_column_list`
129128
function.
130-
For example one can specify the output columns(select_cols) or use other filters(conditions)
129+
For example, one can specify the output columns(select_cols) or use other filters(conditions).
131130
132131
Returns
133132
-------
@@ -137,7 +136,7 @@ def query_region_async(self, coordinates, *, radius=3*u.arcmin, limit=5000, offs
137136
self.limit = limit
138137

139138
# Check that criteria arguments are valid
140-
self._validate_criteria(**kwargs)
139+
self._validate_criteria(**criteria)
141140

142141
# Put coordinates and radius into consistent format
143142
coordinates = commons.parse_coordinates(coordinates)
@@ -154,7 +153,7 @@ def query_region_async(self, coordinates, *, radius=3*u.arcmin, limit=5000, offs
154153

155154
params['conditions'] = []
156155
# adding additional user specified parameters
157-
for prop, value in kwargs.items():
156+
for prop, value in criteria.items():
158157
if prop not in self._search_option_fields:
159158
params['conditions'].append({prop: value})
160159
else:
@@ -189,12 +188,11 @@ def query_criteria_async(self, *, coordinates=None, objectname=None, radius=3*u.
189188
select_cols: list
190189
names of columns that will be included in the astropy table
191190
**criteria
192-
Criteria to apply. At least one non-positional criteria must be supplied.
191+
Criteria to apply. At least one non-positional criterion must be supplied.
193192
Valid criteria are coordinates, objectname, radius (as in
194193
`~astroquery.mast.missions.MastMissionsClass.query_region` and
195194
`~astroquery.mast.missions.MastMissionsClass.query_object` functions),
196195
and all fields listed in the column documentation for the mission being queried.
197-
Any invalid keys passed in criteria are ignored by the API.
198196
List of all valid fields that can be used to match results on criteria can be retrieved by calling
199197
`~astroquery.mast.missions.MastMissionsClass.get_column_list` function.
200198
@@ -234,7 +232,7 @@ def query_criteria_async(self, *, coordinates=None, objectname=None, radius=3*u.
234232
return self._service_api_connection.service_request_async(self.service, params, use_json=True)
235233

236234
@class_or_instance
237-
def query_object_async(self, objectname, *, radius=3*u.arcmin, limit=5000, offset=0, **kwargs):
235+
def query_object_async(self, objectname, *, radius=3*u.arcmin, limit=5000, offset=0, **criteria):
238236
"""
239237
Given an object name, returns a list of matching rows.
240238
@@ -253,11 +251,11 @@ def query_object_async(self, objectname, *, radius=3*u.arcmin, limit=5000, offse
253251
offset : int
254252
Optional and default is 0.
255253
the number of records you wish to skip before selecting records.
256-
**kwargs
257-
Mission-specific keyword args.
258-
Any invalid keys are ignored by the API.
259-
All valid keys can be found by calling `~astroquery.mast.missions.MastMissionsClass.get_column_list`
254+
**criteria
255+
Other mission-specific criteria arguments.
256+
All valid filters can be found using `~astroquery.mast.missions.MastMissionsClass.get_column_list`
260257
function.
258+
For example, one can specify the output columns(select_cols) or use other filters(conditions).
261259
262260
Returns
263261
-------
@@ -266,7 +264,7 @@ def query_object_async(self, objectname, *, radius=3*u.arcmin, limit=5000, offse
266264

267265
coordinates = utils.resolve_object(objectname)
268266

269-
return self.query_region_async(coordinates, radius=radius, limit=limit, offset=offset, **kwargs)
267+
return self.query_region_async(coordinates, radius=radius, limit=limit, offset=offset, **criteria)
270268

271269
@class_or_instance
272270
def get_column_list(self):
@@ -294,8 +292,8 @@ def get_column_list(self):
294292
# Create Table with parsed data
295293
col_table = Table(rows=rows, names=('name', 'data_type', 'description'))
296294
self.columns[self.mission] = col_table
297-
except Exception:
298-
raise Exception(f'Error occurred while trying to get column list for mission {self.mission}')
295+
except Exception as ex:
296+
raise RuntimeError(f'Error occurred while trying to get column list for mission {self.mission}: {ex}')
299297

300298
return self.columns[self.mission]
301299

astroquery/mast/tests/data/README.rst

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
===============
2+
MAST Test Data
3+
===============
4+
5+
This directory contains sample data that is used to mock functions in `~astroquery.mast.tests.test_mast.py`.
6+
7+
To generate `~astroquery.mast.tests.data.mission_columns.json`, use the following:
8+
9+
.. code-block:: python
10+
11+
>>> import json
12+
>>> from astroquery.mast import utils
13+
14+
>>> params = {'mission': 'hst'}
15+
>>> resp = utils._simple_request(f'https://mast.stsci.edu/search/util/api/v0.1/column_list', {'mission': 'hst'})
16+
>>> with open('mission_columns.json', 'w') as file:
17+
>>> json.dump(resp.json(), file, indent=4)

0 commit comments

Comments
 (0)