Region Shapes¶
Regions provides Region
objects, defined in pixel or sky
coordinates, representing shapes such as circles, ellipses, rectangles,
polygons, lines, and points. There are also regions defining circular,
elliptical, and rectangular annuli.
Defining Shapes¶
This section shows examples of how to construct a region for each shape that’s currently supported.
Circle¶
CircleSkyRegion
and CirclePixelRegion
>>> from astropy.coordinates import SkyCoord
>>> from astropy import units as u
>>> from regions import PixCoord
>>> from regions import CircleSkyRegion, CirclePixelRegion
>>> center_sky = SkyCoord(42, 43, unit='deg', frame='fk5')
>>> region_sky = CircleSkyRegion(center=center_sky, radius=3 * u.deg)
>>> region_pix = CirclePixelRegion(center=PixCoord(x=42, y=43),
... radius=4.2)
CircleAnnulusSkyRegion
and CircleAnnulusPixelRegion
>>> from astropy.coordinates import SkyCoord
>>> from astropy import units as u
>>> from regions import PixCoord
>>> from regions import CircleAnnulusSkyRegion, CircleAnnulusPixelRegion
>>> center_sky = SkyCoord(42, 43, unit='deg', frame='fk5')
>>> region_sky = CircleAnnulusSkyRegion(center=center_sky,
... inner_radius=3 * u.deg,
... outer_radius=4 * u.deg)
>>> region_pix = CircleAnnulusPixelRegion(center=PixCoord(x=42, y=43),
... inner_radius=4.2,
... outer_radius=5.2)
Ellipse¶
EllipseSkyRegion
and EllipsePixelRegion
>>> from astropy.coordinates import SkyCoord
>>> from astropy import units as u
>>> from regions import PixCoord
>>> from regions import EllipseSkyRegion, EllipsePixelRegion
>>> center_sky = SkyCoord(42, 43, unit='deg', frame='fk5')
>>> region_sky = EllipseSkyRegion(center=center_sky,
... height=3 * u.deg, width=3 * u.deg,
... angle=5 * u.deg)
>>> region_pix = EllipsePixelRegion(center=PixCoord(x=42, y=43),
... height=4.2, width=4.2,
... angle=5 * u.deg)
EllipseAnnulusSkyRegion
and
EllipseAnnulusPixelRegion
>>> from astropy.coordinates import SkyCoord
>>> from astropy import units as u
>>> from regions import PixCoord
>>> from regions import EllipseAnnulusSkyRegion, EllipseAnnulusPixelRegion
>>> center_sky = SkyCoord(42, 43, unit='deg', frame='fk5')
>>> region_sky = EllipseAnnulusSkyRegion(center=center_sky,
... inner_width=3 * u.deg,
... outer_width=4 * u.deg,
... inner_height=6 * u.deg,
... outer_height=7 * u.deg,
... angle=6 * u.deg)
>>> region_pix = EllipseAnnulusPixelRegion(center=PixCoord(x=42, y=43),
... inner_width=4.2,
... outer_width=5.2,
... inner_height=7.2,
... outer_height=8.2,
... angle=6 * u.deg)
Rectangle¶
RectangleSkyRegion
and RectanglePixelRegion
>>> from astropy.coordinates import SkyCoord
>>> from astropy import units as u
>>> from regions import PixCoord
>>> from regions import RectangleSkyRegion, RectanglePixelRegion
>>> center_sky = SkyCoord(42, 43, unit='deg', frame='fk5')
>>> region_sky = RectangleSkyRegion(center=center_sky,
... width=3 * u.deg, height=4 * u.deg,
... angle=5 * u.deg)
>>> region_pix = RectanglePixelRegion(center=PixCoord(x=42, y=43),
... width=3, height=4,
... angle=5 * u.deg)
RectangleAnnulusSkyRegion
and
RectangleAnnulusPixelRegion
>>> from astropy.coordinates import SkyCoord
>>> from astropy import units as u
>>> from regions import PixCoord, RectangleAnnulusSkyRegion
>>> from regions import RectangleAnnulusPixelRegion
>>> center_sky = SkyCoord(42, 43, unit='deg', frame='fk5')
>>> region_sky = RectangleAnnulusSkyRegion(center=center_sky,
... inner_width=3 * u.deg,
... outer_width=4 * u.deg,
... inner_height=6 * u.deg,
... outer_height=7 * u.deg,
... angle=15 * u.deg)
>>> region_pix = RectangleAnnulusPixelRegion(center=PixCoord(x=42, y=43),
... inner_width=4.2,
... outer_width=5.2,
... inner_height=7.2,
... outer_height=8.2,
... angle=15 * u.deg)
Polygon¶
PolygonSkyRegion
, PolygonPixelRegion
, and
RegularPolygonPixelRegion
>>> from astropy.coordinates import SkyCoord
>>> from regions import PixCoord, PolygonSkyRegion, PolygonPixelRegion
>>> from regions import RegularPolygonPixelRegion
>>> vertices = SkyCoord([1, 2, 2], [1, 1, 2], unit='deg', frame='fk5')
>>> region_sky = PolygonSkyRegion(vertices=vertices)
>>> vertices = PixCoord(x=[1, 2, 2], y=[1, 1, 2])
>>> region_pix = PolygonPixelRegion(vertices=vertices)
>>> center = PixCoord(25, 25)
>>> region2_pix = RegularPolygonPixelRegion(center, 6, 15)
Point¶
PointSkyRegion
and PointPixelRegion
>>> from astropy.coordinates import SkyCoord
>>> from regions import PixCoord, PointSkyRegion, PointPixelRegion
>>> center_sky = SkyCoord(42, 43, unit='deg', frame='fk5')
>>> region_sky = PointSkyRegion(center=center_sky)
>>> region_pix = PointPixelRegion(center=PixCoord(x=42, y=43))
Line¶
LineSkyRegion
and LinePixelRegion
>>> from astropy.coordinates import SkyCoord
>>> from regions import PixCoord, LineSkyRegion, LinePixelRegion
>>> start_sky = SkyCoord(42, 43, unit='deg', frame='fk5')
>>> end_sky = SkyCoord(52, 53, unit='deg', frame='fk5')
>>> region_sky = LineSkyRegion(start=start_sky, end=end_sky)
>>> region_pix = LinePixelRegion(start=PixCoord(x=42, y=43),
... end=PixCoord(x=52, y=53))
Text¶
The text regions can be used to annotate a text string on an image.
TextSkyRegion
and TextPixelRegion
>>> from astropy.coordinates import SkyCoord
>>> from regions import PixCoord, TextSkyRegion, TextPixelRegion
>>> center_sky = SkyCoord(42, 43, unit='deg', frame='fk5')
>>> region_sky = TextSkyRegion(center=center_sky, text='Demo Text')
>>> region_pix = TextPixelRegion(center=PixCoord(x=42, y=43),
... text='Demo Text')
Region Transformations¶
For every region shape there are two classes, one representing a “sky
region” and another representing a “pixel region” on a given image. A
key feature of the regions package is that it is possible to convert
back and forth between sky and image regions given a WCS object (e.g.,
astropy.wcs.WCS
).
As an example, let’s use the CircleSkyRegion
, a sky
circle region:
>>> from astropy.coordinates import Angle, SkyCoord
>>> from regions import CircleSkyRegion
>>> center = SkyCoord(50, 10, unit='deg')
>>> radius = Angle(30, 'arcsec')
>>> sky_reg = CircleSkyRegion(center, radius)
To convert it to a pixel circle region (i.e.,
CirclePixelRegion
), call the
to_pixel()
method with a WCS object:
>>> pix_reg = sky_reg.to_pixel(wcs)
>>> print(pix_reg)
Region: CirclePixelRegion
center: PixCoord(x=55.35205711214607, y=40.0958313892697)
radius: 0.010259141135043101
Also to convert a PixelRegion
to a SkyRegion
, call the
to_sky()
method with a WCS object:
>>> sky_reg = pix_reg.to_sky(wcs)
>>> print(sky_reg)
Region: CircleSkyRegion
center: <SkyCoord (Galactic): (l, b) in deg
(172.17231545, -38.27972337)>
radius: 18.55481729935556 arcsec
Selectors for Regions¶
Several geometric regions (at this time, RectanglePixelRegion
and EllipsePixelRegion
)
provide a method as_mpl_selector()
to
create an interactive editable matplotlib widget that will be
connected to its parent region.
import matplotlib.pyplot as plt
import numpy as np
from regions import PixCoord, RectanglePixelRegion
x, y = np.mgrid[-15:16, -10:21]
z = np.exp(-(x / 4)**2 - (y / 6)**2)
ax = plt.subplot()
img = ax.imshow(z)
rectangle = RectanglePixelRegion(center=PixCoord(x=12, y=15), width=14, height=10)
selector = rectangle.as_mpl_selector(ax)
(Source code
, png
, hires.png
, pdf
, svg
)
The selector
creates and establishes a link to a matplotlib Selector
widget that allows manually positioning the rectangle
region at the
central point, and scaling it by dragging its corner points.
Several modifier keys as specified by the state_modifier_keys
parameter to
matplotlib.widgets.RectangleSelector
provide further control of the
manipulation of this widget, with the following operations available:
“move”: Move the existing shape from anywhere, default: “space”.
“clear”: Clear the current shape, default: “escape”.
“square”: Make the shape square, default: “shift”.
“center”: Change the shape around its center, default: “ctrl”.
“rotate”: Rotate the shape around its center, default: “r” (toggles, requires Matplotlib 3.6+).
Via the optional callback
parameter this method can be passed a
custom function that will be called on every update of the region,
i.e., after every move or resize of the selector.
For an example of its usage see Interactive Mask Control.
Multiple Regions¶
A Region
object can represent only one region, not an array
(e.g., vector or list) of regions.
This is in contrast to the aperture classes in Photutils like
photutils.aperture.CircularAperture
that do allow the
positions
(but usually not the other parameters) to be arrays:
>>> from photutils import CircularAperture
>>> positions = [(1, 2), (3, 4)]
>>> apertures = CircularAperture(positions, r=4.2)
To represent lists of Region
objects, you can store them in
Python lists or the Regions
class, which effectively acts
like a list of regions. To create many similar regions or process many
regions you can use for loops or list comprehensions.
>>> from regions import PixCoord, CirclePixelRegion
>>> from regions import Regions
>>> regions = [CirclePixelRegion(center=PixCoord(x, y), radius=4.2)
... for x, y in [(1, 2), (3, 4)]]
>>> for region in regions:
... print(region.center)
PixCoord(x=1, y=2)
PixCoord(x=3, y=4)
>>> [region.area for region in regions]
[55.41769440932395, 55.41769440932395]
To create a Regions
object, simply pass in a list of
regions:
>>> regs = Regions(regions)
>>> print(regs[0])
Region: CirclePixelRegion
center: PixCoord(x=1, y=2)
radius: 4.2
>>> [reg.area for reg in regs]
[55.41769440932395, 55.41769440932395]
The Regions
class also provides a unified interface for
reading, writing, parsing, and serializing regions data in
different standard formats.