Skip to content

Commit

Permalink
Merge pull request #13953 from WilliamJamieson/black/coordinates
Browse files Browse the repository at this point in the history
Apply `black` to `astropy.coordinates`
  • Loading branch information
astrofrog committed Nov 14, 2022
2 parents a8cb166 + da8973f commit 01d2839
Show file tree
Hide file tree
Showing 104 changed files with 11,114 additions and 8,193 deletions.
292 changes: 159 additions & 133 deletions astropy/coordinates/angle_formats.py

Large diffs are not rendered by default.

62 changes: 41 additions & 21 deletions astropy/coordinates/angle_utilities.py
Expand Up @@ -4,9 +4,14 @@
used internally in astropy.coordinates.angles, and of possible
"""

__all__ = ['angular_separation', 'position_angle', 'offset_by',
'golden_spiral_grid', 'uniform_spherical_random_surface',
'uniform_spherical_random_volume']
__all__ = [
"angular_separation",
"position_angle",
"offset_by",
"golden_spiral_grid",
"uniform_spherical_random_surface",
"uniform_spherical_random_volume",
]

# Third-party
import numpy as np
Expand All @@ -18,6 +23,8 @@
UnitSphericalRepresentation,
)

_TWOPI = 2 * np.pi


def angular_separation(lon1, lat1, lon2, lat2):
"""
Expand Down Expand Up @@ -85,7 +92,7 @@ def position_angle(lon1, lat1, lon2, lat2):
x = np.sin(lat2) * np.cos(lat1) - colat * np.sin(lat1) * np.cos(deltalon)
y = np.sin(deltalon) * colat

return Angle(np.arctan2(y, x), u.radian).wrap_at(360*u.deg)
return Angle(np.arctan2(y, x), u.radian).wrap_at(360 * u.deg)


def offset_by(lon, lat, posang, distance):
Expand Down Expand Up @@ -139,7 +146,7 @@ def offset_by(lon, lat, posang, distance):
small_sin_c = sin_c < 1e-12
if small_sin_c.any():
# For south pole (cos_c = -1), A = posang; for North pole, A=180 deg - posang
A_pole = (90*u.deg + cos_c*(90*u.deg-Angle(posang, u.radian))).to(u.rad)
A_pole = (90 * u.deg + cos_c * (90 * u.deg - Angle(posang, u.radian))).to(u.rad)
if A.shape:
# broadcast to ensure the shape is like that of A, which is also
# affected by the (possible) shapes of lat, posang, and distance.
Expand All @@ -148,7 +155,7 @@ def offset_by(lon, lat, posang, distance):
else:
A = A_pole

outlon = (Angle(lon, u.radian) + A).wrap_at(360.0*u.deg).to(u.deg)
outlon = (Angle(lon, u.radian) + A).wrap_at(360.0 * u.deg).to(u.deg)
outlat = Angle(np.arcsin(cos_b), u.radian).to(u.deg)

return outlon, outlat
Expand All @@ -175,7 +182,7 @@ def golden_spiral_grid(size):
golden_r = (1 + 5**0.5) / 2

grid = np.arange(0, size, dtype=float) + 0.5
lon = 2*np.pi / golden_r * grid * u.rad
lon = _TWOPI / golden_r * grid * u.rad
lat = np.arcsin(1 - 2 * grid / size) * u.rad

return UnitSphericalRepresentation(lon, lat)
Expand All @@ -197,7 +204,7 @@ def uniform_spherical_random_surface(size=1):

rng = np.random # can maybe switch to this being an input later - see #11628

lon = rng.uniform(0, 2*np.pi, size) * u.rad
lon = rng.uniform(0, _TWOPI, size) * u.rad
lat = np.arcsin(rng.uniform(-1, 1, size=size)) * u.rad

return UnitSphericalRepresentation(lon, lat)
Expand Down Expand Up @@ -232,17 +239,30 @@ def uniform_spherical_random_volume(size=1, max_radius=1):
# # below here can be deleted in v5.0
from astropy.utils.decorators import deprecated

