Commit c3771da2 authored by jay's avatar jay
Browse files

merge from master

parents 9fbd0ba9 7f9248ab
Loading
Loading
Loading
Loading
+3 −1
Original line number Diff line number Diff line
@@ -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.
@@ -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
+2 −0
Original line number Diff line number Diff line
@@ -2,6 +2,8 @@ from time import gmtime, strftime

import pandas as pd

POINT_TYPE = 2
MEASURE_TYPE = 2

class CSeries(pd.Series):
    """
+1 −0
Original line number Diff line number Diff line
@@ -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):
+0 −0

Empty file deleted.

+97 −7
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.

@@ -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)
@@ -36,6 +40,7 @@ class CandidateGraph(DiGraph):

        Parameters
        ==========

        outputfile : str
                     PATH where the JSON will be written
        """
@@ -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