From 18f8ebee0520170bd25d42c8530409a729cf1cfc Mon Sep 17 00:00:00 2001 From: MgeeeeK <40512095+MgeeeeK@users.noreply.github.com> Date: Mon, 24 Feb 2020 14:18:23 +0530 Subject: [PATCH 1/2] added torusW and some fixes --- libpysal/weights/tests/test_util.py | 10 +++ libpysal/weights/util.py | 115 ++++++++++++++++++++++++---- 2 files changed, 109 insertions(+), 16 deletions(-) diff --git a/libpysal/weights/tests/test_util.py b/libpysal/weights/tests/test_util.py index 712b64bd4..b5e4c9982 100644 --- a/libpysal/weights/tests/test_util.py +++ b/libpysal/weights/tests/test_util.py @@ -29,6 +29,16 @@ def test_lat2W(self): self.assertEqual(w9.pct_nonzero, 29.62962962962963) self.assertEqual(w9[0], {1: 1.0, 3: 1.0}) self.assertEqual(w9[3], {0: 1.0, 4: 1.0, 6: 1.0}) + + def test_torusW(self): + wt = torusW(3, 3) + self.assertEqual(wt[0], {1: 1.0, 2: 1.0, 3: 1.0, 6: 1.0}) + self.assertEqual(wt[3], {0: 1.0, 4: 1.0, 5: 1.0, 6: 1.0}) + + def test_hexLat2W(self): + wh = hexLat2W(5, 5) + self.assertEqual(wh[1], {0: 1.0, 6: 1.0, 2: 1.0, 5: 1.0, 7: 1.0}) + self.assertEqual(wh[21], {16: 1.0, 20: 1.0, 22: 1.0}) def test_lat2SW(self): w9 = util.lat2SW(3, 3) diff --git a/libpysal/weights/util.py b/libpysal/weights/util.py index 363fe4a5c..49013d735 100644 --- a/libpysal/weights/util.py +++ b/libpysal/weights/util.py @@ -23,7 +23,7 @@ 'shimbel', 'remap_ids', 'full2W', 'full', 'WSP2W', 'insert_diagonal', 'get_ids', 'get_points_array_from_shapefile', 'min_threshold_distance', 'lat2SW', 'w_local_cluster', - 'higher_order_sp', 'hexLat2W', 'attach_islands', + 'higher_order_sp', 'hexLat2W', 'torusW', 'attach_islands', 'nonplanar_neighbors', 'fuzzy_contiguity'] @@ -113,6 +113,85 @@ def hexLat2W(nrows=5, ncols=5, **kwargs): return W(w, **kwargs) +def torusW(nrows=5, ncols=5, rook=True, **kwargs): + """ + Create a W object for a torus lattice. + + Parameters + ---------- + nrows : int + number of rows + ncols : int + number of columns + rook : boolean + type of contiguity. Default is rook. For queen, rook = False + **kwargs : keyword arguments + optional arguments for :class:`pysal.weights.W` + + Returns + ------- + w : W + instance of spatial weights class W + + Notes + ----- + Observations are row ordered: first k observations are in row 0, next k in row 1, and so on. + + Examples + -------- + >>> from libpysal.weights import lat2W, torusW + >>> w = lat2W(3,3) + >>> w.neighbors[0] + [3, 1] + >>> w.neighbors[3] + [0, 6, 4] + >>> wt = torusW(3,3) + >>> wt.neighbors[0] + [3, 1, 2, 6] + >>> wh.neighbors[3] + [0, 6, 4, 5] + """ + + n = nrows * ncols + r1 = nrows - 1 + c1 = ncols - 1 + lat_pts = range(n) + rid = [i // ncols for i in range(n)] #must be floor! + cid = [i % ncols for i in range(n)] + + w = lat2W(nrows, ncols, rook).neighbors + for i in range(n): + if rid[i] == r1 and r1 not in [0, 1]: + below = rid[i] + 1 + r = lat_pts[(below * ncols + cid[i]) - n] + w[i] = w.get(i, []) + [r] + w[r] = w.get(r, []) + [i] + if cid[i] == c1 and c1 not in [0, 1]: + c = lat_pts[(rid[i] * ncols) - n] + w[i] = w.get(i, []) + [c] + w[c] = w.get(c, []) + [i] + if not rook: + if r1 not in [0, 1]: + if cid[i] < c1 and rid[i] == r1: + r = lat_pts[((rid[i] + 1) * ncols + 1 + cid[i]) - n] + w[i] = w.get(i, []) + [r] + w[r] = w.get(r, []) + [i] + if cid[i] > 0 and rid[i] == r1: + r = lat_pts[((rid[i] + 1) * ncols - 1 + cid[i]) - n] + w[i] = w.get(i, []) + [r] + w[r] = w.get(r, []) + [i] + if c1 not in [0, 1]: + if cid[i] == c1: + r = lat_pts[i + 1 - n] + w[i] = w.get(i, []) + [r] + w[r] = w.get(r, []) + [i] + if cid[i] == 0: + below = rid[i] + 2 + r = lat_pts[(below * ncols - 1) - n] + w[i] = w.get(i, []) + [r] + w[r] = w.get(r, []) + [i] + + return W(w, **kwargs) def lat2W(nrows=5, ncols=5, rook=True, id_type='int', **kwargs): """ @@ -164,7 +243,6 @@ def lat2W(nrows=5, ncols=5, rook=True, id_type='int', **kwargs): rid = [i // ncols for i in range(n)] #must be floor! cid = [i % ncols for i in range(n)] w = {} - r = below = 0 for i in range(n - 1): if rid[i] < r1: below = rid[i] + 1 @@ -1170,22 +1248,27 @@ def lat2SW(nrows=3, ncols=5, criterion="rook", row_st=False): diagonals = [] offsets = [] if criterion == "rook" or criterion == "queen": - d = np.ones((1, n)) - for i in range(ncols - 1, n, ncols): - d[0, i] = 0 - diagonals.append(d) - offsets.append(-1) - - d = np.ones((1, n)) - diagonals.append(d) - offsets.append(-ncols) + if ncols>1: + d = np.ones((1, n)) + for i in range(ncols - 1, n, ncols): + d[0, i] = 0 + if criterion == "queen" and ncols==2: + d = np.ones((1, n)) + diagonals.append(d) + offsets.append(-1) + + if ncols>=1: + d = np.ones((1, n)) + diagonals.append(d) + offsets.append(-ncols) if criterion == "queen" or criterion == "bishop": - d = np.ones((1, n)) - for i in range(0, n, ncols): - d[0, i] = 0 - diagonals.append(d) - offsets.append(-(ncols - 1)) + if (criterion == "bishop" and ncols>=2) or ncols>2: + d = np.ones((1, n)) + for i in range(0, n, ncols): + d[0, i] = 0 + diagonals.append(d) + offsets.append(-(ncols - 1)) d = np.ones((1, n)) for i in range(ncols - 1, n, ncols): From 48a2e36aacbc58f490ca226201bea81ec50f0939 Mon Sep 17 00:00:00 2001 From: MgeeeeK <40512095+MgeeeeK@users.noreply.github.com> Date: Mon, 24 Feb 2020 14:31:16 +0530 Subject: [PATCH 2/2] fixes --- libpysal/weights/tests/test_util.py | 4 ++-- libpysal/weights/util.py | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/libpysal/weights/tests/test_util.py b/libpysal/weights/tests/test_util.py index b5e4c9982..1a9df4235 100644 --- a/libpysal/weights/tests/test_util.py +++ b/libpysal/weights/tests/test_util.py @@ -31,12 +31,12 @@ def test_lat2W(self): self.assertEqual(w9[3], {0: 1.0, 4: 1.0, 6: 1.0}) def test_torusW(self): - wt = torusW(3, 3) + wt = util.torusW(3, 3) self.assertEqual(wt[0], {1: 1.0, 2: 1.0, 3: 1.0, 6: 1.0}) self.assertEqual(wt[3], {0: 1.0, 4: 1.0, 5: 1.0, 6: 1.0}) def test_hexLat2W(self): - wh = hexLat2W(5, 5) + wh = util.hexLat2W(5, 5) self.assertEqual(wh[1], {0: 1.0, 6: 1.0, 2: 1.0, 5: 1.0, 7: 1.0}) self.assertEqual(wh[21], {16: 1.0, 20: 1.0, 22: 1.0}) diff --git a/libpysal/weights/util.py b/libpysal/weights/util.py index 49013d735..36d0eaa0a 100644 --- a/libpysal/weights/util.py +++ b/libpysal/weights/util.py @@ -148,7 +148,7 @@ def torusW(nrows=5, ncols=5, rook=True, **kwargs): >>> wt = torusW(3,3) >>> wt.neighbors[0] [3, 1, 2, 6] - >>> wh.neighbors[3] + >>> wt.neighbors[3] [0, 6, 4, 5] """