From ce2fbf79730e8cbc6d65a3a0c77e5fda8d084e30 Mon Sep 17 00:00:00 2001 From: Jennifer Medina Date: Wed, 29 Mar 2023 09:44:27 -0400 Subject: [PATCH 01/13] Added Warning message for Tesscut requests when cutout size is too large.Adding arg to change API request timeout cutoff. --- CHANGES.rst | 5 +++ astroquery/mast/cutouts.py | 68 ++++++++++++++++++++++++++++++++++---- 2 files changed, 67 insertions(+), 6 deletions(-) diff --git a/CHANGES.rst b/CHANGES.rst index 1a33980a49..00db1e2b6f 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -147,11 +147,16 @@ mast - Resolved issue making PANSTARRS catalog queries when columns and sorting is specified. [#2727] +- Added warning message for ``Tesscut`` requests when input cutout size reaches a + limit of 30 pixels in either dimension, and enables users to modify the request + timeout upper limit from the default 600 seconds. [#2693] + nist ^^^^ - Vectoized ``linename`` option to query multiple spectral lines with one call of ``Nist.query``. [#2678] + ``TesscutClass``. [#2668] oac ^^^ diff --git a/astroquery/mast/cutouts.py b/astroquery/mast/cutouts.py index 8ca35cb3da..6870ae3ded 100644 --- a/astroquery/mast/cutouts.py +++ b/astroquery/mast/cutouts.py @@ -25,6 +25,7 @@ from astropy.table import Table from astropy.io import fits +from .. import log from ..exceptions import InputWarning, NoResultsWarning, InvalidQueryError from .utils import parse_input_location @@ -34,7 +35,7 @@ __all__ = ["TesscutClass", "Tesscut", "ZcutClass", "Zcut"] -def _parse_cutout_size(size): +def _parse_cutout_size(size, timeout_add=None, mission=None): """ Take a user input cutout size and parse it into the regular format [ny,nx] where nx/ny are quantities with units either pixels or degrees. @@ -48,6 +49,17 @@ def _parse_cutout_size(size): ``(ny, nx)`` order. Scalar numbers in ``size`` are assumed to be in units of pixels. `~astropy.units.Quantity` objects must be in pixel or angular units. + mission : str, optional + The mission for which the size parsing is being done. This parameter + is mainly meant to trigger a cutout size warning specifically for TESSCut + requests. Default is None. + timeout_add : int or float, optional + The amount (in seconds) by which the request processing time upper limit will be changed. + The request processing time by default is 600 seconds, meaning an attempt at communicating + with the API will take 600 seconds before timing out. In the context of this function, this + parameter is meant to keep track of whether or not the timeout limit has been modified, which + will affect whether or not a warning message about the cutout size gets triggered. + Default is None. Returns ------- @@ -60,31 +72,50 @@ def _parse_cutout_size(size): if np.isscalar(size): size = np.repeat(size, 2) + limit_reached = size[0] > 30 or size[1] > 30 + if isinstance(size, u.Quantity): size = np.atleast_1d(size) + if len(size) == 1: size = np.repeat(size, 2) + # Based on the literature, TESS resolution is approx. 21 arcseconds per pixel. + # We will convert the recommended upper limit for a dimension from pixels + # to degrees. + unit = size[0].unit + upper_limit = (30 * 21*u.arcsec).to(unit).value + limit_reached = size[0].value > upper_limit or size[1].value > upper_limit + if len(size) > 2: warnings.warn("Too many dimensions in cutout size, only the first two will be used.", InputWarning) # Getting x and y out of the size + if np.isscalar(size[0]): x = size[1] y = size[0] units = "px" + elif size[0].unit == u.pixel: x = size[1].value y = size[0].value units = "px" + elif size[0].unit.physical_type == 'angle': x = size[1].to(u.deg).value y = size[0].to(u.deg).value units = "d" + else: raise InvalidQueryError("Cutout size must be in pixels or angular quantity.") + if (mission == 'TESS') & (limit_reached) & (not timeout_add): + warnings.warn("You have selected a large cutout size that may result in a timeout error. We suggest limiting" + " the size of your requested cutout, or changing the request timeout limit from its" + " default 600 seconds to something higher, using the timeout_add argument.", InputWarning) + return {"x": x, "y": y, "units": units} @@ -108,6 +139,7 @@ def __init__(self): def get_sectors(self, *, coordinates=None, radius=0*u.deg, product='SPOC', objectname=None, moving_target=False, mt_type=None): + """ Get a list of the TESS data sectors whose footprints intersect with the given search area. @@ -223,7 +255,8 @@ def get_sectors(self, *, coordinates=None, radius=0*u.deg, product='SPOC', objec return Table(sector_dict) def download_cutouts(self, *, coordinates=None, size=5, sector=None, product='SPOC', path=".", - inflate=True, objectname=None, moving_target=False, mt_type=None, verbose=False): + inflate=True, objectname=None, moving_target=False, mt_type=None, verbose=False, + timeout_add=None): """ Download cutout target pixel file(s) around the given coordinates with indicated size. @@ -315,7 +348,7 @@ def download_cutouts(self, *, coordinates=None, size=5, sector=None, product='SP astrocut_request = f"astrocut?ra={coordinates.ra.deg}&dec={coordinates.dec.deg}" # Adding the arguments that are common between moving/still astrocut requests - size_dict = _parse_cutout_size(size) + size_dict = _parse_cutout_size(size, timeout_add=timeout_add, mission='TESS') astrocut_request += f"&y={size_dict['y']}&x={size_dict['x']}&units={size_dict['units']}" # Making sure input product is either SPOC or TICA, @@ -359,7 +392,7 @@ def download_cutouts(self, *, coordinates=None, size=5, sector=None, product='SP return localpath_table def get_cutouts(self, *, coordinates=None, size=5, product='SPOC', sector=None, - objectname=None, moving_target=False, mt_type=None): + objectname=None, moving_target=False, mt_type=None, timeout_add=None): """ Get cutout target pixel file(s) around the given coordinates with indicated size, and return them as a list of `~astropy.io.fits.HDUList` objects. @@ -408,14 +441,25 @@ def get_cutouts(self, *, coordinates=None, size=5, product='SPOC', sector=None, first majorbody is tried and then smallbody if a matching majorbody is not found. NOTE: If moving_target is supplied, this argument is ignored. + timeout_add : int or float, optional + The amount (in seconds) by which the request processing time upper limit will be changed. + The request processing time by default is 600 seconds, meaning an attempt at communicating + with the API will take 600 seconds before timing out. The timeout upper limit can be modified + using this argument for large cutout requests via TESSCut. Default is None. Returns ------- response : A list of `~astropy.io.fits.HDUList` objects. """ + # Modify TIMEOUT attribute if necessary (usually this is modified for large requests) + if timeout_add: + self._service_api_connection.TIMEOUT = self._service_api_connection.TIMEOUT + timeout_add + log.info(f"Request timeout upper limit is being changed to {self._service_api_connection.TIMEOUT}" + " seconds.") + # Setting up the cutout size - param_dict = _parse_cutout_size(size) + param_dict = _parse_cutout_size(size, timeout_add=timeout_add, mission='TESS') # Add sector if present if sector: @@ -548,7 +592,7 @@ def get_surveys(self, coordinates, *, radius="0d"): return survey_json def download_cutouts(self, coordinates, *, size=5, survey=None, cutout_format="fits", path=".", inflate=True, - verbose=False, **img_params): + verbose=False, timeout_add=None, **img_params): """ Download cutout FITS/image file(s) around the given coordinates with indicated size. @@ -589,12 +633,24 @@ def download_cutouts(self, coordinates, *, size=5, survey=None, cutout_format="f The Column Name is the keyword, with the argument being one or more acceptable values for that parameter, except for fields with a float datatype where the argument should be in the form [minVal, maxVal]. + timeout_add : int or float, optional + The amount (in seconds) by which the request processing time upper limit will be changed. + The request processing time by default is 600 seconds, meaning an attempt at communicating + with the API will take 600 seconds before timing out. The timeout upper limit can be modified + using this argument for large cutout requests via TESSCut. Default is None. Returns ------- response : `~astropy.table.Table` Cutout file(s) for given coordinates """ + + # Modify TIMEOUT attribute if necessary (usually this is modified for large requests) + if timeout_add: + self._service_api_connection.TIMEOUT = self._service_api_connection.TIMEOUT + timeout_add + log.info(f"Request timeout upper limit is being changed to {self._service_api_connection.TIMEOUT}" + " seconds.") + # Get Skycoord object for coordinates/object coordinates = parse_input_location(coordinates) size_dict = _parse_cutout_size(size) From c27e3dbca088de6237bae6cb2085360aff0dd805 Mon Sep 17 00:00:00 2001 From: Jennifer Medina Date: Thu, 30 Mar 2023 13:41:50 -0400 Subject: [PATCH 02/13] Updated documentation to include commentary on TESSCut request timeouts --- astroquery/mast/cutouts.py | 2 +- docs/mast/mast.rst | 34 ++++++++++++++++++++++++++++++++++ 2 files changed, 35 insertions(+), 1 deletion(-) diff --git a/astroquery/mast/cutouts.py b/astroquery/mast/cutouts.py index 6870ae3ded..e46bb96e20 100644 --- a/astroquery/mast/cutouts.py +++ b/astroquery/mast/cutouts.py @@ -82,7 +82,7 @@ def _parse_cutout_size(size, timeout_add=None, mission=None): # Based on the literature, TESS resolution is approx. 21 arcseconds per pixel. # We will convert the recommended upper limit for a dimension from pixels - # to degrees. + # to the unit being passed. unit = size[0].unit upper_limit = (30 * 21*u.arcsec).to(unit).value limit_reached = size[0].value > upper_limit or size[1].value > upper_limit diff --git a/docs/mast/mast.rst b/docs/mast/mast.rst index 322fcd7115..c01f8c7876 100644 --- a/docs/mast/mast.rst +++ b/docs/mast/mast.rst @@ -1065,6 +1065,40 @@ and because the TICA products are not available for sectors 1-26, we request cut ---------------------------------------------------------- ./tica-s0027-4-2_107.186960_-70.509190_21x14_astrocut.fits +It is important to be mindful of the requested cutout size when using either `~astroquery.mast.TesscutClass.download_cutouts` or `~astroquery.mast.TesscutClass.get_cutouts`, +as it will affect the time it takes to retrieve your cutouts. By default, any request that ``astroquery.mast`` makes to an +API is capped at 600 seconds. Queries that take longer than this will yield a timeout error. +The recommended cutout size for TESSCut is no larger than 30 pixels in either the X or Y +direction, so a user will be met with a warning message if the input cutout size exceeds +those limits. Below is an example of a request using `~astroquery.mast.TesscutClass.get_cutouts` for cutouts of size 0.2 x 0.2 degrees-squared, which is +around 34 x 34 pixels-squared. + +.. doctest-remote-data:: + + >>> import astropy.units as u + >>> from astroquery.mast import Tesscut + >>> from astropy.coordinates import SkyCoord + ... + >>> cutout_coord = SkyCoord(107.18696, -70.50919, unit="deg") + >>> hdulist = Tesscut.get_cutouts(coordinates=cutout_coord, size=0.2*u.deg) + WARNING: InputWarning: You have selected a large cutout size that may result in a timeout error. + We suggest limiting the size of your requested cutout, or changing the request timeout limit from + its default 600 seconds to something higher, using the timeout_add argument. [astroquery.mast.cutouts] + +At this point, users may choose to decrease their cutout size or extend the request timeout limit from +600 seconds to something longer. Using the example above, we will use the ``timeout_add`` argument to extend +the request timeout limit from 600 seconds to 2600 seconds, or approximately 43 minutes. + +.. doctest-remote-data:: + + >>> import astropy.units as u + >>> from astroquery.mast import Tesscut + >>> from astropy.coordinates import SkyCoord + ... + >>> cutout_coord = SkyCoord(107.18696, -70.50919, unit="deg") + >>> hdulist = Tesscut.get_cutouts(coordinates=cutout_coord, size=0.2*u.deg, timeout_add=2000) + INFO: Request timeout upper limit is being changed to 2600 seconds. [astroquery.mast.cutouts] + Sector information ------------------ From a8b6e5ddae4469088620657a38615d5c9126c650 Mon Sep 17 00:00:00 2001 From: Jennifer Medina Date: Thu, 30 Mar 2023 17:41:49 -0400 Subject: [PATCH 03/13] Simplifying code, updating unit tests, error prevention --- CHANGES.rst | 1 - astroquery/mast/cutouts.py | 88 +++++++++++++++-------- astroquery/mast/tests/test_mast_remote.py | 16 ++++- docs/mast/mast.rst | 6 +- 4 files changed, 75 insertions(+), 36 deletions(-) diff --git a/CHANGES.rst b/CHANGES.rst index 00db1e2b6f..9854bb0dca 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -156,7 +156,6 @@ nist - Vectoized ``linename`` option to query multiple spectral lines with one call of ``Nist.query``. [#2678] - ``TesscutClass``. [#2668] oac ^^^ diff --git a/astroquery/mast/cutouts.py b/astroquery/mast/cutouts.py index e46bb96e20..c988d8eba6 100644 --- a/astroquery/mast/cutouts.py +++ b/astroquery/mast/cutouts.py @@ -26,7 +26,7 @@ from astropy.io import fits from .. import log -from ..exceptions import InputWarning, NoResultsWarning, InvalidQueryError +from ..exceptions import InputWarning, LargeQueryWarning, NoResultsWarning, InvalidQueryError from .utils import parse_input_location from .core import MastQueryWithLogin @@ -35,7 +35,7 @@ __all__ = ["TesscutClass", "Tesscut", "ZcutClass", "Zcut"] -def _parse_cutout_size(size, timeout_add=None, mission=None): +def _parse_cutout_size(size, timeout=None, mission=None): """ Take a user input cutout size and parse it into the regular format [ny,nx] where nx/ny are quantities with units either pixels or degrees. @@ -53,8 +53,8 @@ def _parse_cutout_size(size, timeout_add=None, mission=None): The mission for which the size parsing is being done. This parameter is mainly meant to trigger a cutout size warning specifically for TESSCut requests. Default is None. - timeout_add : int or float, optional - The amount (in seconds) by which the request processing time upper limit will be changed. + timeout : int or float, optional + The modified request timeout limit. The request processing time by default is 600 seconds, meaning an attempt at communicating with the API will take 600 seconds before timing out. In the context of this function, this parameter is meant to keep track of whether or not the timeout limit has been modified, which @@ -68,11 +68,15 @@ def _parse_cutout_size(size, timeout_add=None, mission=None): either pixels or degrees. """ + # This local variable will change to True if input cutout size exceeds recommended limits for TESS + limit_reached = False + # Making size into an array [ny, nx] if np.isscalar(size): size = np.repeat(size, 2) - limit_reached = size[0] > 30 or size[1] > 30 + if mission == 'TESS': + limit_reached = (size > 30).any() if isinstance(size, u.Quantity): size = np.atleast_1d(size) @@ -83,14 +87,24 @@ def _parse_cutout_size(size, timeout_add=None, mission=None): # Based on the literature, TESS resolution is approx. 21 arcseconds per pixel. # We will convert the recommended upper limit for a dimension from pixels # to the unit being passed. - unit = size[0].unit - upper_limit = (30 * 21*u.arcsec).to(unit).value - limit_reached = size[0].value > upper_limit or size[1].value > upper_limit + if mission == 'TESS': + with u.set_enabled_equivalencies(u.pixel_scale(21 * u.arcsec / u.pixel)): + limit_reached = (size > 30 * u.pixel).any() if len(size) > 2: warnings.warn("Too many dimensions in cutout size, only the first two will be used.", InputWarning) - + + # Checking 2d size inputs for the recommended cutout size + if (len(size) == 2) & (mission == 'TESS'): + + if np.isscalar(size[0]): + print(size) + size = size * u.pixel + + with u.set_enabled_equivalencies(u.pixel_scale(21 * u.arcsec / u.pixel)): + limit_reached = (size * size[0].unit > 30 * u.pixel).any() + # Getting x and y out of the size if np.isscalar(size[0]): @@ -111,10 +125,10 @@ def _parse_cutout_size(size, timeout_add=None, mission=None): else: raise InvalidQueryError("Cutout size must be in pixels or angular quantity.") - if (mission == 'TESS') & (limit_reached) & (not timeout_add): + if (limit_reached) & (not timeout): warnings.warn("You have selected a large cutout size that may result in a timeout error. We suggest limiting" " the size of your requested cutout, or changing the request timeout limit from its" - " default 600 seconds to something higher, using the timeout_add argument.", InputWarning) + " default 600 seconds to something higher, using the timeout argument.", LargeQueryWarning) return {"x": x, "y": y, "units": units} @@ -137,6 +151,11 @@ def __init__(self): } self._service_api_connection.set_service_params(services, "tesscut") + def _get_default_timeout(self): + """ Gets the default request timeout limit. """ + + return self._service_api_connection.TIMEOUT + def get_sectors(self, *, coordinates=None, radius=0*u.deg, product='SPOC', objectname=None, moving_target=False, mt_type=None): @@ -256,7 +275,7 @@ def get_sectors(self, *, coordinates=None, radius=0*u.deg, product='SPOC', objec def download_cutouts(self, *, coordinates=None, size=5, sector=None, product='SPOC', path=".", inflate=True, objectname=None, moving_target=False, mt_type=None, verbose=False, - timeout_add=None): + timeout=None): """ Download cutout target pixel file(s) around the given coordinates with indicated size. @@ -313,12 +332,23 @@ def download_cutouts(self, *, coordinates=None, size=5, sector=None, product='SP first majorbody is tried and then smallbody if a matching majorbody is not found. NOTE: If moving_target is supplied, this argument is ignored. + timeout : int or float, optional + The modified request timeout limit. + The request processing time by default is 600 seconds, meaning an attempt at communicating + with the API will take 600 seconds before timing out. The timeout upper limit can be modified + using this argument for large cutout requests via TESSCut. Default is None. Returns ------- response : `~astropy.table.Table` """ + # Modify TIMEOUT attribute if necessary (usually this is modified for large requests) + if timeout: + self._service_api_connection.TIMEOUT = timeout + log.info(f"Request timeout upper limit is being changed to {self._service_api_connection.TIMEOUT}" + " seconds.") + if moving_target: # The Moving Targets service is currently only available for SPOC @@ -348,7 +378,7 @@ def download_cutouts(self, *, coordinates=None, size=5, sector=None, product='SP astrocut_request = f"astrocut?ra={coordinates.ra.deg}&dec={coordinates.dec.deg}" # Adding the arguments that are common between moving/still astrocut requests - size_dict = _parse_cutout_size(size, timeout_add=timeout_add, mission='TESS') + size_dict = _parse_cutout_size(size, timeout=timeout, mission='TESS') astrocut_request += f"&y={size_dict['y']}&x={size_dict['x']}&units={size_dict['units']}" # Making sure input product is either SPOC or TICA, @@ -389,10 +419,14 @@ def download_cutouts(self, *, coordinates=None, size=5, sector=None, product='SP os.remove(zipfile_path) localpath_table['Local Path'] = [path+x for x in cutout_files] + + if timeout: + self._service_api_connection.TIMEOUT = self._get_default_timeout() + return localpath_table def get_cutouts(self, *, coordinates=None, size=5, product='SPOC', sector=None, - objectname=None, moving_target=False, mt_type=None, timeout_add=None): + objectname=None, moving_target=False, mt_type=None, timeout=None): """ Get cutout target pixel file(s) around the given coordinates with indicated size, and return them as a list of `~astropy.io.fits.HDUList` objects. @@ -441,8 +475,8 @@ def get_cutouts(self, *, coordinates=None, size=5, product='SPOC', sector=None, first majorbody is tried and then smallbody if a matching majorbody is not found. NOTE: If moving_target is supplied, this argument is ignored. - timeout_add : int or float, optional - The amount (in seconds) by which the request processing time upper limit will be changed. + timeout : int or float, optional + The modified request timeout limit. The request processing time by default is 600 seconds, meaning an attempt at communicating with the API will take 600 seconds before timing out. The timeout upper limit can be modified using this argument for large cutout requests via TESSCut. Default is None. @@ -453,13 +487,13 @@ def get_cutouts(self, *, coordinates=None, size=5, product='SPOC', sector=None, """ # Modify TIMEOUT attribute if necessary (usually this is modified for large requests) - if timeout_add: - self._service_api_connection.TIMEOUT = self._service_api_connection.TIMEOUT + timeout_add + if timeout: + self._service_api_connection.TIMEOUT = timeout log.info(f"Request timeout upper limit is being changed to {self._service_api_connection.TIMEOUT}" " seconds.") # Setting up the cutout size - param_dict = _parse_cutout_size(size, timeout_add=timeout_add, mission='TESS') + param_dict = _parse_cutout_size(size, timeout=timeout, mission='TESS') # Add sector if present if sector: @@ -529,6 +563,9 @@ def get_cutouts(self, *, coordinates=None, size=5, product='SPOC', sector=None, # preserve the original filename in the fits object cutout_hdus_list[-1].filename = name + if timeout: + self._service_api_connection.TIMEOUT = self._get_default_timeout() + return cutout_hdus_list @@ -592,7 +629,7 @@ def get_surveys(self, coordinates, *, radius="0d"): return survey_json def download_cutouts(self, coordinates, *, size=5, survey=None, cutout_format="fits", path=".", inflate=True, - verbose=False, timeout_add=None, **img_params): + verbose=False, **img_params): """ Download cutout FITS/image file(s) around the given coordinates with indicated size. @@ -633,11 +670,6 @@ def download_cutouts(self, coordinates, *, size=5, survey=None, cutout_format="f The Column Name is the keyword, with the argument being one or more acceptable values for that parameter, except for fields with a float datatype where the argument should be in the form [minVal, maxVal]. - timeout_add : int or float, optional - The amount (in seconds) by which the request processing time upper limit will be changed. - The request processing time by default is 600 seconds, meaning an attempt at communicating - with the API will take 600 seconds before timing out. The timeout upper limit can be modified - using this argument for large cutout requests via TESSCut. Default is None. Returns ------- @@ -645,12 +677,6 @@ def download_cutouts(self, coordinates, *, size=5, survey=None, cutout_format="f Cutout file(s) for given coordinates """ - # Modify TIMEOUT attribute if necessary (usually this is modified for large requests) - if timeout_add: - self._service_api_connection.TIMEOUT = self._service_api_connection.TIMEOUT + timeout_add - log.info(f"Request timeout upper limit is being changed to {self._service_api_connection.TIMEOUT}" - " seconds.") - # Get Skycoord object for coordinates/object coordinates = parse_input_location(coordinates) size_dict = _parse_cutout_size(size) diff --git a/astroquery/mast/tests/test_mast_remote.py b/astroquery/mast/tests/test_mast_remote.py index f70f6dd236..59a32a6b60 100644 --- a/astroquery/mast/tests/test_mast_remote.py +++ b/astroquery/mast/tests/test_mast_remote.py @@ -949,7 +949,7 @@ def test_tesscut_download_cutouts_mt(self, tmpdir): assert error_tica_mt in str(error_msg.value) @pytest.mark.parametrize("product", ["tica", "spoc"]) - def test_tesscut_get_cutouts(self, product): + def test_tesscut_get_cutouts(self, product, caplog): coord = SkyCoord(107.18696, -70.50919, unit="deg") @@ -975,6 +975,11 @@ def test_tesscut_get_cutouts(self, product): assert len(cutout_hdus_list) >= 1 assert isinstance(cutout_hdus_list[0], fits.HDUList) + # Check that an INFO message is returned when timeout is adjusted + mast.Tesscut.get_cutouts(product=product, coordinates=coord, size=5, timeout=1000) + with caplog.at_level("INFO", logger="astroquery"): + assert "timeout upper limit is being changed" in caplog.text + def test_tesscut_get_cutouts_mt(self): # Moving target functionality testing @@ -1027,6 +1032,15 @@ def test_tesscut_get_cutouts_mt(self): moving_target=True) assert error_tica_mt in str(error_msg.value) + @pytest.mark.xfail(raises=InputWarning) + @pytest.mark.parametrize("product", ["tica", "spoc"]) + @pytest.mark.parametrize("size", [31, 0.2 * u.deg, 5000 * u.arcsec, 20 * u.arcmin]) + def test_tesscut_timeout_param(self, product, size): + + # Check that a warning comes up when cutout size too big + coordinates = '60 60' + mast.Tesscut.get_cutouts(product=product, coordinates=coordinates, size=size) + ################### # ZcutClass tests # ################### diff --git a/docs/mast/mast.rst b/docs/mast/mast.rst index c01f8c7876..fd64d83294 100644 --- a/docs/mast/mast.rst +++ b/docs/mast/mast.rst @@ -1083,10 +1083,10 @@ around 34 x 34 pixels-squared. >>> hdulist = Tesscut.get_cutouts(coordinates=cutout_coord, size=0.2*u.deg) WARNING: InputWarning: You have selected a large cutout size that may result in a timeout error. We suggest limiting the size of your requested cutout, or changing the request timeout limit from - its default 600 seconds to something higher, using the timeout_add argument. [astroquery.mast.cutouts] + its default 600 seconds to something higher, using the timeout argument. [astroquery.mast.cutouts] At this point, users may choose to decrease their cutout size or extend the request timeout limit from -600 seconds to something longer. Using the example above, we will use the ``timeout_add`` argument to extend +600 seconds to something longer. Using the example above, we will use the ``timeout`` argument to change the request timeout limit from 600 seconds to 2600 seconds, or approximately 43 minutes. .. doctest-remote-data:: @@ -1096,7 +1096,7 @@ the request timeout limit from 600 seconds to 2600 seconds, or approximately 43 >>> from astropy.coordinates import SkyCoord ... >>> cutout_coord = SkyCoord(107.18696, -70.50919, unit="deg") - >>> hdulist = Tesscut.get_cutouts(coordinates=cutout_coord, size=0.2*u.deg, timeout_add=2000) + >>> hdulist = Tesscut.get_cutouts(coordinates=cutout_coord, size=0.2*u.deg, timeout=2600) INFO: Request timeout upper limit is being changed to 2600 seconds. [astroquery.mast.cutouts] Sector information From 324ac459a8649abc29883cc4fc642f691cd753a8 Mon Sep 17 00:00:00 2001 From: Jennifer Medina Date: Thu, 6 Apr 2023 10:45:37 -0400 Subject: [PATCH 04/13] removing timeout example, skipping doctest for largequerywarning example --- docs/mast/mast.rst | 19 ++++--------------- 1 file changed, 4 insertions(+), 15 deletions(-) diff --git a/docs/mast/mast.rst b/docs/mast/mast.rst index fd64d83294..cb971d2a0a 100644 --- a/docs/mast/mast.rst +++ b/docs/mast/mast.rst @@ -1073,7 +1073,7 @@ direction, so a user will be met with a warning message if the input cutout size those limits. Below is an example of a request using `~astroquery.mast.TesscutClass.get_cutouts` for cutouts of size 0.2 x 0.2 degrees-squared, which is around 34 x 34 pixels-squared. -.. doctest-remote-data:: +.. doctest-skip:: >>> import astropy.units as u >>> from astroquery.mast import Tesscut @@ -1081,23 +1081,12 @@ around 34 x 34 pixels-squared. ... >>> cutout_coord = SkyCoord(107.18696, -70.50919, unit="deg") >>> hdulist = Tesscut.get_cutouts(coordinates=cutout_coord, size=0.2*u.deg) - WARNING: InputWarning: You have selected a large cutout size that may result in a timeout error. + WARNING: LargeQueryWarning: You have selected a large cutout size that may result in a timeout error. We suggest limiting the size of your requested cutout, or changing the request timeout limit from its default 600 seconds to something higher, using the timeout argument. [astroquery.mast.cutouts] - -At this point, users may choose to decrease their cutout size or extend the request timeout limit from -600 seconds to something longer. Using the example above, we will use the ``timeout`` argument to change -the request timeout limit from 600 seconds to 2600 seconds, or approximately 43 minutes. -.. doctest-remote-data:: - - >>> import astropy.units as u - >>> from astroquery.mast import Tesscut - >>> from astropy.coordinates import SkyCoord - ... - >>> cutout_coord = SkyCoord(107.18696, -70.50919, unit="deg") - >>> hdulist = Tesscut.get_cutouts(coordinates=cutout_coord, size=0.2*u.deg, timeout=2600) - INFO: Request timeout upper limit is being changed to 2600 seconds. [astroquery.mast.cutouts] +At this point, users may choose to decrease their cutout size or extend the request timeout limit from +600 seconds to something longer. Sector information ------------------ From 9c0e6af62712d9c061c98f9ced778239691206e6 Mon Sep 17 00:00:00 2001 From: Jennifer Medina Date: Thu, 6 Apr 2023 11:08:17 -0400 Subject: [PATCH 05/13] addressing UnitConversionError for list of scalar inputs converted to pixel units --- astroquery/mast/cutouts.py | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/astroquery/mast/cutouts.py b/astroquery/mast/cutouts.py index c988d8eba6..3069565519 100644 --- a/astroquery/mast/cutouts.py +++ b/astroquery/mast/cutouts.py @@ -71,6 +71,15 @@ def _parse_cutout_size(size, timeout=None, mission=None): # This local variable will change to True if input cutout size exceeds recommended limits for TESS limit_reached = False + # Checking 2d size inputs for the recommended cutout size + if isinstance(size, list) & (mission == 'TESS'): + if len(size) == 2: + if np.isscalar(size[0]): + size = [size[0] * u.pixel, size[1] * u.pixel] + + with u.set_enabled_equivalencies(u.pixel_scale(21 * u.arcsec / u.pixel)): + limit_reached = (size * size[0].unit > 30 * u.pixel).any() + # Making size into an array [ny, nx] if np.isscalar(size): size = np.repeat(size, 2) @@ -95,16 +104,6 @@ def _parse_cutout_size(size, timeout=None, mission=None): warnings.warn("Too many dimensions in cutout size, only the first two will be used.", InputWarning) - # Checking 2d size inputs for the recommended cutout size - if (len(size) == 2) & (mission == 'TESS'): - - if np.isscalar(size[0]): - print(size) - size = size * u.pixel - - with u.set_enabled_equivalencies(u.pixel_scale(21 * u.arcsec / u.pixel)): - limit_reached = (size * size[0].unit > 30 * u.pixel).any() - # Getting x and y out of the size if np.isscalar(size[0]): From 0422c8effbbcbbb9f74c90df10c1c5125fdc383e Mon Sep 17 00:00:00 2001 From: Jennifer Medina Date: Thu, 6 Apr 2023 11:18:02 -0400 Subject: [PATCH 06/13] array-like cutout sizes added to test_tesscut_timeout_param --- astroquery/mast/tests/test_mast_remote.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/astroquery/mast/tests/test_mast_remote.py b/astroquery/mast/tests/test_mast_remote.py index 59a32a6b60..72ea4b4d5e 100644 --- a/astroquery/mast/tests/test_mast_remote.py +++ b/astroquery/mast/tests/test_mast_remote.py @@ -15,8 +15,8 @@ from astroquery import mast from ..utils import ResolverError -from ...exceptions import (InputWarning, InvalidQueryError, MaxResultsWarning, - NoResultsWarning) +from ...exceptions import (InputWarning, InvalidQueryError, LargeQueryWarning, + MaxResultsWarning, NoResultsWarning) OBSID = '1647157' @@ -1032,9 +1032,9 @@ def test_tesscut_get_cutouts_mt(self): moving_target=True) assert error_tica_mt in str(error_msg.value) - @pytest.mark.xfail(raises=InputWarning) + @pytest.mark.xfail(raises=LargeQueryWarning) @pytest.mark.parametrize("product", ["tica", "spoc"]) - @pytest.mark.parametrize("size", [31, 0.2 * u.deg, 5000 * u.arcsec, 20 * u.arcmin]) + @pytest.mark.parametrize("size", [31, [5, 60], 0.2 * u.deg, [0.1 * u.deg, 0.2 * u.deg], 5000 * u.arcsec, 20 * u.arcmin]) def test_tesscut_timeout_param(self, product, size): # Check that a warning comes up when cutout size too big From 33f80b383a9e5f4a873443489aae485771c2f43b Mon Sep 17 00:00:00 2001 From: Jennifer Medina Date: Thu, 6 Apr 2023 12:11:44 -0400 Subject: [PATCH 07/13] patched up resetting the default timeout after timeout is adjusted --- astroquery/mast/cutouts.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/astroquery/mast/cutouts.py b/astroquery/mast/cutouts.py index 3069565519..c61bdeaa22 100644 --- a/astroquery/mast/cutouts.py +++ b/astroquery/mast/cutouts.py @@ -344,6 +344,7 @@ def download_cutouts(self, *, coordinates=None, size=5, sector=None, product='SP # Modify TIMEOUT attribute if necessary (usually this is modified for large requests) if timeout: + default_timeout = self._get_default_timeout() self._service_api_connection.TIMEOUT = timeout log.info(f"Request timeout upper limit is being changed to {self._service_api_connection.TIMEOUT}" " seconds.") @@ -420,7 +421,7 @@ def download_cutouts(self, *, coordinates=None, size=5, sector=None, product='SP localpath_table['Local Path'] = [path+x for x in cutout_files] if timeout: - self._service_api_connection.TIMEOUT = self._get_default_timeout() + self._service_api_connection.TIMEOUT = default_timeout return localpath_table @@ -487,6 +488,7 @@ def get_cutouts(self, *, coordinates=None, size=5, product='SPOC', sector=None, # Modify TIMEOUT attribute if necessary (usually this is modified for large requests) if timeout: + default_timeout = self._get_default_timeout() self._service_api_connection.TIMEOUT = timeout log.info(f"Request timeout upper limit is being changed to {self._service_api_connection.TIMEOUT}" " seconds.") @@ -563,7 +565,7 @@ def get_cutouts(self, *, coordinates=None, size=5, product='SPOC', sector=None, cutout_hdus_list[-1].filename = name if timeout: - self._service_api_connection.TIMEOUT = self._get_default_timeout() + self._service_api_connection.TIMEOUT = default_timeout return cutout_hdus_list From 7e0ff900f51248ea8038f9b310b303d4841ba692 Mon Sep 17 00:00:00 2001 From: Jennifer Medina Date: Thu, 6 Apr 2023 12:15:25 -0400 Subject: [PATCH 08/13] asserting that timeout returns to 600s after it is adjusted --- astroquery/mast/tests/test_mast_remote.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/astroquery/mast/tests/test_mast_remote.py b/astroquery/mast/tests/test_mast_remote.py index 72ea4b4d5e..199d8454f8 100644 --- a/astroquery/mast/tests/test_mast_remote.py +++ b/astroquery/mast/tests/test_mast_remote.py @@ -980,6 +980,9 @@ def test_tesscut_get_cutouts(self, product, caplog): with caplog.at_level("INFO", logger="astroquery"): assert "timeout upper limit is being changed" in caplog.text + # Ensure that timeout returns to default (600 seconds) after adjusted in previous call + assert mast.Tesscut._service_api_connection.TIMEOUT == 600 + def test_tesscut_get_cutouts_mt(self): # Moving target functionality testing From 891224318ed8cccfd7ea06e2a3ee1570f20061c0 Mon Sep 17 00:00:00 2001 From: Jennifer Medina Date: Thu, 6 Apr 2023 12:17:18 -0400 Subject: [PATCH 09/13] codestyle --- astroquery/mast/cutouts.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/astroquery/mast/cutouts.py b/astroquery/mast/cutouts.py index c61bdeaa22..59add943b7 100644 --- a/astroquery/mast/cutouts.py +++ b/astroquery/mast/cutouts.py @@ -103,7 +103,7 @@ def _parse_cutout_size(size, timeout=None, mission=None): if len(size) > 2: warnings.warn("Too many dimensions in cutout size, only the first two will be used.", InputWarning) - + # Getting x and y out of the size if np.isscalar(size[0]): From 3d91932d1e5afcd46d496c3f5f43bb8f6754ee75 Mon Sep 17 00:00:00 2001 From: Jennifer Medina Date: Thu, 6 Apr 2023 12:19:12 -0400 Subject: [PATCH 10/13] codestyle --- astroquery/mast/tests/test_mast_remote.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/astroquery/mast/tests/test_mast_remote.py b/astroquery/mast/tests/test_mast_remote.py index 199d8454f8..62dd829a4c 100644 --- a/astroquery/mast/tests/test_mast_remote.py +++ b/astroquery/mast/tests/test_mast_remote.py @@ -1037,7 +1037,8 @@ def test_tesscut_get_cutouts_mt(self): @pytest.mark.xfail(raises=LargeQueryWarning) @pytest.mark.parametrize("product", ["tica", "spoc"]) - @pytest.mark.parametrize("size", [31, [5, 60], 0.2 * u.deg, [0.1 * u.deg, 0.2 * u.deg], 5000 * u.arcsec, 20 * u.arcmin]) + @pytest.mark.parametrize("size", [31, [5, 60], 0.2 * u.deg, [0.1 * u.deg, 0.2 * u.deg], + 5000 * u.arcsec, 20 * u.arcmin]) def test_tesscut_timeout_param(self, product, size): # Check that a warning comes up when cutout size too big From c2935318d454b3b97f28aba5ccbf3c42cdea05a9 Mon Sep 17 00:00:00 2001 From: Jennifer Medina Date: Thu, 6 Apr 2023 12:37:27 -0400 Subject: [PATCH 11/13] catching all array-like inputs. lists, tuples, np arrays --- astroquery/mast/cutouts.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/astroquery/mast/cutouts.py b/astroquery/mast/cutouts.py index 59add943b7..95ec7015ca 100644 --- a/astroquery/mast/cutouts.py +++ b/astroquery/mast/cutouts.py @@ -72,7 +72,7 @@ def _parse_cutout_size(size, timeout=None, mission=None): limit_reached = False # Checking 2d size inputs for the recommended cutout size - if isinstance(size, list) & (mission == 'TESS'): + if not isinstance(size, (int, float, u.Quantity)) & (mission == 'TESS'): if len(size) == 2: if np.isscalar(size[0]): size = [size[0] * u.pixel, size[1] * u.pixel] From 093989a17352a2c04718a6bdc558993380c7667d Mon Sep 17 00:00:00 2001 From: Jennifer Medina Date: Thu, 6 Apr 2023 12:47:39 -0400 Subject: [PATCH 12/13] resolved zcut unit test error --- astroquery/mast/cutouts.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/astroquery/mast/cutouts.py b/astroquery/mast/cutouts.py index 95ec7015ca..b9f61bcd08 100644 --- a/astroquery/mast/cutouts.py +++ b/astroquery/mast/cutouts.py @@ -72,7 +72,7 @@ def _parse_cutout_size(size, timeout=None, mission=None): limit_reached = False # Checking 2d size inputs for the recommended cutout size - if not isinstance(size, (int, float, u.Quantity)) & (mission == 'TESS'): + if (mission == 'TESS') & (not isinstance(size, (int, float, u.Quantity))): if len(size) == 2: if np.isscalar(size[0]): size = [size[0] * u.pixel, size[1] * u.pixel] From 79e6f055b9118489009640883305a7c624bce2c1 Mon Sep 17 00:00:00 2001 From: Jennifer Medina Date: Mon, 1 May 2023 17:48:02 -0400 Subject: [PATCH 13/13] getting default timeout value directly from conf --- astroquery/mast/cutouts.py | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/astroquery/mast/cutouts.py b/astroquery/mast/cutouts.py index b9f61bcd08..06d3d272d9 100644 --- a/astroquery/mast/cutouts.py +++ b/astroquery/mast/cutouts.py @@ -25,6 +25,7 @@ from astropy.table import Table from astropy.io import fits +from . import conf from .. import log from ..exceptions import InputWarning, LargeQueryWarning, NoResultsWarning, InvalidQueryError @@ -150,11 +151,6 @@ def __init__(self): } self._service_api_connection.set_service_params(services, "tesscut") - def _get_default_timeout(self): - """ Gets the default request timeout limit. """ - - return self._service_api_connection.TIMEOUT - def get_sectors(self, *, coordinates=None, radius=0*u.deg, product='SPOC', objectname=None, moving_target=False, mt_type=None): @@ -344,7 +340,7 @@ def download_cutouts(self, *, coordinates=None, size=5, sector=None, product='SP # Modify TIMEOUT attribute if necessary (usually this is modified for large requests) if timeout: - default_timeout = self._get_default_timeout() + default_timeout = conf.timeout self._service_api_connection.TIMEOUT = timeout log.info(f"Request timeout upper limit is being changed to {self._service_api_connection.TIMEOUT}" " seconds.") @@ -488,7 +484,7 @@ def get_cutouts(self, *, coordinates=None, size=5, product='SPOC', sector=None, # Modify TIMEOUT attribute if necessary (usually this is modified for large requests) if timeout: - default_timeout = self._get_default_timeout() + default_timeout = conf.timeout self._service_api_connection.TIMEOUT = timeout log.info(f"Request timeout upper limit is being changed to {self._service_api_connection.TIMEOUT}" " seconds.")