__old_angle_utilities_funcs = ['check_hms_ranges', 'degrees_to_dms',
'degrees_to_string', 'dms_to_degrees',
'format_exception', 'hms_to_degrees',
'hms_to_dms', 'hms_to_hours',
'hms_to_radians', 'hours_to_decimal',
'hours_to_hms', 'hours_to_radians',
'hours_to_string', 'parse_angle',
'radians_to_degrees', 'radians_to_dms',
'radians_to_hms', 'radians_to_hours',
'sexagesimal_to_string']
__old_angle_utilities_funcs = [
"check_hms_ranges",
"degrees_to_dms",
"degrees_to_string",
"dms_to_degrees",
"format_exception",
"hms_to_degrees",
"hms_to_dms",
"hms_to_hours",
"hms_to_radians",
"hours_to_decimal",
"hours_to_hms",
"hours_to_radians",
"hours_to_string",
"parse_angle",
"radians_to_degrees",
"radians_to_dms",
"radians_to_hms",
"radians_to_hours",
"sexagesimal_to_string",
]
for funcname in __old_angle_utilities_funcs:
vars()[funcname] = deprecated(name='astropy.coordinates.angle_utilities.' + funcname,
alternative='astropy.coordinates.angle_formats.' + funcname,
since='v4.3')(getattr(angle_formats, funcname))
vars()[funcname] = deprecated(
name="astropy.coordinates.angle_utilities." + funcname,
alternative="astropy.coordinates.angle_formats." + funcname,
since="v4.3",
)(getattr(angle_formats, funcname))
125 changes: 69 additions & 56 deletions astropy/coordinates/angles.py
Expand Up @@ -15,13 +15,13 @@

from . import angle_formats as form

__all__ = ['Angle', 'Latitude', 'Longitude']
__all__ = ["Angle", "Latitude", "Longitude"]


# these are used by the `hms` and `dms` attributes
hms_tuple = namedtuple('hms_tuple', ('h', 'm', 's'))
dms_tuple = namedtuple('dms_tuple', ('d', 'm', 's'))
signed_dms_tuple = namedtuple('signed_dms_tuple', ('sign', 'd', 'm', 's'))
hms_tuple = namedtuple("hms_tuple", ("h", "m", "s"))
dms_tuple = namedtuple("dms_tuple", ("d", "m", "s"))
signed_dms_tuple = namedtuple("signed_dms_tuple", ("sign", "d", "m", "s"))


class Angle(u.SpecificTypeQuantity):
Expand Down Expand Up @@ -102,11 +102,11 @@ class Angle(u.SpecificTypeQuantity):
`~astropy.units.UnitsError`
If a unit is not provided or it is not an angular unit.
"""

_equivalent_unit = u.radian
_include_easy_conversion_members = True

def __new__(cls, angle, unit=None, dtype=np.inexact, copy=True, **kwargs):

if not isinstance(angle, u.Quantity):
if unit is not None:
unit = cls._convert_unit_to_angle_unit(u.Unit(unit))
Expand All @@ -123,24 +123,23 @@ def __new__(cls, angle, unit=None, dtype=np.inexact, copy=True, **kwargs):
if angle_unit == u.hourangle:
form._check_hour_range(angle[0])
form._check_minute_range(angle[1])
a = np.abs(angle[0]) + angle[1] / 60.
a = np.abs(angle[0]) + angle[1] / 60.0
if len(angle) == 3:
form._check_second_range(angle[2])
a += angle[2] / 3600.
a += angle[2] / 3600.0

angle = np.copysign(a, angle[0])

if angle_unit is not unit:
# Possible conversion to `unit` will be done below.
angle = u.Quantity(angle, angle_unit, copy=False)

elif (isiterable(angle) and
not (isinstance(angle, np.ndarray) and
angle.dtype.kind not in 'SUVO')):
elif isiterable(angle) and not (
isinstance(angle, np.ndarray) and angle.dtype.kind not in "SUVO"
):
angle = [Angle(x, unit, copy=False) for x in angle]

return super().__new__(cls, angle, unit, dtype=dtype, copy=copy,
**kwargs)
return super().__new__(cls, angle, unit, dtype=dtype, copy=copy, **kwargs)

@staticmethod
def _tuple_to_float(angle, unit):
Expand Down Expand Up @@ -196,13 +195,22 @@ def signed_dms(self):
This is primarily intended for use with `dms` to generate string
representations of coordinates that are correct for negative angles.
"""
return signed_dms_tuple(np.sign(self.degree),
*form.degrees_to_dms(np.abs(self.degree)))

