#!/usr/bin/env python
#
# source.py
# Provides a new class that extends astropy SkyCoord.
#
# Copyright (C) 2020 Douglas Boubert
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License along
# with this program; if not, write to the Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
#
from __future__ import print_function, division
import astropy.coordinates as coordinates
import astropy.units as units
from functools import wraps
class Photometry():
def __init__(self,photometry,photometry_error):
self.measurement = {k:v for k,v in photometry.items()}
self.error = {k:v for k,v in photometry_error.items()} if photometry_error is not None else None
class Source():
def __init__(self,*args,photometry={},photometry_error={},**kwargs):
self.coord = coordinates.SkyCoord(*args,**kwargs)
self.photometry = Photometry(photometry,photometry_error) if photometry is not None else None
[docs]def ensure_distance(f):
"""
A decorator for class methods of the form
.. code-block:: python
Class.method(self, coords, **kwargs)
where ``coords`` is an :obj:`astropy.coordinates.SkyCoord` object.
The decorator ensures that the ``coords`` that gets passed to
``Class.method`` is a flat array of Equatorial coordinates. It also reshapes
the output of ``Class.method`` to have the same shape (possibly scalar) as
the input ``coords``. If the output of ``Class.method`` is a tuple or list
(instead of an array), each element in the output is reshaped instead.
Args:
f (class method): A function with the signature
``(self, coords, **kwargs)``, where ``coords`` is a :obj:`SkyCoord`
object containing an array.
Returns:
A function that takes :obj:`SkyCoord` input with any shape (including
scalar).
"""
@wraps(f)
def _wrapper_func(self, sources, **kwargs):
# t0 = time.time()
has_distance = hasattr(sources.coord, 'distance')
if has_distance:
pass
else:
raise ValueError('You need to pass in a distance to use this selection function.')
out = f(self, sources, **kwargs)
return out
return _wrapper_func
[docs]def ensure_gaia_g(f):
"""
A decorator for class methods of the form
.. code-block:: python
Class.method(self, coords, **kwargs)
where ``coords`` is an :obj:`astropy.coordinates.SkyCoord` object.
The decorator ensures that the ``coords`` that gets passed to
``Class.method`` is a flat array of Equatorial coordinates. It also reshapes
the output of ``Class.method`` to have the same shape (possibly scalar) as
the input ``coords``. If the output of ``Class.method`` is a tuple or list
(instead of an array), each element in the output is reshaped instead.
Args:
f (class method): A function with the signature
``(self, coords, **kwargs)``, where ``coords`` is a :obj:`SkyCoord`
object containing an array.
Returns:
A function that takes :obj:`SkyCoord` input with any shape (including
scalar).
"""
@wraps(f)
def _wrapper_func(self, sources, **kwargs):
# t0 = time.time()
has_photometry = hasattr(sources, 'photometry')
if has_photometry:
has_gaia_g = 'gaia_g' in sources.photometry.measurement.keys()
if has_gaia_g:
pass
else:
print('No Gaia G passed, but transformation is not yet implemented.')
raise ValueError('You need to pass in Gaia G-band photometric magnitudes to use this selection function.')
else:
raise ValueError('You need to pass in Gaia G-band photometric magnitudes to use this selection function.')
out = f(self, sources, **kwargs)
return out
return _wrapper_func
[docs]def ensure_gaia_g_gaia_rp(f):
"""
A decorator for class methods of the form
.. code-block:: python
Class.method(self, coords, **kwargs)
where ``coords`` is an :obj:`astropy.coordinates.SkyCoord` object.
The decorator ensures that the ``coords`` that gets passed to
``Class.method`` is a flat array of Equatorial coordinates. It also reshapes
the output of ``Class.method`` to have the same shape (possibly scalar) as
the input ``coords``. If the output of ``Class.method`` is a tuple or list
(instead of an array), each element in the output is reshaped instead.
Args:
f (class method): A function with the signature
``(self, coords, **kwargs)``, where ``coords`` is a :obj:`SkyCoord`
object containing an array.
Returns:
A function that takes :obj:`SkyCoord` input with any shape (including
scalar).
"""
@wraps(f)
def _wrapper_func(self, sources, **kwargs):
# t0 = time.time()
has_photometry = hasattr(sources, 'photometry')
if has_photometry:
has_gaia_g_gaia_rp = ('gaia_g_gaia_rp' in sources.photometry.measurement.keys()) | \
(('gaia_g' in sources.photometry.measurement.keys())&\
('gaia_rp'in sources.photometry.measurement.keys()))
if has_gaia_g_gaia_rp | ( not self.require_colour ):
pass
else:
print('No Gaia G-Grp passed.')
raise ValueError('You need to pass in Gaia G-Grp photometric colour to use this selection function.')
else:
raise ValueError('You need to pass in Gaia G-band photometric magnitudes and G-Grp colour to use this selection function.')
out = f(self, sources, **kwargs)
return out
return _wrapper_func
[docs]def ensure_tmass_hjk(f):
"""
A decorator for class methods of the form
.. code-block:: python
Class.method(self, coords, **kwargs)
where ``coords`` is an :obj:`astropy.coordinates.SkyCoord` object.
The decorator ensures that the ``coords`` that gets passed to
``Class.method`` is a flat array of Equatorial coordinates. It also reshapes
the output of ``Class.method`` to have the same shape (possibly scalar) as
the input ``coords``. If the output of ``Class.method`` is a tuple or list
(instead of an array), each element in the output is reshaped instead.
Args:
f (class method): A function with the signature
``(self, coords, **kwargs)``, where ``coords`` is a :obj:`SkyCoord`
object containing an array.
Returns:
A function that takes :obj:`SkyCoord` input with any shape (including
scalar).
"""
@wraps(f)
def _wrapper_func(self, sources, **kwargs):
# t0 = time.time()
has_photometry = hasattr(sources, 'photometry')
if has_photometry:
has_tmass_h = 'tmass_h' in sources.photometry.measurement.keys()
has_tmass_jk = 'tmass_jk' in sources.photometry.measurement.keys()
if has_tmass_h: pass
else:
print('No 2MASS H magnitude passed (tmass_h), but transformation is not yet implemented.')
raise ValueError('You need to pass in 2MASS H photometric magnitudes to use this selection function.')
if has_tmass_jk: pass
else:
print('No 2MASS J-K colour passed (tmass_jk), but transformation is not yet implemented.')
raise ValueError('You need to pass in 2MASS J-K colour to use this selection function.')
else:
raise ValueError('You need to pass in 2MASS H photometric magnitudes and J-K colours to use this selection function.')
out = f(self, sources, **kwargs)
return out
return _wrapper_func