Skip to content

Commit

Permalink
refactor parser
Browse files Browse the repository at this point in the history
  • Loading branch information
joleroi committed May 11, 2017
1 parent 2743c1c commit ca7f466
Show file tree
Hide file tree
Showing 64 changed files with 623 additions and 613 deletions.
11 changes: 8 additions & 3 deletions dev/regions_parse.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,13 @@
import click
import pyregion
import logging
from regions import read_ds9
from pathlib import Path
from astropy import log

TEST_FILE_DIR = Path('../regions/io/tests/data')
log.setLevel('DEBUG')

TEST_FILE_DIR = Path('../regions/io/ds9/tests/data')

@click.group()
def cli():
Expand All @@ -19,13 +23,14 @@ def list_files():
@cli.command('parse')
@click.option('--interactive', is_flag=True, default=False)
@click.option('--parser', default='regions')
@click.option('--errors', default='strict')
@click.argument('filename')
def parse(filename, interactive, parser):
def parse(filename, interactive, parser, errors):
readname = TEST_FILE_DIR / filename
print('Reading {}'.format(readname))
print('Using parser {}'.format(parser))
if parser == 'regions':
regions = read_ds9(str(readname), errors='warn')
regions = read_ds9(str(readname), errors=errors)
elif parser == 'pyregion':
regions = pyregion.open(str(readname))
print(regions)
Expand Down
100 changes: 50 additions & 50 deletions dev/regions_pyregion_comparison.csv
Original file line number Diff line number Diff line change
@@ -1,52 +1,52 @@
filename,time_regions,time_pyregion,compl_pyregion,compl_regions
ds9.linear.wcsi.reg,0.005,0.842,100.0%,37.1%
ds9.mosaic.fk4.hms.reg,0.029,0.747,100.0%,37.1%
ds9.color.reg,0.005,0.229,100.0%,100.0%
ds9.fk5.strip.reg,0.010,0.345,100.0%,43.3%
ds9.fk5.reg,0.011,0.683,100.0%,36.1%
ds9.physical.strip.reg,0.002,0.368,100.0%,43.3%
ds9.physical.windows.reg,0.002,0.498,100.0%,37.1%
ds9.fk5.hms.reg,0.013,0.477,100.0%,36.1%
ds9.icrs.hms.reg,0.012,0.479,100.0%,36.1%
ds9.icrs.strip.reg,0.010,0.341,100.0%,43.3%
ds9.color.spaces.reg,0.005,0.224,100.0%,100.0%
ds9.mosaic.ecliptic.hms.reg,0.022,0.740,100.0%,37.1%
ds9.linear.wcs.reg,0.004,0.742,100.0%,37.1%
ds9.mosaic.ecliptic.reg,0.019,0.734,100.0%,37.1%
ds9.linear.wcsc.reg,0.004,0.813,100.0%,37.1%
ds9.fk4.hms.strip.reg,0.016,0.400,100.0%,43.3%
ds9.mosaic.galactic.reg,0.021,0.794,100.0%,37.1%
ds9.linear.wcsd.reg,0.004,0.767,100.0%,37.1%
physical_reference.reg,0.001,0.220,100.0%,100.0%
ds9.fk4.reg,0.012,0.467,100.0%,36.1%
ds9.image.strip.reg,0.002,0.321,100.0%,43.3%
ds9.icrs.hms.strip.reg,0.012,0.351,100.0%,43.3%
ds9.image.reg,0.002,0.499,100.0%,36.1%
ds9.mosaic.fk5.hms.reg,0.029,0.777,100.0%,37.1%
ds9.mosaic.image.reg,0.004,0.727,100.0%,37.1%
ds9.physical.reg,0.002,0.437,100.0%,36.1%
ds9.ecliptic.reg,0.010,0.472,100.0%,36.1%
ds9.ecliptic.strip.reg,0.009,0.342,100.0%,43.3%
ds9.fits.reg,0.001,0.253,100.0%,100.0%
ds9.icrs.reg,0.010,0.465,100.0%,36.1%
ds9.mosaic.fk4.reg,0.023,0.739,100.0%,37.1%
ds9.mosaic.icrs.hms.reg,0.023,0.824,100.0%,37.1%
ds9.ecliptic.hms.reg,0.011,0.508,100.0%,36.1%
ds9.fk4.hms.reg,0.014,0.570,100.0%,36.1%
ds9.mosaic.galactic.hms.reg,0.038,0.834,100.0%,37.1%
ds9.mosaic.icrs.reg,0.023,0.820,100.0%,37.1%
ds9.linear.wcsi.reg,0.009,0.775,100.0%,42.9%
ds9.mosaic.fk4.hms.reg,0.034,0.749,100.0%,42.9%
ds9.color.reg,0.005,0.227,100.0%,100.0%
ds9.fk5.strip.reg,0.011,0.350,100.0%,50.0%
ds9.fk5.reg,0.011,0.476,100.0%,41.7%
ds9.physical.strip.reg,0.003,0.338,100.0%,50.0%
ds9.physical.windows.reg,0.003,0.437,100.0%,42.9%
ds9.fk5.hms.reg,0.013,0.506,100.0%,41.7%
ds9.icrs.hms.reg,0.014,0.478,100.0%,41.7%
ds9.icrs.strip.reg,0.010,0.362,100.0%,50.0%
ds9.color.spaces.reg,0.005,0.235,100.0%,100.0%
ds9.mosaic.ecliptic.hms.reg,0.024,0.753,100.0%,42.9%
ds9.linear.wcs.reg,0.008,0.742,100.0%,42.9%
ds9.mosaic.ecliptic.reg,0.021,0.775,100.0%,42.9%
ds9.linear.wcsc.reg,0.007,0.784,100.0%,42.9%
ds9.fk4.hms.strip.reg,0.014,0.346,100.0%,50.0%
ds9.mosaic.galactic.reg,0.022,0.745,100.0%,42.9%
ds9.linear.wcsd.reg,0.007,0.773,100.0%,42.9%
physical_reference.reg,0.001,0.219,100.0%,100.0%
ds9.fk4.reg,0.012,0.484,100.0%,41.7%
ds9.image.strip.reg,0.003,0.324,100.0%,50.0%
ds9.icrs.hms.strip.reg,0.012,0.350,100.0%,50.0%
ds9.image.reg,0.003,0.458,100.0%,41.7%
ds9.mosaic.fk5.hms.reg,0.029,0.771,100.0%,42.9%
ds9.mosaic.image.reg,0.007,0.753,100.0%,42.9%
ds9.physical.reg,0.003,0.446,100.0%,41.7%
ds9.ecliptic.reg,0.011,0.473,100.0%,41.7%
ds9.ecliptic.strip.reg,0.010,0.363,100.0%,50.0%
ds9.fits.reg,0.002,0.262,100.0%,100.0%
ds9.icrs.reg,0.011,0.473,100.0%,41.7%
ds9.mosaic.fk4.reg,0.024,0.768,100.0%,42.9%
ds9.mosaic.icrs.hms.reg,0.025,0.779,100.0%,42.9%
ds9.ecliptic.hms.reg,0.012,0.487,100.0%,41.7%
ds9.fk4.hms.reg,0.014,0.486,100.0%,41.7%
ds9.mosaic.galactic.hms.reg,0.026,0.761,100.0%,42.9%
ds9.mosaic.icrs.reg,0.022,0.764,100.0%,42.9%
ds9.comment.reg,0.000,-1.000,0.0%,nan%
fk5_reference.reg,0.002,0.217,100.0%,100.0%
ds9.mosaic.fk5.reg,0.024,0.847,100.0%,37.1%
ds9.fk4.strip.reg,0.011,0.356,100.0%,43.3%
ds9.galactic.strip.reg,0.013,0.390,100.0%,43.3%
ds9.galactic.reg,0.010,0.543,100.0%,36.1%
ds9.composite.reg,0.011,0.485,100.0%,0.0%
ds9.linear.wcsa.reg,0.005,0.765,100.0%,37.1%
ds9.linear.wcsp.reg,0.005,0.757,100.0%,37.1%
ds9.fk5.hms.strip.reg,0.013,0.342,100.0%,43.3%
ds9.galactic.hms.reg,0.012,0.467,100.0%,36.1%
galactic_reference.reg,0.002,0.219,100.0%,100.0%
ds9.galactic.hms.strip.reg,0.012,0.342,100.0%,43.3%
ds9.mosaic.physical.reg,0.004,0.765,100.0%,37.1%
ds9.ecliptic.hms.strip.reg,0.011,0.343,100.0%,43.3%
fk5_reference.reg,0.003,0.220,100.0%,100.0%
ds9.mosaic.fk5.reg,0.023,0.749,100.0%,42.9%
ds9.fk4.strip.reg,0.012,0.351,100.0%,50.0%
ds9.galactic.strip.reg,0.011,0.349,100.0%,50.0%
ds9.galactic.reg,0.011,0.493,100.0%,41.7%
ds9.composite.reg,0.012,0.474,100.0%,41.7%
ds9.linear.wcsa.reg,0.007,0.775,100.0%,42.9%
ds9.linear.wcsp.reg,0.007,0.760,100.0%,42.9%
ds9.fk5.hms.strip.reg,0.013,0.347,100.0%,50.0%
ds9.galactic.hms.reg,0.013,0.473,100.0%,41.7%
galactic_reference.reg,0.002,0.220,100.0%,100.0%
ds9.galactic.hms.strip.reg,0.013,0.346,100.0%,50.0%
ds9.mosaic.physical.reg,0.007,0.735,100.0%,42.9%
ds9.ecliptic.hms.strip.reg,0.012,0.345,100.0%,50.0%
2 changes: 1 addition & 1 deletion dev/regions_pyregion_comparison.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
import numpy as np
import re

