Skip to content

Commit

Permalink
Merge pull request #194 from sushobhana/plotting
Browse files Browse the repository at this point in the history
Improvement in Plotting methods.
  • Loading branch information
keflavich committed Jul 20, 2018
2 parents 197806d + 694f698 commit 7dd0951
Show file tree
Hide file tree
Showing 21 changed files with 379 additions and 162 deletions.
13 changes: 7 additions & 6 deletions regions/core/attributes.py
Expand Up @@ -278,13 +278,13 @@ class RegionMeta(dict):
"""
A python dictionary subclass which holds the meta attributes of the region.
"""
valid_keys = ['label', 'symbol', 'include', 'frame', 'range', 'veltype',
'restfreq', 'tag', 'comment', 'coord', 'line', 'name',
valid_keys = ['label', 'include', 'frame', 'range', 'veltype',
'restfreq', 'tag', 'comment', 'line', 'name',
'select', 'highlite', 'fixed', 'edit', 'move', 'rotate',
'delete', 'source', 'background', 'corr', 'type'
]

key_mapping = {'point': 'symbol', 'text': 'label'}
key_mapping = {}

def __setitem__(self, key, value):
key = self.key_mapping.get(key, key)
Expand All @@ -303,10 +303,11 @@ class RegionVisual(dict):
A python dictionary subclass which holds the visual attributes of the region.
"""
valid_keys = ['color', 'dash', 'font', 'dashlist', 'symsize', 'symthick',
'fontsize', 'fontstyle', 'usetex', 'labelpos', 'labeloff',
'linewidth', 'linestyle', 'fill', 'line']
'symbol', 'fontsize', 'fontstyle', 'usetex', 'labelpos',
'labeloff', 'linewidth', 'linestyle', 'fill', 'line',
'textangle', 'fontweight']

key_mapping = {'width': 'linewidth'}
key_mapping = {'width': 'linewidth', 'point': 'symbol'}

def __setitem__(self, key, value):
key = self.key_mapping.get(key, key)
Expand Down
44 changes: 42 additions & 2 deletions regions/core/compound.py
@@ -1,12 +1,13 @@
# Licensed under a 3-clause BSD style license - see LICENSE.rst
from __future__ import absolute_import, division, print_function, unicode_literals

import operator as op

import numpy as np

from . import PixelRegion, SkyRegion, BoundingBox, Mask
from ..core.attributes import CompoundRegionPix, CompoundRegionSky


__all__ = ['CompoundPixelRegion', 'CompoundSkyRegion']


Expand Down Expand Up @@ -84,8 +85,47 @@ def to_sky(self, wcs):
operator=self.operator,
region2=skyreg2, meta=self.meta, visual=self.visual)

@staticmethod
def _make_annulus_path(patch_inner, patch_outer):
"""
Define a matplotlib annulus path from two patches.
This preserves the cubic Bezier curves (CURVE4) of the aperture
paths.
# This is borrowed from photutils aperture.
"""

import matplotlib.path as mpath

path_inner = patch_inner.get_path()
transform_inner = patch_inner.get_transform()
path_inner = transform_inner.transform_path(path_inner)

path_outer = patch_outer.get_path()
transform_outer = patch_outer.get_transform()
path_outer = transform_outer.transform_path(path_outer)

verts_inner = path_inner.vertices[:-1][::-1]
verts_inner = np.concatenate((verts_inner, [verts_inner[-1]]))

verts = np.vstack((path_outer.vertices, verts_inner))
codes = np.hstack((path_outer.codes, path_inner.codes))

return mpath.Path(verts, codes)

def as_patch(self, **kwargs):
raise NotImplementedError

if self.region1.center == self.region2.center and self.operator == op.xor:
import matplotlib.patches as mpatches

patch_inner = self.region1.as_patch()
patch_outer = self.region2.as_patch()
path = self._make_annulus_path(patch_inner, patch_outer)
patch = mpatches.PathPatch(path, **kwargs)
return patch
else:
raise NotImplementedError

def to_shapely(self, **kwargs):
raise NotImplementedError
Expand Down
36 changes: 35 additions & 1 deletion regions/core/core.py
Expand Up @@ -4,6 +4,8 @@
import abc
import operator

import numpy as np

from astropy.extern import six

__all__ = ['Region', 'PixelRegion', 'SkyRegion']
Expand Down Expand Up @@ -217,6 +219,36 @@ def as_patch(self, **kwargs):
"""
raise NotImplementedError

def mpl_properties_default(self, shape='patch'):

# The default values are set as per DS9 convention.

kwargs = dict()
kwargs['color'] = self.visual.get('color', 'green')
kwargs['label'] = self.meta.get('label', "")

if shape == 'text':
kwargs['family'] = self.visual.get('font', 'helvetica')
kwargs['rotation'] = self.visual.get('textangle', '0')
kwargs['size'] = self.visual.get('fontsize', '12')
kwargs['style'] = self.visual.get('fontsyle', 'normal')
kwargs['weight'] = self.visual.get('fontweight', 'roman')

else:
if shape == 'Line2D':
kwargs['marker'] = self.visual.get('symbol', 'o')
kwargs['markersize'] = self.visual.get('symsize', 11)
kwargs['markeredgecolor'] = kwargs['color']
kwargs['markeredgewidth'] = self.visual.get('width', 1)
if shape == 'patch':
kwargs['edgecolor'] = kwargs.pop('color')
kwargs['fill'] = self.visual.get('fill', False)

kwargs['linewidth'] = self.visual.get('linewidth', 1)
kwargs['linestyle'] = self.visual.get('linstyle', 'solid')

return kwargs

def plot(self, ax=None, **kwargs):
"""
Calls as_patch method forwarding all kwargs and adds patch
Expand All @@ -232,7 +264,9 @@ def plot(self, ax=None, **kwargs):
if ax is None:
ax = plt.gca()

patch = self.as_patch(**kwargs)
mpl_params = self.mpl_properties_default('patch')
mpl_params.update(kwargs)
patch = self.as_patch(**mpl_params)
ax.add_patch(patch)

return ax
Expand Down
11 changes: 11 additions & 0 deletions regions/core/pixcoord.py
Expand Up @@ -109,6 +109,17 @@ def __getitem__(self, key):
y = self.y[key]
return PixCoord(x=x, y=y)

def __eq__(self, other):
"""
It checks whether ``other`` is `PixCoord` object and whether their
abscissa and ordinate values are equal using ``np.assert_allclose``
with their default tolerance values.
"""
if isinstance(other, PixCoord):
return np.allclose([self.x, self.y], [other.x, other.y])
else:
return False

def to_sky(self, wcs, origin=_DEFAULT_WCS_ORIGIN, mode=_DEFAULT_WCS_MODE):
"""Convert this `PixCoord` to `~astropy.coordinates.SkyCoord`.
Expand Down
47 changes: 38 additions & 9 deletions regions/core/tests/test_pixcoord.py
Expand Up @@ -31,6 +31,9 @@ def test_pixcoord_basics_scalar():
p1 = PixCoord(x=np.array(1), y=2)
p2 = PixCoord(x=np.array(1), y=np.array(2))

assert p == p1
assert p1 == p2

assert p.x == 1
assert p.y == 2

Expand Down Expand Up @@ -121,8 +124,8 @@ def test_pixcoord_to_sky_scalar(wcs):
p2 = PixCoord.from_sky(skycoord=s, wcs=wcs)
assert isinstance(p2.x, float)
assert p2.isscalar
assert_allclose(p2.x, p.x)
assert_allclose(p2.y, p.y)

assert p == p2


def test_pixcoord_to_sky_array_1d(wcs):
Expand All @@ -137,27 +140,30 @@ def test_pixcoord_to_sky_array_1d(wcs):
assert isinstance(p2.x, np.ndarray)
assert p2.x.shape == (2, )
assert not p2.isscalar
assert_allclose(p2.x, p.x)
assert_allclose(p2.y, p.y)

assert p == p2


def test_pixcoord_to_sky_array_2d(wcs):
# p = PixCoord(x=[[17, 17, 17], [18, 18, 18]], y=[[8, 8, 8], [9, 9, 9]])
p1 = PixCoord(x=[[17, 17, 17], [18, 18, 18]], y=[[8, 8, 8], [9, 9, 9]])
p = PixCoord(x=[[17, 18]], y=[[8, 9]])

s = p.to_sky(wcs=wcs)
assert s.name == 'galactic'
# assert_allclose(s.data.lon.deg, [[0, 0, 0], [349.88094, 349.88094, 349.88094]])
# assert_allclose(s.data.lat.deg, [[0, 0, 0], [10.003028, 10.003028, 10.003028]])

s1 = p1.to_sky(wcs=wcs)
assert s.name == 'galactic'
assert_allclose(s1.data.lon.deg, [[0, 0, 0], [349.88094, 349.88094, 349.88094]])
assert_allclose(s1.data.lat.deg, [[0, 0, 0], [10.003028, 10.003028, 10.003028]])
assert_allclose(s.data.lon.deg, [[0, 349.88094]])
assert_allclose(s.data.lat.deg, [[0, 10.003028]])

p2 = PixCoord.from_sky(skycoord=s, wcs=wcs)
assert isinstance(p2.x, np.ndarray)
assert p2.x.shape == (1, 2)
assert not p2.isscalar
assert_allclose(p2.x, p.x)
assert_allclose(p2.y, p.y)

assert p == p2


def test_pixcoord_separation_scalar():
Expand Down Expand Up @@ -202,3 +208,26 @@ def test_pixcoord_shapely_array():
p = PixCoord(x=[1, 2, 3], y=[11, 22, 33])
with pytest.raises(TypeError):
p.to_shapely()


def test_equality():
a = np.array([1, 2])
b = PixCoord(a[0], a[1])
c = PixCoord(a[0]+0.0000001, a[1])

assert not b == a
assert b == b
assert b == c

a = PixCoord(
[[1, 2, 3], [4, 5, 6]],
[[11, 12, 13], [14, 15, 16]],
)

b = PixCoord(
[[1, 2, 3], [4, 5, 6]],
[[11.0000002, 12, 13], [14, 15, 16]],
)

assert a == b
assert a == a

0 comments on commit 7dd0951

Please sign in to comment.