Skip to content

Commit fd2a9cc

Browse files
Clara Brasseurjaymedina
authored andcommitted
adding moving target tesscut and docs
1 parent 31a4164 commit fd2a9cc

File tree

3 files changed

+233
-97
lines changed

3 files changed

+233
-97
lines changed

astroquery/mast/cutouts.py

Lines changed: 116 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -104,10 +104,13 @@ def __init__(self):
104104
super().__init__()
105105

106106
services = {"sector": {"path": "sector"},
107-
"astrocut": {"path": "astrocut"}}
107+
"astrocut": {"path": "astrocut"},
108+
"mt_sector": {"path": "moving_target/sector"},
109+
"mt_astrocut": {"path": "moving_target/astrocut"}
110+
}
108111
self._service_api_connection.set_service_params(services, "tesscut")
109112

110-
def get_sectors(self, coordinates=None, radius=0*u.deg, objectname=None):
113+
def get_sectors(self, coordinates=None, radius=0*u.deg, objectname=None, moving_target=None, mt_type=None):
111114
"""
112115
Get a list of the TESS data sectors whose footprints intersect
113116
with the given search area.
@@ -117,36 +120,64 @@ def get_sectors(self, coordinates=None, radius=0*u.deg, objectname=None):
117120
coordinates : str or `astropy.coordinates` object, optional
118121
The target around which to search. It may be specified as a
119122
string or as the appropriate `astropy.coordinates` object.
120-
One and only one of coordinates and objectname must be supplied.
123+
One and only one of coordinates, objectname, and moving_target must be supplied.
121124
radius : str, float, or `~astropy.units.Quantity` object, optional
122125
Default 0 degrees.
123126
If supplied as a float degrees is the assumed unit.
124127
The string must be parsable by `~astropy.coordinates.Angle`. The
125128
appropriate `~astropy.units.Quantity` object from
126129
`astropy.units` may also be used.
130+
This argument is ignored if moving_target is supplied.
127131
objectname : str, optional
128132
The target around which to search, by name (objectname="M104")
129133
or TIC ID (objectname="TIC 141914082").
130-
One and only one of coordinates and objectname must be supplied.
134+
One and only one of coordinates, objectname, moving_target must be supplied.
135+
moving_target : str, optional
136+
The name or ID (as understood by the
137+
`JPL ephemerides service <https://ssd.jpl.nasa.gov/horizons.cgi>`__)
138+
of a moving target such as an asteroid or comet.
139+
One and only one of coordinates, objectname, and moving_target must be supplied.
140+
mt_type : str, optional
141+
The moving target type, valid inputs are majorbody and smallbody. If not supplied
142+
first majorbody is tried and then smallbody if a matching majorbody is not found.
143+
This argument is ignored unless moving_target is supplied.
131144
132145
Returns
133146
-------
134147
response : `~astropy.table.Table`
135-
Sector/camera/chip information for given coordinates/raduis.
148+
Sector/camera/chip information for given coordinates/objectname/moving_target.
136149
"""
137150

138-
# Get Skycoord object for coordinates/object
139-
coordinates = parse_input_location(coordinates, objectname)
151+
if moving_target:
140152

141-
# If radius is just a number we assume degrees
142-
radius = Angle(radius, u.deg)
153+
# Check only ony object designator has been passed in
154+
if objectname or coordinates:
155+
raise InvalidQueryError("Only one of objectname, coordinates, and moving_target may be specified.")
143156

144-
params = {"ra": coordinates.ra.deg,
145-
"dec": coordinates.dec.deg,
146-
"radius": radius.deg}
157+
params = {"obj_id": moving_target}
147158

148-
response = self._service_api_connection.service_request_async("sector", params)
149-
response.raise_for_status() # Raise any errors
159+
# Add optional parameter is present
160+
if mt_type:
161+
params["obj_type"] = mt_type
162+
163+
response = self._service_api_connection.service_request_async("mt_sector", params)
164+
165+
else:
166+
167+
# Get Skycoord object for coordinates/object
168+
coordinates = parse_input_location(coordinates, objectname)
169+
170+
# If radius is just a number we assume degrees
171+
radius = Angle(radius, u.deg)
172+
173+
params = {"ra": coordinates.ra.deg,
174+
"dec": coordinates.dec.deg,
175+
"radius": radius.deg}
176+
177+
response = self._service_api_connection.service_request_async("sector", params)
178+
179+
# Raise any errors
180+
response.raise_for_status()
150181

