2
2
Planar Point Pattern Class
3
3
4
4
"""
5
+
5
6
import numpy as np
6
7
import sys
7
8
from libpysal .cg import KDTree
8
9
from .centrography import hull
9
- from .window import as_window , poly_from_bbox
10
+ from .window import as_window , poly_from_bbox
10
11
from .util import cached_property
11
12
import pandas as pd
12
13
from matplotlib import pyplot as plt
13
14
from matplotlib .collections import PatchCollection
14
15
from matplotlib .patches import Polygon
15
16
16
17
__author__ = "Serge Rey [email protected] "
17
- __all__ = [' PointPattern' ]
18
+ __all__ = [" PointPattern" ]
18
19
19
20
if sys .version_info [0 ] > 2 :
20
21
xrange = range
@@ -63,8 +64,8 @@ class PointPattern(object):
63
64
7638.200000000001
64
65
65
66
"""
66
- def __init__ (self , points , window = None , names = None , coord_names = None ):
67
67
68
+ def __init__ (self , points , window = None , names = None , coord_names = None ):
68
69
# first two series in df are x, y unless coor_names and names are
69
70
# specified
70
71
@@ -75,12 +76,12 @@ def __init__(self, points, window=None, names=None, coord_names=None):
75
76
if names is not None :
76
77
coord_names = names [:2 ]
77
78
else :
78
- coord_names = ['x' , 'y' ]
79
+ coord_names = ["x" , "y" ]
79
80
if names is None :
80
81
col_names = coord_names
81
82
if p > 2 :
82
83
for m in range (2 , p ):
83
- col_names .append ("mark_{}" .format (m - 2 ))
84
+ col_names .append ("mark_{}" .format (m - 2 ))
84
85
coord_names = coord_names [:2 ]
85
86
else :
86
87
col_names = names
@@ -143,19 +144,19 @@ def get_window(self):
143
144
144
145
:class:`.window.Window`
145
146
"""
146
- if not hasattr (self , ' _window' ) or self ._window is None :
147
+ if not hasattr (self , " _window" ) or self ._window is None :
147
148
# use bbox as window
148
149
self .set_window (as_window (poly_from_bbox (self .mbb )))
149
150
return self ._window
150
151
151
152
window = property (get_window , set_window )
152
153
153
154
def summary (self ):
154
- '''
155
+ """
155
156
Description of the point pattern.
156
- '''
157
+ """
157
158
158
- print (' Point Pattern' )
159
+ print (" Point Pattern" )
159
160
print ("{} points" .format (self .n ))
160
161
print ("Bounding rectangle [({},{}), ({},{})]" .format (* self .mbb ))
161
162
print ("Area of window: {}" .format (self .window .area ))
@@ -165,13 +166,12 @@ def summary(self):
165
166
def add_marks (self , marks , mark_names = None ):
166
167
if mark_names is None :
167
168
nm = range (len (marks ))
168
- mark_names = ["mark_{}" .format (self ._n_marks + 1 + j ) for j in nm ]
169
+ mark_names = ["mark_{}" .format (self ._n_marks + 1 + j ) for j in nm ]
169
170
for name , mark in zip (mark_names , marks ):
170
171
self .df [name ] = mark
171
172
self ._n_marks += 1
172
173
173
- def plot (self , window = False , title = "Point Pattern" , hull = False ,
174
- get_ax = False ):
174
+ def plot (self , window = False , title = "Point Pattern" , hull = False , get_ax = False ):
175
175
"""
176
176
Plot function for a point pattern.
177
177
@@ -187,15 +187,15 @@ def plot(self, window=False, title="Point Pattern", hull=False,
187
187
pattern. If not, don't plot convex hull.
188
188
get_ax : boolean
189
189
If get_ax is True, return the current plot ax.
190
-
190
+
191
191
Returns
192
192
-------
193
193
ax : matplotlib.axes._subplots.AxesSubplot
194
194
Current plot ax. Only return it when get_ax is True.
195
195
196
196
"""
197
197
fig , ax = plt .subplots ()
198
- plt .plot (self .df [self ._x ], self .df [self ._y ], '.' )
198
+ plt .plot (self .df [self ._x ], self .df [self ._y ], "." )
199
199
# plt.scatter(self.df[self._x], self.df[self._y])
200
200
plt .title (title )
201
201
if window :
@@ -234,7 +234,7 @@ def _mbb_area(self):
234
234
Area of minimum bounding box
235
235
"""
236
236
237
- return np .product (self .mbb [[2 , 3 ]]- self .mbb [[0 , 1 ]])
237
+ return np .prod (self .mbb [[2 , 3 ]] - self .mbb [[0 , 1 ]])
238
238
239
239
mbb_area = cached_property (_mbb_area )
240
240
@@ -253,15 +253,15 @@ def _rot(self):
253
253
One-quarter the smallest side of the mbb.
254
254
"""
255
255
w , s , e , n = self .mbb
256
- return 0.25 * min (e - w , n - s )
256
+ return 0.25 * min (e - w , n - s )
257
257
258
258
rot = cached_property (_rot )
259
259
260
260
def _lambda_mbb (self ):
261
261
"""
262
262
Intensity based on minimum bounding box
263
263
"""
264
- return self .n * 1. / self .mbb_area
264
+ return self .n * 1.0 / self .mbb_area
265
265
266
266
lambda_mbb = cached_property (_lambda_mbb )
267
267
@@ -304,24 +304,25 @@ def _hull_area(self):
304
304
Area of convex hull
305
305
"""
306
306
h = self .hull
307
- if not np .alltrue (h [0 ] == h [- 1 ]):
307
+ if not np .all (h [0 ] == h [- 1 ]):
308
308
# not in closed cartographic form
309
309
h = np .vstack ((h , h [0 ]))
310
310
s = h [:- 1 , 0 ] * h [1 :, 1 ] - h [1 :, 0 ] * h [:- 1 , 1 ]
311
- return s .sum () / 2.
311
+ return s .sum () / 2.0
312
312
313
313
hull_area = cached_property (_hull_area )
314
314
315
315
def _lambda_hull (self ):
316
316
"""
317
317
Intensity based on convex hull
318
318
"""
319
- return self .n * 1. / self .hull_area
319
+ return self .n * 1.0 / self .hull_area
320
320
321
321
lambda_hull = cached_property (_lambda_hull )
322
322
323
323
def _build_tree (self ):
324
324
return KDTree (self .points )
325
+
325
326
tree = cached_property (_build_tree )
326
327
327
328
def knn (self , k = 1 ):
@@ -343,8 +344,8 @@ def knn(self, k=1):
343
344
nearest neighbor
344
345
"""
345
346
if k < 1 :
346
- raise ValueError (' k must be at least 1' )
347
- nn = self .tree .query (self .tree .data , k = k + 1 )
347
+ raise ValueError (" k must be at least 1" )
348
+ nn = self .tree .query (self .tree .data , k = k + 1 )
348
349
return nn [1 ][:, 1 :], nn [0 ][:, 1 :]
349
350
350
351
def _nn_sum (self ):
@@ -419,7 +420,7 @@ def knn_other(self, other, k=1):
419
420
nearest neighbor
420
421
"""
421
422
if k < 1 :
422
- raise ValueError (' k must be at least 1' )
423
+ raise ValueError (" k must be at least 1" )
423
424
try :
424
425
nn = self .tree .query (np .asarray (other .points ), k = k )
425
426
except :
@@ -447,10 +448,10 @@ def explode(self, mark):
447
448
pps = [self .df [self .df [mark ] == v ] for v in uv ]
448
449
names = self .df .columns .values .tolist ()
449
450
cnames = self .coord_names
450
- return [PointPattern (pp , names = names , coord_names = cnames ) for pp in pps ]
451
+ return [PointPattern (pp , names = names , coord_names = cnames ) for pp in pps ]
451
452
452
453
def unique (self ):
453
- """ Remove duplicate points in the point pattern.
454
+ """Remove duplicate points in the point pattern.
454
455
455
456
Two points in a point pattern are deemed to be identical if their
456
457
coordinates are the same, and their marks are the same (if any)
@@ -475,8 +476,9 @@ def unique(self):
475
476
coord_names = self .coord_names
476
477
window = self .set_window
477
478
unique_df = self .df .drop_duplicates ()
478
- return PointPattern (unique_df , names = names , coord_names = coord_names ,
479
- window = window )
479
+ return PointPattern (
480
+ unique_df , names = names , coord_names = coord_names , window = window
481
+ )
480
482
481
483
def superimpose (self , point_pattern ):
482
484
"""Returns a superimposed point pattern.
@@ -511,14 +513,16 @@ def superimpose(self, point_pattern):
511
513
names_pp2 = point_pattern .df .columns .values .tolist ()
512
514
cnames_pp2 = point_pattern .coord_names
513
515
if names_pp1 != names_pp2 or cnames_pp1 != cnames_pp2 :
514
- raise TypeError ('Both point patterns should have similar\
515
- attributes and spatial coordinates ' )
516
+ raise TypeError (
517
+ "Both point patterns should have similar\
518
+ attributes and spatial coordinates "
519
+ )
516
520
pp = pd .concat ((self .df , point_pattern .df ))
517
521
pp = pp .drop_duplicates ()
518
522
return PointPattern (pp , names = names_pp1 , coord_names = cnames_pp1 )
519
523
520
524
def flip_coordinates (self ):
521
- """ Flips the coordinates of a point pattern.
525
+ """Flips the coordinates of a point pattern.
522
526
523
527
Doesn't change the structure of data frame. This function swaps
524
528
`_x` and `_y` variables, which are used to represent coordinates.
@@ -527,5 +531,5 @@ def flip_coordinates(self):
527
531
528
532
# Pandas facade
529
533
def _facade (self ):
530
- self .head = self .df .head
531
- self .tail = self .df .tail
534
+ self .head = self .df .head
535
+ self .tail = self .df .tail
0 commit comments