Skip to content

Commit

Permalink
Merge pull request #2442 from jfoster17/add-regiondata
Browse files Browse the repository at this point in the history
Add regiondata
  • Loading branch information
astrofrog authored Oct 23, 2023
2 parents fdc9157 + 75f8bff commit 4f7efcb
Show file tree
Hide file tree
Showing 9 changed files with 1,111 additions and 6 deletions.
1 change: 1 addition & 0 deletions doc/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@
"astropy": ("https://docs.astropy.org/en/stable/", None),
"echo": ("https://echo.readthedocs.io/en/latest/", None),
"pandas": ("https://pandas.pydata.org/pandas-docs/stable/", None),
"shapely": ("https://shapely.readthedocs.io/en/stable/", None),
}

# -- Options for HTML output -------------------------------------------------
Expand Down
105 changes: 104 additions & 1 deletion glue/core/component.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import numpy as np
import pandas as pd
import shapely

from glue.core.coordinate_helpers import dependent_axes, pixel2world_single_axis
from glue.utils import shape_to_string, coerce_numeric, categorical_ndarray
Expand All @@ -13,7 +14,7 @@
DASK_INSTALLED = False

__all__ = ['Component', 'DerivedComponent', 'CategoricalComponent',
'CoordinateComponent', 'DateTimeComponent']
'CoordinateComponent', 'DateTimeComponent', 'ExtendedComponent']


class Component(object):
Expand Down Expand Up @@ -107,6 +108,13 @@ def datetime(self):
"""
return False

@property
def extended(self):
"""
Whether or not or not the datatype represents an extended region
"""
return False

def __str__(self):
return "%s with shape %s" % (self.__class__.__name__, shape_to_string(self.shape))

Expand Down Expand Up @@ -549,3 +557,98 @@ def categorical(self):
@property
def datetime(self):
return False


class ExtendedComponent(Component):
"""
A data component representing an extent or a region.
This component can be used when a dataset describes regions or ranges
and is typically used with a `RegionData` object, since that object
provides helper functions to display regions on viewers. For example,
a `RegionData` object might provide properties of geographic
regions, and the boundaries of these regions would be an ExtendedComponent.
Data loaders are required to know how to convert regions to a list
of Shapely objects which can be used to initialize an ExtendedComponent.
A circular region can be represented as:
>>> circle = shapely.Point(x, y).buffer(rad)
A range in one dimension can be represented as:
>>> range = shapely.LineString([[x0,0],[x1,0]])
(This is a bit of an odd representation, since we are forced to specify a y
coordinate for this line. We adopt a convention of y == 0.)
ExtendedComponents are NOT used directly in linking. Instead, ExtendedComponents
always have corresponding ComponentIDs that represent the x (and y) coordinates
over which the regions are defined. If not specified otherwise, a
`RegionData` object will create 'representative points'
for each region, representing a point near the center of the reigon that is
guaranteed to be inside the region.
NOTE: that this implementation does not support regions in more than
two dimensions. (Shapely has limited support for 3D shapes, but not more).
Parameters
----------
data : list of `shapely.Geometry`` objects
The data to store.
center_comp_ids : list of :class:`glue.core.component_id.ComponentID` objects
The ComponentIDs of the `center` of the extended region. These do not
have to be the literal center of the region, but they must be in the x (and y)
coordinates of the regions. These ComponentIDs are used in the linking
framework to allow an ExtendedComponent to be linked to other components.
units : `str`, optional
Unit description.
Attributes
----------
x : ComponentID
The ComponentID of the x coordinate at the center of the extended region.
y : ComponentID
The ComponentID of the y coordinate at the center of the extended region.
Raises
------
TypeError
If data is not a list of ``shapely.Geometry`` objects
ValueError
If center_comp_ids is not a list of length 1 or 2
"""
def __init__(self, data, center_comp_ids, units=None):
if not all(isinstance(s, shapely.Geometry) for s in data):
raise TypeError(
"Input data for a ExtendedComponent should be a list of shapely.Geometry objects"
)
if len(center_comp_ids) == 2:
self.x = center_comp_ids[0]
self.y = center_comp_ids[1]
elif len(center_comp_ids) == 1:
self.x = center_comp_ids[0]
self.y = None
else:
raise ValueError(
"ExtendedComponent must be initialized with one or two ComponentIDs"
)
self.units = units
self._data = data

@property
def extended(self):
return True

@property
def numeric(self):
return False

@property
def datetime(self):
return False

@property
def categorical(self):
return False
2 changes: 2 additions & 0 deletions glue/core/data.py
Original file line number Diff line number Diff line change
Expand Up @@ -1427,6 +1427,8 @@ def get_kind(self, cid):
return 'numerical'
elif comp.categorical:
return 'categorical'
elif comp.extended:
return 'extended'
else:
raise TypeError("Unknown data kind")

Expand Down
Loading

0 comments on commit 4f7efcb

Please sign in to comment.