Commit 24989545 authored by Adam Paquette's avatar Adam Paquette
Browse files

Added more voronoi notebook code to the code base.

parent dca2dca0
Loading
Loading
Loading
Loading
+18 −20
Changes for autocnet/cg/cg.py: 18 added lines, 20 removed lines.
Original line number Diff line number Diff line
import pandas as pd
import numpy as np
import networkx as nx
import geopandas as gpd
import ogr

@@ -110,16 +111,16 @@ def get_area(poly1, poly2):
    return intersection_area


def vor(graph, clean_keys=[], s=30):
def vor(graph, clean_keys, s=30):
        """
        Creates a voronoi diagram for an edge using either the coordinate
        transformation or using the homography between source and destination.
        Creates a voronoi diagram for a complete graph using either the coordinate
        transformation or using the homography based around a source node.

        The coordinate transformation uses the footprint of source and destination to
        calculate an intersection between the two images, then transforms the vertices of
        The coordinate transformation uses the footprint of each image to
        calculate an intersection between the image set, then transforms the vertices of
        the intersection back into pixel space.

        If a coordinate transform does not exist, use the homography to project the destination image
        If a coordinate transform does not exist, use the homography to project the n - 1 images
        onto the source image, producing an area of intersection.

        The intersection vertices are then scaled by a factor of s (default 30), this accounts for the
@@ -129,8 +130,8 @@ def vor(graph, clean_keys=[], s=30):

        Parameters
        ----------
        edge : object
               An edge object
        graph : object
               A networkx graph object

        clean_keys : list
                     Of strings used to apply masks to omit correspondences
@@ -147,10 +148,8 @@ def vor(graph, clean_keys=[], s=30):
                     3 column pandas dataframe of x, y, and weights

        """
        num_neighbors = len(graph.nodes()) - 1
        for n in graph.nodes():
            neighbors = len(graph.neighbors(n))
            if neighbors != num_neighbors:
        neighbors_dict = nx.degree(graph)
        if not all(value == len(graph.neighbors(graph.nodes()[0])) for value in neighbors_dict.values()):
                raise AssertionError('The graph is not complete')

        intersection, proj_gdf, source_gdf = compute_intersection(graph.nodes()[0], graph, clean_keys)
@@ -165,7 +164,6 @@ def vor(graph, clean_keys=[], s=30):
                intersection_ind = intersection.query('overlaps_all == True').index.values[0]

            edge = graph.edge[e[0]][e[1]]
            matches, mask = edge.clean(clean_keys = clean_keys)
            kps = edge.get_keypoints('source', clean_keys=clean_keys, homogeneous=True)

            kps['geometry'] = kps.apply(lambda x: Point(x['x'], x['y']), axis=1)
@@ -200,7 +198,7 @@ def vor(graph, clean_keys=[], s=30):
                                       'weight'] = poly_area
                i += 1

            edge.weight['vor_weight'] = voronoi_df['weight']
            edge['weights']['vor_weight'] = voronoi_df['weight']


def compute_intersection(source, graph, clean_keys=[]):
@@ -210,23 +208,23 @@ def compute_intersection(source, graph, clean_keys=[]):
    source_corners = source.geodata.xy_corners
    source_poly = Polygon(source_corners)

    source_gdf = gpd.GeoDataFrame({'source_geom': [source_poly], 'source_node': [source.node_id]}).set_geometry('source_geom')
    source_gdf = gpd.GeoDataFrame({'source_geom': [source_poly], 'source_node': [source['node_id']]}).set_geometry('source_geom')

    proj_list = []
    proj_nodes = []
    # Begin iterating through the nodes in the graph excluding the source node
    for n in graph.nodes_iter():
        if n == source.node_id:
        if n == source['node_id']:
            continue

        # Define the edge, matches, and destination based on the zero node and the nth node
        destination = graph.node[n]
        destination_corners = destination.geodata.xy_corners

        edge = graph.edge[source.node_id][destination.node_id]
        edge = graph.edge[source['node_id']][destination['node_id']]

        # Will still need the check but the helper function will make these calls much easier to understand
        if source.node_id > destination.node_id:
        if source['node_id'] > destination['node_id']:
            kp2 = edge.get_keypoints('source', clean_keys = clean_keys, homogeneous = True)
            kp1 = edge.get_keypoints('destination', clean_keys = clean_keys, homogeneous = True)
        else:
