2525from astropy .table import Table
2626from astropy .io import fits
2727
28+ from .. import log
2829from ..exceptions import InputWarning , NoResultsWarning , InvalidQueryError
2930
3031from .utils import parse_input_location
3435__all__ = ["TesscutClass" , "Tesscut" , "ZcutClass" , "Zcut" ]
3536
3637
37- def _parse_cutout_size (size ):
38+ def _parse_cutout_size (size , timeout_add = None , mission = None ):
3839 """
3940 Take a user input cutout size and parse it into the regular format
4041 [ny,nx] where nx/ny are quantities with units either pixels or degrees.
@@ -48,6 +49,17 @@ def _parse_cutout_size(size):
4849 ``(ny, nx)`` order. Scalar numbers in ``size`` are assumed to be in
4950 units of pixels. `~astropy.units.Quantity` objects must be in pixel or
5051 angular units.
52+ mission : str, optional
53+ The mission for which the size parsing is being done. This parameter
54+ is mainly meant to trigger a cutout size warning specifically for TESSCut
55+ requests. Default is None.
56+ timeout_add : int or float, optional
57+ The amount (in seconds) by which the request processing time upper limit will be changed.
58+ The request processing time by default is 600 seconds, meaning an attempt at communicating
59+ with the API will take 600 seconds before timing out. In the context of this function, this
60+ parameter is meant to keep track of whether or not the timeout limit has been modified, which
61+ will affect whether or not a warning message about the cutout size gets triggered.
62+ Default is None.
5163
5264 Returns
5365 -------
@@ -60,31 +72,50 @@ def _parse_cutout_size(size):
6072 if np .isscalar (size ):
6173 size = np .repeat (size , 2 )
6274
75+ limit_reached = size [0 ] > 30 or size [1 ] > 30
76+
6377 if isinstance (size , u .Quantity ):
6478 size = np .atleast_1d (size )
79+
6580 if len (size ) == 1 :
6681 size = np .repeat (size , 2 )
6782
83+ # Based on the literature, TESS resolution is approx. 21 arcseconds per pixel.
84+ # We will convert the recommended upper limit for a dimension from pixels
85+ # to degrees.
86+ unit = size [0 ].unit
87+ upper_limit = (30 * 21 * u .arcsec ).to (unit ).value
88+ limit_reached = size [0 ].value > upper_limit or size [1 ].value > upper_limit
89+
6890 if len (size ) > 2 :
6991 warnings .warn ("Too many dimensions in cutout size, only the first two will be used." ,
7092 InputWarning )
7193
7294 # Getting x and y out of the size
95+
7396 if np .isscalar (size [0 ]):
7497 x = size [1 ]
7598 y = size [0 ]
7699 units = "px"
100+
77101 elif size [0 ].unit == u .pixel :
78102 x = size [1 ].value
79103 y = size [0 ].value
80104 units = "px"
105+
81106 elif size [0 ].unit .physical_type == 'angle' :
82107 x = size [1 ].to (u .deg ).value
83108 y = size [0 ].to (u .deg ).value
84109 units = "d"
110+
85111 else :
86112 raise InvalidQueryError ("Cutout size must be in pixels or angular quantity." )
87113
114+ if (mission == 'TESS' ) & (limit_reached ) & (not timeout_add ):
115+ warnings .warn ("You have selected a large cutout size that may result in a timeout error. We suggest limiting"
116+ " the size of your requested cutout, or changing the request timeout limit from its"
117+ " default 600 seconds to something higher, using the timeout_add argument." , InputWarning )
118+
88119 return {"x" : x , "y" : y , "units" : units }
89120
90121
@@ -108,6 +139,7 @@ def __init__(self):
108139
109140 def get_sectors (self , * , coordinates = None , radius = 0 * u .deg , product = 'SPOC' , objectname = None ,
110141 moving_target = False , mt_type = None ):
142+
111143 """
112144 Get a list of the TESS data sectors whose footprints intersect
113145 with the given search area.
@@ -223,7 +255,8 @@ def get_sectors(self, *, coordinates=None, radius=0*u.deg, product='SPOC', objec
223255 return Table (sector_dict )
224256
225257 def download_cutouts (self , * , coordinates = None , size = 5 , sector = None , product = 'SPOC' , path = "." ,
226- inflate = True , objectname = None , moving_target = False , mt_type = None , verbose = False ):
258+ inflate = True , objectname = None , moving_target = False , mt_type = None , verbose = False ,
259+ timeout_add = None ):
227260 """
228261 Download cutout target pixel file(s) around the given coordinates with indicated size.
229262
@@ -315,7 +348,7 @@ def download_cutouts(self, *, coordinates=None, size=5, sector=None, product='SP
315348 astrocut_request = f"astrocut?ra={ coordinates .ra .deg } &dec={ coordinates .dec .deg } "
316349
317350 # Adding the arguments that are common between moving/still astrocut requests
318- size_dict = _parse_cutout_size (size )
351+ size_dict = _parse_cutout_size (size , timeout_add = timeout_add , mission = 'TESS' )
319352 astrocut_request += f"&y={ size_dict ['y' ]} &x={ size_dict ['x' ]} &units={ size_dict ['units' ]} "
320353
321354 # 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
359392 return localpath_table
360393
361394 def get_cutouts (self , * , coordinates = None , size = 5 , product = 'SPOC' , sector = None ,
362- objectname = None , moving_target = False , mt_type = None ):
395+ objectname = None , moving_target = False , mt_type = None , timeout_add = None ):
363396 """
364397 Get cutout target pixel file(s) around the given coordinates with indicated size,
365398 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,
408441 first majorbody is tried and then smallbody if a matching majorbody is not found.
409442
410443 NOTE: If moving_target is supplied, this argument is ignored.
444+ timeout_add : int or float, optional
445+ The amount (in seconds) by which the request processing time upper limit will be changed.
446+ The request processing time by default is 600 seconds, meaning an attempt at communicating
447+ with the API will take 600 seconds before timing out. The timeout upper limit can be modified
448+ using this argument for large cutout requests via TESSCut. Default is None.
411449
412450 Returns
413451 -------
414452 response : A list of `~astropy.io.fits.HDUList` objects.
415453 """
416454
455+ # Modify TIMEOUT attribute if necessary (usually this is modified for large requests)
456+ if timeout_add :
457+ self ._service_api_connection .TIMEOUT = self ._service_api_connection .TIMEOUT + timeout_add
458+ log .info (f"Request timeout upper limit is being changed to { self ._service_api_connection .TIMEOUT } "
459+ " seconds." )
460+
417461 # Setting up the cutout size
418- param_dict = _parse_cutout_size (size )
462+ param_dict = _parse_cutout_size (size , timeout_add = timeout_add , mission = 'TESS' )
419463
420464 # Add sector if present
421465 if sector :
@@ -548,7 +592,7 @@ def get_surveys(self, coordinates, *, radius="0d"):
548592 return survey_json
549593
550594 def download_cutouts (self , coordinates , * , size = 5 , survey = None , cutout_format = "fits" , path = "." , inflate = True ,
551- verbose = False , ** img_params ):
595+ verbose = False , timeout_add = None , ** img_params ):
552596 """
553597 Download cutout FITS/image file(s) around the given coordinates with indicated size.
554598
@@ -589,12 +633,24 @@ def download_cutouts(self, coordinates, *, size=5, survey=None, cutout_format="f
589633 The Column Name is the keyword, with the argument being one or more acceptable
590634 values for that parameter, except for fields with a float datatype where the
591635 argument should be in the form [minVal, maxVal].
636+ timeout_add : int or float, optional
637+ The amount (in seconds) by which the request processing time upper limit will be changed.
638+ The request processing time by default is 600 seconds, meaning an attempt at communicating
639+ with the API will take 600 seconds before timing out. The timeout upper limit can be modified
640+ using this argument for large cutout requests via TESSCut. Default is None.
592641
593642 Returns
594643 -------
595644 response : `~astropy.table.Table`
596645 Cutout file(s) for given coordinates
597646 """
647+
648+ # Modify TIMEOUT attribute if necessary (usually this is modified for large requests)
649+ if timeout_add :
650+ self ._service_api_connection .TIMEOUT = self ._service_api_connection .TIMEOUT + timeout_add
651+ log .info (f"Request timeout upper limit is being changed to { self ._service_api_connection .TIMEOUT } "
652+ " seconds." )
653+
598654 # Get Skycoord object for coordinates/object
599655 coordinates = parse_input_location (coordinates )
600656 size_dict = _parse_cutout_size (size )
0 commit comments