Loading .travis.yml +3 −1 Changes for .travis.yml: 3 added lines, 1 removed line. Original line number Diff line number Diff line Loading @@ -9,6 +9,7 @@ python: - "3.5" before_install: install: # We do this conditionally because it saves us some downloading if the # version is the same. Loading @@ -26,11 +27,12 @@ install: - conda info -a # Create a virtual env and install dependencies - conda create -y -q -n test-env python=$TRAVIS_PYTHON_VERSION nose gdal numpy scipy pandas - conda create -y -q -n test-env python=$TRAVIS_PYTHON_VERSION nose gdal numpy pillow scipy pandas networkx # Activate the env - source activate test-env # Install the non-conda packages if required, requirements.txt duplicates are ignored - conda install -c https://conda.binstar.org/menpo opencv3 - conda install -c osgeo proj4 - pip install -r requirements.txt - pip install coverage Loading autocnet/control/control.py +2 −0 Changes for autocnet/control/control.py: 2 added lines, 0 removed lines. Original line number Diff line number Diff line Loading @@ -2,6 +2,8 @@ from time import gmtime, strftime import pandas as pd POINT_TYPE = 2 MEASURE_TYPE = 2 class CSeries(pd.Series): """ Loading autocnet/fileio/io_gdal.py +1 −0 Changes for autocnet/fileio/io_gdal.py: 1 added line, 0 removed lines. Original line number Diff line number Diff line Loading @@ -350,6 +350,7 @@ class GeoDataset(object): xextent, yextent).astype(dtype) return array def array_to_raster(array, file_name, projection=None, geotransform=None, outformat='GTiff', ndv=None): Loading autocnet/fileio/tests/io_controlnetwork.pydeleted 100644 → 0 +0 −0 Empty file deleted. autocnet/graph/network.py +97 −7 Changes for autocnet/graph/network.py: 97 added lines, 7 removed lines. Original line number Diff line number Diff line from collections import Hashable from networkx import DiGraph import networkx as nx import pandas as pd from autocnet.control.control import C, POINT_TYPE, MEASURE_TYPE from autocnet.fileio import io_json class CandidateGraph(DiGraph): class CandidateGraph(nx.Graph): """ A NetworkX derived directed graph to store candidate overlap images. Loading @@ -12,8 +18,6 @@ class CandidateGraph(DiGraph): Attributes ---------- """ #TODO: This would be better with composition, and then dispatch the # network X calls to the graph object. def __init__(self,*args, **kwargs): super(CandidateGraph, self).__init__(*args, **kwargs) Loading @@ -36,6 +40,7 @@ class CandidateGraph(DiGraph): Parameters ========== outputfile : str PATH where the JSON will be written """ Loading @@ -44,18 +49,103 @@ class CandidateGraph(DiGraph): adjacency_dict[n] = self.neighbors(n) io_json.write_json(adjacency_dict, outputfile) def add_matches(self, source_node, matches): """ Adds match data to a node and attributes the data to the appropriate edges, e.g. if A-B have a match, edge A-B is attributes with the pandas dataframe. Parameters ---------- source_node : str The identifier for the node matches : dataframe The pandas dataframe containing the matches """ #TODO: This really belongs in an outlier detection matcher class, not here. # Remove erroneous self neighbors matches = matches.loc[matches['matched_to'] != source_node] groups = matches.groupby('matched_to') for destination_node, group in groups: try: edge = self[source_node][destination_node] except: edge = self[destination_node][source_node] if 'matches' in edge.keys(): df = edge['matches'] edge['matches'] = pd.merge(df, matches, left_on='queryIdx', right_on='trainIdx') else: edge['matches'] = matches def to_cnet(self): """ Returns ------- cnet : C A control network object """ data = [] point_ids = [] serials = [] for source, destination, attributes in self.edges_iter(data=True): for i, row in attributes['matches'].iterrows(): # Get the source and destination x,y coordinates for matches source_idx = row['queryIdx_x'] source_keypoints = (self.node[source]['keypoints'][source_idx].pt[0], self.node[source]['keypoints'][source_idx].pt[1]) destination_idx = row['queryIdx_y'] destination_keypoints = (self.node[destination]['keypoints'][destination_idx].pt[0], self.node[destination]['keypoints'][destination_idx].pt[1]) data.append(source_keypoints) data.append(destination_keypoints) serials.append(source) serials.append(destination) point_ids.append(i) point_ids.append(i) point_types = [2] * len(point_ids) measure_types = [2] * len(point_ids) multi_index = pd.MultiIndex.from_tuples(list(zip(point_ids,point_types, serials, measure_types))) columns = ['x', 'y'] cnet = C(data, index=multi_index, columns=columns) # TODO: This method assumes a 2 image match and should be generalized to build an n-image C object return cnet @classmethod def from_adjacency(cls, inputfile): """ Instantiate the class using an adjacency list Parameters ========== ---------- inputfile : str The input file containing the graph representation Returns ------- : object A Network graph object Examples -------- >>> from autocnet.examples import get_path >>> inputfile = get_path('adjacency.json') >>> candidate_graph = network.CandidateGraph.from_adjacency(inputfile) """ #TODO: This is better as a generic reader that tries drivers until # a valid dict is returned. adjacency_dict = io_json.read_json(inputfile) return cls(adjacency_dict) Loading Loading
.travis.yml +3 −1 Changes for .travis.yml: 3 added lines, 1 removed line. Original line number Diff line number Diff line Loading @@ -9,6 +9,7 @@ python: - "3.5" before_install: install: # We do this conditionally because it saves us some downloading if the # version is the same. Loading @@ -26,11 +27,12 @@ install: - conda info -a # Create a virtual env and install dependencies - conda create -y -q -n test-env python=$TRAVIS_PYTHON_VERSION nose gdal numpy scipy pandas - conda create -y -q -n test-env python=$TRAVIS_PYTHON_VERSION nose gdal numpy pillow scipy pandas networkx # Activate the env - source activate test-env # Install the non-conda packages if required, requirements.txt duplicates are ignored - conda install -c https://conda.binstar.org/menpo opencv3 - conda install -c osgeo proj4 - pip install -r requirements.txt - pip install coverage Loading
autocnet/control/control.py +2 −0 Changes for autocnet/control/control.py: 2 added lines, 0 removed lines. Original line number Diff line number Diff line Loading @@ -2,6 +2,8 @@ from time import gmtime, strftime import pandas as pd POINT_TYPE = 2 MEASURE_TYPE = 2 class CSeries(pd.Series): """ Loading
autocnet/fileio/io_gdal.py +1 −0 Changes for autocnet/fileio/io_gdal.py: 1 added line, 0 removed lines. Original line number Diff line number Diff line Loading @@ -350,6 +350,7 @@ class GeoDataset(object): xextent, yextent).astype(dtype) return array def array_to_raster(array, file_name, projection=None, geotransform=None, outformat='GTiff', ndv=None): Loading
autocnet/graph/network.py +97 −7 Changes for autocnet/graph/network.py: 97 added lines, 7 removed lines. Original line number Diff line number Diff line from collections import Hashable from networkx import DiGraph import networkx as nx import pandas as pd from autocnet.control.control import C, POINT_TYPE, MEASURE_TYPE from autocnet.fileio import io_json class CandidateGraph(DiGraph): class CandidateGraph(nx.Graph): """ A NetworkX derived directed graph to store candidate overlap images. Loading @@ -12,8 +18,6 @@ class CandidateGraph(DiGraph): Attributes ---------- """ #TODO: This would be better with composition, and then dispatch the # network X calls to the graph object. def __init__(self,*args, **kwargs): super(CandidateGraph, self).__init__(*args, **kwargs) Loading @@ -36,6 +40,7 @@ class CandidateGraph(DiGraph): Parameters ========== outputfile : str PATH where the JSON will be written """ Loading @@ -44,18 +49,103 @@ class CandidateGraph(DiGraph): adjacency_dict[n] = self.neighbors(n) io_json.write_json(adjacency_dict, outputfile) def add_matches(self, source_node, matches): """ Adds match data to a node and attributes the data to the appropriate edges, e.g. if A-B have a match, edge A-B is attributes with the pandas dataframe. Parameters ---------- source_node : str The identifier for the node matches : dataframe The pandas dataframe containing the matches """ #TODO: This really belongs in an outlier detection matcher class, not here. # Remove erroneous self neighbors matches = matches.loc[matches['matched_to'] != source_node] groups = matches.groupby('matched_to') for destination_node, group in groups: try: edge = self[source_node][destination_node] except: edge = self[destination_node][source_node] if 'matches' in edge.keys(): df = edge['matches'] edge['matches'] = pd.merge(df, matches, left_on='queryIdx', right_on='trainIdx') else: edge['matches'] = matches def to_cnet(self): """ Returns ------- cnet : C A control network object """ data = [] point_ids = [] serials = [] for source, destination, attributes in self.edges_iter(data=True): for i, row in attributes['matches'].iterrows(): # Get the source and destination x,y coordinates for matches source_idx = row['queryIdx_x'] source_keypoints = (self.node[source]['keypoints'][source_idx].pt[0], self.node[source]['keypoints'][source_idx].pt[1]) destination_idx = row['queryIdx_y'] destination_keypoints = (self.node[destination]['keypoints'][destination_idx].pt[0], self.node[destination]['keypoints'][destination_idx].pt[1]) data.append(source_keypoints) data.append(destination_keypoints) serials.append(source) serials.append(destination) point_ids.append(i) point_ids.append(i) point_types = [2] * len(point_ids) measure_types = [2] * len(point_ids) multi_index = pd.MultiIndex.from_tuples(list(zip(point_ids,point_types, serials, measure_types))) columns = ['x', 'y'] cnet = C(data, index=multi_index, columns=columns) # TODO: This method assumes a 2 image match and should be generalized to build an n-image C object return cnet @classmethod def from_adjacency(cls, inputfile): """ Instantiate the class using an adjacency list Parameters ========== ---------- inputfile : str The input file containing the graph representation Returns ------- : object A Network graph object Examples -------- >>> from autocnet.examples import get_path >>> inputfile = get_path('adjacency.json') >>> candidate_graph = network.CandidateGraph.from_adjacency(inputfile) """ #TODO: This is better as a generic reader that tries drivers until # a valid dict is returned. adjacency_dict = io_json.read_json(inputfile) return cls(adjacency_dict) Loading