Commit 89cf4c57 authored by Jesse Mapel's avatar Jesse Mapel Committed by Stuart Sides
Browse files

Updated MDIS tests to new load approach (#261)

* Updated MDIS tests to new load approach

* Added scope back to test_kernels fixture in mdis

* Fixed warning and minor updates

* Updated MDIS tests again

* Clean up from comments
parent c821b1da
Loading
Loading
Loading
Loading
+2 −2
Original line number Diff line number Diff line
@@ -331,8 +331,8 @@ class NaifSpice():
                vel.append(state[3:])
            # By default, spice works in km, and the vector returned by spkezr points the opposite
            # direction to what ALE needs, so it must be multiplied by (-1)
            self._position = [p * -1000 for p in pos]
            self._velocity = [v * -1000 for v in vel]
            self._position = np.asarray([p * -1000 for p in pos])
            self._velocity = np.asarray([v * -1000 for v in vel])
        return self._position, self._velocity, self.ephemeris_time

    @property
+1 −1
Original line number Diff line number Diff line
@@ -51,7 +51,7 @@ class LineScanner():
        : ndarray
          ephemeris times split based on image lines
        """
        return np.linspace(self.ephemeris_start_time,  self.ephemeris_stop_time, self.image_lines / 64)
        return np.linspace(self.ephemeris_start_time,  self.ephemeris_stop_time, max(2, int(self.image_lines / 64)))

    @property
    def ephemeris_stop_time(self):
+19 −3
Original line number Diff line number Diff line
@@ -223,8 +223,24 @@ class MessengerMdisPds3NaifSpiceDriver(Framer, Pds3Label, NaifSpice, Driver):
class MessengerMdisIsisLabelNaifSpiceDriver(IsisLabel, NaifSpice, Framer, Driver):
    """
    Driver for reading MDIS ISIS3 Labels. These are Labels that have been ingested
    into ISIS from PDS EDR images but have not been spiceinit'd yet.
    into ISIS from PDS EDR images. Any SPCIE data attached by the spiceinit application
    will be ignored.
    """
    @property
    def platform_name(self):
        """
        Returns the name of the platform containing the sensor. This is usually
        the spacecraft name.

        Messenger MDIS ISIS labels use upper camel case so this converts it to
        all upper case.

        Returns
        -------
        : str
          Spacecraft name
        """
        return super().platform_name.upper()

    @property
    def instrument_id(self):
@@ -315,7 +331,7 @@ class MessengerMdisIsisLabelNaifSpiceDriver(IsisLabel, NaifSpice, Framer, Driver
        : double
          focal length in meters
        """
        coeffs = spice.gdpool('INS{}_FL_TEMP_COEFFS '.format(self.fikid), 0, 5)
        coeffs = spice.gdpool('INS{}_FL_TEMP_COEFFS'.format(self.fikid), 0, 6)
        # reverse coeffs, MDIS coeffs are listed a_0, a_1, a_2 ... a_n where
        # numpy wants them a_n, a_n-1, a_n-2 ... a_0
        f_t = np.poly1d(coeffs[::-1])
+0 −1
Original line number Diff line number Diff line
@@ -65,7 +65,6 @@ def test_kernels():
def test_dawn_load(test_kernels, usgscsm_compare_dict):
    label_file = get_image_label('FC21A0038582_15170161546F6F')
    usgscsm_isd = ale.load(label_file, props={'kernels': test_kernels}, formatter='usgscsm')
    print(usgscsm_isd)
    assert compare_dicts(usgscsm_isd, usgscsm_compare_dict) == []


+181 −205
Original line number Diff line number Diff line
@@ -4,230 +4,206 @@ import numpy as np
import spiceypy as spice
from importlib import reload
import json
import unittest
from unittest.mock import patch

from conftest import get_image_label, get_image_kernels, convert_kernels

from conftest import get_image_label, get_image_kernels, convert_kernels, compare_dicts
import ale
from ale.drivers.mes_drivers import MessengerMdisPds3NaifSpiceDriver
from ale.drivers.mes_drivers import MessengerMdisIsisLabelNaifSpiceDriver

@pytest.fixture(scope="module", autouse=True)
@pytest.fixture(scope='module')
def test_kernels():
    kernels = get_image_kernels('EN1072174528M')
    updated_kernels, binary_kernels = convert_kernels(kernels)
    spice.furnsh(updated_kernels)
    yield updated_kernels
    spice.unload(updated_kernels)
    for kern in binary_kernels:
        os.remove(kern)

@pytest.fixture(params=["Pds3NaifDriver", "IsisNaifDriver"])
def driver(request):
    if request.param == "IsisNaifDriver":
        label = get_image_label("EN1072174528M", "isis3")
        return MessengerMdisIsisLabelNaifSpiceDriver(label)
@pytest.fixture()
def usgscsm_compare_dict():
    return {
    'radii': {
        'semimajor': 2439.4,
        'semiminor': 2439.4,
        'unit': 'km'},
    'sensor_position': {
        'positions': np.array([[ -629496.48621395, -1582946.00913133,  1783952.64031042]]),
        'velocities': np.array([[1732.18666313, 2502.76825324, 2412.65232223]]),
        'unit': 'm'},
    'sun_position': {
        'positions': np.array([[-4.68946673e+10, -5.36158427e+08,  2.71167863e+07]]),
        'velocities': np.array([[-4629.73346128, 256.72086237, 10.63960444]]),
        'unit': 'm'},
    'sensor_orientation': {
        'quaternions': np.array([[ 0.93418372,  0.00144773, -0.00449382, -0.35676112]])},
    'detector_sample_summing': 2,
    'detector_line_summing': 2,
    'focal_length_model': {
        'focal_length': 549.5535053027719},
    'detector_center': {
        'line': 512,
        'sample': 512},
    'starting_detector_line': 1,
    'starting_detector_sample': 9,
    'focal2pixel_lines': [0.0, 0.0, 71.42857143],
    'focal2pixel_samples': [0.0, 71.42857143, 0.0],
    'optical_distortion': {
        'transverse': {
            'x': [0.0, 1.001854269623802, 0.0, 0.0, -0.0005094440474941111, 0.0, 1.004010471468856e-05, 0.0, 1.004010471468856e-05, 0.0],
            'y': [0.0, 0.0, 1.0, 0.0009060010594996751, 0.0, 0.0003574842626620758, 0.0, 1.004010471468856e-05, 0.0, 1.004010471468856e-05]}},
    'image_lines': 512,
    'image_samples': 512,
    'name_platform': 'MESSENGER',
    'name_sensor': 'MERCURY DUAL IMAGING SYSTEM NARROW ANGLE CAMERA',
    'reference_height': {
        'maxheight': 1000,
        'minheight': -1000,
        'unit': 'm'},
    'name_model': 'USGS_ASTRO_FRAME_SENSOR_MODEL',
    'center_ephemeris_time': 483122606.85252464}

@pytest.mark.parametrize("label_type", ["pds3", "isis3"])
def test_load(test_kernels, usgscsm_compare_dict, label_type):
    label_file = get_image_label('EN1072174528M', label_type)

    usgscsm_isd_str = ale.loads(label_file, props={'kernels': test_kernels}, formatter='usgscsm')
    usgscsm_isd_obj = json.loads(usgscsm_isd_str)

    else:
    assert compare_dicts(usgscsm_isd_obj, usgscsm_compare_dict) == []

# ========= Test Pds3 Label and NAIF Spice driver =========
class test_pds3_naif(unittest.TestCase):

    def setUp(self):
        label = get_image_label("EN1072174528M", "pds3")
        return MessengerMdisPds3NaifSpiceDriver(label)
        self.driver = MessengerMdisPds3NaifSpiceDriver(label)

def test_short_mission_name(driver):
    assert driver.short_mission_name=='mes'
    def test_short_mission_name(self):
        assert self.driver.short_mission_name=='mes'

def test_no_metakernels(driver, tmpdir, monkeypatch):
    monkeypatch.setenv('ALESPICEROOT', str(tmpdir))
    reload(ale)
    def test_spacecraft_name(self):
        assert self.driver.spacecraft_name == 'MESSENGER'

    with pytest.raises(ValueError):
        with driver as failure:
            pass
    def test_fikid(self):
        with patch('ale.base.data_naif.spice.bods2c', return_value=-12345) as bods2c:
            assert self.driver.spacecraft_name == 'MESSENGER'

def test_no_spice_root(driver, monkeypatch):
    monkeypatch.delenv('ALESPICEROOT', raising=False)
    reload(ale)
    def test_instrument_id(self):
        assert self.driver.instrument_id == 'MSGR_MDIS_NAC'

    with pytest.raises(EnvironmentError):
        with driver as failure:
            pass
    def test_sampling_factor(self):
        assert self.driver.sampling_factor == 2

def test_load(test_kernels):
    label_file = get_image_label('EN1072174528M')
    def test_focal_length(self):
        with patch('ale.drivers.mes_drivers.spice.gdpool', return_value=np.array([pow(4.07, -x) for x in np.arange(6)])) as gdpool, \
             patch('ale.base.data_naif.spice.bods2c', return_value=-12345) as bods2c:
            assert self.driver.focal_length == pytest.approx(6.0)
            gdpool.assert_called_with('INS-12345_FL_TEMP_COEFFS', 0, 6)

    usgscsm_isd_str = ale.loads(label_file, props={'kernels': test_kernels}, formatter='usgscsm')
    usgscsm_isd_obj = json.loads(usgscsm_isd_str)
    def test_detector_start_sample(self):
        with patch('ale.drivers.mes_drivers.spice.gdpool', return_value=np.array([10.0])) as gdpool, \
             patch('ale.base.data_naif.spice.bods2c', return_value=-12345) as bods2c:
            assert self.driver.detector_start_sample == 10.0
            gdpool.assert_called_with('INS-12345_FPUBIN_START_SAMPLE', 0, 1)

    def test_detector_start_line(self):
        with patch('ale.drivers.mes_drivers.spice.gdpool', return_value=np.array([10.0])) as gdpool, \
             patch('ale.base.data_naif.spice.bods2c', return_value=-12345) as bods2c:
            assert self.driver.detector_start_line == 10.0
            gdpool.assert_called_with('INS-12345_FPUBIN_START_LINE', 0, 1)

    assert usgscsm_isd_obj['name_platform'] == 'MESSENGER'
    assert usgscsm_isd_obj['name_sensor'] == 'MERCURY DUAL IMAGING SYSTEM NARROW ANGLE CAMERA'
    assert usgscsm_isd_obj['name_model'] == 'USGS_ASTRO_FRAME_SENSOR_MODEL'

def test_test_image_lines(driver):
    assert driver.image_lines == 512

def test_image_samples(driver):
    assert driver.image_samples == 512

def test_usgscsm_distortion_model(driver):
    dist = driver.usgscsm_distortion_model
    assert 'transverse' in dist
    assert 'x' in dist['transverse']
    assert 'y' in dist['transverse']
    np.testing.assert_almost_equal(dist['transverse']['x'],
                                   [0.0,
                                    1.0018542696238023333,
                                    0.0,
                                    0.0,
                                   -5.0944404749411114E-4,
                                    0.0,
                                    1.0040104714688569E-5,
                                    0.0,
                                    1.0040104714688569E-5,
                                    0.0])
    np.testing.assert_almost_equal(dist['transverse']['y'],
                                   [0.0,
                                    0.0,
                                    1.0,
                                    9.06001059499675E-4,
                                    0.0,
                                    3.5748426266207586E-4,
                                    0.0,
                                    1.0040104714688569E-5,
                                    0.0,
                                    1.0040104714688569E-5])

def test_detector_start_line(driver):
    assert driver.detector_start_line == 1

def test_detector_start_sample(driver):
    assert driver.detector_start_sample == 9

def test_sample_summing(driver):
    assert driver.sample_summing == 2

def test_line_summing(driver):
    assert driver.line_summing == 2

def test_platform_name(driver):
    assert driver.platform_name.upper() == 'MESSENGER'

def test_sensor_name(driver):
    assert driver.sensor_name == 'MERCURY DUAL IMAGING SYSTEM NARROW ANGLE CAMERA'

def test_target_body_radii(driver):
    np.testing.assert_equal(driver.target_body_radii, [2439.4, 2439.4, 2439.4])

def test_focal_length(driver):
    assert driver.focal_length == 549.5535053027719

def test_detector_center_line(driver):
    assert driver.detector_center_line == 512

def test_detector_center_sample(driver):
    assert driver.detector_center_sample == 512

def test_sensor_position(driver):
    """
    Returns
    -------
    : (positions, velocities, times)
      a tuple containing a list of positions, a list of velocities, and a list of times
    """
    position, velocity, time = driver.sensor_position
    image_et = spice.scs2e(-236, '2/0072174528:989000') + 0.0005
    expected_state, _ = spice.spkez(199, image_et, 'IAU_MERCURY', 'LT+S', -236)
    expected_position = -1000 * np.asarray(expected_state[:3])
    expected_velocity = -1000 * np.asarray(expected_state[3:])
    np.testing.assert_allclose(position,
                               [expected_position],
                               rtol=1e-8)
    np.testing.assert_allclose(velocity,
                               [expected_velocity],
                               rtol=1e-8)
    np.testing.assert_almost_equal(time,
                                   [image_et])

def test_frame_chain(driver):
    assert driver.frame_chain.has_node(1)
    assert driver.frame_chain.has_node(10011)
    assert driver.frame_chain.has_node(-236820)
    image_et = spice.scs2e(-236, '2/0072174528:989000') + 0.0005
    target_to_j2000 = driver.frame_chain.compute_rotation(10011, 1)
    target_to_j2000_mat = spice.pxform('IAU_MERCURY', 'J2000', image_et)
    target_to_j2000_quats = spice.m2q(target_to_j2000_mat)
    np.testing.assert_almost_equal(target_to_j2000.quats,
                                   [-np.roll(target_to_j2000_quats, -1)])
    sensor_to_j2000 = driver.frame_chain.compute_rotation(-236820, 1)
    sensor_to_j2000_mat = spice.pxform('MSGR_MDIS_NAC', 'J2000', image_et)
    sensor_to_j2000_quats = spice.m2q(sensor_to_j2000_mat)
    np.testing.assert_almost_equal(sensor_to_j2000.quats,
                                   [-np.roll(sensor_to_j2000_quats, -1)])

def test_sun_position(driver):
    position, velocity, time = driver.sun_position
    image_et = spice.scs2e(-236, '2/0072174528:989000') + 0.0005
    expected_state, _ = spice.spkez(10, image_et, 'IAU_MERCURY', 'LT+S', 199)
    expected_position = 1000 * np.asarray(expected_state[:3])
    expected_velocity = 1000 * np.asarray(expected_state[3:])
    np.testing.assert_allclose(position,
                               [expected_position],
                               rtol=1e-8)
    np.testing.assert_allclose(velocity,
                               [expected_velocity],
                               rtol=1e-8)
    np.testing.assert_almost_equal(time,
                                   [image_et])

def test_target_name(driver):
    assert driver.target_name.upper() == 'MERCURY'

def test_target_frame_id(driver):
    assert driver.target_frame_id == 10011

def test_sensor_frame_id(driver):
    assert driver.sensor_frame_id == -236820

def test_isis_naif_keywords(driver):
    expected_keywords = {
        'BODY199_RADII' : driver.target_body_radii,
        'BODY_FRAME_CODE' : 10011,
        'INS-236820_PIXEL_PITCH' : 0.014,
        'INS-236820_ITRANSL' : [0.0, 0.0, 71.42857143],
        'INS-236820_ITRANSS' : [0.0, 71.42857143, 0.0],
        'INS-236820_FOCAL_LENGTH' : 549.1178195372703,
        'INS-236820_BORESIGHT_SAMPLE' : 512.5,
        'INS-236820_BORESIGHT_LINE' : 512.5
    }
    print(driver.isis_naif_keywords.keys())
    assert set(expected_keywords.keys()).issubset(set(driver.isis_naif_keywords.keys()))
    for key, value in expected_keywords.items():
        if isinstance(value, np.ndarray) or isinstance(value, list):
            np.testing.assert_almost_equal(value, driver.isis_naif_keywords[key])
        else:
            assert value == driver.isis_naif_keywords[key]

def test_sensor_model_version(driver):
    assert driver.sensor_model_version == 2

def test_focal2pixel_lines(driver):
    np.testing.assert_almost_equal(driver.focal2pixel_lines,
                                   [0.0, 0.0, 71.42857143])

def test_focal2pixel_samples(driver):
    np.testing.assert_almost_equal(driver.focal2pixel_samples,
                                   [0.0, 71.42857143, 0.0])

def test_pixel2focal_x(driver):
    np.testing.assert_almost_equal(driver.pixel2focal_x,
                                   [0.0, 0.014, 0.0])

def test_pixel2focal_y(driver):
    np.testing.assert_almost_equal(driver.pixel2focal_y,
                                   [0.0, 0.0, 0.014])

def test_ephemeris_start_time(driver):
    assert driver.ephemeris_start_time == 483122606.8520247

def test_ephemeris_stop_time(driver):
    assert driver.ephemeris_stop_time == 483122606.85302466

def test_center_ephemeris_time(driver):
    assert driver.center_ephemeris_time == 483122606.85252464
    def test_detector_center_sample(self):
        assert self.driver.detector_center_sample == 512

    def test_detector_center_line(self):
        assert self.driver.detector_center_line == 512

    def test_sensor_model_version(self):
        assert self.driver.sensor_model_version == 2

    def test_usgscsm_distortion_model(self):
        with patch('ale.drivers.mes_drivers.spice.gdpool', side_effect=[np.array([1, 2, 3, 4, 5]), np.array([-1, -2, -3, -4, -5])]) as gdpool, \
             patch('ale.base.data_naif.spice.bods2c', return_value=-12345) as bods2c:
            assert self.driver.usgscsm_distortion_model == {"transverse" : {
                                                                "x" : [1, 2, 3, 4, 5],
                                                                "y" : [-1, -2, -3, -4, -5]}}



    def test_pixel_size(self):
        with patch('ale.drivers.mes_drivers.spice.gdpool', return_value=np.array([0.1])) as gdpool, \
             patch('ale.base.data_naif.spice.bods2c', return_value=-12345) as bods2c:
            assert self.driver.pixel_size == 0.1
            gdpool.assert_called_with('INS-12345_PIXEL_PITCH', 0, 1)

# ========= Test ISIS3 Label and NAIF Spice driver =========
class test_isis3_naif(unittest.TestCase):

    def setUp(self):
        label = get_image_label("EN1072174528M", "isis3")
        self.driver = MessengerMdisIsisLabelNaifSpiceDriver(label)

    def test_short_mission_name(self):
        assert self.driver.short_mission_name=='mes'

    def test_platform_name(self):
        assert self.driver.platform_name == 'MESSENGER'

    def test_fikid(self):
        with patch('ale.base.data_naif.spice.bods2c', return_value=-12345) as bods2c:
            assert self.driver.spacecraft_name == 'MESSENGER'

    def test_instrument_id(self):
        assert self.driver.instrument_id == 'MSGR_MDIS_NAC'

    def test_sampling_factor(self):
        assert self.driver.sampling_factor == 2

    def test_focal_length(self):
        with patch('ale.drivers.mes_drivers.spice.gdpool', return_value=np.array([pow(4.07, -x) for x in np.arange(6)])) as gdpool, \
             patch('ale.base.data_naif.spice.bods2c', return_value=-12345) as bods2c:
            assert self.driver.focal_length == pytest.approx(6.0)
            gdpool.assert_called_with('INS-12345_FL_TEMP_COEFFS', 0, 6)

    def test_detector_start_sample(self):
        with patch('ale.drivers.mes_drivers.spice.gdpool', return_value=np.array([10.0])) as gdpool, \
             patch('ale.base.data_naif.spice.bods2c', return_value=-12345) as bods2c:
            assert self.driver.detector_start_sample == 10.0
            gdpool.assert_called_with('INS-12345_FPUBIN_START_SAMPLE', 0, 1)

    def test_detector_start_line(self):
        with patch('ale.drivers.mes_drivers.spice.gdpool', return_value=np.array([10.0])) as gdpool, \
             patch('ale.base.data_naif.spice.bods2c', return_value=-12345) as bods2c:
            assert self.driver.detector_start_line == 10.0
            gdpool.assert_called_with('INS-12345_FPUBIN_START_LINE', 0, 1)

    def test_detector_center_sample(self):
        with patch('ale.drivers.mes_drivers.spice.gdpool', return_value=np.array([512.5, 512.5, 1])) as gdpool, \
             patch('ale.base.data_naif.spice.bods2c', return_value=-12345) as bods2c:
            assert self.driver.detector_center_sample == 512
            gdpool.assert_called_with('INS-12345_CCD_CENTER', 0, 3)

    def test_detector_center_line(self):
        with patch('ale.drivers.mes_drivers.spice.gdpool', return_value=np.array([512.5, 512.5, 1])) as gdpool, \
             patch('ale.base.data_naif.spice.bods2c', return_value=-12345) as bods2c:
            assert self.driver.detector_center_line == 512
            gdpool.assert_called_with('INS-12345_CCD_CENTER', 0, 3)

    def test_sensor_model_version(self):
        assert self.driver.sensor_model_version == 2

    def test_usgscsm_distortion_model(self):
        with patch('ale.drivers.mes_drivers.spice.gdpool', side_effect=[np.array([1, 2, 3, 4, 5]), np.array([-1, -2, -3, -4, -5])]) as gdpool, \
             patch('ale.base.data_naif.spice.bods2c', return_value=-12345) as bods2c:
            assert self.driver.usgscsm_distortion_model == {"transverse" : {
                                                                "x" : [1, 2, 3, 4, 5],
                                                                "y" : [-1, -2, -3, -4, -5]}}



    def test_pixel_size(self):
        with patch('ale.drivers.mes_drivers.spice.gdpool', return_value=np.array([0.1])) as gdpool, \
             patch('ale.base.data_naif.spice.bods2c', return_value=-12345) as bods2c:
            assert self.driver.pixel_size == 0.1
            gdpool.assert_called_with('INS-12345_PIXEL_PITCH', 0, 1)