@@ -234,8 +232,8 @@ def compute_intersection(source, graph, clean_keys=[]):
            kp1 = edge.get_keypoints('source', clean_keys = clean_keys, homogeneous = True)

        # If the source image has coordinate transformation data
        if (source.geodata.coordinate_transformation.this != None) and \
        (destination.geodata.coordinate_transformation.this != None):
        if (source.geodata.coordinate_transformation.this is None) and \
           (destination.geodata.coordinate_transformation.this is None):
            proj_poly = Polygon(destination.geodata.xy_corners)

        # Else, use the homography transform to get an intersection of the two images
+17 −2
Changes for autocnet/graph/network.py: 17 added lines, 2 removed lines.
Original line number Diff line number Diff line
@@ -9,6 +9,7 @@ import pandas as pd
from plio.io import io_hdf, io_json
from plio.utils import utils as io_utils
from plio.io.io_gdal import GeoDataset
from autocnet.cg.cg import vor
from autocnet.graph import markov_cluster
from autocnet.graph.edge import Edge
from autocnet.graph.node import Node
@@ -684,5 +685,19 @@ class CandidateGraph(nx.Graph):
        edges = [(u, v) for u, v, edge in self.edges_iter(data=True) if func(edge, *args, **kwargs)]
        return self.create_edge_subgraph(edges)

    def compute_vor_weight(self, clean_keys = [], **kwargs):
        pass
    def compute_cliques(self, node_id):
        if node_id is not None:
            return list(nx.cliques_containing_node(self, nodes=node_id))
        else:
            return list(nx.find_cliques(self))

    def compute_vor_weight(self, clean_keys, node_id=None, clique=False):
        if clique:
            cliques = self.compute_cliques(node_id)
            for g in cliques:
                subgraph = self.create_node_subgraph(g)
                vor(subgraph, clean_keys)
        else:
            for e in self.edges_iter():
                subgraph = self.create_node_subgraph(e)
                vor(subgraph, clean_keys)
+2 −0
Changes for autocnet/utils/utils.py: 2 added lines, 0 removed lines.
Original line number Diff line number Diff line
@@ -4,6 +4,7 @@ from functools import reduce

import numpy as np
import pandas as pd
import networkx as nx

from osgeo import ogr

@@ -386,3 +387,4 @@ def scale_point(point, centroid, scale):
    centroid = centroid[:2]
    vector = ((point - centroid)*scale) + centroid
    return vector
+86 −58
Changes for notebooks/Testing_geopandas.ipynb: 86 added lines, 58 removed lines.
Original line number Diff line number Diff line
%% Cell type:code id: tags:

``` python
import os
import sys

sys.path.insert(0, os.path.abspath('..'))

import cv2
import numpy as np
import geopandas as gpd
import pandas as pd
import networkx as nx
from shapely.geometry import Polygon as Poly, Point
from shapely.affinity import scale
import ogr
import time
from scipy.spatial import Voronoi

from autocnet.examples import get_path
from autocnet.graph.network import CandidateGraph
from autocnet.cg import cg

from unittest.mock import Mock
from unittest.mock import MagicMock
from autocnet.graph import edge
from autocnet.graph import node
from autocnet.graph.node import Node
from plio.io import io_gdal

from autocnet.utils.utils import array_to_poly

from IPython.display import display

%pylab inline
figsize(20, 20)
```

%% Output

    Populating the interactive namespace from numpy and matplotlib

%% Cell type:code id: tags:

``` python
def scale_point(point, centroid, scalar):
    point = np.asarray(point)
    centroid = centroid[:2]
    vector = ((point - centroid)*scalar) + centroid
    return (vector)
```

%% Cell type:code id: tags:

``` python
def reproj_point(H, point):
    """
    Reproject a pixel in one image into another image

    Parameters
    ----------
    H : object
        (3,3) ndarray or Homography object

    corner : iterable
             A 2 element iterable in the form x, y
    """
    if len(point) == 2:
        coords = np.array([point[0],point[1],1])
    elif len(point) == 3:
        coords = np.asarray(point)
        coords *= coords[-1]  # Homogenize

    return H.dot(coords)
```

