From 0bf1bbd8899ba9b0466a1658a36bc7bc9d8a736f Mon Sep 17 00:00:00 2001 From: acpaquette Date: Fri, 27 Mar 2020 09:53:53 -0700 Subject: [PATCH] LRO Direction Fix + Summing Mode Fix (#333) * Updated spacecraft direction for lro * Fixes the focal2pixel transform to account for the summing mode of the camera. * Fixed lro tests --- ale/base/data_naif.py | 4 ++- ale/drivers/lro_drivers.py | 40 +++++++++++++++++++--------- tests/pytests/test_lro_drivers.py | 43 +++++++++++++++++-------------- 3 files changed, 54 insertions(+), 33 deletions(-) diff --git a/ale/base/data_naif.py b/ale/base/data_naif.py index 60c0abc15..98d07805e 100644 --- a/ale/base/data_naif.py +++ b/ale/base/data_naif.py @@ -411,7 +411,9 @@ def frame_chain(self): v_vec = rotated_velocities velocity_axis = 2 - trans_x = self.focal2pixel_lines + # Get the default line translation with no potential flipping + # from the driver + trans_x = np.array(list(spice.gdpool('INS{}_ITRANSL'.format(self.ikid), 0, 3))) if (trans_x[0] < trans_x[1]): velocity_axis = 1 diff --git a/ale/drivers/lro_drivers.py b/ale/drivers/lro_drivers.py index 0ddc160cf..014c6a48d 100644 --- a/ale/drivers/lro_drivers.py +++ b/ale/drivers/lro_drivers.py @@ -141,8 +141,11 @@ def focal2pixel_lines(self): : list focal plane to detector lines """ - focal2pixel_lines = np.array(list(spice.gdpool('INS{}_ITRANSL'.format(self.ikid), 0, 3))) - return focal2pixel_lines + focal2pixel_lines = np.array(list(spice.gdpool('INS{}_ITRANSL'.format(self.ikid), 0, 3))) / self.sampling_factor + if self.spacecraft_direction < 0: + return -focal2pixel_lines + else: + return focal2pixel_lines @property def ephemeris_start_time(self): @@ -259,10 +262,15 @@ def spacecraft_direction(self): 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] + frame_chain = self.frame_chain + lro_bus_id = spice.bods2c('LRO_SC_BUS') + time = self.ephemeris_start_time + state, _ = spice.spkezr(self.spacecraft_name, time, 'J2000', 'None', self.target_name) + position = state[:3] + velocity = state[3:] + rotation = frame_chain.compute_rotation(1, lro_bus_id) + rotated_velocity = spice.mxv(rotation._rots.as_dcm()[0], velocity) + return rotated_velocity[0] @@ -398,8 +406,11 @@ def focal2pixel_lines(self): : list focal plane to detector lines """ - focal2pixel_lines = np.array(list(spice.gdpool('INS{}_ITRANSL'.format(self.ikid), 0, 3))) - return focal2pixel_lines + focal2pixel_lines = np.array(list(spice.gdpool('INS{}_ITRANSL'.format(self.ikid), 0, 3))) / self.sampling_factor + if self.spacecraft_direction < 0: + return -focal2pixel_lines + else: + return focal2pixel_lines @property def multiplicative_line_error(self): @@ -485,7 +496,12 @@ def spacecraft_direction(self): 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] + frame_chain = self.frame_chain + lro_bus_id = spice.bods2c('LRO_SC_BUS') + time = self.ephemeris_start_time + state, _ = spice.spkezr(self.spacecraft_name, time, 'J2000', 'None', self.target_name) + position = state[:3] + velocity = state[3:] + rotation = frame_chain.compute_rotation(1, lro_bus_id) + rotated_velocity = spice.mxv(rotation._rots.as_dcm()[0], velocity) + return rotated_velocity[0] diff --git a/tests/pytests/test_lro_drivers.py b/tests/pytests/test_lro_drivers.py index 5328b53ed..326b0eb99 100644 --- a/tests/pytests/test_lro_drivers.py +++ b/tests/pytests/test_lro_drivers.py @@ -271,17 +271,18 @@ def test_exposure_duration(self): 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) + patch('ale.drivers.lro_drivers.spice.bods2c', return_value=-12345) as bods2c, \ + patch('ale.drivers.lro_drivers.spice.spkezr', return_value=[[1, 1, 1, 1, 1, 1], 0]) as spkezr, \ + patch('ale.drivers.lro_drivers.spice.mxv', return_value=[1, 1, 1]) as mxv: + ephemeris_start_time.return_value = 0 + assert self.driver.spacecraft_direction > 0 + bods2c.assert_called_with('LRO_SC_BUS') + spkezr.assert_called_with(self.driver.spacecraft_name, 0, 'J2000', 'None', self.driver.target_name) + compute_rotation.assert_called_with(1, -12345) + np.testing.assert_array_equal(np.array([[-1.0, 0.0, 0.0], [0.0, -1.0, 0.0], [0.0, 0.0, 1.0]]), mxv.call_args[0][0]) + np.testing.assert_array_equal(np.array([1, 1, 1]), mxv.call_args[0][1]) def test_focal2pixel_lines(self): with patch('ale.drivers.lro_drivers.spice.gdpool', return_value=[0, 1, 0]) as gdpool, \ @@ -290,7 +291,7 @@ def test_focal2pixel_lines(self): 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]) + 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]) @@ -362,17 +363,19 @@ def test_sampling_factor(self): 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) + patch('ale.drivers.lro_drivers.spice.cidfrm', return_value=[-12345]) as cidfrm, \ + patch('ale.drivers.lro_drivers.spice.scs2e', return_value=0) as scs2e, \ + patch('ale.drivers.lro_drivers.spice.bods2c', return_value=-12345) as bods2c, \ + patch('ale.drivers.lro_drivers.spice.spkezr', return_value=[[1, 1, 1, 1, 1, 1], 0]) as spkezr, \ + patch('ale.drivers.lro_drivers.spice.mxv', return_value=[1, 1, 1]) as mxv: + ephemeris_start_time.return_value = 0 + assert self.driver.spacecraft_direction > 0 + spkezr.assert_called_with(self.driver.spacecraft_name, 0, 'J2000', 'None', self.driver.target_name) + compute_rotation.assert_called_with(1, -12345) + np.testing.assert_array_equal(np.array([[-1.0, 0.0, 0.0], [0.0, -1.0, 0.0], [0.0, 0.0, 1.0]]), mxv.call_args[0][0]) + np.testing.assert_array_equal(np.array([1, 1, 1]), mxv.call_args[0][1]) def test_focal2pixel_lines(self): with patch('ale.drivers.lro_drivers.spice.gdpool', return_value=[0, 1, 0]) as gdpool, \ @@ -381,6 +384,6 @@ def test_focal2pixel_lines(self): 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]) + 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])