def to_string(self, unit=None, decimal=False, sep='fromunit',
precision=None, alwayssign=False, pad=False,
fields=3, format=None):
""" A string representation of the angle.
return signed_dms_tuple(
np.sign(self.degree), *form.degrees_to_dms(np.abs(self.degree))
)

def to_string(
self,
unit=None,
decimal=False,
sep="fromunit",
precision=None,
alwayssign=False,
pad=False,
fields=3,
format=None,
):
"""A string representation of the angle.
Parameters
----------
Expand Down Expand Up @@ -277,41 +285,44 @@ def to_string(self, unit=None, decimal=False, sep='fromunit',
unit = self._convert_unit_to_angle_unit(u.Unit(unit))

separators = {
'generic': {
u.degree: 'dms',
u.hourangle: 'hms'},
'latex': {
u.degree: [r'^\circ', r'{}^\prime', r'{}^{\prime\prime}'],
u.hourangle: [r'^{\mathrm{h}}', r'^{\mathrm{m}}', r'^{\mathrm{s}}']},
'unicode': {
u.degree: '°′″',
u.hourangle: 'ʰᵐˢ'}
"generic": {u.degree: "dms", u.hourangle: "hms"},
"latex": {
u.degree: [r"^\circ", r"{}^\prime", r"{}^{\prime\prime}"],
u.hourangle: [r"^{\mathrm{h}}", r"^{\mathrm{m}}", r"^{\mathrm{s}}"],
},
"unicode": {u.degree: "°′″", u.hourangle: "ʰᵐˢ"},
}
# 'latex_inline' provides no functionality beyond what 'latex' offers,
# but it should be implemented to avoid ValueErrors in user code.
separators['latex_inline'] = separators['latex']
separators["latex_inline"] = separators["latex"]
# Default separators are as for generic.
separators[None] = separators['generic']
separators[None] = separators["generic"]

# Create an iterator so we can format each element of what
# might be an array.
if not decimal and (unit_is_deg := unit == u.degree
or unit == u.hourangle):
if not decimal and (unit_is_deg := unit == u.degree or unit == u.hourangle):
# Sexagesimal.
if sep == 'fromunit':
if sep == "fromunit":
if format not in separators:
raise ValueError(f"Unknown format '{format}'")
sep = separators[format][unit]
func = functools.partial(
form.degrees_to_string if unit_is_deg else form.hours_to_string,
precision=precision, sep=sep, pad=pad, fields=fields)
precision=precision,
sep=sep,
pad=pad,
fields=fields,
)
else:
if sep != 'fromunit':
raise ValueError(f"'{unit}' can not be represented in sexagesimal notation")
if sep != "fromunit":
raise ValueError(
f"'{unit}' can not be represented in sexagesimal notation"
)
func = ("{:g}" if precision is None else f"{{0:0.{precision}f}}").format
if not (decimal and format is None): # Don't add unit by default for decimal.
# Don't add unit by default for decimal.
if not (decimal and format is None):
unit_string = unit.to_string(format=format)
if format == 'latex' or format == 'latex_inline':
if format == "latex" or format == "latex_inline":
unit_string = unit_string[1:-1]
format_func = func
func = lambda x: format_func(x) + unit_string
Expand All @@ -321,16 +332,16 @@ def do_format(val):
# a hexagesimal string.
if not np.isnan(val):
s = func(float(val))
if alwayssign and not s.startswith('-'):
s = '+' + s
if format == 'latex' or format == 'latex_inline':
s = f'${s}$'
if alwayssign and not s.startswith("-"):
s = "+" + s
if format == "latex" or format == "latex_inline":
s = f"${s}$"
return s
s = f"{val}"
return s