TEST_FILE_DIR = Path('../regions/io/tests/data')
TEST_FILE_DIR = Path('../regions/io/ds9/tests/data')
REPETITIONS = 1

p_region_count = re.compile(r"[^=\)]\(")
Expand Down
6 changes: 1 addition & 5 deletions regions/io/__init__.py
Original file line number Diff line number Diff line change
@@ -1,5 +1 @@
# Licensed under a 3-clause BSD style license - see LICENSE.rst
"""Region I/O.
"""
from .read_ds9 import *
from .write_ds9 import *
from .ds9 import *
2 changes: 2 additions & 0 deletions regions/io/ds9/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
from .read import *
from .write import *
160 changes: 160 additions & 0 deletions regions/io/ds9/core.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,160 @@
# Licensed under a 3-clause BSD style license - see LICENSE.rst
from __future__ import absolute_import, division, print_function
import string
import itertools
import re
import copy
from astropy import units as u
from astropy import coordinates
from astropy.coordinates import BaseCoordinateFrame
from astropy import log
from astropy.utils.exceptions import AstropyUserWarning
from warnings import warn
from ... import shapes
from ...core import PixCoord

__all__ = [
'Shape',
'ShapeList',
]

class ShapeList(list):
"""List of Shape
"""
def to_region(self):
regions = list()
for shape in self:
log.debug(shape)
region = shape.to_region()
log.debug(region)
regions.append(region)
return regions

