Executing ADQL queries from the command line and external scripts
The entry point is a TAP (Table Access Protocol) server, that allows to execute queries that returns data as tables. To get final products like images or spectra please read their corresponding sections.
You may use HTTP protocol to execute TAP requests at https://eas.esac.esa.int/tap-server/tap.
TAP provides two operation modes: Synchronous and Asynchronous:
Synchronous: the response to the request will be generated as soon as the request received by the server.
Asynchronous: the server will start a job that will execute the request. The first response to the request is the required information (a link) to obtain the job status. Once the job is finished, the results can be retrieved.
Our TAP server provides two access modes: public and authenticated:
Public: this is the standard TAP access. A user can execute ADQL queries and upload tables to be used in a query 'on-the-fly' (these tables will be removed once the query is executed). The results are available to any other user and they will remain in the server for a limited space of time.
Authenticated: some functionalities are restricted to authenticated users only. The results are saved in a private user space and they will remain in their account. The user account space is limited, currently of 10 GB by default . The user can select specific jobs and delete them manually from the ADQL FORM interface.
ADQL queries and results are saved in a user private area.
Cross-match operations: a catalogue cross-match operation can be executed. Cross-match operations results are saved in a user private area.
Persistence of uploaded tables: a user can upload a table in a private space (top left options of the ADQL FORM). These tables can be used in queries as well as in cross-matches operations.
Below you will find some examples on how to execute queries using the curl tool. This method can be used in scripts and programs to automatically get data from the Euclid databases. The URLs for the curl command can also be pasted in a browser tab for a quick test (remember to log in to access private tables).
Non authenticated access
Getting all public tables
curl
"https://eas.esac.esa.int/tap-server/tap/tables"
Authenticated access
To authenticate (log in and out) using the command line, you can use the following two commands. Any query in next subsections should be executed between them.
curl -k -c cookies.txt -X POST -d username=USER -d password=PASSWORD -L
"https://eas.esac.esa.int/tap-server/login"
curl -k -b cookies.txt -X POST -d -L
"https://eas.esac.esa.int/tap-server/logout"
Synchronous query
curl -k -b cookies.txt -X GET
"https://eas.esac.esa.int/tap-server/tap/sync?REQUEST=doQuery&LANG=ADQL&FORMAT=csv&QUERY=SELECT+TOP+50+object_id,right_ascension,declination+FROM+sascat_sc8.mer_final_cat_sc8"
> out.csv
The retrieved results is CSV table, or a VO table if FORMAT is not specified (see '3.2. Synchronous Queries' section parameters to specify a different output format). Ending the command with a > out.csv, the results can be saved in a file and inspected using any analysis tool like TOPCAT, for instance.
Asynchronous query
curl -i -k -b cookies.txt -X POST --data
"PHASE=run&LANG=ADQL&REQUEST=doQuery&QUERY=SELECT+TOP+50+object_id,right_ascension,declination+FROM+sascat_sc8.mer_final_cat_sc8"
"https://eas.esac.esa.int/tap-server/tap/async"
The response will contain the URL of the job running at server side (see Location header):
HTTP/
1.1
303
See Other
Date: Thu,
21
Sep
2017
16
:
16
:
08
GMT
Server: Apache-Coyote/
1.1
Location: https:
//eas.esac.esa.int/tap-server/tap/async/1506010568630L
Content-Type: text/plain;charset=ISO-
8859
-
1
Connection: close
Transfer-Encoding: chunked
To obtain the status of the running job:
curl -k -b cookies.txt -X GET
"https://eas.esac.esa.int/tap-server/tap/async/1506010568630L"
The status response is something like:
<?xml version=
"1.0"
encoding=
"UTF-8"
?>
<uws:job xmlns:uws=
"http://www.ivoa.net/xml/UWS/v1.0"
xmlns:xlink=
"http://www.w3.org/1999/xlink"
xmlns:xs=
"http://www.w3.org/2001/XMLSchema"
xmlns:xsi=
"http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation=
"http://www.ivoa.net/xml/UWS/v1.0 http://www.ivoa.net/xml/UWS/v1.0"
>
<uws:jobId><![CDATA[1506010568630L]]></uws:jobId>
<uws:runId xsi:nil=
"true"
/>
<uws:ownerId><![CDATA[anonymous]]></uws:ownerId>
<uws:phase>COMPLETED</uws:phase>
<uws:quote>-
1
</uws:quote>
<uws:startTime>
2021
-
09
-21T18:
16
:
09.052
+
0200
</uws:startTime>
<uws:endTime>
2021
-
09
-21T18:
16
:
09.323
+
0200
</uws:endTime>
<uws:executionDuration>
0
</uws:executionDuration>
<uws:destruction>
2021
-
09
-24T18:
16
:
08.630
+
0200
</uws:destruction>
<uws:creationTime>
2021
-
09
-21T18:
16
:
08.630
+
0200
</uws:creationTime>
<uws:parameters>
<uws:parameter id=
"query"
><![CDATA[SELECT TOP
50
objectid,rightascension,declination FROM sascat_sc8.mer_final_cat_sc8]]></uws:parameter>
<uws:parameter id=
"request"
><![CDATA[doQuery]]></uws:parameter>
<uws:parameter id=
"format"
><![CDATA[csv]]></uws:parameter>
<uws:parameter id=
"phase"
><![CDATA[run]]></uws:parameter>
<uws:parameter id=
"lang"
><![CDATA[ADQL]]></uws:parameter>
</uws:parameters>
<uws:results>
<uws:result id=
"result"
xlink:type=
"simple"
xlink:href=
"https://eas.esac.esa.int/tap-server/tap/async/1506010568630L/results/result"
mime=
"application/x-csv+xml"
size=
"2148"
rows=
"50"
/>
</uws:results>
<uws:errorSummary xsi:nil=
"true"
/>
</uws:job>
To obtain the results of the job (once the job is finished):
curl -k -b cookies.txt -X GET
"https://eas.esac.esa.int/tap-server/tap/async/1506010568630L/results/result"
The retrieved results is a VO table by default (see '3.3. Asynchronous Queries' section parameters to specify a different output format). As in previous examples the results can be saved in a file and inspected using any analysis tool like TOPCAT, for instance.
Python 3 script to execute an asynchronous query and wait until the results are available
See also the Jupyter Notebook section.
#ASYNCHRONOUS REQUEST
import
urllib.parse
import
urllib.request
import
time
from xml.dom.minidom
import
parseString
url =
"https://eas.esac.esa.int/tap-server/tap/async"
contenttype =
"application/x-www-form-urlencoded"
textplain =
"text/plain"
#-------------------------------------
#Create job
params = urllib.parse.urlencode({\
"REQUEST"
:
"doQuery"
, \
"LANG"
:
"ADQL"
, \
"FORMAT"
:
"csv"
, \
"PHASE"
:
"RUN"
, \
"JOBNAME"
:
"Any name (optional)"
, \
"JOBDESCRIPTION"
:
"Any description (optional)"
, \
"QUERY"
:
"SELECT DISTANCE(POINT('ICRS', right_ascension, declination), POINT('ICRS',9.95,-19.20)) AS dist, * FROM sascat_sc8.mer_final_cat_sc8 WHERE 1=CONTAINS(POINT('ICRS', right_ascension, declination),CIRCLE('ICRS',9.95,-19.20,0.05)) ORDER BY dist ASC"
})
request = urllib.request.Request(url, method=
"POST"
)
request.add_header(
"Content-type"
,
"application/x-www-form-urlencoded"
)
request.add_header(
"Accept"
,
"text/plain"
)
connection = urllib.request.urlopen(request, data=params.encode(
"UTF-8"
))
#Status
print (
"Status: "
+str(connection.getcode()),
"Reason: "
+ str(connection.reason))
#Server job location (URL)
info = connection.info()
redirection = connection.geturl()
#Jobid
jobid = redirection[redirection.rfind(
'/'
)+
1
:]
print (
"Job id: "
+ jobid)
connection.close()
#-------------------------------------
#Check job status, wait until finished
while
True:
request = urllib.request.Request(redirection, method=
"GET"
)
connection = urllib.request.urlopen(request)
data = connection.read().decode(
"UTF-8"
)
#XML response: parse it to obtain the current status
dom = parseString(data)
phaseElement = dom.getElementsByTagName(
'uws:phase'
)[
0
]
phaseValueElement = phaseElement.firstChild
phase = phaseValueElement.toxml()
print (
"Status: "
+ phase)
#Check finished
if
phase ==
'COMPLETED'
:
break
#wait and repeat
time.sleep(
0.2
)
connection.close()
#-------------------------------------
#Get results
request = urllib.request.Request(redirection+
"/results/result"
, method=
"GET"
)
connection = urllib.request.urlopen(request)
data = connection.read().decode(
"UTF-8"
)
outputFileName =
"example3_csv_output.csv"
outputFile = open(outputFileName,
"w"
)
outputFile.write(data)
outputFile.close()
connection.close()
print (
"Data saved in: "
+ outputFileName)
The saved file is a VO table (by default, see '3.3. Asynchronous Queries' section parameters to specify a different output format). The file can be inspected using any analysis tool like TOPCAT, for instance.
Python 3 script to save the results of asynchronous job into VOSpace account
To insert files into VOSpace we need to generate the following XML file transfer_push_to_a.xml, where:
target: is the VOSpace URI to put the query result
direction: to upload files, it should be fixed to 'pushToVoSpace'
view: parameter fixed to 'text'
protocol: parameter fixed to 'httpput'
To use the following Python code, you should fill the following parameters:
user: name of the ESA Ldap user account
pssd: password of the ESA Ldap account
metadataTransfer: name of the above file
toupload: name of the file to upload to VOSpace
import
urllib.request, requests, ssl, base64, time, json
import
xml.dom.minidom
user=
'user-ldap-name'
pssd=
'user-password'
metadataTransfer=
'name-xml-metadata-file'
toupload=
'name-file-to-be-saved'
transfer_url=
'https://vospace.esac.esa.int/vospace/servlet/transfers/async?PHASE=RUN'
end_point =
"https://vospace.esac.esa.int/vospace/service/data/"
f = open(metadataTransfer,
'r'
, encoding=
"utf-8"
).read()
files = {
'file'
: (metadataTransfer, f)}
try
:
upload_request = requests.post(transfer_url, files=files, auth=(user, pssd))
except requests.exceptions.RequestException as e: # This is the correct syntax
print (upload_request.text)
sys.exit(
1
)
else
: #
200
redirection = upload_request.url
jobid = redirection[redirection.rfind(
'/'
)+
1
:]
#print (
"Job id: "
+ jobid)
upload_request.close()
while
True:
request = requests.get(redirection, auth=(user, pssd))
#XML response: parse it to obtain the current status
data=request.text
dom = xml.dom.minidom.parseString(data)
phaseElement = dom.getElementsByTagName(
'uws:phase'
)[
0
]
phaseValueElement = phaseElement.firstChild
phase = phaseValueElement.toxml()
print (
"Status: "
+ phase)
#Check finished
if
phase ==
'COMPLETED'
:
break
if
phase ==
'ERROR'
: sys.exit(
1
)
#wait and repeat
time.sleep(
0.3
)
# Open XML document using minidom parser
DOMTree = xml.dom.minidom.parseString(data)
collection = DOMTree.documentElement
jobId_element = collection.getElementsByTagName(
'uws:jobId'
)[
0
]
jobId = jobId_element.childNodes[
0
].data
f = open(toupload,
'rb'
).read()
files = {
'file'
: (toupload, f)}
try
:
upload_post = requests.post(end_point + user +
"/"
+ jobId, files=files, auth=(user, pssd))
except requests.exceptions.RequestException as e: # This is the correct syntax
print (upload_post.text)
sys.exit(
1
)
else
: #
200
#print(upload_post.text)
redirection = upload_post.url
jobid = redirection[redirection.rfind(
'/'
)+
1
:]
print (
"Job id: "
+ jobid)
upload_post.close()
if
upload_post.ok:
print (
"Done, Ok........................................................."
);
Interface
See the following specifications:
TAP resources
https://eas.esac.esa.int/tap-server/tap/
Tables |
https://eas.esac.esa.int/tap-server/tap/tables |
Synchronous access |
https://eas.esac.esa.int/tap-server/tap/sync |
Asynchronous access |
https://eas.esac.esa.int/tap-server/tap/async |
Service availability |
https://eas.esac.esa.int/tap-server/tap/availability |
Synchronous Queries
Parameter |
Value |
Comments |
REQUEST |
doQuery |
Requests to execute the provided query |
LANG |
ADQL |
Query language |
FORMAT |
- votable |
Results output format |
QUERY |
ADQL query |
query |
Asynchronous Queries
Parameter |
Value |
Comments |
Same parameters as those defined in 3.2 Synchronous Queries and |
||
PHASE |
run |
Query job initial phase |
The response header will contain the location of the job.
TAP+ login
Parameter |
Value |
Comments |
username |
user_name |
User name |
password |
user_password |
User password |
The response header will contain the session identifier.
TAP+ logout
Parameter |
Value |
Comments |
session identifier |
session identifier |
Session identifier provided by a login request |