Loading autocnet/graph/edge.py +63 −0 Changes for autocnet/graph/edge.py: 63 added lines, 0 removed lines. Original line number Diff line number Diff line Loading @@ -7,6 +7,7 @@ import pandas as pd from scipy.spatial.distance import cdist import autocnet from autocnet.graph.node import Node from autocnet.utils import utils from autocnet.matcher import outlier_detector as od from autocnet.matcher import suppression_funcs as spf Loading Loading @@ -479,3 +480,65 @@ class Edge(dict, MutableMapping): """ pass def get_keypoints(self, node, clean_keys): """ Returns a list of keypoint coordinates that match the specified paramaters Parameters ---------- node : str or Node Can be "source" or "destination" based on which node we're pulling keypoint data for; Also can pass Node obj itself clean_keys : list List of clean key strings Return ------ masked_keypts : Dataframe Dataframe of keypoints that match the specified masks on the specified node """ # Assert parameter types are correct try: assert (isinstance(node, str) or isinstance(node, Node)) except AssertionError: raise TypeError('Parameter "node" must be of type str or type Node') try: assert isinstance(clean_keys, list) except AssertionError: raise TypeError('Parameter "clean_keys" must be of type list') # If node param is a string, make sure it's one of the right strings if isinstance(node, str): try: assert (node in ["source", "destination"]) # Define the node if str is passed as param if node == "source": node = self.source elif node == "destination": node = self.destination except AssertionError: raise KeyError('node" parameter must be "source"' + 'or "destination"') # Get cleaned, combined src & dst keypt df for this edge ("matches") matches, mask = self.clean(clean_keys) # Grab the keypt indices filtered by clean_keys as ints, pandas # complains when you use them as indicies if they're not ints if node == self.source: keypt_indices = matches["source_idx"].astype(int) elif node == self.destination: keypt_indices = matches["destination_idx"].astype(int) # Get all keypts for the specified node all_keypts = node.get_keypoints() # Return keypts @ masked indecies for the node masked_keypts = all_keypts.iloc[keypt_indices].sort_index() return masked_keypts autocnet/graph/tests/test_edge.py +72 −0 Changes for autocnet/graph/tests/test_edge.py: 72 added lines, 0 removed lines. Original line number Diff line number Diff line Loading @@ -249,3 +249,75 @@ class TestEdge(unittest.TestCase): for i in e.matches['vor_weights']: self.assertAlmostEquals(i, weights['vor_weights'][k]) k += 1 def test_get_keypoints(self): src_keypoint_df = pd.DataFrame({'x': (0, 1, 2, 3, 4), 'y': (5, 6, 7, 8, 9), 'response': (10, 11, 12, 13, 14), 'size': (15, 16, 17, 18, 19), 'angle': (20, 21, 22, 23, 24), 'octave': (25, 26, 27, 28, 29), 'layer': (30, 31, 32, 33, 34)}) dst_keypoint_df = pd.DataFrame({'x': (34, 33, 32, 31, 30), 'y': (29, 28, 27, 26, 25), 'response': (24, 23, 22, 21, 20), 'size': (19, 18, 17, 16, 15), 'angle': (14, 13, 12, 11, 10), 'octave': (9, 8, 7, 6, 5), 'layer': (4, 3, 2, 1, 0)}) keypoint_matches = [[0, 0, 1, 4], [0, 1, 1, 3], [0, 2, 1, 2], [0, 3, 1, 1], [0, 4, 1, 0]] matches_df = pd.DataFrame(data=keypoint_matches, columns=['source_image', 'source_idx', 'destination_image', 'destination_idx']) e = edge.Edge() source_node = MagicMock(spec=node.Node()) destination_node = MagicMock(spec=node.Node()) source_node.get_keypoints = MagicMock(return_value=src_keypoint_df) destination_node.get_keypoints = MagicMock(return_value=dst_keypoint_df) e.source = source_node e.destination = destination_node e.clean = MagicMock(return_value=(matches_df, None)) e.matches = matches_df clean_keys = ["fundamental", "ratio", "symmetry"] # Test all uses for edge.get_keypoints() src_matched_keypts = e.get_keypoints("source", clean_keys) src_matched_keypts2 = e.get_keypoints(e.source, clean_keys) dst_matched_keypts = e.get_keypoints("destination", clean_keys) dst_matched_keypts2 = e.get_keypoints(e.destination, clean_keys) # [output df to test] [name of node] [df to test against] to_test = [[src_matched_keypts, "source", src_keypoint_df], [src_matched_keypts2, "source", src_keypoint_df], [dst_matched_keypts, "destination", dst_keypoint_df], [dst_matched_keypts2, "destination", dst_keypoint_df]] for out_df in to_test: # For each row index in the appropriate column of the matches_df, # assert that row index exists in the function's returned df [self.assertIn(row_idx, out_df[0].index.values) for row_idx in matches_df[out_df[1] + '_idx']] # For each row index in the returned df for row_idx in out_df[0].index.values: # Assert that row_idx exists in the matches_df's appropriate # column self.assertIn(row_idx, matches_df[out_df[1] + '_idx']) # Assert that all row_idx[column] vals returned by function # match their counterpart in orig df for column in out_df[0].columns: self.assertTrue(out_df[0].iloc[row_idx][column] == out_df[2].iloc[row_idx][column]) # Assert type-checking in method throws proper errors with self.assertRaises(TypeError): e.get_keypoints("source", 1) with self.assertRaises(TypeError): e.get_keypoints(1, clean_keys) # Check key error thrown when string arg != "source" or "destination" with self.assertRaises(KeyError): e.get_keypoints("string", clean_keys) Loading
autocnet/graph/edge.py +63 −0 Changes for autocnet/graph/edge.py: 63 added lines, 0 removed lines. Original line number Diff line number Diff line Loading @@ -7,6 +7,7 @@ import pandas as pd from scipy.spatial.distance import cdist import autocnet from autocnet.graph.node import Node from autocnet.utils import utils from autocnet.matcher import outlier_detector as od from autocnet.matcher import suppression_funcs as spf Loading Loading @@ -479,3 +480,65 @@ class Edge(dict, MutableMapping): """ pass def get_keypoints(self, node, clean_keys): """ Returns a list of keypoint coordinates that match the specified paramaters Parameters ---------- node : str or Node Can be "source" or "destination" based on which node we're pulling keypoint data for; Also can pass Node obj itself clean_keys : list List of clean key strings Return ------ masked_keypts : Dataframe Dataframe of keypoints that match the specified masks on the specified node """ # Assert parameter types are correct try: assert (isinstance(node, str) or isinstance(node, Node)) except AssertionError: raise TypeError('Parameter "node" must be of type str or type Node') try: assert isinstance(clean_keys, list) except AssertionError: raise TypeError('Parameter "clean_keys" must be of type list') # If node param is a string, make sure it's one of the right strings if isinstance(node, str): try: assert (node in ["source", "destination"]) # Define the node if str is passed as param if node == "source": node = self.source elif node == "destination": node = self.destination except AssertionError: raise KeyError('node" parameter must be "source"' + 'or "destination"') # Get cleaned, combined src & dst keypt df for this edge ("matches") matches, mask = self.clean(clean_keys) # Grab the keypt indices filtered by clean_keys as ints, pandas # complains when you use them as indicies if they're not ints if node == self.source: keypt_indices = matches["source_idx"].astype(int) elif node == self.destination: keypt_indices = matches["destination_idx"].astype(int) # Get all keypts for the specified node all_keypts = node.get_keypoints() # Return keypts @ masked indecies for the node masked_keypts = all_keypts.iloc[keypt_indices].sort_index() return masked_keypts
autocnet/graph/tests/test_edge.py +72 −0 Changes for autocnet/graph/tests/test_edge.py: 72 added lines, 0 removed lines. Original line number Diff line number Diff line Loading @@ -249,3 +249,75 @@ class TestEdge(unittest.TestCase): for i in e.matches['vor_weights']: self.assertAlmostEquals(i, weights['vor_weights'][k]) k += 1 def test_get_keypoints(self): src_keypoint_df = pd.DataFrame({'x': (0, 1, 2, 3, 4), 'y': (5, 6, 7, 8, 9), 'response': (10, 11, 12, 13, 14), 'size': (15, 16, 17, 18, 19), 'angle': (20, 21, 22, 23, 24), 'octave': (25, 26, 27, 28, 29), 'layer': (30, 31, 32, 33, 34)}) dst_keypoint_df = pd.DataFrame({'x': (34, 33, 32, 31, 30), 'y': (29, 28, 27, 26, 25), 'response': (24, 23, 22, 21, 20), 'size': (19, 18, 17, 16, 15), 'angle': (14, 13, 12, 11, 10), 'octave': (9, 8, 7, 6, 5), 'layer': (4, 3, 2, 1, 0)}) keypoint_matches = [[0, 0, 1, 4], [0, 1, 1, 3], [0, 2, 1, 2], [0, 3, 1, 1], [0, 4, 1, 0]] matches_df = pd.DataFrame(data=keypoint_matches, columns=['source_image', 'source_idx', 'destination_image', 'destination_idx']) e = edge.Edge() source_node = MagicMock(spec=node.Node()) destination_node = MagicMock(spec=node.Node()) source_node.get_keypoints = MagicMock(return_value=src_keypoint_df) destination_node.get_keypoints = MagicMock(return_value=dst_keypoint_df) e.source = source_node e.destination = destination_node e.clean = MagicMock(return_value=(matches_df, None)) e.matches = matches_df clean_keys = ["fundamental", "ratio", "symmetry"] # Test all uses for edge.get_keypoints() src_matched_keypts = e.get_keypoints("source", clean_keys) src_matched_keypts2 = e.get_keypoints(e.source, clean_keys) dst_matched_keypts = e.get_keypoints("destination", clean_keys) dst_matched_keypts2 = e.get_keypoints(e.destination, clean_keys) # [output df to test] [name of node] [df to test against] to_test = [[src_matched_keypts, "source", src_keypoint_df], [src_matched_keypts2, "source", src_keypoint_df], [dst_matched_keypts, "destination", dst_keypoint_df], [dst_matched_keypts2, "destination", dst_keypoint_df]] for out_df in to_test: # For each row index in the appropriate column of the matches_df, # assert that row index exists in the function's returned df [self.assertIn(row_idx, out_df[0].index.values) for row_idx in matches_df[out_df[1] + '_idx']] # For each row index in the returned df for row_idx in out_df[0].index.values: # Assert that row_idx exists in the matches_df's appropriate # column self.assertIn(row_idx, matches_df[out_df[1] + '_idx']) # Assert that all row_idx[column] vals returned by function # match their counterpart in orig df for column in out_df[0].columns: self.assertTrue(out_df[0].iloc[row_idx][column] == out_df[2].iloc[row_idx][column]) # Assert type-checking in method throws proper errors with self.assertRaises(TypeError): e.get_keypoints("source", 1) with self.assertRaises(TypeError): e.get_keypoints(1, clean_keys) # Check key error thrown when string arg != "source" or "destination" with self.assertRaises(KeyError): e.get_keypoints("string", clean_keys)