151182
sector_json = response.json()['results']
152183
sector_dict = {'sectorName': [],
@@ -164,7 +195,8 @@ def get_sectors(self, coordinates=None, radius=0*u.deg, objectname=None):
164195
warnings.warn("Coordinates are not in any TESS sector.", NoResultsWarning)
165196
return Table(sector_dict)
166197

167-
def download_cutouts(self, coordinates=None, size=5, sector=None, path=".", inflate=True, objectname=None):
198+
def download_cutouts(self, coordinates=None, size=5, sector=None, path=".", inflate=True,
199+
objectname=None, moving_target=None, mt_type=None):
168200
"""
169201
Download cutout target pixel file(s) around the given coordinates with indicated size.
170202
@@ -173,7 +205,7 @@ def download_cutouts(self, coordinates=None, size=5, sector=None, path=".", infl
173205
coordinates : str or `astropy.coordinates` object, optional
174206
The target around which to search. It may be specified as a
175207
string or as the appropriate `astropy.coordinates` object.
176-
One and only one of coordinates and objectname must be supplied.
208+
One and only one of coordinates, objectname, and moving_target must be supplied.
177209
size : int, array-like, `~astropy.units.Quantity`
178210
Optional, default 5 pixels.
179211
The size of the cutout array. If ``size`` is a scalar number or
@@ -198,27 +230,45 @@ def download_cutouts(self, coordinates=None, size=5, sector=None, path=".", infl
198230
objectname : str, optional
199231
The target around which to search, by name (objectname="M104")
200232
or TIC ID (objectname="TIC 141914082").
201-
One and only one of coordinates and objectname must be supplied.
233+
One and only one of coordinates, objectname, and moving_target must be supplied.
234+
moving_target : str, optional
235+
The name or ID (as understood by the
236+
`JPL ephemerides service <https://ssd.jpl.nasa.gov/horizons.cgi>`__)
237+
of a moving target such as an asteroid or comet.
238+
One and only one of coordinates, objectname, and moving_target must be supplied.
239+
mt_type : str, optional
240+
The moving target type, valid inputs are majorbody and smallbody. If not supplied
241+
first majorbody is tried and then smallbody if a matching majorbody is not found.
242+
This argument is ignored unless moving_target is supplied.
202243
203244
Returns
204245
-------
205246
response : `~astropy.table.Table`
206247
"""
207248

208-
# Get Skycoord object for coordinates/object
209-
coordinates = parse_input_location(coordinates, objectname)
249+
if moving_target:
250+
# Check only ony object designator has been passed in
251+
if objectname or coordinates:
252+
raise InvalidQueryError("Only one of objectname, coordinates, and moving_target may be specified.")
253+
254+
astrocut_request = f"moving_target/astrocut?obj_id={moving_target}"
255+
if mt_type:
256+
astrocut_request += f"&obj_type={mt_type}"
257+
else:
258+
# Get Skycoord object for coordinates/object
259+
coordinates = parse_input_location(coordinates, objectname)
260+
261+
astrocut_request = f"astrocut?ra={coordinates.ra.deg}&dec={coordinates.dec.deg}"
262+
263+
# Adding the arguments that are common between moving/still astrocut requests
210264
size_dict = _parse_cutout_size(size)
211-
212-
path = os.path.join(path, '')
213-
astrocut_request = "ra={}&dec={}&y={}&x={}&units={}".format(coordinates.ra.deg,
214-
coordinates.dec.deg,
215-
size_dict["y"],
216-
size_dict["x"],
217-
size_dict["units"])
265+
astrocut_request += f"&y={size_dict['y']}&x={size_dict['x']}&units={size_dict['units']}"
266+
218267
if sector:
219268
astrocut_request += "&sector={}".format(sector)
220269

221-
astrocut_url = self._service_api_connection.REQUEST_URL + "astrocut?" + astrocut_request
270+
astrocut_url = self._service_api_connection.REQUEST_URL + astrocut_request
271+
path = os.path.join(path, '')
222272
zipfile_path = "{}tesscut_{}.zip".format(path, time.strftime("%Y%m%d%H%M%S"))
223273
self._download_file(astrocut_url, zipfile_path)
224274

@@ -246,7 +296,8 @@ def download_cutouts(self, coordinates=None, size=5, sector=None, path=".", infl
246296
localpath_table['Local Path'] = [path+x for x in cutout_files]
247297
return localpath_table
248298

249-
def get_cutouts(self, coordinates=None, size=5, sector=None, objectname=None):
299+
def get_cutouts(self, coordinates=None, size=5, sector=None,
300+
objectname=None, moving_target=None, mt_type=None):
250301
"""
251302
Get cutout target pixel file(s) around the given coordinates with indicated size,
252303
and return them as a list of `~astropy.io.fits.HDUList` objects.
@@ -256,7 +307,7 @@ def get_cutouts(self, coordinates=None, size=5, sector=None, objectname=None):
256307
coordinates : str or `astropy.coordinates` object, optional
257308
The target around which to search. It may be specified as a
258309
string or as the appropriate `astropy.coordinates` object.
259-
One and only one of coordinates and objectname must be supplied.
310+
One and only one of coordinates, objectname, and moving_target must be supplied.
260311
size : int, array-like, `~astropy.units.Quantity`
261312
Optional, default 5 pixels.
262313
The size of the cutout array. If ``size`` is a scalar number or
@@ -272,24 +323,53 @@ def get_cutouts(self, coordinates=None, size=5, sector=None, objectname=None):
272323
objectname : str, optional
273324
The target around which to search, by name (objectname="M104")
274325
or TIC ID (objectname="TIC 141914082").
275-
One and only one of coordinates and objectname must be supplied.
326+
One and only one of coordinates, objectname, and moving_target must be supplied.
327+
moving_target : str, optional
328+
The name or ID (as understood by the
329+
`JPL ephemerides service <https://ssd.jpl.nasa.gov/horizons.cgi>`__)
330+
of a moving target such as an asteroid or comet.
331+
One and only one of coordinates, objectname, and moving_target must be supplied.
332+
mt_type : str, optional
333+
The moving target type, valid inputs are majorbody and smallbody. If not supplied
334+
first majorbody is tried and then smallbody if a matching majorbody is not found.
335+
This argument is ignored unless moving_target is supplied.
276336
277337
Returns
278338
-------
279339
response : A list of `~astropy.io.fits.HDUList` objects.
280340
"""
281341

282-
# Get Skycoord object for coordinates/object
283-
coordinates = parse_input_location(coordinates, objectname)
284-
342+
# Setting up the cutout size
285343
param_dict = _parse_cutout_size(size)
286-
param_dict["ra"] = coordinates.ra.deg
287-
param_dict["dec"] = coordinates.dec.deg
288344

345+
# Add sector if present
289346
if sector:
290347
param_dict["sector"] = sector
348+
349+
if moving_target:
350+
351+
# Check only on object designator has been passed in
352+
if objectname or coordinates:
353+
raise InvalidQueryError("Only one of objectname, coordinates, and moving_target may be specified.")
354+
355+
param_dict["obj_id"] = moving_target
356+
357+
# Add optional parameter if present
358+
if mt_type:
359+
param_dict["obj_type"] = mt_type
360+
361+
response = self._service_api_connection.service_request_async("mt_astrocut", param_dict)
362+
363+
else:
364+
365+
# Get Skycoord object for coordinates/object
366+
coordinates = parse_input_location(coordinates, objectname)
367+
368+
param_dict["ra"] = coordinates.ra.deg
369+
param_dict["dec"] = coordinates.dec.deg
370+
371+
response = self._service_api_connection.service_request_async("astrocut", param_dict)
291372

292-
response = self._service_api_connection.service_request_async("astrocut", param_dict)
293373
response.raise_for_status() # Raise any errors
294374

295375
try:

astroquery/mast/observations.py

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -551,11 +551,18 @@ def download_file(self, uri, local_path=None, base_url=None, cache=True, cloud_o
551551
url = None
552552

553553
try:
554-
if self._cloud_connection is not None and self._cloud_connection.is_supported(data_product):
555-
try:
556-
self._cloud_connection.download_file(data_product, local_path, cache)
557-
except Exception as ex:
558-
log.exception("Error pulling from S3 bucket: {}".format(ex))
554+
if self._cloud_connection is not None:
555+
fall_back = False
556+
if not self._cloud_connection.is_supported(data_product):
557+
log.warn("Data product not in S3.")
558+
fall_back = True
559+
else:
560+
try:
561+
self._cloud_connection.download_file(data_product, local_path, cache)
562+
except Exception as ex:
563+
log.exception("Error pulling from S3 bucket: {}".format(ex))
564+
fall_back = True
565+
if fall_back:
559566
if cloud_only:
560567
log.warn("Skipping file...")
561568
local_path = ""
@@ -565,6 +572,7 @@ def download_file(self, uri, local_path=None, base_url=None, cache=True, cloud_o
565572
self._download_file(data_url, local_path,
566573
cache=cache, head_safe=True, continuation=False)
567574
else:
575+
568576
self._download_file(data_url, local_path,
569577
cache=cache, head_safe=True, continuation=False)
570578

0 commit comments

Comments
 (0)