%% Cell type:code id: tags:

``` python
def compute_intersection(source, graph, clean_keys=[]):
    if type(source) is int:
        source = graph.node[source]

    source_corners = source.geodata.xy_corners
    source_poly = Poly(source_corners)

    source_gdf = gpd.GeoDataFrame({'source_geom': [source_poly], 'source_node': [source['node_id']]}).set_geometry('source_geom')

    proj_list = []
    proj_nodes = []
    # Begin iterating through the nodes in the graph excluding the source node
    for n in graph.nodes_iter():
        if n == source['node_id']:
            continue

        # Define the edge, matches, and destination based on the zero node and the nth node
        destination = graph.node[n]
        destination_corners = destination.geodata.xy_corners
        print(source, destination)

        edge = graph.edge[source['node_id']][destination['node_id']]

        # Will still need the check but the helper function will make these calls much easier to understand
        if source['node_id'] > destination['node_id']:
            kp2 = edge.get_keypoints('source', clean_keys = clean_keys, homogeneous = True)
            kp1 = edge.get_keypoints('destination', clean_keys = clean_keys, homogeneous = True)
        else:
            kp2 = edge.get_keypoints('destination', clean_keys = clean_keys, homogeneous = True)
            kp1 = edge.get_keypoints('source', clean_keys = clean_keys, homogeneous = True)

        # If the source image has coordinate transformation data
        if (source.geodata.coordinate_transformation.this != None) and \
        (destination.geodata.coordinate_transformation.this != None):
            proj_poly = Poly(destination.geodata.xy_corners)

        # Else, use the homography transform to get an intersection of the two images
        else:
            H, mask = cv2.findHomography(kp2.values, kp1.values, cv2.RANSAC, 2.0)
            proj_corners = []
            for c in destination_corners:
                x, y, h = reproj_point(H, c)
                x /= h
                y /= h
                h /= h
                proj_corners.append((x, y))

            proj_poly = Poly(proj_corners)

        proj_list.append(proj_poly)
        proj_nodes.append(n)

    proj_gdf = gpd.GeoDataFrame({'proj_geom': proj_list, 'proj_node': proj_nodes}).set_geometry('proj_geom')

    intersect_gdf = gpd.overlay(source_gdf, proj_gdf, how='intersection')
    intersect_gdf = intersect_gdf.rename(columns = {'geometry':'intersect_geom'}).set_geometry('intersect_geom')
    intersect_gdf['overlaps_all'] = intersect_gdf.geometry.apply(lambda x:proj_gdf.geometry.contains(scale(x, .9, .9)).all())
    intersection = intersect_gdf.query('overlaps_all == True').set_geometry('intersect_geom')
    return intersection, proj_gdf, source_gdf
```

%% Cell type:code id: tags:

