Source code for autocnet.control.control

import warnings
import networkx as nx
import numpy as np
import pandas as pd
import geopandas as gpd
from shapely.geometry import Point

from autocnet.matcher import subpixel as sp

from plio.io.io_controlnetwork import to_isis, write_filelist
from plio.utils import covariance

[docs]def compute_covariance(df, latsigma, lonsigma, radsigma, radius): """ Compute the covariance matrices for constrained or fixed points. Parameters ---------- df : pd.DataFrame with columns pointtype, adjustedY, and adjustedX latsigma : int/float The estimated sigma (error) in the latitude direction lonsigma : int/float The estimated sigma (error) in the longitude direction radsigma : int/float The estimated sigma (error) in the radius direction radius : int/float The body semimajor radius """ def compute_covar(row, latsigma, lonsigma, radsigma, radius): if row['pointtype'] == 3 or row['pointtype'] == 4: return covariance.compute_covariance(row['adjustedY'], row['adjustedX'], radius, latsigma=latsigma, lonsigma=lonsigma, radsigma=radsigma, semimajor_axis=radius) return [] df['aprioriCovar'] = df.apply(compute_covar, axis=1, args=(latsigma, lonsigma, radsigma, radius)) return df
[docs]def identify_potential_overlaps(cg, cn, overlap=True): """ Identify those points that could have additional measures Parameters ---------- overlap : boolean If True, apply aprint(g)n additional point in polygon check, where the polygon is the footprint intersection between images and the point is a keypoint projected into lat/lon space. Note that the projection can be inaccurate if the method used estimates the transformation. Returns ------- candidate_cliques : DataFrame with the index as the point id (in the data attribute) and the value as an iterable of image ids to search for a new point. """ fc = cg.compute_fully_connected_components() candidate_cliques = [] geoms = [] idx = [] for i, p in cn.groupby('point_id'): # Which images are covered already. This finds any connected cycles that # a node is in (this can be more than one - an hourglass network for example) # Extract the fully connected subgraph for each covered image in order to # identify which subgraph the measure is in covered = p['image_index'] candidate_cycles = [fc[c] for c in covered] cycle = [i for i in candidate_cycles if candidate_cycles.count(i) > 1] cycle_to_punch = cycle[0][0] # Using the cycles to punch, which images could also be covered? uncovered = tuple(set(cycle_to_punch).difference(set(covered))) # All candidates are covered, skip this point if not uncovered: continue # Determine whether a 'real' lat/lon are to be used and reproject if overlap: row = p.iloc[0] lat, lon = cg.nodes[row.image_index]['data'].geodata.pixel_to_latlon( row.x, row.y) else: lat, lon = 0, 0 # Build the data for the geodataframe - can the index be cleaner? geoms.append(Point(lon, lat)) candidate_cliques.append([uncovered, cycle_to_punch]) idx.append(i) candidate_cliques = gpd.GeoDataFrame(candidate_cliques, index=idx, columns=['candidates', 'subgraph'], geometry=geoms) def overlaps(group): """ Take a group, find the subgraph, compute the intersection of footprints and apply a group point in polygon check. This is an optimization where n-points are intersected with the poly at once (as opposed to the single iteration approach.) """ cycle_to_punch = group.subgraph.iloc[0] subgraph = cg.create_node_subgraph(cycle_to_punch) union, _ = subgraph.compute_intersection( cycle_to_punch[0]) # .query('overlaps_all == True') intersection = group.intersects(union.unary_union) return intersection # If the overlap check is going to be used, apply it. if overlap: candidate_cliques['overlap'] = False for i, g in candidate_cliques.groupby('candidates'): intersection = overlaps(g) candidate_cliques.loc[intersection.index, 'overlap'] = intersection return candidate_cliques.query('overlap == True')['candidates'] else: return candidate_cliques.candidates