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

Add regiondata #2442

Merged
merged 20 commits into from
Oct 23, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
eabe4e3
Add ExtendedComponent and RegionData classes
jfoster17 Sep 13, 2023
5d7d0ee
Add action to convert subset of regions to subset over coordinates
jfoster17 Sep 13, 2023
26c062a
Change name for subset conversion action
jfoster17 Sep 13, 2023
a44a27e
Codestyle fixes
jfoster17 Sep 13, 2023
9db0dd2
Fix documentation links
jfoster17 Sep 14, 2023
7404528
Add extended type to data get_kind
jfoster17 Sep 18, 2023
8cead7a
Merge branch 'glue-viz:main' into add-regiondata
jfoster17 Sep 19, 2023
4ffc1c8
Move RegionData to own file and motivate use
jfoster17 Sep 22, 2023
7f6b846
Add convenience funcs for checking validity and transforming regions
jfoster17 Sep 22, 2023
60da317
Improve and test the validation and transformation logic
jfoster17 Sep 22, 2023
7bcd9dd
Make linked_to_center_comp work with MultiLinks
jfoster17 Sep 22, 2023
585469c
Update to work for MultiLink links
jfoster17 Sep 25, 2023
fbc88bb
Consolidate to a single function for 1D/2D transformation function
jfoster17 Sep 25, 2023
e22e6bc
Change transform signature to work with shapely transform
jfoster17 Sep 25, 2023
3d63e11
Codestyle fix
jfoster17 Sep 25, 2023
288f713
Move test file to parallel location
jfoster17 Sep 25, 2023
0005024
Save ComponentID uuids to allow region_data save/restore
jfoster17 Sep 26, 2023
08fc900
Add documentation for why we use RegionData
jfoster17 Sep 26, 2023
395602a
Fix naming for _save_shapely_geometry
jfoster17 Sep 26, 2023
75f8bff
Merge remote-tracking branch 'refs/remotes/origin/add-regiondata' int…
jfoster17 Sep 26, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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 @@
"""
return False

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

Check warning on line 116 in glue/core/component.py

View check run for this annotation

Codecov / codecov/patch

glue/core/component.py#L116

Added line #L116 was not covered by tests

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

Expand Down Expand Up @@ -549,3 +557,98 @@
@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