``` python
def vor(graph, clean_keys=[], verbose=False, s = 30):

    num_neighbors = len(graph.nodes()) - 1
    for n in graph.nodes():
        neighbors = len(graph.neighbors(n))
        if neighbors != num_neighbors:
            raise AssertionError('The graph is not complete')
    neighbors_dict = nx.degree(graph)
    if not all(value == len(graph.neighbors(graph.nodes()[0])) for value in neighbors_dict.values()):
        raise AssertionError('The graph is not complete')

    # Have compute_intersection get the intersections of the subgraph, the projected nodes in the
    # subgraph, and the source image all in there own geopandas dataframes
    intersection, proj_gdf, source_gdf = compute_intersection(graph.nodes()[0], graph, clean_keys)

    # Get the intersection for the given subgrpah
    intersection_ind = intersection.query('overlaps_all == True').index.values[0]

    source_node = graph.nodes()[0]
    # Set the source, destination, edge, matches, and keypoints(kps) based on the first edge in the subgraph
    # which should be the smallest node in the graph
    for e in graph.edges():
        # Recompute the intersection if the source node of the n + 1 edge is different from the n edge
        if e[0] != source_node:
            source_node = e[0]
            intersection, proj_gdf, source_gdf = compute_intersection(source_node, graph, clean_keys)
            intersection_ind = intersection.query('overlaps_all == True').index.values[0]


        edge = graph.edge[e[0]][e[1]]
        matches, mask = edge.clean(clean_keys = clean_keys)
        kps = edge.get_keypoints('source', clean_keys = clean_keys, homogeneous = True)

        # Get all of the keypoints that are inside of the intersection then mask out the points
        # in kps that lie outside of the intersection
        # All of these operations on kps are extremely expensive
        kps['geometry'] = kps.apply(lambda x: Point(x['x'], x['y']), axis = 1)
        kps.mask = kps['geometry'].apply(lambda x: intersection.geometry.contains(x).all())

        # Creates a mask for displaying the voronoi points
        # Currently erronious and produces NaN values
        # mask[mask] = kps.mask
        # edge.masks = ('voronoi', mask)

        keypoints = []
        kps[kps.mask].apply(lambda x: keypoints.append((x['x'], x['y'])), axis = 1)
        coords = source_gdf.geometry.apply(lambda x:scale(x, s, s).exterior.coords)

        for point in coords:
            keypoints = np.vstack((keypoints, point))

        vor = Voronoi(keypoints)

        # For weight computation
        # Should move to its own method
        voronoi_df = pd.DataFrame(data = kps, columns = ['x', 'y', 'weight'])

        i = 0
        vor_points = np.asarray(vor.points)
        for region in vor.regions:
            region_point = vor_points[np.argwhere(vor.point_region==i)]
            if not -1 in region:
                polygon_points = [vor.vertices[i] for i in region]
                if len(polygon_points) != 0:
                    polygon = Poly(polygon_points)
                    poly_area = polygon.intersection(intersection.geometry[intersection_ind]).area
                    voronoi_df.loc[(voronoi_df["x"] == region_point[0][0][0]) &
                                   (voronoi_df["y"] == region_point[0][0][1]),
                                   'weight'] = poly_area
            i+=1

        edge['weights']['vor_weight'] = voronoi_df['weight']
```

%% Cell type:code id: tags:

``` python
#Point to the adjacency Graph
adjacency = get_path('vor_adjacency1.json')
basepath = get_path('Apollo15')
cang = CandidateGraph.from_adjacency(adjacency, basepath=basepath)

#Apply SIFT to extract f"eatures
cang.extract_features(method='sift', extractor_parameters={'nfeatures':1500})

#Match
cang.match()

#Apply outlier detection
# cg.apply_func_to_edges(Edge.symmetry_check)
cang.symmetry_checks()
# cg.apply_func_to_edges(Edge.ratio_check)
cang.ratio_checks()


#Compute a homography and apply RANSAC
cang.apply_func_to_edges("compute_fundamental_matrix", clean_keys=['ratio', 'symmetry'])
```

%% Output

    /home/acpaquette/autocnet/autocnet/transformation/fundamental_matrix.py:252: UserWarning: Unable to apply MLE.  Not enough correspondences.  Returning with a RANSAC computed F matrix.
      warnings.warn("Unable to apply MLE.  Not enough correspondences.  Returning with a RANSAC computed F matrix.")

%% Cell type:code id: tags:

``` python
def compute_weights(cang, source_id, clean_keys = [], verbose = False):
    cliques = compute_cliques(cang, source_id)
    source = cang.node[source_id]
    for g in cliques:
        subgraph = cang.create_node_subgraph(g)
        gdf_tup = vor(subgraph, source, clean_keys, verbose)
def compute_weights(cang, clean_keys = [], node_id=None, clique = False,):
    if clique:
        cliques = compute_cliques(cang, node_id)
        for g in cliques:
            subgraph = cang.create_node_subgraph(g)
            cg.vor(subgraph, clean_keys)
    else:
        for e in cang.edges_iter():
            subgraph = cang.create_node_subgraph(e)
            cg.vor(subgraph, clean_keys)
```

%% Cell type:code id: tags:

``` python
def compute_cliques(graph, source_id):
    if source_id is not None:
        return list(nx.cliques_containing_node(cang, nodes=source_id))
def compute_cliques(graph, node_id):
    if node_id is not None:
        return list(nx.cliques_containing_node(graph, nodes=node_id))
    else:
        return list(nx.find_cliques(graph))
```

%% Cell type:code id: tags:

