Skip to content

Commit abc73e4

Browse files
committed
fix skyums algorithm
1 parent 5f6a85a commit abc73e4

1 file changed

Lines changed: 34 additions & 27 deletions

File tree

pointpats/centrography.py

Lines changed: 34 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -172,14 +172,14 @@ def minimum_rotated_rectangle(points, return_angle=False):
172172
[ 4.08727852, 30.41752523],
173173
[ 36.40164577, 104.61744544],
174174
[107.91345156, 73.47376296]])
175-
175+
176176
177177
>>> minimum_rotated_rectangle(coords, return_angle=True)
178178
(array([[ 75.5990843 , -0.72615725],
179179
[ 4.08727852, 30.41752523],
180180
[ 36.40164577, 104.61744544],
181181
[107.91345156, 73.47376296]]), 66.466678613503)
182-
182+
183183
Passing a GeoPandas object returns a shapely geometry.
184184
185185
>>> geoms = gpd.GeoSeries.from_xy(*coords.T)
@@ -591,10 +591,10 @@ def _(points: GeoPandasBase) -> np.float64:
591591
return std_distance(coords)
592592

593593

594-
595594
@singledispatch
596-
def ellipse(points, weights=None, method="crimestat",
597-
crimestatCorr=True, degfreedCorr=True):
595+
def ellipse(
596+
points, weights=None, method="crimestat", crimestatCorr=True, degfreedCorr=True
597+
):
598598
"""
599599
Computes a weighted standard deviational ellipse for a set of point geometries.
600600
@@ -659,8 +659,7 @@ def ellipse(points, weights=None, method="crimestat",
659659
"""
660660
try:
661661
points = np.asarray(points)
662-
return ellipse(points, weights, method,
663-
crimestatCorr, degfreedCorr)
662+
return ellipse(points, weights, method, crimestatCorr, degfreedCorr)
664663
except AttributeError as e:
665664
raise NotImplementedError
666665

@@ -669,9 +668,10 @@ def ellipse(points, weights=None, method="crimestat",
669668
def _(
670669
points: np.ndarray,
671670
weights=None,
672-
method='crimestat',
671+
method="crimestat",
673672
crimestatCorr=True,
674-
degfreedCorr=True ) -> tuple[float, float, float]:
673+
degfreedCorr=True,
674+
) -> tuple[float, float, float]:
675675
method = method.lower()
676676
if method not in ("crimestat", "yuill"):
677677
raise ValueError("`method` must be either 'crimestat' or 'yuill'")
@@ -685,7 +685,7 @@ def _(
685685
weights = np.asarray(weights)
686686
if len(weights) != len(points):
687687
raise ValueError("weights must have same length as points")
688-
688+
689689
w = weights
690690
sumw = w.sum()
691691
meanx = np.average(x, weights=w)
@@ -709,8 +709,8 @@ def _(
709709
theta1 = np.arctan(-(left + right) / den)
710710
theta2 = np.arctan(-(left - right) / den)
711711

712-
term1 = np.sum(w * (ym * np.cos(theta1) - xm * np.sin(theta1))**2)
713-
term2 = np.sum(w * (ym * np.cos(theta2) - xm * np.sin(theta2))**2)
712+
term1 = np.sum(w * (ym * np.cos(theta1) - xm * np.sin(theta1)) ** 2)
713+
term2 = np.sum(w * (ym * np.cos(theta2) - xm * np.sin(theta2)) ** 2)
714714

715715
sx = np.sqrt(term1 / sumw)
716716
sy = np.sqrt(term2 / sumw)
@@ -737,23 +737,28 @@ def _(
737737

738738
return major_axis, minor_axis, major_angle
739739

740+
740741
@ellipse.register
741-
def _(points: GeoPandasBase,
742-
weights=None,
743-
method='crimestat',
744-
crimestatCorr=True,
745-
degfreedCorr=True) -> shapely.Polygon:
742+
def _(
743+
points: GeoPandasBase,
744+
weights=None,
745+
method="crimestat",
746+
crimestatCorr=True,
747+
degfreedCorr=True,
748+
) -> shapely.Polygon:
746749
coords = shapely.get_coordinates(points.geometry)
747-
major, minor, rotation = ellipse(coords,
748-
weights=weights,
749-
method=method,
750-
crimestatCorr=crimestatCorr,
751-
degfreedCorr=degfreedCorr)
750+
major, minor, rotation = ellipse(
751+
coords,
752+
weights=weights,
753+
method=method,
754+
crimestatCorr=crimestatCorr,
755+
degfreedCorr=degfreedCorr,
756+
)
752757
if weights is None:
753758
centre = mean_center(points).buffer(1)
754759
else:
755760
centre = weighted_mean_center(points, weights=weights).buffer(1)
756-
761+
757762
scaled = shapely.affinity.scale(centre, major, minor)
758763
rotated = shapely.affinity.rotate(scaled, rotation, use_radians=True)
759764
return rotated
@@ -1022,7 +1027,7 @@ def _skyum_lists(points):
10221027
for p in points
10231028
]
10241029
radii = [c[0] for c in circles]
1025-
lexord = np.lexsort((radii, angles)) # confusing as hell defaults...
1030+
lexord = np.lexsort((angles, radii)) # confusing as hell defaults...
10261031
lexmax = lexord[-1]
10271032
candidate = (
10281033
_prec(points[lexmax], points),
@@ -1068,10 +1073,12 @@ def _skyum_iteration(points):
10681073
circles[i] = _circle(p, q, r)
10691074
radii = circles[:, 0]
10701075
# workaround for no lexsort in numba
1071-
angle_argmax = angles.argmax()
1072-
angle_max = angles[angle_argmax]
1076+
radius_argmax = radii.argmax()
1077+
radius_max = radii[radius_argmax]
1078+
# angle_argmax = angles.argmax()
1079+
# angle_max = angles[angle_argmax]
10731080
# the maximum radius for the largest angle
1074-
lexmax = (radii * (angles == angle_max)).argmax()
1081+
lexmax = (angles * (radii == radius_max)).argmax()
10751082

10761083
if angles[lexmax] <= (np.pi / 2.0):
10771084
return True, points, lexmax, circles[lexmax]

0 commit comments

Comments
 (0)