Loading autocnet/camera/sensor_model.py +48 −35 Original line number Diff line number Diff line Loading @@ -21,7 +21,9 @@ try: except Exception as exception: from autocnet.utils.utils import FailedImport isis = FailedImport(exception) from knoten.csm import create_csm from knoten.csm import create_csm, generate_ground_point, generate_image_coordinate from csmapi import csmapi # set up the logger file log = logging.getLogger(__name__) Loading @@ -30,8 +32,8 @@ class BaseSensor: def __init__(self, data_path, dem): self.data_path = data_path self.dem = dem self.semi_major = dem.a self.semi_minor = dem.b self.semi_major = self.dem.a self.semi_minor = self.dem.c def _check_arg(self, x, y, z=None): if isinstance(x, collections.abc.Sequence) and isinstance(y, collections.abc.Sequence) and (isinstance(z, collections.abc.Sequence) or z is None): Loading Loading @@ -79,6 +81,12 @@ class BaseSensor: else: return x_coords, y_coords def _flatten_results(self, x, results): if isinstance(x, (collections.abc.Sequence, np.ndarray)): return results else: return results[0] @abc.abstractmethod def lonlat2xyz(self, lon, lat, height): return Loading @@ -99,6 +107,7 @@ class BaseSensor: def sampline2lonlat(sample, line): return class ISISSensor(BaseSensor): """ ISIS defaults to ocentric latitudes for everything. Loading Loading @@ -226,12 +235,6 @@ class ISISSensor(BaseSensor): return self._flatten_results(x, results) def _flatten_results(self, x, results): if isinstance(x, (collections.abc.Sequence, np.ndarray)): return results else: return results[0] def _get_value(self, obj): """Returns *obj*, unless *obj* is of type pvl.collections.Quantity, in which case, the .value component of the object is returned.""" Loading @@ -241,7 +244,8 @@ class ISISSensor(BaseSensor): return obj def xyz2sampline(self, x, y, z): lon, lat = xyz2oc(x, y, z, self.semi_major, self.semi_minor) # No ocentric conversion here. That conversion is handled in lonlat2sampline lon, lat = xyz2og(x, y, z, self.semi_major, self.semi_minor) return self.lonlat2sampline(lon, lat) def lonlat2sampline(self, lon, lat, allowoutside=False): Loading Loading @@ -269,7 +273,6 @@ class ISISSensor(BaseSensor): # ISIS is expecting ocentric latitudes. Convert from ographic before passing. lonoc, latoc = og2oc(lon, lat, self.semi_major, self.semi_minor) res = self._point_info(lonoc, latoc, "ground", allowoutside=allowoutside) if isinstance(lon, (collections.abc.Sequence, np.ndarray)): samples, lines = np.asarray([[r["Sample"], r["Line"]] for r in res]).T else: Loading Loading @@ -375,9 +378,10 @@ class ISISSensor(BaseSensor): return lons, lats def lonlat2xyz(self, lon, lat, height=0): xyz = og2xyz(lon, lat, height, self.semi_major, self.semi_minor) return xyz def lonlat2xyz(self, lon, lat): sample, line = self.lonlat2sampline(lon, lat) return self.sampline2xyz(sample, line) class CSMSensor(BaseSensor): """ Loading @@ -392,14 +396,12 @@ class CSMSensor(BaseSensor): self.dem = dem def xyz2sampline(self, x, y, z): x_coords, y_coords, z_coords = self._check_args(x, y, z) x_coords, y_coords, z_coords = self._check_arg(x, y, z) results = [] for coord in zip(x_coords, y_coords, z_coords): ecef = csmapi.EcefCoord(coord[0], coord[1], coord[2]) imagept = self.sensor.groundToImage(ecef) results+=[imagept.sample, imagept.line] return self._flatten_results(results) imagept = generate_image_coordinate(coord, self.sensor) results+=[imagept.samp, imagept.line] return self._flatten_results(x_coords, results) def lonlat2sampline(self, lon, lat): """ Loading @@ -423,13 +425,15 @@ class CSMSensor(BaseSensor): line: int lint of point """ semi_major = self.dem.a semi_minor = self.dem.b x_coords, y_coords = self._check_args(lat, lon) heights = [self.get.get_height(i[0], i[1]) for i in zip(x_coords, y_coords)] x,y,z = og2xyz(lon, lat, heights, semi_major, semi_minor) return self.xyz2linesamp(x,y,z) x_coords, y_coords = self._check_arg(lon, lat) results = [] for coord in zip(x_coords, y_coords): # get_height needs lat, lon ordering height = self.dem.get_height(coord[1], coord[0]) x,y,z = og2xyz(lon, lat, height, self.semi_major, self.semi_minor) results += [x,y,z] results = self._flatten_results(lat, results) return self.xyz2sampline(x,y,z) def sampline2xyz(self, sample, line): """ Loading Loading @@ -459,18 +463,27 @@ class CSMSensor(BaseSensor): x,y,z : int(s) x,y,z coordinates of the point """ semi_major = self.dem.a semi_minor = self.dem.b sample, line = self._check_arg(sample, line) results = [] # CSMAPI using line/sample ordering. Swap here. for coord in zip(line, sample): # self.dem is an autocnet surface model dem that has a GeoDataset attribute bcbf = generate_ground_point(self.dem, coord, self.sensor) results += [bcbf.x, bcbf.y, bcbf.z] image_coord = csmapi.ImageCoord(sample, line) pcoord = self.sensor.imageToGround(image_coord) return pcoord.x, pcoord.y, pcoord.z return self._flatten_results(sample, results) def sampline2lonlat(self, sample, line): x,y,z = self.sampline2xyz(sample, line) lon, lat = xyz2og(x, y, z, self.semi_major, self.semi_minor) return lon, lat def lonlat2xyz(self, lon, lat): sample, line = self.lonlat2sampline(lon, lat) print(sample, line) return self.sampline2xyz(sample, line) def create_sensor(sensor_type, cam_path, dem=None): sensor_type = sensor_type.lower() sensor_classes = { Loading autocnet/camera/tests/test_sensor_model.py +136 −42 Original line number Diff line number Diff line Loading @@ -9,15 +9,19 @@ import numpy as np import numpy.testing as npt import autocnet.camera.sensor_model as sm from autocnet.spatial.surface import GdalDem from autocnet.examples import get_path from autocnet.camera import sensor_model as sm from autocnet.spatial.surface import EllipsoidDem, GdalDem from knoten.surface import EllipsoidDem, GdalDem @pytest.fixture def ctx_path(): def ctx_ellipsoid_path(): return get_path('G02_019154_1800_XN_00N133W.ellipsoid.crop.cub') @pytest.fixture def ctx_dem_path(): return get_path('G02_019154_1800_XN_00N133W.crop.cub') @pytest.fixture def remote_mola_height_dem(): path = '/vsicurl/https://asc-mars.s3.us-west-2.amazonaws.com/basemaps/Mars_MGS_MOLA_DEM_mosaic_global_463m.tif' Loading @@ -34,20 +38,30 @@ def isis_mola_radius_dem(): @pytest.fixture def ellipsoid(): return EllipsoidDem(semi_major=3396190, semi_minor=3396190) return EllipsoidDem(semi_major=3396190, semi_minor=3376200) @pytest.fixture def ctx_isis_sensor(ctx_path, isis_mola_radius_dem): return sm.ISISSensor(ctx_path, isis_mola_radius_dem) def ctx_ellipsoid_isis_sensor(ctx_ellipsoid_path, ellipsoid): return sm.ISISSensor(ctx_ellipsoid_path, ellipsoid) @pytest.fixture def ctx_csm_sensor(ctx_path, isis_mola_radius_dem): return sm.CSMSensor(ctx_path, isis_mola_radius_dem) def ctx_dem_isis_sensor(ctx_dem_path, isis_mola_radius_dem): return sm.ISISSensor(ctx_dem_path, isis_mola_radius_dem) @pytest.fixture def ctx_ellipsoid_csm_sensor(ctx_ellipsoid_path, ellipsoid): return sm.CSMSensor(ctx_ellipsoid_path, ellipsoid) @pytest.fixture def base_sensor(ellipsoid): return sm.BaseSensor(None,ellipsoid) @pytest.fixture def ctx_dtm_csm_sensor(ctx_dem_path, isis_mola_radius_dem): return sm.CSMSensor(ctx_dem_path, isis_mola_radius_dem) # @pytest.fixture # def isis_dtm_csm_sensor(ctx_path) class TestBaseSensor(): def test__check_args(self, base_sensor): Loading Loading @@ -100,43 +114,80 @@ class TestBaseSensor(): base_sensor._check_arg({10, 20}, {10, 20}) class TestIsisSensor(): class TestIsisSensor_DTM(): def test_raise_bad_coord_type(self, ctx_isis_sensor): def test_raise_bad_coord_type(self, ctx_dem_isis_sensor): with pytest.raises(ValueError): ctx_isis_sensor._point_info(10, 10, point_type='bogus') ctx_dem_isis_sensor._point_info(10, 10, point_type='bogus') def test_sampline2lonlat(self, ctx_isis_sensor): lon, lat = ctx_isis_sensor.sampline2lonlat(10.0, 10.0) def test_sampline2lonlat(self, ctx_dem_isis_sensor): lon, lat = ctx_dem_isis_sensor.sampline2lonlat(10.0, 10.0) assert lon == 226.76892358441 assert lat == -0.31770729411217 def test_sampline2xyz(self, ctx_isis_sensor): x, y, z = ctx_isis_sensor.sampline2xyz(10.0, 10.0) def test_sampline2xyz(self, ctx_dem_isis_sensor): x, y, z = ctx_dem_isis_sensor.sampline2xyz(10.0, 10.0) assert x == pytest.approx(-2327023.0983832) assert y == pytest.approx(-2475336.0552312) assert z == pytest.approx(-18838.904973497) def test_lonlat2sampline(self, ctx_isis_sensor): samp, line = ctx_isis_sensor.lonlat2sampline(226.8, -0.25) def test_lonlat2sampline(self, ctx_dem_isis_sensor): samp, line = ctx_dem_isis_sensor.lonlat2sampline(226.8, -0.25) assert samp == pytest.approx(450.47864761698) assert line == pytest.approx(638.5458457207) def test_xyz2sampline(self, ctx_isis_sensor): def test_xyz2sampline(self, ctx_dem_isis_sensor): x = -2327023.0983832 y = -2475336.0552312 z = -18838.904973497 samp, line = ctx_isis_sensor.xyz2sampline(x,y,z) samp, line = ctx_dem_isis_sensor.xyz2sampline(x,y,z) assert samp == pytest.approx(10.0,6) assert line == pytest.approx(10.0,6) def test_lonlat2xyz(self, ctx_isis_sensor): x, y, z = ctx_isis_sensor.lonlat2xyz(226.76892358441, -0.31770729411217) def test_lonlat2xyz(self, ctx_dem_isis_sensor): x, y, z = ctx_dem_isis_sensor.lonlat2xyz(226.76892358441, -0.31770729411217) assert x == pytest.approx(-2327023.0983832) assert y == pytest.approx(-2475336.0552312) assert z == pytest.approx(-18838.904973497) class TestIsisSensor_Ellipsoid(): def test_raise_bad_coord_type(self, ctx_ellipsoid_isis_sensor): with pytest.raises(ValueError): ctx_ellipsoid_isis_sensor._point_info(10, 10, point_type='bogus') def test_sampline2lonlat(self, ctx_ellipsoid_isis_sensor): lon, lat = ctx_ellipsoid_isis_sensor.sampline2lonlat(10.0, 10.0) assert lon == 226.76918706968 assert lat == -0.32147903205638 def test_sampline2xyz(self, ctx_ellipsoid_isis_sensor): x, y, z = ctx_ellipsoid_isis_sensor.sampline2xyz(10.0, 10.0) assert x == pytest.approx(-2326146.9211099) assert y == pytest.approx(-2474426.8363236) assert z == pytest.approx(-18831.814749997) def test_lonlat2sampline(self, ctx_ellipsoid_isis_sensor): samp, line = ctx_ellipsoid_isis_sensor.lonlat2sampline(226.76918706968,-0.32147903205638) assert samp == pytest.approx(10.0, abs=0.001) assert line == pytest.approx(10.0, abs=0.001) def test_xyz2sampline(self, ctx_ellipsoid_isis_sensor): x = -2326146.9211099 y = -2474426.8363236 z = -18831.814749997 samp, line = ctx_ellipsoid_isis_sensor.xyz2sampline(x,y,z) assert samp == pytest.approx(10.0, abs=0.001) assert line == pytest.approx(10.0, abs=0.001) def test_lonlat2xyz(self, ctx_ellipsoid_isis_sensor): x, y, z = ctx_ellipsoid_isis_sensor.lonlat2xyz(226.76918706968,-0.32147903205638) assert x == pytest.approx(-2326146.9211099) assert y == pytest.approx(-2474426.8363236) assert z == pytest.approx(-18831.814749997) class TestISIS(unittest.TestCase): def setUp(self) -> None: Loading Loading @@ -251,28 +302,71 @@ class TestISIS(unittest.TestCase): npt.assert_allclose(np.array([goal_samp, 961.03569217]), samples) npt.assert_allclose(np.array([goal_line, 20.50009032]), lines) class TestCsmSensor(): def test_sampline2lonlat(self, ctx_csm_sensor): lon, lat = ctx_csm_sensor.sampline2lonlat(10.0, 10.0) assert lon == 226.76892358441 assert lat == -0.31770729411217 def test_sampline2xyz(self, ctx_csm_sensor): x, y, z = ctx_csm_sensor.sampline2xyz(10.0, 10.0) assert x == pytest.approx(-2327023.0983832) assert y == pytest.approx(-2475336.0552312) assert z == pytest.approx(-18838.904973497) def test_lonlat2sampline(self, ctx_csm_sensor): samp, line = ctx_csm_sensor.lonlat2sampline(226.8, -0.25) assert samp == pytest.approx(450.47864761698) assert line == pytest.approx(638.5458457207) def test_xyz2sampline(self, ctx_csm_sensor): class TestCsmSensor_Ellipsoid(): def test_sampline2lonlat(self, ctx_ellipsoid_csm_sensor): # No tracking of a crop occurs, so manually offset x,y lon, lat = ctx_ellipsoid_csm_sensor.sampline2lonlat(710.0, 310.0) assert lon == pytest.approx(226.76918706968, abs=0.01) assert lat == pytest.approx(-0.32147903205638, abs=0.01) def test_sampline2xyz(self, ctx_ellipsoid_csm_sensor): # No tracking of a crop occurs, so manually offset x,y x, y, z = ctx_ellipsoid_csm_sensor.sampline2xyz(710.0, 310.0) assert x == pytest.approx(-2326146.9211099, abs=5) assert y == pytest.approx(-2474426.8363236, abs=5) assert z == pytest.approx(-18831.814749997, abs=7) # How is this point off by a whole pixel?!?!?! def test_lonlat2sampline(self, ctx_ellipsoid_csm_sensor): samp, line = ctx_ellipsoid_csm_sensor.lonlat2sampline(226.76918706968, -0.32147903205638) assert samp == pytest.approx(710.0, abs=1.0) assert line == pytest.approx(310.0, abs=1.0) def test_xyz2sampline(self, ctx_ellipsoid_csm_sensor): x = -2326146.9211099 y = -2474426.8363236 z = -18831.814749997 samp, line = ctx_ellipsoid_csm_sensor.xyz2sampline(x,y,z) assert samp == pytest.approx(710.0,6) assert line == pytest.approx(310.0,6) class TestCsmSensor_DTM(): def test_sampline2lonlat(self, ctx_dtm_csm_sensor): lon, lat = ctx_dtm_csm_sensor.sampline2lonlat(710, 310) assert lon == pytest.approx(226.76892358441, abs=0.001) assert lat == pytest.approx(-0.31770729411217, abs=0.001) def test_sampline2xyz(self, ctx_dtm_csm_sensor): # No tracking of a crop occurs, so manually offset x,y x, y, z = ctx_dtm_csm_sensor.sampline2xyz(710.0, 310.0) assert x == pytest.approx(-2327023.0983832, abs=4) assert y == pytest.approx(-2475336.0552312, abs=4) assert z == pytest.approx(-18838.904973497, abs=7) def test_lonlat2sampline(self, ctx_dtm_csm_sensor): # CSM Radius: 3397503 # ISIS Radius: 3397506.7524735 # CSM XYZ: -2325728.70656223 -2476649.5224272553 -14824.356384854329 # ISIS XYZ: -2325731.2752827, -2476652.2578367, -14824.372758057 samp, line = ctx_dtm_csm_sensor.lonlat2sampline(226.76892358441, -0.31770729411217) assert samp == pytest.approx(710.0, abs=1.0) assert line == pytest.approx(310.0, abs=1.0) def test_xyz2sampline(self, ctx_dtm_csm_sensor): x = -2327023.0983832 y = -2475336.0552312 z = -18838.904973497 samp, line = ctx_csm_sensor.xyz2sampline(x,y,z) print(samp, line) assert samp == pytest.approx(10.0,6) assert line == pytest.approx(10.0,6) # Why is this a whole pixel? samp, line = ctx_dtm_csm_sensor.xyz2sampline(x,y,z) assert samp == pytest.approx(710.0,abs=1.0) assert line == pytest.approx(310.0,abs=1.0) def test_lonlat2xyz(self, ctx_dtm_csm_sensor): x, y, z = ctx_dtm_csm_sensor.lonlat2xyz(226.76892358441, -0.31770729411217) assert x == pytest.approx(-2327023.0983832) assert y == pytest.approx(-2475336.0552312) assert z == pytest.approx(-18838.904973497) No newline at end of file autocnet/control/control.py +1 −1 Original line number Diff line number Diff line Loading @@ -20,7 +20,7 @@ def compute_covariance(df, dem, latsigma, lonsigma, radsigma): df : pd.DataFrame with columns pointtype, adjustedY, and adjustedX dem : ~autocnet.spatial.surface.EllipsoidDem or ~autocnet.spatial.surface.GdalDem dem : knoten.surface.EllipsoidDem or ~autocnet.knoten.surface.GdalDem Digital Elevation Model (DEM) object described the target body latsigma : int/float Loading autocnet/control/tests/test_control.py +1 −1 Original line number Diff line number Diff line Loading @@ -5,7 +5,7 @@ from shapely.geometry import Polygon import pytest from autocnet.control import control from autocnet.spatial.surface import EllipsoidDem from knoten.surface import EllipsoidDem def test_identify_potential_overlaps(controlnetwork, candidategraph): res = control.identify_potential_overlaps(candidategraph, Loading autocnet/examples/CTX/G02_019154_1800_XN_00N133W.ellipsoid.crop.cub 0 → 100644 +4.55 MiB File added.Preview size limit exceeded, changes collapsed. View file Loading
autocnet/camera/sensor_model.py +48 −35 Original line number Diff line number Diff line Loading @@ -21,7 +21,9 @@ try: except Exception as exception: from autocnet.utils.utils import FailedImport isis = FailedImport(exception) from knoten.csm import create_csm from knoten.csm import create_csm, generate_ground_point, generate_image_coordinate from csmapi import csmapi # set up the logger file log = logging.getLogger(__name__) Loading @@ -30,8 +32,8 @@ class BaseSensor: def __init__(self, data_path, dem): self.data_path = data_path self.dem = dem self.semi_major = dem.a self.semi_minor = dem.b self.semi_major = self.dem.a self.semi_minor = self.dem.c def _check_arg(self, x, y, z=None): if isinstance(x, collections.abc.Sequence) and isinstance(y, collections.abc.Sequence) and (isinstance(z, collections.abc.Sequence) or z is None): Loading Loading @@ -79,6 +81,12 @@ class BaseSensor: else: return x_coords, y_coords def _flatten_results(self, x, results): if isinstance(x, (collections.abc.Sequence, np.ndarray)): return results else: return results[0] @abc.abstractmethod def lonlat2xyz(self, lon, lat, height): return Loading @@ -99,6 +107,7 @@ class BaseSensor: def sampline2lonlat(sample, line): return class ISISSensor(BaseSensor): """ ISIS defaults to ocentric latitudes for everything. Loading Loading @@ -226,12 +235,6 @@ class ISISSensor(BaseSensor): return self._flatten_results(x, results) def _flatten_results(self, x, results): if isinstance(x, (collections.abc.Sequence, np.ndarray)): return results else: return results[0] def _get_value(self, obj): """Returns *obj*, unless *obj* is of type pvl.collections.Quantity, in which case, the .value component of the object is returned.""" Loading @@ -241,7 +244,8 @@ class ISISSensor(BaseSensor): return obj def xyz2sampline(self, x, y, z): lon, lat = xyz2oc(x, y, z, self.semi_major, self.semi_minor) # No ocentric conversion here. That conversion is handled in lonlat2sampline lon, lat = xyz2og(x, y, z, self.semi_major, self.semi_minor) return self.lonlat2sampline(lon, lat) def lonlat2sampline(self, lon, lat, allowoutside=False): Loading Loading @@ -269,7 +273,6 @@ class ISISSensor(BaseSensor): # ISIS is expecting ocentric latitudes. Convert from ographic before passing. lonoc, latoc = og2oc(lon, lat, self.semi_major, self.semi_minor) res = self._point_info(lonoc, latoc, "ground", allowoutside=allowoutside) if isinstance(lon, (collections.abc.Sequence, np.ndarray)): samples, lines = np.asarray([[r["Sample"], r["Line"]] for r in res]).T else: Loading Loading @@ -375,9 +378,10 @@ class ISISSensor(BaseSensor): return lons, lats def lonlat2xyz(self, lon, lat, height=0): xyz = og2xyz(lon, lat, height, self.semi_major, self.semi_minor) return xyz def lonlat2xyz(self, lon, lat): sample, line = self.lonlat2sampline(lon, lat) return self.sampline2xyz(sample, line) class CSMSensor(BaseSensor): """ Loading @@ -392,14 +396,12 @@ class CSMSensor(BaseSensor): self.dem = dem def xyz2sampline(self, x, y, z): x_coords, y_coords, z_coords = self._check_args(x, y, z) x_coords, y_coords, z_coords = self._check_arg(x, y, z) results = [] for coord in zip(x_coords, y_coords, z_coords): ecef = csmapi.EcefCoord(coord[0], coord[1], coord[2]) imagept = self.sensor.groundToImage(ecef) results+=[imagept.sample, imagept.line] return self._flatten_results(results) imagept = generate_image_coordinate(coord, self.sensor) results+=[imagept.samp, imagept.line] return self._flatten_results(x_coords, results) def lonlat2sampline(self, lon, lat): """ Loading @@ -423,13 +425,15 @@ class CSMSensor(BaseSensor): line: int lint of point """ semi_major = self.dem.a semi_minor = self.dem.b x_coords, y_coords = self._check_args(lat, lon) heights = [self.get.get_height(i[0], i[1]) for i in zip(x_coords, y_coords)] x,y,z = og2xyz(lon, lat, heights, semi_major, semi_minor) return self.xyz2linesamp(x,y,z) x_coords, y_coords = self._check_arg(lon, lat) results = [] for coord in zip(x_coords, y_coords): # get_height needs lat, lon ordering height = self.dem.get_height(coord[1], coord[0]) x,y,z = og2xyz(lon, lat, height, self.semi_major, self.semi_minor) results += [x,y,z] results = self._flatten_results(lat, results) return self.xyz2sampline(x,y,z) def sampline2xyz(self, sample, line): """ Loading Loading @@ -459,18 +463,27 @@ class CSMSensor(BaseSensor): x,y,z : int(s) x,y,z coordinates of the point """ semi_major = self.dem.a semi_minor = self.dem.b sample, line = self._check_arg(sample, line) results = [] # CSMAPI using line/sample ordering. Swap here. for coord in zip(line, sample): # self.dem is an autocnet surface model dem that has a GeoDataset attribute bcbf = generate_ground_point(self.dem, coord, self.sensor) results += [bcbf.x, bcbf.y, bcbf.z] image_coord = csmapi.ImageCoord(sample, line) pcoord = self.sensor.imageToGround(image_coord) return pcoord.x, pcoord.y, pcoord.z return self._flatten_results(sample, results) def sampline2lonlat(self, sample, line): x,y,z = self.sampline2xyz(sample, line) lon, lat = xyz2og(x, y, z, self.semi_major, self.semi_minor) return lon, lat def lonlat2xyz(self, lon, lat): sample, line = self.lonlat2sampline(lon, lat) print(sample, line) return self.sampline2xyz(sample, line) def create_sensor(sensor_type, cam_path, dem=None): sensor_type = sensor_type.lower() sensor_classes = { Loading
autocnet/camera/tests/test_sensor_model.py +136 −42 Original line number Diff line number Diff line Loading @@ -9,15 +9,19 @@ import numpy as np import numpy.testing as npt import autocnet.camera.sensor_model as sm from autocnet.spatial.surface import GdalDem from autocnet.examples import get_path from autocnet.camera import sensor_model as sm from autocnet.spatial.surface import EllipsoidDem, GdalDem from knoten.surface import EllipsoidDem, GdalDem @pytest.fixture def ctx_path(): def ctx_ellipsoid_path(): return get_path('G02_019154_1800_XN_00N133W.ellipsoid.crop.cub') @pytest.fixture def ctx_dem_path(): return get_path('G02_019154_1800_XN_00N133W.crop.cub') @pytest.fixture def remote_mola_height_dem(): path = '/vsicurl/https://asc-mars.s3.us-west-2.amazonaws.com/basemaps/Mars_MGS_MOLA_DEM_mosaic_global_463m.tif' Loading @@ -34,20 +38,30 @@ def isis_mola_radius_dem(): @pytest.fixture def ellipsoid(): return EllipsoidDem(semi_major=3396190, semi_minor=3396190) return EllipsoidDem(semi_major=3396190, semi_minor=3376200) @pytest.fixture def ctx_isis_sensor(ctx_path, isis_mola_radius_dem): return sm.ISISSensor(ctx_path, isis_mola_radius_dem) def ctx_ellipsoid_isis_sensor(ctx_ellipsoid_path, ellipsoid): return sm.ISISSensor(ctx_ellipsoid_path, ellipsoid) @pytest.fixture def ctx_csm_sensor(ctx_path, isis_mola_radius_dem): return sm.CSMSensor(ctx_path, isis_mola_radius_dem) def ctx_dem_isis_sensor(ctx_dem_path, isis_mola_radius_dem): return sm.ISISSensor(ctx_dem_path, isis_mola_radius_dem) @pytest.fixture def ctx_ellipsoid_csm_sensor(ctx_ellipsoid_path, ellipsoid): return sm.CSMSensor(ctx_ellipsoid_path, ellipsoid) @pytest.fixture def base_sensor(ellipsoid): return sm.BaseSensor(None,ellipsoid) @pytest.fixture def ctx_dtm_csm_sensor(ctx_dem_path, isis_mola_radius_dem): return sm.CSMSensor(ctx_dem_path, isis_mola_radius_dem) # @pytest.fixture # def isis_dtm_csm_sensor(ctx_path) class TestBaseSensor(): def test__check_args(self, base_sensor): Loading Loading @@ -100,43 +114,80 @@ class TestBaseSensor(): base_sensor._check_arg({10, 20}, {10, 20}) class TestIsisSensor(): class TestIsisSensor_DTM(): def test_raise_bad_coord_type(self, ctx_isis_sensor): def test_raise_bad_coord_type(self, ctx_dem_isis_sensor): with pytest.raises(ValueError): ctx_isis_sensor._point_info(10, 10, point_type='bogus') ctx_dem_isis_sensor._point_info(10, 10, point_type='bogus') def test_sampline2lonlat(self, ctx_isis_sensor): lon, lat = ctx_isis_sensor.sampline2lonlat(10.0, 10.0) def test_sampline2lonlat(self, ctx_dem_isis_sensor): lon, lat = ctx_dem_isis_sensor.sampline2lonlat(10.0, 10.0) assert lon == 226.76892358441 assert lat == -0.31770729411217 def test_sampline2xyz(self, ctx_isis_sensor): x, y, z = ctx_isis_sensor.sampline2xyz(10.0, 10.0) def test_sampline2xyz(self, ctx_dem_isis_sensor): x, y, z = ctx_dem_isis_sensor.sampline2xyz(10.0, 10.0) assert x == pytest.approx(-2327023.0983832) assert y == pytest.approx(-2475336.0552312) assert z == pytest.approx(-18838.904973497) def test_lonlat2sampline(self, ctx_isis_sensor): samp, line = ctx_isis_sensor.lonlat2sampline(226.8, -0.25) def test_lonlat2sampline(self, ctx_dem_isis_sensor): samp, line = ctx_dem_isis_sensor.lonlat2sampline(226.8, -0.25) assert samp == pytest.approx(450.47864761698) assert line == pytest.approx(638.5458457207) def test_xyz2sampline(self, ctx_isis_sensor): def test_xyz2sampline(self, ctx_dem_isis_sensor): x = -2327023.0983832 y = -2475336.0552312 z = -18838.904973497 samp, line = ctx_isis_sensor.xyz2sampline(x,y,z) samp, line = ctx_dem_isis_sensor.xyz2sampline(x,y,z) assert samp == pytest.approx(10.0,6) assert line == pytest.approx(10.0,6) def test_lonlat2xyz(self, ctx_isis_sensor): x, y, z = ctx_isis_sensor.lonlat2xyz(226.76892358441, -0.31770729411217) def test_lonlat2xyz(self, ctx_dem_isis_sensor): x, y, z = ctx_dem_isis_sensor.lonlat2xyz(226.76892358441, -0.31770729411217) assert x == pytest.approx(-2327023.0983832) assert y == pytest.approx(-2475336.0552312) assert z == pytest.approx(-18838.904973497) class TestIsisSensor_Ellipsoid(): def test_raise_bad_coord_type(self, ctx_ellipsoid_isis_sensor): with pytest.raises(ValueError): ctx_ellipsoid_isis_sensor._point_info(10, 10, point_type='bogus') def test_sampline2lonlat(self, ctx_ellipsoid_isis_sensor): lon, lat = ctx_ellipsoid_isis_sensor.sampline2lonlat(10.0, 10.0) assert lon == 226.76918706968 assert lat == -0.32147903205638 def test_sampline2xyz(self, ctx_ellipsoid_isis_sensor): x, y, z = ctx_ellipsoid_isis_sensor.sampline2xyz(10.0, 10.0) assert x == pytest.approx(-2326146.9211099) assert y == pytest.approx(-2474426.8363236) assert z == pytest.approx(-18831.814749997) def test_lonlat2sampline(self, ctx_ellipsoid_isis_sensor): samp, line = ctx_ellipsoid_isis_sensor.lonlat2sampline(226.76918706968,-0.32147903205638) assert samp == pytest.approx(10.0, abs=0.001) assert line == pytest.approx(10.0, abs=0.001) def test_xyz2sampline(self, ctx_ellipsoid_isis_sensor): x = -2326146.9211099 y = -2474426.8363236 z = -18831.814749997 samp, line = ctx_ellipsoid_isis_sensor.xyz2sampline(x,y,z) assert samp == pytest.approx(10.0, abs=0.001) assert line == pytest.approx(10.0, abs=0.001) def test_lonlat2xyz(self, ctx_ellipsoid_isis_sensor): x, y, z = ctx_ellipsoid_isis_sensor.lonlat2xyz(226.76918706968,-0.32147903205638) assert x == pytest.approx(-2326146.9211099) assert y == pytest.approx(-2474426.8363236) assert z == pytest.approx(-18831.814749997) class TestISIS(unittest.TestCase): def setUp(self) -> None: Loading Loading @@ -251,28 +302,71 @@ class TestISIS(unittest.TestCase): npt.assert_allclose(np.array([goal_samp, 961.03569217]), samples) npt.assert_allclose(np.array([goal_line, 20.50009032]), lines) class TestCsmSensor(): def test_sampline2lonlat(self, ctx_csm_sensor): lon, lat = ctx_csm_sensor.sampline2lonlat(10.0, 10.0) assert lon == 226.76892358441 assert lat == -0.31770729411217 def test_sampline2xyz(self, ctx_csm_sensor): x, y, z = ctx_csm_sensor.sampline2xyz(10.0, 10.0) assert x == pytest.approx(-2327023.0983832) assert y == pytest.approx(-2475336.0552312) assert z == pytest.approx(-18838.904973497) def test_lonlat2sampline(self, ctx_csm_sensor): samp, line = ctx_csm_sensor.lonlat2sampline(226.8, -0.25) assert samp == pytest.approx(450.47864761698) assert line == pytest.approx(638.5458457207) def test_xyz2sampline(self, ctx_csm_sensor): class TestCsmSensor_Ellipsoid(): def test_sampline2lonlat(self, ctx_ellipsoid_csm_sensor): # No tracking of a crop occurs, so manually offset x,y lon, lat = ctx_ellipsoid_csm_sensor.sampline2lonlat(710.0, 310.0) assert lon == pytest.approx(226.76918706968, abs=0.01) assert lat == pytest.approx(-0.32147903205638, abs=0.01) def test_sampline2xyz(self, ctx_ellipsoid_csm_sensor): # No tracking of a crop occurs, so manually offset x,y x, y, z = ctx_ellipsoid_csm_sensor.sampline2xyz(710.0, 310.0) assert x == pytest.approx(-2326146.9211099, abs=5) assert y == pytest.approx(-2474426.8363236, abs=5) assert z == pytest.approx(-18831.814749997, abs=7) # How is this point off by a whole pixel?!?!?! def test_lonlat2sampline(self, ctx_ellipsoid_csm_sensor): samp, line = ctx_ellipsoid_csm_sensor.lonlat2sampline(226.76918706968, -0.32147903205638) assert samp == pytest.approx(710.0, abs=1.0) assert line == pytest.approx(310.0, abs=1.0) def test_xyz2sampline(self, ctx_ellipsoid_csm_sensor): x = -2326146.9211099 y = -2474426.8363236 z = -18831.814749997 samp, line = ctx_ellipsoid_csm_sensor.xyz2sampline(x,y,z) assert samp == pytest.approx(710.0,6) assert line == pytest.approx(310.0,6) class TestCsmSensor_DTM(): def test_sampline2lonlat(self, ctx_dtm_csm_sensor): lon, lat = ctx_dtm_csm_sensor.sampline2lonlat(710, 310) assert lon == pytest.approx(226.76892358441, abs=0.001) assert lat == pytest.approx(-0.31770729411217, abs=0.001) def test_sampline2xyz(self, ctx_dtm_csm_sensor): # No tracking of a crop occurs, so manually offset x,y x, y, z = ctx_dtm_csm_sensor.sampline2xyz(710.0, 310.0) assert x == pytest.approx(-2327023.0983832, abs=4) assert y == pytest.approx(-2475336.0552312, abs=4) assert z == pytest.approx(-18838.904973497, abs=7) def test_lonlat2sampline(self, ctx_dtm_csm_sensor): # CSM Radius: 3397503 # ISIS Radius: 3397506.7524735 # CSM XYZ: -2325728.70656223 -2476649.5224272553 -14824.356384854329 # ISIS XYZ: -2325731.2752827, -2476652.2578367, -14824.372758057 samp, line = ctx_dtm_csm_sensor.lonlat2sampline(226.76892358441, -0.31770729411217) assert samp == pytest.approx(710.0, abs=1.0) assert line == pytest.approx(310.0, abs=1.0) def test_xyz2sampline(self, ctx_dtm_csm_sensor): x = -2327023.0983832 y = -2475336.0552312 z = -18838.904973497 samp, line = ctx_csm_sensor.xyz2sampline(x,y,z) print(samp, line) assert samp == pytest.approx(10.0,6) assert line == pytest.approx(10.0,6) # Why is this a whole pixel? samp, line = ctx_dtm_csm_sensor.xyz2sampline(x,y,z) assert samp == pytest.approx(710.0,abs=1.0) assert line == pytest.approx(310.0,abs=1.0) def test_lonlat2xyz(self, ctx_dtm_csm_sensor): x, y, z = ctx_dtm_csm_sensor.lonlat2xyz(226.76892358441, -0.31770729411217) assert x == pytest.approx(-2327023.0983832) assert y == pytest.approx(-2475336.0552312) assert z == pytest.approx(-18838.904973497) No newline at end of file
autocnet/control/control.py +1 −1 Original line number Diff line number Diff line Loading @@ -20,7 +20,7 @@ def compute_covariance(df, dem, latsigma, lonsigma, radsigma): df : pd.DataFrame with columns pointtype, adjustedY, and adjustedX dem : ~autocnet.spatial.surface.EllipsoidDem or ~autocnet.spatial.surface.GdalDem dem : knoten.surface.EllipsoidDem or ~autocnet.knoten.surface.GdalDem Digital Elevation Model (DEM) object described the target body latsigma : int/float Loading
autocnet/control/tests/test_control.py +1 −1 Original line number Diff line number Diff line Loading @@ -5,7 +5,7 @@ from shapely.geometry import Polygon import pytest from autocnet.control import control from autocnet.spatial.surface import EllipsoidDem from knoten.surface import EllipsoidDem def test_identify_potential_overlaps(controlnetwork, candidategraph): res = control.identify_potential_overlaps(candidategraph, Loading
autocnet/examples/CTX/G02_019154_1800_XN_00N133W.ellipsoid.crop.cub 0 → 100644 +4.55 MiB File added.Preview size limit exceeded, changes collapsed. View file