Loading ale/base/data_naif.py +2 −2 Original line number Diff line number Diff line Loading @@ -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 Loading ale/base/type_sensor.py +1 −1 Original line number Diff line number Diff line Loading @@ -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): Loading ale/drivers/mes_drivers.py +19 −3 Original line number Diff line number Diff line Loading @@ -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): Loading Loading @@ -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]) Loading tests/pytests/test_dawn_drivers.py +0 −1 Original line number Diff line number Diff line Loading @@ -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) == [] Loading tests/pytests/test_mdis_drivers.py +181 −205 Original line number Diff line number Diff line Loading @@ -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) Loading
ale/base/data_naif.py +2 −2 Original line number Diff line number Diff line Loading @@ -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 Loading
ale/base/type_sensor.py +1 −1 Original line number Diff line number Diff line Loading @@ -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): Loading
ale/drivers/mes_drivers.py +19 −3 Original line number Diff line number Diff line Loading @@ -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): Loading Loading @@ -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]) Loading
tests/pytests/test_dawn_drivers.py +0 −1 Original line number Diff line number Diff line Loading @@ -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) == [] Loading
tests/pytests/test_mdis_drivers.py +181 −205 Original line number Diff line number Diff line Loading @@ -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)