class Shape(object):
"""Helper class to represent a DS9
This serves as intermediate step in the parsing process.
Parameters
---------
coordsys : str
Coordinate system
region_type : str
Region type
coord : list of `~astropy.coordinates.Angle` or `~astropy.units.Quantity`
Coordinates
meta : dict
Meta attributed
composite : bool
Composite region
include : bool
Include/exclude region
"""
shape_to_sky_region = dict(
circle=shapes.CircleSkyRegion,
ellipse=shapes.EllipseSkyRegion,
box=shapes.RectangleSkyRegion,
polygon=shapes.PolygonSkyRegion,
annulus=shapes.CircleAnnulusSkyRegion,
line=shapes.LineSkyRegion,
point=shapes.PointSkyRegion,
)
shape_to_pixel_region = dict(
circle=shapes.CirclePixelRegion,
ellipse=shapes.EllipsePixelRegion,
box=shapes.RectanglePixelRegion,
polygon=shapes.PolygonPixelRegion,
annulus=shapes.CircleAnnulusPixelRegion,
line=shapes.LinePixelRegion,
point=shapes.PointPixelRegion,
)

def __init__(self, coordsys, region_type, coord, meta, composite, include):
self.coordsys = coordsys
self.region_type=region_type
self.coord=coord
self.meta=meta
self.composite=composite
self.include=include