``` python
start = time.clock()
cliques = compute_cliques(cang, None)
for g in cliques:
    subgraph = cang.create_node_subgraph(g)
    vor(subgraph, clean_keys = ['fundamental'])
compute_weights(cang, clique = True, clean_keys = ['fundamental'])
print(time.clock() - start)

start = time.clock()
compute_weights(cang, clique = False, clean_keys = ['fundamental'])
print(time.clock() - start)
```

%% Output

    3.1514979999999966
    2.8140520000000038

%% Cell type:code id: tags:

``` python
start = time.clock()
cang.compute_vor_weight(clean_keys = ['fundamental'], clique = True)
print(time.clock() - start)

start = time.clock()
for e in cang.edges_iter():
    subgraph = cang.create_node_subgraph(e)
    vor(subgraph, clean_keys = ['fundamental'])
cang.compute_vor_weight(clean_keys = ['fundamental'], clique = False)
print(time.clock() - start)
```

%% Output

    Getting CT
    CT <osgeo.osr.CoordinateTransformation; proxy of None >
    Getting CT
    CT <osgeo.osr.CoordinateTransformation; proxy of None >
    Getting CT
    CT <osgeo.osr.CoordinateTransformation; proxy of None >
    Getting CT
    CT <osgeo.osr.CoordinateTransformation; proxy of None >
    Getting CT
    CT <osgeo.osr.CoordinateTransformation; proxy of None >
    Getting CT
    CT <osgeo.osr.CoordinateTransformation; proxy of None >
    2.850580000000001
    2.9477230000000016
    3.1148349999999994
    2.8084049999999934

%% Cell type:code id: tags:

``` python
source_keypoint_df = pd.DataFrame({'x': (15, 18, 18, 12, 12), 'y': (6, 10, 15, 15, 10)})
destination_keypoint_df = pd.DataFrame({'x': (5, 8, 8, 2, 2), 'y': (1, 5, 10, 10, 5)})
keypoint_matches = [[0, 0, 1, 0],
                    [0, 1, 1, 1],
                    [0, 2, 1, 2],
                    [0, 3, 1, 3],
                    [0, 4, 1, 4]]

matches_df = pd.DataFrame(data = keypoint_matches, columns = ['source_image', 'source_idx',
                                                                  'destination_image', 'destination_idx'])
# Source and Destination Node Setup
source_node = MagicMock(spec = Node())
destination_node = MagicMock(spec = Node())

source_node.get_keypoint_coordinates = MagicMock(return_value=source_keypoint_df)
destination_node.get_keypoint_coordinates = MagicMock(return_value=destination_keypoint_df)
source_node.__get_item__ = 0
destination_node.__get_item__ = 1

source_geodata = Mock(spec = io_gdal.GeoDataset)
destination_geodata = Mock(spec = io_gdal.GeoDataset)

source_node.geodata = source_geodata
destination_node.geodata = destination_geodata

source_node.geodata.coordinate_transformation.this = None
destination_node.geodata.coordinate_transformation.this = None

source_corners = [(0, 0),
                  (20, 0),
                  (20, 20),
                  (0, 20)]

destination_corners = [(0, 0),
                       (20, 0),
                       (20, 20),
                       (0, 20)]

source_node.geodata.xy_corners = source_corners
destination_node.geodata.xy_corners = destination_corners

# Edge Setup
e = edge.Edge(source = source_node, destination = destination_node)

e.clean = MagicMock(return_value=(matches_df, None))
e.matches = matches_df

def side_effect(node, clean_keys, **kwargs):
    if type(node) is str:
        node = node.lower()

    if isinstance(node, Node):
        node = node['node_id']

    if node == "source" or node == "s" or node == source_node['node_id']:
        return e.source.get_keypoint_coordinates().copy(deep=True)
    if node == "destination" or node == "d" or node == destination_node['node_id']:
        return e.destination.get_keypoint_coordinates().copy(deep=True)

my_dict_source = {'node_id':0}

def getitem_source(name):
    return my_dict_source[name]

my_dict_destination = {'node_id':1}

def getitem_destination(name):
    return my_dict_destination[name]

source_node.__getitem__.side_effect = getitem_source
destination_node.__getitem__.side_effect = getitem_destination

e.get_keypoints = MagicMock(side_effect = side_effect)

cang = MagicMock(spec = CandidateGraph())

cang.nodes = MagicMock(return_value=([0, 1]))
cang.node = [source_node, destination_node]
cang.nodes_iter = MagicMock(return_value=([0, 1]))
cang.neighbors = MagicMock(return_value = [1])
cang.edges = MagicMock(return_value=([(0, 1)]))
cang.edge = {0:{1:e}, 1:{0:e}}
```

