Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

New service: THOR survey #1372

Open
wants to merge 3 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 33 additions & 0 deletions astroquery/surveys/thor/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
# Licensed under a 3-clause BSD style license - see LICENSE.rst
"""
THOR Image Query Tool
---------------------
.. topic:: Revision History

:Originally contributed by:

Adam Ginsburg ([email protected])

"""
from astropy import config as _config


class Conf(_config.ConfigNamespace):
"""
Configuration parameters for `astroquery.magpis`.
"""
server = _config.ConfigItem(
['http://astro.kent.ac.uk'],
'Name of the THOR server.')
timeout = _config.ConfigItem(
60,
'Time limit for connecting to THOR server.')


conf = Conf()

from .core import Thor, ThorClass

__all__ = ['Thor', 'ThorClass',
'Conf', 'conf',
]
125 changes: 125 additions & 0 deletions astroquery/surveys/thor/core.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
# Licensed under a 3-clause BSD style license - see LICENSE.rst
from __future__ import print_function
import os
import astropy.units as u
import astropy.coordinates as coord
from astropy.io import fits
from ...query import BaseQuery
from ...utils import commons, prepend_docstr_nosections
from ...utils.process_asyncs import async_to_sync
from . import conf
from ...exceptions import InvalidQueryError

import tarfile
from bs4 import BeautifulSoup

__all__ = ['Thor', 'ThorClass']


@async_to_sync
class ThorClass(BaseQuery):
URL = conf.server
TIMEOUT = conf.timeout

def _args_to_payload(self, coordinates, image_size=1 * u.arcmin):
"""
Fetches image cutouts from THOR surveys.

Parameters
----------
coordinates : str or `astropy.coordinates` object
The target around which to search. It may be specified as a
string in which case it is resolved using online services or as
the appropriate `astropy.coordinates` object. ICRS coordinates
may also be entered as strings as specified in the
`astropy.coordinates` module.
image_size : str or `~astropy.units.Quantity` object, optional
The string must be parsable by `astropy.coordinates.Angle`. The
appropriate `~astropy.units.Quantity` object from `astropy.units`
may also be used. Specifies the symmetric size of the
image. Defaults to 1 arcmin.
"""
request_payload = {}
request_payload["catalogue"] = "thor"
c = commons.parse_coordinates(coordinates).transform_to('galactic')
request_payload["x_coord"] = "{0:0.5f}".format(c.l.deg)
request_payload["y_coord"] = "{0:0.5f}".format(c.b.deg)
request_payload["coord_type"] = "Galactic"
request_payload["size_long"] = coord.Angle(image_size).deg
request_payload["size_lat"] = coord.Angle(image_size).deg
request_payload["size_type"] = "degrees"
request_payload["cmap"] = "Greyscale"
request_payload["scale"] = "99.99"
request_payload["sigma_value"] = ""

assert len(request_payload) == 10

return request_payload

@prepend_docstr_nosections("\n" + _args_to_payload.__doc__)
def get_images_async(self, coordinates, image_size=1 * u.arcmin,
get_query_payload=False, **kwargs):
"""
get_query_payload : bool, optional
if set to `True` then returns the dictionary sent as the HTTP
request. Defaults to `False`

Returns
-------
response : `requests.Response`
The HTTP response returned from the service
"""
request_payload = self._args_to_payload(coordinates,
image_size=image_size)
if get_query_payload:
return request_payload

# the THOR server expects WebkitForm stuff, i.e., files
files = {key:(None, str(val)) for key, val in request_payload.items()}

# initialize the session; probably not needed?
imageserver = self.URL + '/thor_server/image_server'
init_session = self._request("GET", imageserver)
init_session.raise_for_status()

response = self._request("POST", url=imageserver, files=files,
timeout=self.TIMEOUT, verify=False)
response.raise_for_status()

return response

def _parse_result(self, response, verbose=False):
"""
"""
soup = BeautifulSoup(response.text, 'html5lib')

links = soup.findAll('a')

download_link = [x for x in links if x.text == 'Download FITS Files'][0]

url = self.URL + download_link.attrs['href']
filename = url.split("/")[-1]

local_filepath = os.path.join(self.cache_location, filename)

self._download_file(url, local_filepath, timeout=self.TIMEOUT)

tf = tarfile.open(local_filepath)

paths = []

for ff in tf.getmembers():
if '.fits' in ff.name:
# remove the leading path
ff.name = os.path.basename(ff.name)

tf.extract(member=ff, path=self.cache_location)
paths.append(os.path.join(self.cache_location, ff.name))

tf.close()

return paths



Thor = ThorClass()