Commit 1bec1bfe authored by jay's avatar jay
Browse files

Updates testing for control and tries centerilized testing repo

parent 3a1d050f
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -176,7 +176,7 @@ class ControlNetwork(object):

        return self.data.groupby('point_id').apply(func)

    def to_isis(self, outname, serials, olist, *args, **kwargs):
    def to_isis(self, outname, serials, olist, *args, **kwargs): #pragma: no cover
        """
        Write the control network out to the ISIS3 control network format.
        """

tests/READEME.md

0 → 100644
+3 −0
Original line number Diff line number Diff line
## Testing

The project is slowly transitioning over to using pytest (from Nose) for all testing.  Traditionally, the conftest.py file is used to support session wide testing fixtures.  We are using the same model here, defining Mocks of our primary objects that are used throughout the testing suite.

tests/conftest.py

0 → 100644
+129 −0
Original line number Diff line number Diff line
from unittest.mock import Mock, MagicMock

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

from autocnet.control import control
from autocnet.graph.network import CandidateGraph
from autocnet.graph.node import Node
from plio.io.io_gdal import GeoDataset

@pytest.fixture(scope='session')
def candidategraph(geodata_a, geodata_b, geodata_c):
    cg = CandidateGraph()

    # Create a candidategraph object - we instantiate a real CandidateGraph to
    # have access of networkx functionality we do not want to test and then
    # mock all autocnet functionality to control test behavior.
    edges = [(0,1), (0,2), (1,2)]
    cg.add_edges_from(edges)

    match_indices = [([0,1,2,3,4,5,6,7], [0,1,2,3,4,5,6,7]),
                     ([0,1,2,3,4,5,8,9], [0,1,2,3,4,5,8,9]),
                     ([0,1,2,3,4,5,8,9], [0,1,2,3,4,5,6,7])]

    matches = []
    for i, e in enumerate(edges):
        c = match_indices[i]
        source_image = np.repeat(e[0], 8)
        destin_image = np.repeat(e[1], 8)
        coords = np.zeros(8)
        data = np.vstack((source_image, c[0], destin_image, c[1],
                          coords, coords, coords, coords)).T
        matches_df = pd.DataFrame(data, columns=['source_image', 'source_idx', 'destination_image', 'destination_idx',
                                                 'source_x', 'source_y', 'destination_x', 'destination_y'])
        matches.append(matches_df)

    # Mock in autocnet methods
    cg.get_matches = MagicMock(return_value=matches)

    # Mock in the node objects onto the candidate graph
    cg.node[0] = geodata_a
    cg.node[1] = geodata_b
    cg.node[2] = geodata_c

    return cg

#TODO: Can these be a single parameterized fixture - so much boilerplate!
@pytest.fixture(scope='session')
def geodata_a():
    a = Mock(spec=Node)
    a.geodata = Mock(spec=GeoDataset)
    a.geodata.pixel_to_latlon = MagicMock(side_effect=lambda x, y: (x, y))
    return a

@pytest.fixture(scope='session')
def geodata_b():
    b = Mock(spec=Node)
    b.geodata = Mock(spec=GeoDataset)
    b.geodata.pixel_to_latlon = MagicMock(side_effect=lambda x, y: (x, y))
    return b

@pytest.fixture(scope='session')
def geodata_c():
    c = Mock(spec=Node)
    c.geodata = Mock(spec=GeoDataset)
    c.geodata.pixel_to_latlon = MagicMock(side_effect=lambda x, y: (x, y))
    return c