values = self.to_value(unit)
format_ufunc = np.vectorize(do_format, otypes=['U'])
format_ufunc = np.vectorize(do_format, otypes=["U"])
result = format_ufunc(values)

if result.ndim == 0:
Expand All @@ -352,7 +363,7 @@ def _wrap_at(self, wrap_angle):
# Do the wrapping, but only if any angles need to be wrapped
#
# Catch any invalid warnings from the floor division.
with np.errstate(invalid='ignore'):
with np.errstate(invalid="ignore"):
wraps = (self_angle - wrap_angle_floor) // a360
valid = np.isfinite(wraps) & (wraps != 0)
if np.any(valid):
Expand Down Expand Up @@ -455,13 +466,13 @@ def _str_helper(self, format=None):
def formatter(x):
return x.to_string(format=format)

return np.array2string(self, formatter={'all': formatter})
return np.array2string(self, formatter={"all": formatter})

def __str__(self):
return self._str_helper()

def _repr_latex_(self):
return self._str_helper(format='latex')
return self._str_helper(format="latex")


def _no_angle_subclass(obj):
Expand Down Expand Up @@ -522,6 +533,7 @@ class Latitude(Angle):
`TypeError`
If the angle parameter is an instance of :class:`~astropy.coordinates.Longitude`.
"""

def __new__(cls, angle, unit=None, **kwargs):
# Forbid creating a Lat from a Long.
if isinstance(angle, Longitude):
Expand Down Expand Up @@ -550,11 +562,12 @@ def _validate_angles(self, angles=None):
else:
limit = u.degree.to(angles.unit, 90.0)

invalid_angles = (np.any(angles.value < -limit)
or np.any(angles.value > limit))
invalid_angles = np.any(angles.value < -limit) or np.any(angles.value > limit)
if invalid_angles:
raise ValueError('Latitude angle(s) must be within -90 deg <= angle <= 90 deg, '
'got {}'.format(angles.to(u.degree)))
raise ValueError(
"Latitude angle(s) must be within -90 deg <= angle <= 90 deg, "
f"got {angles.to(u.degree)}"
)

def __setitem__(self, item, value):
# Forbid assigning a Long to a Lat.
Expand All @@ -572,7 +585,7 @@ def __array_ufunc__(self, *args, **kwargs):


class LongitudeInfo(u.QuantityInfo):
_represent_as_dict_attrs = u.QuantityInfo._represent_as_dict_attrs + ('wrap_angle',)
_represent_as_dict_attrs = u.QuantityInfo._represent_as_dict_attrs + ("wrap_angle",)


class Longitude(Angle):
Expand Down Expand Up @@ -636,11 +649,12 @@ class Longitude(Angle):
def __new__(cls, angle, unit=None, wrap_angle=None, **kwargs):
# Forbid creating a Long from a Lat.
if isinstance(angle, Latitude):
raise TypeError("A Longitude angle cannot be created from "
"a Latitude angle.")
raise TypeError(
"A Longitude angle cannot be created from a Latitude angle."
)
self = super().__new__(cls, angle, unit=unit, **kwargs)
if wrap_angle is None:
wrap_angle = getattr(angle, 'wrap_angle', self._default_wrap_angle)
wrap_angle = getattr(angle, "wrap_angle", self._default_wrap_angle)
self.wrap_angle = wrap_angle # angle-like b/c property setter
return self

Expand All @@ -662,8 +676,7 @@ def wrap_angle(self, value):

def __array_finalize__(self, obj):
super().__array_finalize__(obj)
self._wrap_angle = getattr(obj, '_wrap_angle',
self._default_wrap_angle)
self._wrap_angle = getattr(obj, "_wrap_angle", self._default_wrap_angle)

# Any calculation should drop to Angle
def __array_ufunc__(self, *args, **kwargs):
Expand Down

0 comments on commit 01d2839

Please sign in to comment.