@@ -50,19 +50,21 @@ class EuclidClass(TapPlus):
5050 __regex_designation = re .compile (r"\s*(\S+)\s(-?\d+)\s*" , flags = re .MULTILINE | re .UNICODE )
5151
5252 def __init__ (self , * , environment = 'PDR' , tap_plus_conn_handler = None , datalink_handler = None , cutout_handler = None ,
53- verbose = False , show_server_messages = True ):
53+ sia_handler = None , verbose = False , show_server_messages = True ):
5454 """Constructor for EuclidClass.
5555
5656 Parameters
5757 ----------
5858 environment : str, mandatory if no tap, data or cutout hosts is specified, default 'PDR'
5959 The Euclid Science Archive environment: 'PDR', 'IDR', 'OTF' and 'REG'
6060 tap_plus_conn_handler : tap connection handler object, optional, default None
61- HTTP(s) connection hander (creator). If no handler is provided, a new one is created.
62- datalink_handler : dataliink connection handler object, optional, default None
63- HTTP(s) connection hander (creator). If no handler is provided, a new one is created.
61+ HTTP(s) connection handler (creator). If no handler is provided, a new one is created.
62+ datalink_handler : datalink connection handler object, optional, default None
63+ HTTP(s) connection handler (creator). If no handler is provided, a new one is created.
6464 cutout_handler : cutout connection handler object, optional, default None
65- HTTP(s) connection hander (creator). If no handler is provided, a new one is created.
65+ HTTP(s) connection handler (creator). If no handler is provided, a new one is created.
66+ sia_handler : siap connection handler object, optional, default None
67+ HTTP(s) connection handler (creator). If no handler is provided, a new one is created.
6668 verbose : bool, optional, default 'True'
6769 flag to display information about the process
6870 show_server_messages : bool, optional, default 'True'
@@ -123,6 +125,20 @@ def __init__(self, *, environment='PDR', tap_plus_conn_handler=None, datalink_ha
123125 else :
124126 self .__euclidcutout = cutout_handler
125127
128+ if sia_handler is None :
129+ self .__euclidsia = TapPlus (url = url_server ,
130+ server_context = "sas-sia" ,
131+ tap_context = "tap-server" ,
132+ upload_context = "Upload" ,
133+ table_edit_context = "TableTool" ,
134+ data_context = "sia2/query" ,
135+ datalink_context = "datalink" ,
136+ verbose = verbose ,
137+ client_id = 'ASTROQUERY' ,
138+ use_names_over_ids = conf .USE_NAMES_OVER_IDS )
139+ else :
140+ self .__euclidsia = sia_handler
141+
126142 if show_server_messages :
127143 self .get_status_messages ()
128144
@@ -665,6 +681,8 @@ def login(self, *, user=None, password=None, credentials_file=None, verbose=Fals
665681 self .__eucliddata .login (user = tap_user , password = tap_password , verbose = verbose )
666682 log .info (f"Login to Euclid cutout service: { self .__euclidcutout ._TapPlus__getconnhandler ().get_host_url ()} " )
667683 self .__euclidcutout .login (user = tap_user , password = tap_password , verbose = verbose )
684+ log .info (f"Login to Euclid sia service: { self .__euclidsia ._TapPlus__getconnhandler ().get_host_url ()} " )
685+ self .__euclidsia .login (user = tap_user , password = tap_password , verbose = verbose )
668686 except HTTPError as err :
669687 log .error ('Error logging in data or cutout services: %s' % (str (err )))
670688 log .error ("Logging out from TAP server" )
@@ -709,6 +727,14 @@ def login_gui(self, verbose=False):
709727 log .error ("Logging out from TAP server" )
710728 TapPlus .logout (self , verbose = verbose )
711729
730+ try :
731+ log .info (f"Login to Euclid sia server: { self .__euclidsia ._TapPlus__getconnhandler ().get_host_url ()} " )
732+ self .__euclidsia .login (user = tap_user , password = tap_password , verbose = verbose )
733+ except HTTPError as err :
734+ log .error ('Error logging in sia server: %s' % (str (err )))
735+ log .error ("Logging out from TAP server" )
736+ TapPlus .logout (self , verbose = verbose )
737+
712738 def logout (self , verbose = False ):
713739 """
714740 Performs a logout
@@ -744,6 +770,12 @@ def logout(self, verbose=False):
744770 except HTTPError as err :
745771 log .error ('Error logging out cutout server: %s' % (str (err )))
746772
773+ try :
774+ self .__euclidsia .logout (verbose = verbose )
775+ log .info ("Euclid sia server logout OK" )
776+ except HTTPError as err :
777+ log .error ('Error logging out sia server: %s' % (str (err )))
778+
747779 @staticmethod
748780 def __get_quantity_input (value , msg ):
749781 if value is None :
@@ -1059,7 +1091,7 @@ def get_product_list(self, *, observation_id=None, tile_index=None, product_type
10591091 observation id for observations. It is not compatible with parameter tile_index.
10601092
10611093 Searchable products by observation_id: 'dpdVisRawFrame', 'dpdNispRawFrame',
1062- , 'DpdVisCalibratedQuadFrame','DpdVisCalibratedFrameCatalog', 'DpdVisStackedFrame',
1094+ 'DpdVisCalibratedQuadFrame','DpdVisCalibratedFrameCatalog', 'DpdVisStackedFrame',
10631095 'DpdVisStackedFrameCatalog',
10641096 'DpdNirCalibratedFrame', 'DpdNirCalibratedFrameCatalog', 'DpdNirStackedFrameCatalog', 'DpdNirStackedFrame',
10651097 'DpdMerSegmentationMap', 'dpdMerFinalCatalog',
@@ -1442,6 +1474,110 @@ def __is_multiple(self, value):
14421474
14431475 return not isinstance (value , int ) and ((isinstance (value , (list , tuple )) and len (value ) > 1 ) or ',' in value )
14441476
1477+ def get_sia (self , * , search_type = 'CIRCLE' , ra , dec , radius , calibration = 2 , instrument = 'ALL' , band = None ,
1478+ collection = 'sedm' , dsr_part1 = None , dsr_part2 = None , dsr_part3 = None , output_file = None , verbose = False ):
1479+ """
1480+ Access the Euclid Observation Images by VO SIAP v2.0. This service will return public images from Calibrated
1481+ and Stacked NISP and VIS images, MER Mosaics from VIS and NISP and Level 1 (RAW) images for NISP and VIS
1482+
1483+ Parameters
1484+ ----------
1485+ search_type : str, mandatory, default None
1486+ search region: CIRCLE or BOX
1487+ ra : float (degrees), str or astropy.coordinate, mandatory
1488+ right ascension
1489+ dec : float (degrees), str or astropy.coordinate, mandatory
1490+ declination
1491+ radius : float (degrees), str or astropy.coordinate, mandatory
1492+ search radius of the cutout to generate
1493+ calibration: int, optional, default 2
1494+ calibration level according to ObsCore VO standard: 0 (raw instrumental data), 1 (instrumental data in a
1495+ standard format), 2 (science ready data) or 3 (enhanced data products).
1496+ instrument: str, mandatory, default ALL
1497+ instrument name: ALL, VIS or NISP
1498+ band: str, optional, default None
1499+ filter name only valid if instrument is different from ALL: VIS for instrument VIS or NIR_H, NIR_J, NIR_Y
1500+ or NISP for instrument NISP
1501+ collection : str, mandatory, default sedm
1502+ the name of the data collection
1503+ dsr_part1: str, optional, default None
1504+ the data set release part 1: for OTF environment, the activity code; for REG and IDR, the target environment
1505+ dsr_part2: str, optional, default None
1506+ the data set release part 2: for OTF environment, the patch id (a positive integer); for REG and IDR,
1507+ the activity code
1508+ dsr_part3: str, optional, default None
1509+ the data set release part 3: for OTF, REG and IDR environment, the version (an integer greater than 1)
1510+ output_file : string, optional, default None
1511+ file where the results are saved.
1512+ verbose : bool, optional, default 'False'
1513+ flag to display information about the process
1514+
1515+ Returns
1516+ -------
1517+ A table object or votable file
1518+ """
1519+
1520+ valid_search_types = {'CIRCLE' , 'BOX' }
1521+ valid_calibrations = {0 : 'CALIB_ZERO' , 1 : 'CALIB_ONE' , 2 : 'CALIB_TWO' , 3 : 'CALIB_THREE' }
1522+ valid_instruments = {'ALL' , 'VIS' , 'NISP' }
1523+ valid_band_vis = {'VIS' }
1524+ valid_band_nisp = {'NIR_H' , 'NIR_J' , 'NIR_Y' , 'NISP' }
1525+
1526+ if search_type not in valid_search_types :
1527+ raise ValueError (f"Invalid search tyype { search_type } " )
1528+
1529+ if calibration is not None and calibration not in valid_calibrations :
1530+ raise ValueError (f"Invalid calibration { calibration } " )
1531+
1532+ if instrument not in valid_instruments :
1533+ raise ValueError (f"Invalid instrument { instrument } " )
1534+
1535+ if instrument == 'ALL' and band is not None :
1536+ raise ValueError (f"For instrument { instrument } band must be None" )
1537+
1538+ if instrument == 'VIS' and band is not None and band not in valid_band_vis :
1539+ raise ValueError (f"Invalid band { band } for instrument { instrument } " )
1540+
1541+ if instrument == 'NISP' and band is not None and band not in valid_band_nisp :
1542+ raise ValueError (f"Invalid band { band } for instrument { instrument } " )
1543+
1544+ ra_deg = self .coordinates_degrees (ra )
1545+ dec_deg = self .coordinates_degrees (dec )
1546+ radius_deg = self .coordinates_degrees (radius )
1547+
1548+ params_dict = dict ()
1549+ params_dict ['TAPCLIENT' ] = 'ASTROQUERY'
1550+ params_dict [
1551+ 'POS' ] = f"{ search_type } ,{ ra_deg .to_value (u .deg )} ,{ dec_deg .to_value (u .deg )} ,{ radius_deg .to_value (u .deg )} "
1552+ params_dict ['INSTRUMENT' ] = instrument
1553+ params_dict ['COLLECTION' ] = collection
1554+
1555+ if calibration is not None :
1556+ params_dict ['CALIB' ] = valid_calibrations [calibration ]
1557+
1558+ if instrument != 'ALL' and band is not None :
1559+ params_dict ['BAND' ] = band
1560+
1561+ if dsr_part1 is not None :
1562+ params_dict ['DSP1' ] = dsr_part1
1563+
1564+ if dsr_part2 is not None :
1565+ params_dict ['DSP2' ] = dsr_part2
1566+
1567+ if dsr_part3 is not None :
1568+ params_dict ['DSP3' ] = dsr_part3
1569+
1570+ return self .__euclidsia .load_data (params_dict = params_dict , output_file = output_file , http_method = 'GET' ,
1571+ verbose = verbose )
1572+
1573+ def coordinates_degrees (self , coord ):
1574+
1575+ if not isinstance (coord , units .Quantity ):
1576+ radius_quantity = Quantity (value = coord , unit = u .deg )
1577+ else :
1578+ radius_quantity = coord .to (u .deg )
1579+ return radius_quantity
1580+
14451581 @deprecated_renamed_argument (('instrument' , 'id' ), (None , None ), since = '0.4.12' )
14461582 def get_cutout (self , * , file_path = None , coordinate , radius , output_file = None , verbose = False , instrument = None ,
14471583 id = None ):
0 commit comments