def __str__(self):
ss = self.__class__.__name__
ss += '\nCoord sys : {}'.format(self.coordsys)
ss += '\nRegion type : {}'.format(self.region_type)
ss += '\nCoord: {}'.format(self.coord)
ss += '\nMeta: {}'.format(self.meta)
ss += '\nComposite: {}'.format(self.composite)
ss += '\nInclude: {}'.format(self.include)
ss += '\n'
return ss

def convert_coords(self):
"""Process list of coordinates
This mainly seaches for tuple of coordinates in the coordinate list and
creates a SkyCoord or PixCoord object from them if appropriate for a
given region type. This involves again some coordinate transformation,
so this step could be moved to the parsing process
"""
from .read import DS9Parser
if self.coordsys in DS9Parser.coordsys_mapping:
coords = self._convert_sky_coords()
else:
coords = self._convert_pix_coords()

if self.region_type == 'line':
coords = [coords[0][0], coords[0][1]]

return coords

def _convert_sky_coords(self):
"""Convert to sky coords"""
parsed_angles = [(x, y)
for x, y in zip(self.coord[:-1:2], self.coord[1::2])
if (isinstance(x, coordinates.Angle) and
isinstance(y, coordinates.Angle))
]
frame = coordinates.frame_transform_graph.lookup_name(self.coordsys)

lon, lat = zip(*parsed_angles)
if hasattr(lon, '__len__') and hasattr(lon, '__lat__') and len(lon) == 1 and len(lat==1):
# force entries to be scalar if they are length-1
lon, lat = u.Quantity(lon[0]), u.Quantity(lat[0])
else:
# otherwise, they are vector quantitites
lon, lat = u.Quantity(lon), u.Quantity(lat)
sphcoords = coordinates.UnitSphericalRepresentation(lon, lat)
coords = [frame(sphcoords)]

if self.region_type != 'polygon':
coords += self.coord[len(coords * 2):]

return coords

def _convert_pix_coords(self):
"""Convert to pix coords"""
if self.region_type in ['polygon', 'line']:
# have to special-case polygon in the phys coord case
# b/c can't typecheck when iterating as in sky coord case
coords = [PixCoord(self.coord[0::2], self.coord[1::2])]
else:
temp = [_.value for _ in self.coord]
coord = PixCoord(temp[0], temp[1])
coords = [coord] + temp[2:]

return coords

def to_region(self):
"""Convert to region object
"""
coords = self.convert_coords()
log.debug(coords)
viz_keywords = ['color', 'dashed', 'width', 'point', 'font']

if isinstance(coords[0], BaseCoordinateFrame):
reg = self.shape_to_sky_region[self.region_type](*coords)
elif isinstance(coords[0], PixCoord):
reg = self.shape_to_pixel_region[self.region_type](*coords)
else:
raise DS9RegionParserError("No central coordinate")
return reg
Loading

0 comments on commit ca7f466

Please sign in to comment.