@pytest.fixture(scope='session')
def controlnetwork_data():
    df = pd.DataFrame([[0, 0.0, 0.0, (0.0, 1.0), 0, 0.0, 0.0],
                             [0, 1.0, 0.0, (0.0, 1.0), 0, 0.0, 0.0],
                             [1, 0.0, 1.0, (0.0, 1.0), 1, 0.0, 0.0],
                             [1, 1.0, 1.0, (0.0, 1.0), 1, 0.0, 0.0],
                             [2, 0.0, 2.0, (0.0, 1.0), 2, 0.0, 0.0],
                             [2, 1.0, 2.0, (0.0, 1.0), 2, 0.0, 0.0],
                             [3, 0.0, 3.0, (0.0, 1.0), 3, 0.0, 0.0],
                             [3, 1.0, 3.0, (0.0, 1.0), 3, 0.0, 0.0],
                             [4, 0.0, 4.0, (0.0, 1.0), 4, 0.0, 0.0],
                             [4, 1.0, 4.0, (0.0, 1.0), 4, 0.0, 0.0],
                             [5, 0.0, 5.0, (0.0, 1.0), 5, 0.0, 0.0],
                             [5, 1.0, 5.0, (0.0, 1.0), 5, 0.0, 0.0],
                             [6, 0.0, 6.0, (0.0, 1.0), 6, 0.0, 0.0],
                             [6, 1.0, 6.0, (0.0, 1.0), 6, 0.0, 0.0],
                             [7, 0.0, 7.0, (0.0, 1.0), 7, 0.0, 0.0],
                             [7, 1.0, 7.0, (0.0, 1.0), 7, 0.0, 0.0],
                             [0, 2.0, 0.0, (0.0, 2.0), 0, 0.0, 0.0],
                             [1, 2.0, 1.0, (0.0, 2.0), 1, 0.0, 0.0],
                             [2, 2.0, 2.0, (0.0, 2.0), 2, 0.0, 0.0],
                             [3, 2.0, 3.0, (0.0, 2.0), 3, 0.0, 0.0],
                             [4, 2.0, 4.0, (0.0, 2.0), 4, 0.0, 0.0],
                             [5, 2.0, 5.0, (0.0, 2.0), 5, 0.0, 0.0],
                             [8, 0.0, 8.0, (0.0, 2.0), 6, 0.0, 0.0],
                             [8, 2.0, 8.0, (0.0, 2.0), 6, 0.0, 0.0],
                             [9, 0.0, 9.0, (0.0, 2.0), 7, 0.0, 0.0],
                             [9, 2.0, 9.0, (0.0, 2.0), 7, 0.0, 0.0],
                             [10, 1.0, 8.0, (1.0, 2.0), 6, 0.0, 0.0],
                             [10, 2.0, 6.0, (1.0, 2.0), 6, 0.0, 0.0],
                             [11, 1.0, 9.0, (1.0, 2.0), 7, 0.0, 0.0],
                             [11, 2.0, 7.0, (1.0, 2.0), 7, 0.0, 0.0]],
                            columns=['point_id', 'image_index', 'keypoint_index',
                                     'edge', 'match_idx', 'x', 'y'])

    df.index.name = 'measure_id'

    #Fix types
    df['point_id'] = df['point_id'].astype(object)
    df['match_idx'] = df['match_idx'].astype(object)

    return df

@pytest.fixture(scope='session')
def controlnetwork(controlnetwork_data):
    cn = control.ControlNetwork()
    cn.data = controlnetwork_data
    # Patching data this way does NOT update the internal _measure_id and _point_id attributes
    return cn

@pytest.fixture(scope='session')
def bad_controlnetwork(controlnetwork_data):
    cn = control.ControlNetwork()
    cn.data = controlnetwork_data
    # Since the data is being patched in, fix the measure counter
    cn._measure_id = len(cn.data) + 1
    # Add a duplicate measure in image 0 to point 0
    cn.add_measure((0,11), (0,1), 2, [1,1], point_id=0)
    return cn
+63 −0
Original line number Diff line number Diff line
from unittest.mock import MagicMock
import geopandas as gpd
import pandas as pd
from shapely.geometry import Polygon
from autocnet.control import control

def test_fromcandidategraph(candidategraph, controlnetwork_data):#, controlnetwork):
    matches = candidategraph.get_matches()
    cn = control.ControlNetwork.from_candidategraph(matches)
    assert cn.data.equals(controlnetwork_data)

def test_add_measure():
    cn = control.ControlNetwork()

    # Add the point 0 from image 0
    key = (0,0)
    cn.add_measure(key, (0,1), 3, [1,1])
    assert key in cn.measure_to_point.keys()
    assert cn.measure_to_point[key] == 0

    # Add the point 1 from image 2
    key = (1,2)
    cn.add_measure(key, (0,1), 2, [1,1])
    assert key in cn.measure_to_point.keys()

    # Add another measure associated with point (0,0)
    #  Key is the source and this methods is called to add the destination
    key = (2,1)
    cn.add_measure(key, (0,2), 3, [1,1], point_id = 0)
    assert key in cn.measure_to_point.keys()
    assert cn.measure_to_point[key] == 0

def test_validate_points(controlnetwork):
    assert controlnetwork.validate_points().any()

def test_bad_validate_points(bad_controlnetwork):
    assert bad_controlnetwork.validate_points().iloc[0] == False
    assert bad_controlnetwork.validate_points().iloc[1:].all()

def test_identify_potential_overlaps(controlnetwork, candidategraph):
    res = control.identify_potential_overlaps(candidategraph,
                                              controlnetwork,
                                              overlap=False)

    assert res.equals(pd.Series([(2,), (2,),
                                 (1,), (1,),
                                 (0,), (0,)],
                                 index=[6,7,8,9,10,11]))

def test_potential_overlap(controlnetwork, candidategraph):
    # Patch in an intersection check so that all points intersect all geoms
    candidategraph.create_node_subgraph = MagicMock(return_value=candidategraph)
    coords = [(-1., -1.), (-1., 1.), (1., 1.), (1., -1.), (-1., -1.)]
    poly = gpd.GeoSeries(Polygon(coords))
    candidategraph.compute_intersection = MagicMock(return_value=(poly, 0))
    res = control.identify_potential_overlaps(candidategraph,
                                              controlnetwork,
                                              overlap=True)

    assert res.equals(pd.Series([(2,), (2,),
                                 (1,), (1,),
                                 (0,), (0,)],
                                 index=[6,7,8,9,10,11]))