diff --git a/ale/drivers/lro_drivers.py b/ale/drivers/lro_drivers.py index 635ac532520c2d6a61b1b40e1d3f6c3bd3c376ac..7ddc7783963243bb2910f83e4079a83a57c700a6 100644 --- a/ale/drivers/lro_drivers.py +++ b/ale/drivers/lro_drivers.py @@ -129,6 +129,24 @@ class LroLrocPds3LabelNaifSpiceDriver(LineScanner, NaifSpice, Pds3Label, Driver) """ return super().detector_center_sample - 0.5 + @property + def focal2pixel_lines(self): + """ + Expects ikid to be defined. This must be the integer Naif id code of + the instrument. For LROC NAC this is flipped depending on the spacecraft + direction. + + Returns + ------- + : list<double> + focal plane to detector lines + """ + focal2pixel_lines = np.array(list(spice.gdpool('INS{}_ITRANSL'.format(self.ikid), 0, 3))) + if self.spacecraft_direction < 0: + return focal2pixel_lines + else: + return -focal2pixel_lines + @property def ephemeris_start_time(self): """ @@ -222,6 +240,34 @@ class LroLrocPds3LabelNaifSpiceDriver(LineScanner, NaifSpice, Pds3Label, Driver) """ return self.crosstrack_summing + @property + def spacecraft_direction(self): + """ + Returns the x axis of the first velocity vector relative to the + spacecraft. This indicates of the craft is moving forwards or backwards. + + From LROC Frame Kernel: lro_frames_2014049_v01.tf + "+X axis is in the direction of the velocity vector half the year. The + other half of the year, the +X axis is opposite the velocity vector" + + Hence we rotate the first velocity vector into the sensor reference + frame, but the X component of that vector is inverted compared to the + spacecraft so a +X indicates backwards and -X indicates forwards + + The returned velocity is also slightly off from the spacecraft velocity + due to the sensor being attached to the craft with wax. + + Returns + ------- + direction : double + X value of the first velocity relative to the sensor + """ + rotation = self.frame_chain.compute_rotation(self.target_frame_id, self.sensor_frame_id) + positions, velocities, times = self.sensor_position + velocity = rotation.rotate_velocity_at([positions[0]], [velocities[0]], [times[0]])[0] + return velocity[0] + + class LroLrocIsisLabelNaifSpiceDriver(LineScanner, NaifSpice, IsisLabel, Driver): @property @@ -343,6 +389,24 @@ class LroLrocIsisLabelNaifSpiceDriver(LineScanner, NaifSpice, IsisLabel, Driver) """ return super().exposure_duration * (1 + self.multiplicative_line_error) + self.additive_line_error + @property + def focal2pixel_lines(self): + """ + Expects ikid to be defined. This must be the integer Naif id code of + the instrument. For LROC NAC this is flipped depending on the spacecraft + direction. + + Returns + ------- + : list<double> + focal plane to detector lines + """ + focal2pixel_lines = np.array(list(spice.gdpool('INS{}_ITRANSL'.format(self.ikid), 0, 3))) + if self.spacecraft_direction < 0: + return focal2pixel_lines + else: + return -focal2pixel_lines + @property def multiplicative_line_error(self): """ @@ -404,3 +468,30 @@ class LroLrocIsisLabelNaifSpiceDriver(LineScanner, NaifSpice, IsisLabel, Driver) Number of samples and lines combined from the original data to produce a single pixel in this image """ return self.label['IsisCube']['Instrument']['SpatialSumming'] + + @property + def spacecraft_direction(self): + """ + Returns the x axis of the first velocity vector relative to the + spacecraft. This indicates of the craft is moving forwards or backwards. + + From LROC Frame Kernel: lro_frames_2014049_v01.tf + "+X axis is in the direction of the velocity vector half the year. The + other half of the year, the +X axis is opposite the velocity vector" + + Hence we rotate the first velocity vector into the sensor reference + frame, but the X component of that vector is inverted compared to the + spacecraft so a +X indicates backwards and -X indicates forwards + + The returned velocity is also slightly off from the spacecraft velocity + due to the sensor being attached to the craft with wax. + + Returns + ------- + direction : double + X value of the first velocity relative to the sensor + """ + rotation = self.frame_chain.compute_rotation(self.target_frame_id, self.sensor_frame_id) + positions, velocities, times = self.sensor_position + velocity = rotation.rotate_velocity_at([positions[0]], [velocities[0]], [times[0]])[0] + return velocity[0] diff --git a/ale/drivers/mex_drivers.py b/ale/drivers/mex_drivers.py index f29c82c7b2e2e20b7f4cc6eccb6b49e7295e8968..d28cffd1e53c3d79e030cfa65d3ccf11c7be3949 100644 --- a/ale/drivers/mex_drivers.py +++ b/ale/drivers/mex_drivers.py @@ -270,17 +270,6 @@ class MexHrscPds3NaifSpiceDriver(LineScanner, Pds3Label, NaifSpice, RadialDistor return FILTER_SPECIFIC_LOOKUP[self.fikid][2] - @property - def detector_start_line(self): - """ - Returns - ------- - : int - Detector sample corresponding to the first image sample - """ - return 1 - - @property def detector_center_line(self): """ diff --git a/ale/drivers/selene_drivers.py b/ale/drivers/selene_drivers.py index 9ef774864bb89339c2376bb772685c95cbbd5b0c..91f012505854e94d9a530517b79cbea385bcd81c 100644 --- a/ale/drivers/selene_drivers.py +++ b/ale/drivers/selene_drivers.py @@ -245,7 +245,10 @@ class KaguyaTcPds3NaifSpiceDriver(LineScanner, Pds3Label, NaifSpice, Driver): focal plane to detector lines """ pixel_size = spice.gdpool('INS{}_PIXEL_SIZE'.format(self.ikid), 0, 1)[0] - return [0, -1/pixel_size, 0] + if self.spacecraft_direction < 0: + return [0, -1/pixel_size, 0] + elif self.spacecraft_direction > 0: + return [0, 1/pixel_size, 0] @property @@ -306,7 +309,7 @@ class KaguyaTcPds3NaifSpiceDriver(LineScanner, Pds3Label, NaifSpice, Driver): return spice.gdpool('INS{}_BORESIGHT'.format(self.ikid), 1, 1)[0] @property - def line_exposure_duration(self): + def exposure_duration(self): """ Returns Line Exposure Duration @@ -432,7 +435,27 @@ class KaguyaTcPds3NaifSpiceDriver(LineScanner, Pds3Label, NaifSpice, Driver): : int Detector sample corresponding to the first image sample """ - return self.label["FIRST_PIXEL_NUMBER"] + return self.label["FIRST_PIXEL_NUMBER"] - .5 + + @property + def detector_start_line(self): + if self.spacecraft_direction < 0: + return super().detector_start_line + elif self.spacecraft_direction > 0: + return 1 + + @property + def spacecraft_direction(self): + """ + Gets the moving direction of the spacecraft from the label, where -1 is moving + as intended and 1 is moving inverted. + + Returns + ------- + : int + Moving direction of the spacecraft + """ + return int(self.label['SATELLITE_MOVING_DIRECTION']) @property diff --git a/tests/pytests/test_kaguya_drivers.py b/tests/pytests/test_kaguya_drivers.py index 8d501285a32bd82e9113e507754933cd5a466d66..6c3fa969a0a9c5ea8dd3cdf3c909092792d33255 100644 --- a/tests/pytests/test_kaguya_drivers.py +++ b/tests/pytests/test_kaguya_drivers.py @@ -6,7 +6,8 @@ import spiceypy as spice from importlib import reload import json -from unittest.mock import PropertyMock, patch +import unittest +from unittest.mock import MagicMock, PropertyMock, patch from conftest import get_image_label, get_image_kernels, convert_kernels, compare_dicts @@ -54,9 +55,9 @@ image_dict = { 'detector_center': { 'line': 0.5, 'sample': 2048.0}, - 'starting_detector_line': 0, - 'starting_detector_sample': 1, - 'focal2pixel_lines': [0, -142.85714285714286, 0], + 'starting_detector_line': 1, + 'starting_detector_sample': .5, + 'focal2pixel_lines': [0, 142.85714285714286, 0], 'focal2pixel_samples': [0, 0, -142.85714285714286], 'optical_distortion': { 'kaguyalism': { @@ -216,72 +217,81 @@ def test_kaguya_load(test_kernels, label_type, formatter, image): assert compare_dicts(usgscsm_isd_obj, image_dict[image][formatter]) == [] -@pytest.fixture(params=["Pds3NaifDriver"]) -def driver(request): - if request.param == "Pds3NaifDriver": +# ========= Test pdslabel and naifspice driver ========= +class test_pds_naif(unittest.TestCase): + + def setUp(self): label = get_image_label("TC1S2B0_01_06691S820E0465", "pds3") - return KaguyaTcPds3NaifSpiceDriver(label) + self.driver = KaguyaTcPds3NaifSpiceDriver(label) + + def test_short_mission_name(self): + assert self.driver.short_mission_name == 'selene' -def test_short_mission_name(driver): - assert driver.short_mission_name == 'selene' + def test_utc_start_time(self): + assert self.driver.utc_start_time == datetime.datetime(2009, 4, 5, 20, 9, 53, 607478, tzinfo=datetime.timezone.utc) -def test_utc_start_time(driver): - assert driver.utc_start_time == datetime.datetime(2009, 4, 5, 20, 9, 53, 607478, tzinfo=datetime.timezone.utc) + def test_utc_stop_time(self): + assert self.driver.utc_stop_time == datetime.datetime(2009, 4, 5, 20, 10, 23, 864978, tzinfo=datetime.timezone.utc) -def test_utc_stop_time(driver): - assert driver.utc_stop_time == datetime.datetime(2009, 4, 5, 20, 10, 23, 864978, tzinfo=datetime.timezone.utc) + def test_instrument_id(self): + assert self.driver.instrument_id == 'LISM_TC1_STF' -def test_instrument_id(driver): - assert driver.instrument_id == 'LISM_TC1_STF' + def test_sensor_frame_id(self): + with patch('ale.drivers.selene_drivers.spice.namfrm', return_value=12345) as namfrm: + assert self.driver.sensor_frame_id == 12345 + namfrm.assert_called_with('LISM_TC1_HEAD') -def test_sensor_frame_id(driver): - with patch('ale.drivers.selene_drivers.spice.namfrm', return_value=12345) as namfrm: - assert driver.sensor_frame_id == 12345 - namfrm.assert_called_with('LISM_TC1_HEAD') + def test_instrument_host_name(self): + assert self.driver.instrument_host_name == 'SELENE-M' -def test_instrument_host_name(driver): - assert driver.instrument_host_name == 'SELENE-M' + def test_ikid(self): + with patch('ale.drivers.selene_drivers.spice.bods2c', return_value=12345) as bods2c: + assert self.driver.ikid == 12345 + bods2c.assert_called_with('LISM_TC1') -def test_ikid(driver): - with patch('ale.drivers.selene_drivers.spice.bods2c', return_value=12345) as bods2c: - assert driver.ikid == 12345 - bods2c.assert_called_with('LISM_TC1') + def test_spacecraft_name(self): + assert self.driver.spacecraft_name == 'SELENE' -def test_spacecraft_name(driver): - assert driver.spacecraft_name == 'SELENE' + def test_spacecraft_clock_start_count(self): + assert self.driver.spacecraft_clock_start_count == 922997380.174174 -def test_spacecraft_clock_start_count(driver): - assert driver.spacecraft_clock_start_count == 922997380.174174 + def test_spacecraft_clock_stop_count(self): + assert self.driver.spacecraft_clock_stop_count == 922997410.431674 -def test_spacecraft_clock_stop_count(driver): - assert driver.spacecraft_clock_stop_count == 922997410.431674 + def test_ephemeris_start_time(self): + with patch('ale.drivers.selene_drivers.spice.sct2e', return_value=12345) as sct2e, \ + patch('ale.drivers.selene_drivers.spice.bods2c', return_value=-12345) as bods2c: + assert self.driver.ephemeris_start_time == 12345 + sct2e.assert_called_with(-12345, 922997380.174174) -def test_ephemeris_start_time(driver): - with patch('ale.drivers.selene_drivers.spice.sct2e', return_value=12345) as sct2e, \ - patch('ale.drivers.selene_drivers.spice.bods2c', return_value=-12345) as bods2c: - assert driver.ephemeris_start_time == 12345 - sct2e.assert_called_with(-12345, 922997380.174174) + def test_detector_center_line(self): + with patch('ale.drivers.selene_drivers.spice.gdpool', return_value=np.array([54321, 12345])) as gdpool, \ + patch('ale.drivers.selene_drivers.spice.bods2c', return_value=-12345) as bods2c: + assert self.driver.detector_center_line == 12344.5 + gdpool.assert_called_with('INS-12345_CENTER', 0, 2) -def test_detector_center_line(driver): - with patch('ale.drivers.selene_drivers.spice.gdpool', return_value=np.array([54321, 12345])) as gdpool, \ - patch('ale.drivers.selene_drivers.spice.bods2c', return_value=-12345) as bods2c: - assert driver.detector_center_line == 12344.5 - gdpool.assert_called_with('INS-12345_CENTER', 0, 2) + def test_detector_center_sample(self): + with patch('ale.drivers.selene_drivers.spice.gdpool', return_value=np.array([54321, 12345])) as gdpool, \ + patch('ale.drivers.selene_drivers.spice.bods2c', return_value=-12345) as bods2c: + assert self.driver.detector_center_sample == 54320.5 + gdpool.assert_called_with('INS-12345_CENTER', 0, 2) -def test_detector_center_sample(driver): - with patch('ale.drivers.selene_drivers.spice.gdpool', return_value=np.array([54321, 12345])) as gdpool, \ - patch('ale.drivers.selene_drivers.spice.bods2c', return_value=-12345) as bods2c: - assert driver.detector_center_sample == 54320.5 - gdpool.assert_called_with('INS-12345_CENTER', 0, 2) + def test_focal2pixel_samples(self): + with patch('ale.drivers.selene_drivers.spice.gdpool', return_value=np.array([2])) as gdpool, \ + patch('ale.drivers.selene_drivers.spice.bods2c', return_value=-12345) as bods2c: + assert self.driver.focal2pixel_samples == [0, 0, -1/2] + gdpool.assert_called_with('INS-12345_PIXEL_SIZE', 0, 1) -def test_focal2pixel_samples(driver): - with patch('ale.drivers.selene_drivers.spice.gdpool', return_value=np.array([2])) as gdpool, \ - patch('ale.drivers.selene_drivers.spice.bods2c', return_value=-12345) as bods2c: - assert driver.focal2pixel_samples == [0, 0, -1/2] - gdpool.assert_called_with('INS-12345_PIXEL_SIZE', 0, 1) + def test_focal2pixel_lines(self): + with patch('ale.drivers.selene_drivers.spice.gdpool', return_value=np.array([2])) as gdpool, \ + patch('ale.drivers.selene_drivers.spice.bods2c', return_value=-12345) as bods2c, \ + patch('ale.drivers.selene_drivers.KaguyaTcPds3NaifSpiceDriver.spacecraft_direction', \ + new_callable=PropertyMock) as spacecraft_direction: + spacecraft_direction.return_value = 1 + assert self.driver.focal2pixel_lines == [0, 1/2, 0] + spacecraft_direction.return_value = -1 + assert self.driver.focal2pixel_lines == [0, -1/2, 0] + gdpool.assert_called_with('INS-12345_PIXEL_SIZE', 0, 1) -def test_focal2pixel_lines(driver): - with patch('ale.drivers.selene_drivers.spice.gdpool', return_value=np.array([2])) as gdpool, \ - patch('ale.drivers.selene_drivers.spice.bods2c', return_value=-12345) as bods2c: - assert driver.focal2pixel_lines == [0, -1/2, 0] - gdpool.assert_called_with('INS-12345_PIXEL_SIZE', 0, 1) + def test_spacecraft_direction(self): + assert self.driver.spacecraft_direction == 1 diff --git a/tests/pytests/test_lro_drivers.py b/tests/pytests/test_lro_drivers.py index 6f967dea16c4828bf9b8e1e3ac89aaeefbf1ac64..fc605de2901a2d303c9717d350f9c6a7d38355c3 100644 --- a/tests/pytests/test_lro_drivers.py +++ b/tests/pytests/test_lro_drivers.py @@ -2,7 +2,7 @@ import pytest import numpy as np import os import unittest -from unittest.mock import PropertyMock, patch +from unittest.mock import MagicMock, PropertyMock, patch import spiceypy as spice import json @@ -10,6 +10,7 @@ import ale from ale import util from ale.drivers.lro_drivers import LroLrocPds3LabelNaifSpiceDriver from ale.drivers.lro_drivers import LroLrocIsisLabelNaifSpiceDriver +from ale.transformation import TimeDependentRotation from conftest import get_image_label, get_image_kernels, convert_kernels, compare_dicts @@ -200,59 +201,6 @@ def test_kernels(): for kern in kern_list: os.remove(kern) -@pytest.fixture(params=["Pds3NaifDriver"]) -def driver(request): - if request.param == "Pds3NaifDriver": - label = get_image_label("M103595705LE", "pds3") - return LroLrocPds3LabelNaifSpiceDriver(label) - -def test_short_mission_name(driver): - assert driver.short_mission_name=='lro' - -def test_instrument_id_left(driver): - driver.label['FRAME_ID'] = 'LEFT' - assert driver.instrument_id == 'LRO_LROCNACL' - -def test_instrument_id_right(driver): - driver.label['FRAME_ID'] = 'RIGHT' - assert driver.instrument_id == 'LRO_LROCNACR' - -def test_spacecraft_name(driver): - assert driver.spacecraft_name == 'LRO' - -def test_sensor_model_version(driver): - assert driver.sensor_model_version == 2 - -def test_odtk(driver): - with patch('ale.drivers.lro_drivers.spice.gdpool', return_value=np.array([1.0])) as gdpool, \ - patch('ale.drivers.lro_drivers.spice.bods2c', return_value=-12345) as bods2c: - assert driver.odtk == [1.0] - gdpool.assert_called_with('INS-12345_OD_K', 0, 1) - -def test_usgscsm_distortion_model(driver): - with patch('ale.drivers.lro_drivers.LroLrocPds3LabelNaifSpiceDriver.odtk', \ - new_callable=PropertyMock) as odtk: - odtk.return_value = [1.0] - distortion_model = driver.usgscsm_distortion_model - assert distortion_model['lrolrocnac']['coefficients'] == [1.0] - -def test_ephemeris_start_time(driver): - with patch('ale.drivers.lro_drivers.spice.scs2e', return_value=5) as scs2e, \ - patch('ale.drivers.lro_drivers.LroLrocPds3LabelNaifSpiceDriver.exposure_duration', \ - new_callable=PropertyMock) as exposure_duration, \ - patch('ale.drivers.lro_drivers.LroLrocPds3LabelNaifSpiceDriver.spacecraft_id', \ - new_callable=PropertyMock) as spacecraft_id: - exposure_duration.return_value = 0.1 - spacecraft_id.return_value = 1234 - assert driver.ephemeris_start_time == 107.4 - scs2e.assert_called_with(1234, "1/270649237:07208") - -def test_exposure_duration(driver): - with patch('ale.base.label_pds3.Pds3Label.exposure_duration', \ - new_callable=PropertyMock) as exposure_duration: - exposure_duration.return_value = 1 - assert driver.exposure_duration == 1.0045 - @pytest.mark.parametrize("label_type", ['isis3']) @pytest.mark.parametrize("formatter", ['isis']) @pytest.mark.parametrize("image", image_dict.keys()) @@ -263,6 +211,90 @@ def test_load_isis(test_kernels, label_type, formatter, image): print(json.dumps(isis_isd_obj, indent=4)) assert compare_dicts(isis_isd_obj, image_dict[image][formatter]) == [] +# ========= Test pdslabel and naifspice driver ========= +class test_pds_naif(unittest.TestCase): + + def setUp(self): + label = get_image_label('M103595705LE', 'pds3') + self.driver = LroLrocPds3LabelNaifSpiceDriver(label) + + def test_short_mission_name(self): + assert self.driver.short_mission_name=='lro' + + def test_instrument_id_left(self): + self.driver.label['FRAME_ID'] = 'LEFT' + assert self.driver.instrument_id == 'LRO_LROCNACL' + + def test_instrument_id_right(self): + self.driver.label['FRAME_ID'] = 'RIGHT' + assert self.driver.instrument_id == 'LRO_LROCNACR' + + def test_spacecraft_name(self): + assert self.driver.spacecraft_name == 'LRO' + + def test_sensor_model_version(self): + assert self.driver.sensor_model_version == 2 + + def test_odtk(self): + with patch('ale.drivers.lro_drivers.spice.gdpool', return_value=np.array([1.0])) as gdpool, \ + patch('ale.drivers.lro_drivers.spice.bods2c', return_value=-12345) as bods2c: + assert self.driver.odtk == [1.0] + gdpool.assert_called_with('INS-12345_OD_K', 0, 1) + + def test_usgscsm_distortion_model(self): + with patch('ale.drivers.lro_drivers.LroLrocPds3LabelNaifSpiceDriver.odtk', \ + new_callable=PropertyMock) as odtk: + odtk.return_value = [1.0] + distortion_model = self.driver.usgscsm_distortion_model + assert distortion_model['lrolrocnac']['coefficients'] == [1.0] + + def test_ephemeris_start_time(self): + with patch('ale.drivers.lro_drivers.spice.scs2e', return_value=5) as scs2e, \ + patch('ale.drivers.lro_drivers.LroLrocPds3LabelNaifSpiceDriver.exposure_duration', \ + new_callable=PropertyMock) as exposure_duration, \ + patch('ale.drivers.lro_drivers.LroLrocPds3LabelNaifSpiceDriver.spacecraft_id', \ + new_callable=PropertyMock) as spacecraft_id: + exposure_duration.return_value = 0.1 + spacecraft_id.return_value = 1234 + assert self.driver.ephemeris_start_time == 107.4 + scs2e.assert_called_with(1234, "1/270649237:07208") + + def test_exposure_duration(self): + with patch('ale.base.label_pds3.Pds3Label.exposure_duration', \ + new_callable=PropertyMock) as exposure_duration: + exposure_duration.return_value = 1 + assert self.driver.exposure_duration == 1.0045 + + @patch('ale.transformation.FrameChain') + @patch('ale.transformation.FrameChain.from_spice', return_value=ale.transformation.FrameChain()) + @patch('ale.transformation.FrameChain.compute_rotation', return_value=TimeDependentRotation([[0, 0, 1, 0]], [0], 0, 0)) + def test_spacecraft_direction(self, compute_rotation, from_spice, frame_chain): + with patch('ale.drivers.lro_drivers.LroLrocPds3LabelNaifSpiceDriver.target_frame_id', \ + new_callable=PropertyMock) as target_frame_id, \ + patch('ale.drivers.lro_drivers.LroLrocPds3LabelNaifSpiceDriver.sensor_frame_id', \ + new_callable=PropertyMock) as sensor_frame_id, \ + patch('ale.drivers.lro_drivers.LroLrocPds3LabelNaifSpiceDriver.ephemeris_start_time', \ + new_callable=PropertyMock) as ephemeris_start_time, \ + patch('ale.drivers.lro_drivers.LroLrocPds3LabelNaifSpiceDriver.ephemeris_stop_time', \ + new_callable=PropertyMock) as ephemeris_end_time, \ + patch('ale.drivers.lro_drivers.LroLrocPds3LabelNaifSpiceDriver.sensor_position', \ + new_callable=PropertyMock) as sensor_position: + sensor_position.return_value = [[np.array([50, 50, 50])], [np.array([1, 1, 1])], [0]] + assert self.driver.spacecraft_direction < 0 + compute_rotation.assert_called_with(target_frame_id.return_value, sensor_frame_id.return_value) + + def test_focal2pixel_lines(self): + with patch('ale.drivers.lro_drivers.spice.gdpool', return_value=[0, 1, 0]) as gdpool, \ + patch('ale.drivers.lro_drivers.LroLrocPds3LabelNaifSpiceDriver.ikid', \ + new_callable=PropertyMock) as ikid, \ + patch('ale.drivers.lro_drivers.LroLrocPds3LabelNaifSpiceDriver.spacecraft_direction', \ + new_callable=PropertyMock) as spacecraft_direction: + spacecraft_direction.return_value = -1 + np.testing.assert_array_equal(self.driver.focal2pixel_lines, [0, 1, 0]) + spacecraft_direction.return_value = 1 + np.testing.assert_array_equal(self.driver.focal2pixel_lines, [0, -1, 0]) + + # ========= Test isislabel and naifspice driver ========= class test_isis_naif(unittest.TestCase): @@ -323,3 +355,32 @@ class test_isis_naif(unittest.TestCase): def test_sampling_factor(self): assert self.driver.sampling_factor == 1 + + @patch('ale.transformation.FrameChain') + @patch('ale.transformation.FrameChain.from_spice', return_value=ale.transformation.FrameChain()) + @patch('ale.transformation.FrameChain.compute_rotation', return_value=TimeDependentRotation([[0, 0, 1, 0]], [0], 0, 0)) + def test_spacecraft_direction(self, compute_rotation, from_spice, frame_chain): + with patch('ale.drivers.lro_drivers.LroLrocIsisLabelNaifSpiceDriver.target_frame_id', \ + new_callable=PropertyMock) as target_frame_id, \ + patch('ale.drivers.lro_drivers.LroLrocIsisLabelNaifSpiceDriver.sensor_frame_id', \ + new_callable=PropertyMock) as sensor_frame_id, \ + patch('ale.drivers.lro_drivers.LroLrocIsisLabelNaifSpiceDriver.ephemeris_start_time', \ + new_callable=PropertyMock) as ephemeris_start_time, \ + patch('ale.drivers.lro_drivers.LroLrocIsisLabelNaifSpiceDriver.ephemeris_stop_time', \ + new_callable=PropertyMock) as ephemeris_end_time, \ + patch('ale.drivers.lro_drivers.LroLrocIsisLabelNaifSpiceDriver.sensor_position', \ + new_callable=PropertyMock) as sensor_position: + sensor_position.return_value = [[np.array([50, 50, 50])], [np.array([1, 1, 1])], [0]] + assert self.driver.spacecraft_direction < 0 + compute_rotation.assert_called_with(target_frame_id.return_value, sensor_frame_id.return_value) + + def test_focal2pixel_lines(self): + with patch('ale.drivers.lro_drivers.spice.gdpool', return_value=[0, 1, 0]) as gdpool, \ + patch('ale.drivers.lro_drivers.LroLrocIsisLabelNaifSpiceDriver.ikid', \ + new_callable=PropertyMock) as ikid, \ + patch('ale.drivers.lro_drivers.LroLrocIsisLabelNaifSpiceDriver.spacecraft_direction', \ + new_callable=PropertyMock) as spacecraft_direction: + spacecraft_direction.return_value = -1 + np.testing.assert_array_equal(self.driver.focal2pixel_lines, [0, 1, 0]) + spacecraft_direction.return_value = 1 + np.testing.assert_array_equal(self.driver.focal2pixel_lines, [0, -1, 0]) diff --git a/tests/pytests/test_mex_drivers.py b/tests/pytests/test_mex_drivers.py index 68941356ebd80d425db74e807fa85e766ec8c82a..fe541f719b9d4c94cef66e02af9bdd1c0a55b74f 100644 --- a/tests/pytests/test_mex_drivers.py +++ b/tests/pytests/test_mex_drivers.py @@ -153,7 +153,7 @@ def usgscsm_compare_dict(): "line": 0.0, "sample": 2592.0 }, - "starting_detector_line": 1, + "starting_detector_line": 0, "starting_detector_sample": 0, "focal2pixel_lines": [ -7113.11359717265, @@ -570,7 +570,7 @@ def test_mex_load(test_kernels, formatter, usgscsm_compare_dict, label): binary_exposure_durations.return_value = [0.012800790786743165, 0.012800790786743165, 0.013227428436279297] binary_lines.return_value = [0.5, 1.5, 15086.5] - usgscsm_isd = ale.load(label_file, props={'kernels': test_kernels}, formatter=formatter, verbose='true') + usgscsm_isd = ale.load(label_file, props={'kernels': test_kernels}, formatter=formatter) assert compare_dicts(usgscsm_isd, usgscsm_compare_dict['h5270_0000_ir2'][formatter]) == [] # ========= Test mex pds3label and naifspice driver ========= @@ -637,7 +637,7 @@ class test_mex_pds3_naif(unittest.TestCase): [49.7917927568053, 3.079982431615e-06, 0.006999999322408]) def test_detector_start_line(self): - assert self.driver.detector_start_line == 1 + assert self.driver.detector_start_line == 0.0 def test_detector_center_line(self): assert self.driver.detector_center_line == 0.0