# Licensed under a 3-clause BSD style license - see LICENSE.rst
"""
This module defines text regions in both pixel and sky coordinates.
"""
import math
import astropy.units as u
from regions._utils.wcs_helpers import (pixel_shape_to_sky_svd,
sky_shape_to_pixel_svd)
from regions.core.attributes import (RegionMetaDescr, RegionVisualDescr,
ScalarPixCoord, ScalarSkyCoord)
from regions.core.pixcoord import PixCoord
from regions.shapes.point import PointPixelRegion, PointSkyRegion
__all__ = ['TextSkyRegion', 'TextPixelRegion']
[docs]
class TextPixelRegion(PointPixelRegion):
"""
A text string in pixel coordinates.
Parameters
----------
center : `~regions.PixCoord`
The leftmost point of the text string before rotation.
text : str
The text string.
meta : `~regions.RegionMeta` or `dict`, optional
A dictionary that stores the meta attributes of the region.
visual : `~regions.RegionVisual` or `dict`, optional
A dictionary that stores the visual meta attributes of the
region.
Examples
--------
.. plot::
:include-source:
import matplotlib.pyplot as plt
from regions import PixCoord, RegionVisual, TextPixelRegion
fig, ax = plt.subplots()
center = PixCoord(x=15, y=10)
visual = RegionVisual({'textangle': 30})
reg = TextPixelRegion(center=center, text='Hello World!',
visual=visual)
reg.plot(ax=ax)
ax.set_xlim(10, 30)
ax.set_ylim(2.5, 20)
ax.set_aspect('equal')
"""
_params = ('center', 'text')
_mpl_artist = 'Text'
center = ScalarPixCoord('The leftmost pixel position (before rotation) '
'as a |PixCoord|.')
meta = RegionMetaDescr('The meta attributes as a |RegionMeta|')
visual = RegionVisualDescr('The visual attributes as a |RegionVisual|.')
def __init__(self, center, text, meta=None, visual=None):
super().__init__(center, meta, visual)
self.text = text
[docs]
def to_sky(self, wcs):
rotation_rad = math.radians(self.visual.get('rotation', 0.0))
# Extract the sky rotation angle of the text via a unit-size SVD
# ellipse so the conversion correctly handles WCS shear. The
# photutils SVD helpers measure the sky rotation as a position
# angle (PA) from North; regions measures it from the RA axis.
# Convert between them with a 90 deg offset.
center, _, _, sky_angle = pixel_shape_to_sky_svd(
(self.center.x, self.center.y), wcs, 1.0, 1.0, rotation_rad)
sky_angle = (sky_angle + 90 * u.deg).wrap_at(360 * u.deg)
# Rotation value is relative to the coordinate system axes;
# convert from counterclockwise angle from the positive x axis
# to angle relative to WCS longitude axis.
visual = self.visual
if 'rotation' in self.visual:
visual = visual.copy()
visual['rotation'] = sky_angle.to('deg').value
return TextSkyRegion(center, self.text, meta=self.meta.copy(),
visual=visual.copy())
[docs]
def to_spherical_sky(self, wcs=None, include_boundary_distortions=False,
n_points=None):
raise NotImplementedError
[docs]
def as_artist(self, origin=(0, 0), **kwargs):
"""
Return a matplotlib Text object for this region
(`matplotlib.text.Text`).
Parameters
----------
origin : array_like, optional
The ``(x, y)`` pixel position of the origin of the displayed
image.
**kwargs : dict
Any keyword arguments accepted by `~matplotlib.text.Text`.
These keywords will override any visual meta attributes of
this region.
Returns
-------
artist : `~matplotlib.text.Text`
A matplotlib Text object.
"""
from matplotlib.text import Text
mpl_kwargs = self.visual.define_mpl_kwargs(self._mpl_artist)
mpl_kwargs.update(kwargs)
return Text(self.center.x - origin[0], self.center.y - origin[1],
self.text, **mpl_kwargs)
[docs]
class TextSkyRegion(PointSkyRegion):
"""
A text string in sky coordinates.
Parameters
----------
center : `~astropy.coordinates.SkyCoord`
The leftmost position of the text string before rotation.
text : str
The text string.
meta : `~regions.RegionMeta` or `dict`, optional
A dictionary that stores the meta attributes of the region.
visual : `~regions.RegionVisual` or `dict`, optional
A dictionary that stores the visual meta attributes of the
region.
"""
_params = ('center', 'text')
center = ScalarSkyCoord('The leftmost position (before rotation) as a '
'|SkyCoord|.')
meta = RegionMetaDescr('The meta attributes as a |RegionMeta|')
visual = RegionVisualDescr('The visual attributes as a |RegionVisual|.')
def __init__(self, center, text, meta=None, visual=None):
super().__init__(center, meta, visual)
self.text = text
[docs]
def to_pixel(self, wcs):
rotation_rad = math.radians(self.visual.get('rotation', 0.0))
# Extract the pixel rotation angle of the text via a unit-size
# SVD ellipse so the conversion correctly handles WCS shear.
# Convert regions sky angle (from RA axis) to photutils PA (from
# North) by subtracting 90 deg.
center, _, _, pixel_angle = sky_shape_to_pixel_svd(
self.center, wcs, 1.0, 1.0, rotation_rad - math.pi / 2)
# Rotation value is relative to the WCS longitude axis;
# convert to counterclockwise angle from the positive x axis.
visual = self.visual
if 'rotation' in self.visual:
visual = visual.copy()
visual['rotation'] = pixel_angle.to('deg').value
return TextPixelRegion(PixCoord(*center), self.text,
meta=self.meta.copy(),
visual=visual.copy())
[docs]
def to_spherical_sky(self, wcs=None, include_boundary_distortions=False,
n_points=None):
raise NotImplementedError