%% Cell type:code id: tags:

``` python
start = time.clock()
vor(cang, clean_keys = ['fundamental'])
print(time.clock() - start)
print(e['weights'])
```

%% Output

    <MagicMock spec='Node' id='140434391257040'> <MagicMock spec='Node' id='140434391257040'>

    ---------------------------------------------------------------------------
    KeyError                                  Traceback (most recent call last)
    <ipython-input-22-60125f4ee637> in <module>()
    ----> 1 vor(cang, clean_keys = ['fundamental'])

    <ipython-input-5-733ea7cc66d3> in vor(graph, clean_keys, verbose, s)
          9     # Have compute_intersection get the intersections of the subgraph, the projected nodes in the
         10     # subgraph, and the source image all in there own geopandas dataframes
    ---> 11     intersection, proj_gdf, source_gdf = compute_intersection(graph.nodes()[0], graph, clean_keys)
         12
         13     # Get the intersection for the given subgrpah
    <ipython-input-12-7fbccd493ab1> in compute_intersection(source, graph, clean_keys)
         20         print(source, destination)
         21
    ---> 22         edge = graph.edge[source['node_id']][destination['node_id']]
         23
         24         # Will still need the check but the helper function will make these calls much easier to understand
    KeyError: <MagicMock name='mock.__getitem__()' id='140434391038104'>
    0.031369000000001535
    {'vor_weight': 0    22.50
    1    26.25
    2    37.50
    3    37.50
    4    26.25
    Name: weight, dtype: float64}

%% Cell type:code id: tags:

``` python
# adjacency = get_path('two_image_adjacency.json')
# basepath = get_path('Apollo15')
# cg = CandidateGraph.from_adjacency(adjacency, basepath=basepath)
keypoint_df = pd.DataFrame({'x': (15, 18, 18, 12, 12), 'y': (6, 10, 15, 15, 10)})
keypoint_matches = [[0, 0, 1, 0],
                    [0, 1, 1, 1],
                    [0, 2, 1, 2],
                    [0, 3, 1, 3],
                    [0, 4, 1, 4]]

matches_df = pd.DataFrame(data = keypoint_matches, columns = ['source_image', 'source_idx',
                                                                  'destination_image', 'destination_idx'])
e = edge.Edge(source = source_node, destination = destination_node)

e.clean = MagicMock(return_value=(matches_df, None))
e.matches = matches_df

source_node = MagicMock(spec = node.Node())
destination_node = MagicMock(spec = node.Node())

cang = MagicMock(spec = CandidateGraph())

cang.nodes = MagicMock(return_value=([0, 1]))
cang.node = [source_node, destination_node]
cang.nodes_iter = MagicMock(return_value=([0, 1]))
cang.neighbors = MagicMock(return_value=([0]))
cang.edges = MagicMock(return_value=([(0, 1)]))
cang.edge = {0:{1:e}, 1:{0:e}}

source_node.get_keypoint_coordinates = MagicMock(return_value=keypoint_df)
destination_node.get_keypoint_coordinates = MagicMock(return_value=keypoint_df)
source_node['node_id'] = 0
destination_node['node_id'] = 1

def side_effect(node, clean_keys, **kwargs):
    if type(node) is str:
        node = node.lower()

    if isinstance(node, Node):
        node = node['node_id']

    if node == "source" or node == "s" or node == source_node['node_id']:
        return e.source.get_keypoint_coordinates()
    if node == "destination" or node == "d" or node == destination_node['node_id']:
        return e.destination.get_keypoint_coordinates()

e.get_keypoints = MagicMock(side_effect = side_effect)

e.source = source_node
e.destination = destination_node

source_geodata = Mock(spec = io_gdal.GeoDataset)
destination_geodata = Mock(spec = io_gdal.GeoDataset)

e.source.geodata = source_geodata
e.destination.geodata = destination_geodata

source_corners = [(0, 0),
                  (20, 0),
                  (20, 20),
                  (0, 20)]

destination_corners = [(10, 5),
                       (30, 5),
                       (30, 25),
                       (10, 25)]

source_xy_extent = [(0, 20), (0, 20)]

destination_xy_extent = [(10, 30), (5, 25)]

source_poly = array_to_poly(source_corners)
destination_poly = array_to_poly(destination_corners)

vals = {(10, 5):(10, 5), (20, 5):(20, 5), (20, 20):(20, 20), (10, 20):(10, 20)}

def latlon_to_pixel(i, j):
    return vals[(i, j)]

my_dict_source = {'node_id':0}

def getitem_source(name):
    return my_dict_source[name]

my_dict_destination = {'node_id':1}

def getitem_destination(name):
    return my_dict_destination[name]

source_node.__getitem__.side_effect = getitem_source
destination_node.__getitem__.side_effect = getitem_destination

e.source.geodata.latlon_to_pixel = MagicMock(side_effect = latlon_to_pixel)
e.destination.geodata.latlon_to_pixel = MagicMock(side_effect = latlon_to_pixel)

e.source.geodata.footprint = source_poly
e.source.geodata.xy_corners = source_corners
e.source.geodata.xy_extent = source_xy_extent
e.destination.geodata.footprint = destination_poly
e.destination.geodata.xy_corners = destination_corners
e.destination.geodata.xy_extent = destination_xy_extent
```

