Skip to content

Commit

Permalink
rename to Graph and move namespace
Browse files Browse the repository at this point in the history
  • Loading branch information
martinfleis committed Jul 28, 2023
1 parent c65d3e5 commit ded0625
Show file tree
Hide file tree
Showing 16 changed files with 92 additions and 93 deletions.
File renamed without changes.
1 change: 1 addition & 0 deletions libpysal/graph/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
from .base import Graph # noqa
File renamed without changes.
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ def kernel(
to be constant across samples. If None, no truncation is conduted.
ids : numpy.narray (default: None)
ids to use for each sample in coordinates. Generally, construction functions
that are accessed via W.from_kernel() will set this automatically from
that are accessed via Graph.build_kernel() will set this automatically from
the index of the input. Do not use this argument directly unless you intend
to set the indices separately from your input data. Otherwise, use
data.set_index(ids) to ensure ordering is respected. If None, then the index
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -63,35 +63,35 @@ def intersects(left, right):

def intersection(left, right):
"""
Keep only links that are in both left and right W objects.
Keep only links that are in both left and right Graph objects.
"""
from .base import W
from .base import Graph

new_table = left.adjacency.join(
right.adjacency, on=("focal", "neighbor"), how="inner"
)
return W(new_table)
return Graph(new_table)


def symmetric_difference(left, right):
"""
Filter out links that are in both left and right W objects.
Filter out links that are in both left and right Graph objects.
"""
from .base import W
from .base import Graph

join = left.adjacency.merge(
right.adjacency, on=("focal", "neighbor"), how="outer", indicator=True
)
return W(join[join._merge.str.endswith("only")].drop("_merge", axis=1))
return Graph(join[join._merge.str.endswith("only")].drop("_merge", axis=1))


def union(left, right):
"""
Provide the union of two W objects, collecing all links that are in either graph.
Provide the union of two Graph objects, collecing all links that are in either graph.
"""
from .base import W
from .base import Graph

return W(
return Graph(
left.adjacency.merge(right.adjacency, on=("focal", "neighbor"), how="outer")
)

Expand All @@ -101,21 +101,21 @@ def difference(left, right):
Provide the set difference between the graph on the left and the graph on the right.
This returns all links in the left graph that are not in the right graph.
"""
from .base import W
from .base import Graph

join = left.adjacency.merge(
right.adjacency, on=("focal", "neighbor"), how="outer", indicator=True
)
return W(join[join._merge == "left_only"].drop("_merge", axis=1))
return Graph(join[join._merge == "left_only"].drop("_merge", axis=1))


# TODO: profile the "not intersects(left, right)" vs. the empty join test:


def isdisjoint(left, right):
"""
Return True if there are no links in the left W that also occur in the right W. If
any link in the left W occurs in the right W, the two are not disjoint.
Return True if there are no links in the left Graph that also occur in the right Graph. If
any link in the left Graph occurs in the right Graph, the two are not disjoint.
"""
return not intersects(left, right)
join = left.adjacency.join(right.adjacency, on=("focal", "neighbor"), how="inner")
Expand All @@ -124,8 +124,8 @@ def isdisjoint(left, right):

def issubgraph(left, right):
"""
Return True if every link in the left W also occurs in the right W. This requires
both W are label_equal.
Return True if every link in the left Graph also occurs in the right Graph. This requires
both Graph are label_equal.
"""
join = left.adjacency.merge(
right.adjacency, on=("focal", "neighbor"), how="outer", indicator=True
Expand All @@ -135,8 +135,8 @@ def issubgraph(left, right):

def issupergraph(left, right):
"""
Return True if every link in the left W also occurs in the right W. This requires
both W are label_equal.
Return True if every link in the left Graph also occurs in the right Graph. This requires
both Graph are label_equal.
"""
join = left.adjacency.merge(
right.adjacency, on=("focal", "neighbor"), how="outer", indicator=True
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
from ._contiguity import _queen, _rook, _vertex_set_intersection
from ._kernel import _kernel_functions
from ._utils import _validate_geometry_input
from .base import W
from .base import Graph

try:
from numba import njit
Expand Down Expand Up @@ -36,7 +36,7 @@ def delaunay(coordinates, ids=None, bandwidth=numpy.inf, kernel="boxcar"):
delaunay triangulation
ids : numpy.narray (default: None)
ids to use for each sample in coordinates. Generally, construction functions
that are accessed via W.from_kernel() will set this automatically from
that are accessed via Graph.build_kernel() will set this automatically from
the index of the input. Do not use this argument directly unless you intend
to set the indices separately from your input data. Otherwise, use
data.set_index(ids) to ensure ordering is respected. If None, then the index
Expand Down Expand Up @@ -94,7 +94,7 @@ def delaunay(coordinates, ids=None, bandwidth=numpy.inf, kernel="boxcar"):
axis=1
).squeeze() ** 0.5
weights = _kernel_functions[kernel](distances, bandwidth)
return W.from_arrays(head, tail, weights)
return Graph.from_arrays(head, tail, weights)


def gabriel(coordinates, ids=None, bandwidth=numpy.inf, kernel="boxcar"):
Expand All @@ -119,7 +119,7 @@ def gabriel(coordinates, ids=None, bandwidth=numpy.inf, kernel="boxcar"):
delaunay triangulation
ids : numpy.narray (default: None)
ids to use for each sample in coordinates. Generally, construction functions
that are accessed via W.from_kernel() will set this automatically from
that are accessed via Graph.build_kernel() will set this automatically from
the index of the input. Do not use this argument directly unless you intend
to set the indices separately from your input data. Otherwise, use
data.set_index(ids) to ensure ordering is respected. If None, then the index
Expand Down Expand Up @@ -156,7 +156,7 @@ def gabriel(coordinates, ids=None, bandwidth=numpy.inf, kernel="boxcar"):
axis=1
).squeeze() ** 0.5
weights = _kernel_functions[kernel](distances, bandwidth)
return W.from_arrays(head, tail, weights)
return Graph.from_arrays(head, tail, weights)


def relative_neighborhood(coordinates, ids=None, bandwidth=numpy.inf, kernel="boxcar"):
Expand All @@ -179,7 +179,7 @@ def relative_neighborhood(coordinates, ids=None, bandwidth=numpy.inf, kernel="bo
delaunay triangulation
ids : numpy.narray (default: None)
ids to use for each sample in coordinates. Generally, construction functions
that are accessed via W.from_kernel() will set this automatically from
that are accessed via Graph.build_kernel() will set this automatically from
the index of the input. Do not use this argument directly unless you intend
to set the indices separately from your input data. Otherwise, use
data.set_index(ids) to ensure ordering is respected. If None, then the index
Expand Down Expand Up @@ -208,7 +208,7 @@ def relative_neighborhood(coordinates, ids=None, bandwidth=numpy.inf, kernel="bo

head, tail, distance = zip(*output)
weight = _kernel_functions[kernel](distance, bandwidth)
return W.from_arrays(head, tail, weight)
return Graph.from_arrays(head, tail, weight)


def voronoi(
Expand All @@ -230,22 +230,22 @@ def voronoi(
delaunay triangulation
ids : numpy.narray (default: None)
ids to use for each sample in coordinates. Generally, construction functions
that are accessed via W.from_kernel() will set this automatically from
that are accessed via Graph.build_kernel() will set this automatically from
the index of the input. Do not use this argument directly unless you intend
to set the indices separately from your input data. Otherwise, use
data.set_index(ids) to ensure ordering is respected. If None, then the index
clip : str (default: 'bbox')
An overloaded option about how to clip the voronoi cells passed to cg.voronoi_frames()
Default is ``'extent'``. Options are as follows.
* ``'none'``/``None`` -- No clip is applied. Voronoi cells may be arbitrarily larger that the source map. Note that this may lead to cells that are many orders of magnitude larger in extent than the original map. Not recommended.
* ``'bbox'``/``'extent'``/``'bounding box'`` -- Clip the voronoi cells to the bounding box of the input points.
* ``'chull``/``'convex hull'`` -- Clip the voronoi cells to the convex hull of the input points.
* ``'ashape'``/``'ahull'`` -- Clip the voronoi cells to the tightest hull that contains all points (e.g. the smallest alphashape, using ``libpysal.cg.alpha_shape_auto``).
* Polygon -- Clip to an arbitrary Polygon.
contiguity_type : str (default: 'v')
What kind of contiguity to apply to the voronoi diagram. There are three
recognized options:
recognized options:
1. "v" (Default): use vertex_set_contiguity()
2. "r": use rook() contiguity
3. "q": use queen() contiguity (not recommended)
Expand All @@ -260,8 +260,8 @@ def voronoi(
-----
In theory, the rook contiguity graph for a Voronoi diagram
is the delaunay triangulation of the generators of the
voronoi diagram. Yet, this is *not* the case when voronoi
cells are clipped to an arbitrary shape, including the
voronoi diagram. Yet, this is *not* the case when voronoi
cells are clipped to an arbitrary shape, including the
original bounding box of the input points or anything tighter.
This can arbitrarily delete links present in the delaunay.
However, clipped voronoi weights make sense over pure
Expand Down Expand Up @@ -290,7 +290,7 @@ def voronoi(

head, tail, distance = zip(*output)
weight = _kernel_functions[kernel](distance, bandwidth)
return W.from_arrays(head, tail, weight)
return Graph.from_arrays(head, tail, weight)


#### utilities
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ def _validate_geometry_input(geoms, ids=None, valid_geometry_types=None):
valid_geometry_types = set(valid_geometry_types)
if not geom_types <= valid_geometry_types:
raise ValueError(
"this W type is only well-defined for "
"this Graph type is only well-defined for "
f"geom_types: {valid_geometry_types}."
)
coordinates = shapely.get_coordinates(geoms)
Expand All @@ -72,9 +72,9 @@ def _validate_geometry_input(geoms, ids=None, valid_geometry_types=None):
)


def lat2W(nrows=5, ncols=5, rook=True, id_type="int"):
def lat2Graph(nrows=5, ncols=5, rook=True, id_type="int"):
"""
Create a W object for a regular lattice.
Create a Graph object for a regular lattice.
Parameters
----------
Expand All @@ -86,18 +86,15 @@ def lat2W(nrows=5, ncols=5, rook=True, id_type="int"):
rook : boolean
type of contiguity. Default is rook. For queen, rook =False
id_type : string
string defining the type of IDs to use in the final W object;
string defining the type of IDs to use in the final Graph object;
options are 'int' (0, 1, 2 ...; default), 'float' (0.0,
1.0, 2.0, ...) and 'string' ('id0', 'id1', 'id2', ...)
**kwargs : keyword arguments
optional arguments for :class:`pysal.weights.W`
Returns
-------
w : W
instance of spatial weights class W
Graph
libpysal.graph.Graph
Notes
-----
Expand All @@ -108,16 +105,17 @@ def lat2W(nrows=5, ncols=5, rook=True, id_type="int"):
Examples
--------
>>> from libpysal.weights import lat2W
>>> w9 = lat2W(3,3)
>>> from libpysal.weights import lat2Graph
>>> w9 = lat2Graph(3,3)
>>> "%.3f"%w9.pct_nonzero
'29.630'
>>> w9[0] == {1: 1.0, 3: 1.0}
True
>>> w9[3] == {0: 1.0, 4: 1.0, 6: 1.0}
True
"""
from .base import W
# TODO: this seems to be broken now
from .base import Graph

n = nrows * ncols
r1 = nrows - 1
Expand Down Expand Up @@ -169,4 +167,4 @@ def lat2W(nrows=5, ncols=5, rook=True, id_type="int"):
w = alt_w
weights = alt_weights

return W.from_dicts(weights)
return Graph.from_dicts(weights)
Loading

0 comments on commit ded0625

Please sign in to comment.