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

Implement compound regions #26

Merged
merged 2 commits into from
May 4, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
13 changes: 9 additions & 4 deletions regions/core/compound.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,16 +29,21 @@ class CompoundSkyRegion(SkyRegion):
Represents the logical combination of two regions in sky coordinates.
"""

def __init__(self, region1, operator, region2):
def __init__(self, region1, region2, operator):
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The reason I had operator in the center is because it makes it clearer how to deal with non-symmetric cases (e.g. region 1 without region 2)

Copy link
Contributor Author

@joleroi joleroi May 4, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There was a bug (e.g. https://github.com/astropy/regions/blob/master/regions/core/core.py#L67) . It was just easier to change this line instead of all the others .. Do you need the operator in the middle?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah I see - I personally think it would make it more readable, but up to you :)

Copy link
Contributor Author

@joleroi joleroi May 4, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm more the RPN guy, you know 😉

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

😆

self.region1 = region1
self.region2 = region2
self.operator = operator

def __contains__(self, skycoord):
raise NotImplementedError("")
def contains(self, skycoord):
return self.operator(self.region1.contains(skycoord),
self.region2.contains(skycoord))

def to_pixel(self, wcs, mode='local', tolerance=None):
raise NotImplementedError("")

def __repr__(self):
return "({0} {1} {2})".format(self.region1, self.operator, self.region2)
return "({0}\n{1}\n{2})".format(self.region1, self.operator, self.region2)

@property
def area(self):
raise NotImplementedError("")
8 changes: 6 additions & 2 deletions regions/core/core.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,10 @@ def __or__(self, other):
def __xor__(self, other):
return self.symmetric_difference(other)

def __contains__(self, coord):
# Todo: only works for scalar cases, test for this?
return self.contains(coord)


@six.add_metaclass(abc.ABCMeta)
class PixelRegion(Region):
Expand Down Expand Up @@ -72,7 +76,7 @@ def union(self, other):
return CompoundPixelRegion(self, other, operator.or_)

@abc.abstractmethod
def __contains__(self, pixcoord):
def contains(self, pixcoord):
"""
Checks whether a position or positions fall inside the region.

Expand Down Expand Up @@ -192,7 +196,7 @@ def union(self, other):
return CompoundSkyRegion(self, other, operator.or_)