%% Cell type:code id: tags:

``` python
start = time.clock()
vor(cang, clean_keys = ['fundamental'])
print(time.clock() - start)
print(e['weights'])
```

%% Output

    0.03340599999999938
    {'vor_weight': 0    22.50
    1    26.25
    2    37.50
    3    37.50
    4    26.25
    Name: weight, dtype: float64}

%% Cell type:code id: tags:

``` python
```

%% Cell type:code id: tags:

``` python
def vor_plot(graph, clean_keys = []):

    num_neighbors = len(graph.nodes()) - 1
    for n in graph.nodes():
        neighbors = len(graph.neighbors(n))
        if neighbors != num_neighbors:
            raise AssertionError('The graph is not complete')

    intersection, proj_gdf, source_gdf = compute_intersection(graph.nodes()[0], graph, clean_keys)

    source_node = graph.nodes()[0]

    for e in graph.edges():
        if e[0] != source_node:
            source_node = e[0]
            start_inter = time.clock()
            intersection, proj_gdf, source_gdf = compute_intersection(source_node, graph, clean_keys)

        edge = graph.edge[e[0]][e[1]]
        kps = edge.get_keypoints('source', clean_keys = clean_keys, homogeneous = True)
        kps = kps[edge.vor_mask]

        vor = edge.voronoi

        i = 0
        poly_array = []
        vor_points = np.asarray(vor.points)
        for region in vor.regions:
            region_point = vor_points[np.argwhere(vor.point_region==i)]
            if not -1 in region:
                polygon_points = [vor.vertices[i] for i in region]
                if len(polygon_points) != 0:
                    polygon = Poly(polygon_points)
                    poly_array.append(polygon)
            i+=1

        poly_gdf = gpd.GeoDataFrame(data = poly_array, columns = ['geometry'])
        vor_poly_gdf = gpd.overlay(poly_gdf, intersection, how='intersection')

        ax = proj_gdf.query('proj_node != ' + str(n)).plot(color='#388aff', alpha=0.1)
        proj_gdf.query('proj_node == ' + str(n)).plot(color = 'g', alpha=0.1, ax = ax)
        source_gdf.plot(color='r', alpha=0.1, ax=ax)
        vor_poly_gdf.plot(cmap='Set1', alpha=.5, ax=ax)
#             graph.edge[0][3].plot(clean_keys = ['fundamental'], ax = ax)
        edge.source.plot(index_mask = edge.matches['destination_idx'], alpha = 0)
        matplotlib.pyplot.scatter(kps['x'], kps['y'], color = 'black', alpha = 1)
```
+1 −1

File changed.

Contains only whitespace changes.