Skip to content

Commit

Permalink
COMPAT: compatibility with numpy (#147)
Browse files Browse the repository at this point in the history
* COMPAT: compatibility with numpy

* pin fiona
  • Loading branch information
martinfleis authored Sep 9, 2024
1 parent 8c20108 commit c49f7d2
Show file tree
Hide file tree
Showing 3 changed files with 39 additions and 32 deletions.
1 change: 1 addition & 0 deletions ci/envs/310-minimal.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ dependencies:
- pandas=1.4
- scipy=1.10
- shapely=2
- fiona<1.10
# tests
- scikit-learn=1.2
- statsmodels
Expand Down
2 changes: 2 additions & 0 deletions pointpats/centrography.py
Original file line number Diff line number Diff line change
Expand Up @@ -170,6 +170,8 @@ def mean_center(points):
return points.mean(axis=0)




def weighted_mean_center(points, weights):
"""
Find weighted mean center of a marked point pattern.
Expand Down
68 changes: 36 additions & 32 deletions pointpats/pointpattern.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,19 +2,20 @@
Planar Point Pattern Class
"""

import numpy as np
import sys
from libpysal.cg import KDTree
from .centrography import hull
from .window import as_window, poly_from_bbox
from .window import as_window, poly_from_bbox
from .util import cached_property
import pandas as pd
from matplotlib import pyplot as plt
from matplotlib.collections import PatchCollection
from matplotlib.patches import Polygon

__author__ = "Serge Rey [email protected]"
__all__ = ['PointPattern']
__all__ = ["PointPattern"]

if sys.version_info[0] > 2:
xrange = range
Expand Down Expand Up @@ -63,8 +64,8 @@ class PointPattern(object):
7638.200000000001
"""
def __init__(self, points, window=None, names=None, coord_names=None):

def __init__(self, points, window=None, names=None, coord_names=None):
# first two series in df are x, y unless coor_names and names are
# specified

Expand All @@ -75,12 +76,12 @@ def __init__(self, points, window=None, names=None, coord_names=None):
if names is not None:
coord_names = names[:2]
else:
coord_names = ['x', 'y']
coord_names = ["x", "y"]
if names is None:
col_names = coord_names
if p > 2:
for m in range(2, p):
col_names.append("mark_{}".format(m-2))
col_names.append("mark_{}".format(m - 2))
coord_names = coord_names[:2]
else:
col_names = names
Expand Down Expand Up @@ -143,19 +144,19 @@ def get_window(self):
:class:`.window.Window`
"""
if not hasattr(self, '_window') or self._window is None:
if not hasattr(self, "_window") or self._window is None:
# use bbox as window
self.set_window(as_window(poly_from_bbox(self.mbb)))
return self._window

window = property(get_window, set_window)

def summary(self):
'''
"""
Description of the point pattern.
'''
"""

print('Point Pattern')
print("Point Pattern")
print("{} points".format(self.n))
print("Bounding rectangle [({},{}), ({},{})]".format(*self.mbb))
print("Area of window: {}".format(self.window.area))
Expand All @@ -165,13 +166,12 @@ def summary(self):
def add_marks(self, marks, mark_names=None):
if mark_names is None:
nm = range(len(marks))
mark_names = ["mark_{}".format(self._n_marks+1+j) for j in nm]
mark_names = ["mark_{}".format(self._n_marks + 1 + j) for j in nm]
for name, mark in zip(mark_names, marks):
self.df[name] = mark
self._n_marks += 1

def plot(self, window=False, title="Point Pattern", hull=False,
get_ax=False):
def plot(self, window=False, title="Point Pattern", hull=False, get_ax=False):
"""
Plot function for a point pattern.
Expand All @@ -187,15 +187,15 @@ def plot(self, window=False, title="Point Pattern", hull=False,
pattern. If not, don't plot convex hull.
get_ax : boolean
If get_ax is True, return the current plot ax.
Returns
-------
ax : matplotlib.axes._subplots.AxesSubplot
Current plot ax. Only return it when get_ax is True.
"""
fig, ax = plt.subplots()
plt.plot(self.df[self._x], self.df[self._y], '.')
plt.plot(self.df[self._x], self.df[self._y], ".")
# plt.scatter(self.df[self._x], self.df[self._y])
plt.title(title)
if window:
Expand Down Expand Up @@ -234,7 +234,7 @@ def _mbb_area(self):
Area of minimum bounding box
"""

return np.product(self.mbb[[2, 3]]-self.mbb[[0, 1]])
return np.prod(self.mbb[[2, 3]] - self.mbb[[0, 1]])

mbb_area = cached_property(_mbb_area)

Expand All @@ -253,15 +253,15 @@ def _rot(self):
One-quarter the smallest side of the mbb.
"""
w, s, e, n = self.mbb
return 0.25 * min(e-w, n-s)
return 0.25 * min(e - w, n - s)

rot = cached_property(_rot)

def _lambda_mbb(self):
"""
Intensity based on minimum bounding box
"""
return self.n * 1. / self.mbb_area
return self.n * 1.0 / self.mbb_area

lambda_mbb = cached_property(_lambda_mbb)

Expand Down Expand Up @@ -304,24 +304,25 @@ def _hull_area(self):
Area of convex hull
"""
h = self.hull
if not np.alltrue(h[0] == h[-1]):
if not np.all(h[0] == h[-1]):
# not in closed cartographic form
h = np.vstack((h, h[0]))
s = h[:-1, 0] * h[1:, 1] - h[1:, 0] * h[:-1, 1]
return s.sum() / 2.
return s.sum() / 2.0

hull_area = cached_property(_hull_area)

def _lambda_hull(self):
"""
Intensity based on convex hull
"""
return self.n * 1. / self.hull_area
return self.n * 1.0 / self.hull_area

lambda_hull = cached_property(_lambda_hull)

def _build_tree(self):
return KDTree(self.points)

tree = cached_property(_build_tree)

def knn(self, k=1):
Expand All @@ -343,8 +344,8 @@ def knn(self, k=1):
nearest neighbor
"""
if k < 1:
raise ValueError('k must be at least 1')
nn = self.tree.query(self.tree.data, k=k+1)
raise ValueError("k must be at least 1")
nn = self.tree.query(self.tree.data, k=k + 1)
return nn[1][:, 1:], nn[0][:, 1:]

def _nn_sum(self):
Expand Down Expand Up @@ -419,7 +420,7 @@ def knn_other(self, other, k=1):
nearest neighbor
"""
if k < 1:
raise ValueError('k must be at least 1')
raise ValueError("k must be at least 1")
try:
nn = self.tree.query(np.asarray(other.points), k=k)
except:
Expand Down Expand Up @@ -447,10 +448,10 @@ def explode(self, mark):
pps = [self.df[self.df[mark] == v] for v in uv]
names = self.df.columns.values.tolist()
cnames = self.coord_names
return[PointPattern(pp, names=names, coord_names=cnames) for pp in pps]
return [PointPattern(pp, names=names, coord_names=cnames) for pp in pps]

def unique(self):
""" Remove duplicate points in the point pattern.
"""Remove duplicate points in the point pattern.
Two points in a point pattern are deemed to be identical if their
coordinates are the same, and their marks are the same (if any)
Expand All @@ -475,8 +476,9 @@ def unique(self):
coord_names = self.coord_names
window = self.set_window
unique_df = self.df.drop_duplicates()
return PointPattern(unique_df, names=names, coord_names=coord_names,
window=window)
return PointPattern(
unique_df, names=names, coord_names=coord_names, window=window
)

def superimpose(self, point_pattern):
"""Returns a superimposed point pattern.
Expand Down Expand Up @@ -511,14 +513,16 @@ def superimpose(self, point_pattern):
names_pp2 = point_pattern.df.columns.values.tolist()
cnames_pp2 = point_pattern.coord_names
if names_pp1 != names_pp2 or cnames_pp1 != cnames_pp2:
raise TypeError('Both point patterns should have similar\
attributes and spatial coordinates ')
raise TypeError(
"Both point patterns should have similar\
attributes and spatial coordinates "
)
pp = pd.concat((self.df, point_pattern.df))
pp = pp.drop_duplicates()
return PointPattern(pp, names=names_pp1, coord_names=cnames_pp1)

def flip_coordinates(self):
""" Flips the coordinates of a point pattern.
"""Flips the coordinates of a point pattern.
Doesn't change the structure of data frame. This function swaps
`_x` and `_y` variables, which are used to represent coordinates.
Expand All @@ -527,5 +531,5 @@ def flip_coordinates(self):

# Pandas facade
def _facade(self):
self.head = self.df.head
self.tail = self.df.tail
self.head = self.df.head
self.tail = self.df.tail

0 comments on commit c49f7d2

Please sign in to comment.