@abc.abstractmethod
def __contains__(self, skycoord):
def contains(self, skycoord):
"""
Checks whether a position or positions fall inside the region.

Expand Down
4 changes: 4 additions & 0 deletions regions/core/tests/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
# Licensed under a 3-clause BSD style license - see LICENSE.rst
"""
This packages contains affiliated package tests.
"""
31 changes: 31 additions & 0 deletions regions/core/tests/coveragerc
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
[run]
source = {packagename}
omit =
{packagename}/_astropy_init*
{packagename}/conftest*
{packagename}/cython_version*
{packagename}/setup_package*
{packagename}/*/setup_package*
{packagename}/*/*/setup_package*
{packagename}/tests/*
{packagename}/*/tests/*
{packagename}/*/*/tests/*
{packagename}/version*

[report]
exclude_lines =
# Have to re-enable the standard pragma
pragma: no cover

# Don't complain about packages we have installed
except ImportError

# Don't complain if tests don't hit assertions
raise AssertionError
raise NotImplementedError

# Don't complain about script hooks
def main\(.*\):

# Ignore branches that don't pertain to this version of Python
pragma: py{ignore_python_version}
46 changes: 46 additions & 0 deletions regions/core/tests/test_compound.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import astropy.units as u
from astropy.coordinates import SkyCoord

from regions.shapes import CircleSkyRegion


def test_compound():

skycoord1 = SkyCoord(0 * u.deg, 0 * u.deg, frame='galactic')
c1 = CircleSkyRegion(skycoord1, 1 * u.deg)

skycoord2 = SkyCoord(1 * u.deg, 1 * u.deg, frame='galactic')
c2 = CircleSkyRegion(skycoord2, 0.5 * u.deg)

test_coord1 = SkyCoord(1.2 * u.deg, 1.2 * u.deg, frame='galactic')
test_coord2 = SkyCoord(0.5 * u.deg, 0.5 * u.deg, frame='galactic')
test_coord3 = SkyCoord(0.7 * u.deg, 0.7 * u.deg, frame='galactic')
test_coord4 = SkyCoord(2 * u.deg, 5 * u.deg, frame='galactic')

assert test_coord1 in c2 and test_coord1 not in c1
assert test_coord2 not in c2 and test_coord2 in c1
assert test_coord3 in c1 and test_coord3 in c2
assert test_coord4 not in c2 and test_coord4 not in c1

coords = SkyCoord([test_coord1, test_coord2, test_coord3, test_coord4], frame='galactic')

union = c1 | c2
assert (union.contains(coords) == [True, True, True, False]).all()

intersection = c1 & c2
assert (intersection.contains(coords) == [False, False, True, False]).all()

diff = c1 ^ c2
assert (diff.contains(coords) == [True, True, False, False]).all()


c3 = CircleSkyRegion(test_coord4, 0.1 * u.deg)

union = c1 | c2 | c3
assert (union.contains(coords) == [True, True, True, True]).all()

intersection = c1 & c2 & c3
assert (intersection.contains(coords) == [False, False, False, False]).all()

diff = c1 ^ c2 ^ c3
assert (diff.contains(coords) == [True, True, False, True]).all()
12 changes: 9 additions & 3 deletions regions/shapes/circle.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ def __init__(self, center, radius, meta=None, visual=None):
def area(self):
return math.pi * self.radius ** 2

def __contains__(self, pixcoord):
def contains(self, pixcoord):
return np.hypot(pixcoord.x - self.center.x,
pixcoord.y - self.center.y) < self.radius

Expand Down Expand Up @@ -87,8 +87,14 @@ def __init__(self, center, radius, meta=None, visual=None):
def area(self):
return math.pi * self.radius ** 2

def __contains__(self, skycoord):
return self.center.separation(skycoord)
def contains(self, skycoord):
return self.center.separation(skycoord) < self.radius

def __repr__(self):
clsnm = self.__class__.__name__
coord = self.center
rad = self.radius
return '{clsnm}\nCenter:{coord}\nRadius:{rad}'.format(**locals())

def to_pixel(self, mywcs, mode='local', tolerance=None):
"""
Expand Down
4 changes: 2 additions & 2 deletions regions/shapes/ellipse.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ def __init__(self, center, minor, major, angle=0. * u.deg, meta=None,
def area(self):
return math.pi * self.minor * self.major

def __contains__(self, pixcoord):
def contains(self, pixcoord):
# TODO: needs to be implemented
raise NotImplementedError("")

Expand Down Expand Up @@ -85,7 +85,7 @@ def area(self):
# TODO: needs to be implemented
raise NotImplementedError("")

def __contains__(self, skycoord):
def contains(self, skycoord):
# TODO: needs to be implemented
raise NotImplementedError("")

Expand Down
4 changes: 2 additions & 2 deletions regions/shapes/point.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ def __init__(self, center, meta=None, visual=None):
def area(self):
return 0

def __contains__(self, pixcoord):
def contains(self, pixcoord):
return False

def to_shapely(self):
Expand Down Expand Up @@ -62,7 +62,7 @@ def __init__(self, center, meta=None, visual=None):
def area(self):
return 0

def __contains__(self, skycoord):
def contains(self, skycoord):
return False

def to_pixel(self, wcs, mode='local', tolerance=None):
Expand Down
5 changes: 2 additions & 3 deletions regions/shapes/polygon.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ def area(self):
# TODO: needs to be implemented
raise NotImplementedError("")

def __contains__(self, pixcoord):
def contains(self, pixcoord):
# TODO: needs to be implemented
raise NotImplementedError("")

Expand All @@ -39,7 +39,6 @@ def to_mask(self, mode='center'):
raise NotImplementedError("")



class PolygonSkyRegion(SkyRegion):
"""
A polygon in sky coordinates.
Expand All @@ -61,7 +60,7 @@ def area(self):
# TODO: needs to be implemented
raise NotImplementedError("")

def __contains__(self, skycoord):
def contains(self, skycoord):
# TODO: needs to be implemented
raise NotImplementedError("")

Expand Down
4 changes: 2 additions & 2 deletions regions/shapes/rectangle.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ def __init__(self, center, height, width, angle=0 * u.deg, meta=None, visual=Non
def area(self):
return self.width * self.height

def __contains__(self, pixcoord):
def contains(self, pixcoord):
# TODO: needs to be implemented
raise NotImplementedError("")

Expand Down Expand Up @@ -81,7 +81,7 @@ def __init__(self, center, height, width, angle=0 * u.deg, meta=None, visual=Non
def area(self):
return self.width * self.height

def __contains__(self, skycoord):
def contains(self, skycoord):
# TODO: needs to be implemented
raise NotImplementedError("")

Expand Down
1 change: 1 addition & 0 deletions regions/shapes/tests/test_circle.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ def test_init_sky():


# Todo : restructure test to use same circle everywhere
# see https://github.com/astropy/regions/pull/20
@pytest.mark.skipif('not HAS_MATPLOTLIB')
def test_plot():
import matplotlib.pyplot as plt
Expand Down