aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMuriithi Frederick Muriuki2021-07-22 15:47:27 +0300
committerMuriithi Frederick Muriuki2021-07-22 15:47:27 +0300
commit2b32b2da36d880e3d8cdaedd1775be02ebb5cd5f (patch)
tree4ff26a5ccc978fceedf01057e2a62d3e5837a0a2
parentf334b5ec5d51235d0daddc0c4fe700cb65bd825d (diff)
downloadgenenetwork3-2b32b2da36d880e3d8cdaedd1775be02ebb5cd5f.tar.gz
Get shortest distance from two lists/tuples of member coordinates
* gn3/computations/slink.py: add code to ensure new test passes * tests/unit/computations/test_slink.py: new test This one is a little weird: from https://github.com/genenetwork/genenetwork1/blob/master/web/webqtl/heatmap/slink.py#L57-L63 It gets rid of the last coordinates in both the lists of the member coordinates, and uses the remaining coordinates to find the shortest members. For example, given the following member coordinates: - i=[0,1,2] and j=[5,7,9], it uses [0,1] and [5,7] - i=[3,6,1] and j=[7,13], it uses [3,6] and [7] to find the shortest distances. I (fredmanglis) am not sure why it does it this way, since I'd have expected it to use all the coordinates, however, since at this time we need to retain bug-compatibility with the older code, I have done it as it is done in the old code. I also add a statement to raise an exception in the case where i and j are not lists of integers, or integers
-rw-r--r--gn3/computations/slink.py8
-rw-r--r--tests/unit/computations/test_slink.py16
2 files changed, 24 insertions, 0 deletions
diff --git a/gn3/computations/slink.py b/gn3/computations/slink.py
index b15c058..880ce9f 100644
--- a/gn3/computations/slink.py
+++ b/gn3/computations/slink.py
@@ -1,3 +1,5 @@
+from functools import partial
+
class LengthError(BaseException):
pass
@@ -77,3 +79,9 @@ This description should be updated once the form/type of 'distance' identified."
return min(map(lambda j_new: nearest(lists, i, j_new), j))
elif type(j) == int and is_list_or_tuple(i):
return min(map(lambda i_new: nearest(lists, i_new, j), i))
+ elif is_list_or_tuple(i) and is_list_or_tuple(j):
+ partial_i = map(lambda x:partial(nearest, lists, x), i[:-1])
+ ns = list(map(lambda f, x: f(x), partial_i, j[:1]))
+ return min(ns)
+ else:
+ raise ValueError("member values (i or j) should be lists/tuples of integers or integers")
diff --git a/tests/unit/computations/test_slink.py b/tests/unit/computations/test_slink.py
index 64d123c..dd42d5d 100644
--- a/tests/unit/computations/test_slink.py
+++ b/tests/unit/computations/test_slink.py
@@ -184,3 +184,19 @@ class TestSlink(TestCase):
expected_distance=ed):
self.assertEqual(nearest(md, ml, mc), ed)
self.assertEqual(nearest(md, mc, ml), ed)
+
+ def test_given_2_lists_or_tuples_of_members_distances_nearest_returns_shortest_distance(self):
+ for md, ml, mc, ed in [
+ [[[0,9,3,6,11],[9,0,7,5,10],[3,7,0,9,2],[6,5,9,0,8],[11,10,2,8,0]],
+ [0,1,2,3,4],[0,1,2,3,4],0],
+ [[[0,9,3,6,11],[9,0,7,5,10],[3,7,0,9,2],[6,5,9,0,8],[11,10,2,8,0]],
+ [0,1],[3,4],6],
+ [[[0,9,3,6,11],[9,0,7,5,10],[3,7,0,9,2],[6,5,9,0,8],[11,10,2,8,0]],
+ [0,1],[2,3,4],3],
+ [[[0,9,3,6,11],[9,0,7,5,10],[3,7,0,9,2],[6,5,9,0,8],[11,10,2,8,0]],
+ [0,2],[3,4],6]]:
+ with self.subTest(
+ members_distances=md, members_list=ml, member_coordinate=mc,
+ expected_distance=ed):
+ self.assertEqual(nearest(md, ml, mc), ed)
+ self.assertEqual(nearest(md, mc, ml), ed)