Commit 6d3f2b73 authored by Jesse Mapel's avatar Jesse Mapel Committed by Kristin
Browse files

Added ISIS special NAIF keywords (#271)

* Added ISIS special NAIF keywords

* Better variable name

* Moved obs and targ to temp vars

* Added proper observer and target swapping code

* Updated from upstream
parent 89cf4c57
Loading
Loading
Loading
Loading
+64 −16
Original line number Diff line number Diff line
@@ -46,11 +46,12 @@ class NaifSpice():
    def light_time_correction(self):
        """
        Returns the type of light time correciton and abberation correction to
        use in NAIF calls.
        use in NAIF calls. Expects ikid to be defined. This must be the integer
        Naif id code of the instrument.

        This defaults to light time correction and abberation correction (LT+S),
        concrete drivers should override this if they need to either not use
        light time correction or use a different type of light time correction.
        This searches for the value of the NAIF keyword INS<ikid>_LIGHTTIME_CORRECTION.
        If the keyword is not defined, then this defaults to light time
        correction and abberation correction (LT+S).

        Returns
        -------
@@ -59,6 +60,9 @@ class NaifSpice():
          See https://naif.jpl.nasa.gov/pub/naif/toolkit_docs/C/req/abcorr.html
          for the different options available.
        """
        try:
            return spice.gcpool('INS{}_LIGHTTIME_CORRECTION'.format(self.ikid), 0, 1)[0]
        except:
            return 'LT+S'

    @property
@@ -318,21 +322,32 @@ class NaifSpice():
            pos = []
            vel = []

            target = self.target_name
            observer = self.spacecraft_name
            # Check for ISIS flag to fix target and observer swapping
            if self.swap_observer_target:
                target = self.spacecraft_name
                observer = self.target_name

            for time in ephem:
                # spkezr returns a vector from the observer's location to the aberration-corrected
                # location of the target. For more information, see:
                # https://naif.jpl.nasa.gov/pub/naif/toolkit_docs/FORTRAN/spicelib/spkezr.html
                state, _ = spice.spkezr(self.target_name,
                state, _ = spice.spkezr(target,
                                        time,
                                        self.reference_frame,
                                        self.light_time_correction,
                                       self.spacecraft_name,)
                                        observer)
                if self.swap_observer_target:
                    pos.append(state[:3])
                    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 = np.asarray([p * -1000 for p in pos])
            self._velocity = np.asarray([v * -1000 for v in vel])
                else:
                    pos.append(-state[:3])
                    vel.append(-state[3:])

            # By default, SPICE works in km, so convert to m
            self._position = [p * 1000 for p in pos]
            self._velocity = [v * 1000 for v in vel]
        return self._position, self._velocity, self.ephemeris_time

    @property
@@ -427,6 +442,39 @@ class NaifSpice():
        return float(spice.gdpool('INS{}_BORESIGHT_LINE'.format(self.ikid), 0, 1)[0])


    @property
    def swap_observer_target(self):
        """
        Returns if the observer and target should be swapped when determining the
        sensor state relative to the target. This is defined by a keyword in
        ISIS IAKs. If the keyword is not defined in any loaded kernels then False
        is returned.

        Expects ikid to be defined. This should be an integer containing the
        Naif Id code of the instrument.
        """
        try:
            swap = spice.gcpool('INS{}_SWAP_OBSERVER_TARGET'.format(self.ikid), 0, 1)[0]
            return swap.upper() == "TRUE"
        except:
            return False

    @property
    def correct_lt_to_surface(self):
        """
        Returns if light time correction should be made to the surface instead of
        to the center of the body. This is defined by a keyword in ISIS IAKs.
        If the keyword is not defined in any loaded kernels then False is returned.

        Expects ikid to be defined. This should be an integer containing the
        Naif Id code of the instrument.
        """
        try:
            surface_correct = spice.gcpool('INS{}_LT_SURFACE_CORRECT'.format(self.ikid), 0, 1)[0]
            return surface_correct.upper() == "TRUE"
        except:
            return False

    @property
    def isis_naif_keywords(self):
        """
+32 −0
Original line number Diff line number Diff line
@@ -83,6 +83,15 @@ class test_data_naif(unittest.TestCase):
    def test_detector_center_line(self):
        assert self.driver.detector_center_line == 0.430442527

    def test_swap_observer_target(self):
        assert not self.driver.swap_observer_target

    def test_light_time_correction(self):
        assert self.driver.light_time_correction == "LT+S"

    def test_correct_lt_to_surface(self):
        assert not self.driver.correct_lt_to_surface

    def test_sun_position(self):
        sun_positions, sun_velocities, times = self.driver.sun_position
        assert len(sun_positions) == 1
@@ -91,3 +100,26 @@ class test_data_naif(unittest.TestCase):
        np.testing.assert_allclose(sun_velocities[0], [9883868.06162645, 8989183.29614645, 881.9339912834714])
        assert len(times) == 1
        np.testing.assert_allclose(times[0], 297088762.61698407)

def test_light_time_correction_keyword():
    with patch('ale.base.data_naif.spice.gcpool', return_value=['NONE']) as gcpool, \
         patch('ale.base.data_naif.NaifSpice.ikid', new_callable=PropertyMock) as ikid:
        ikid.return_value = -12345
        assert NaifSpice().light_time_correction == 'NONE'
        gcpool.assert_called_with('INS-12345_LIGHTTIME_CORRECTION', 0, 1)

@pytest.mark.parametrize(("key_val, return_val"), [(['TRUE'], True), (['FALSE'], False)])
def test_swap_observer_target_keyword(key_val, return_val):
    with patch('ale.base.data_naif.spice.gcpool', return_value=key_val) as gcpool, \
         patch('ale.base.data_naif.NaifSpice.ikid', new_callable=PropertyMock) as ikid:
        ikid.return_value = -12345
        assert NaifSpice().swap_observer_target == return_val
        gcpool.assert_called_with('INS-12345_SWAP_OBSERVER_TARGET', 0, 1)

@pytest.mark.parametrize(("key_val, return_val"), [(['TRUE'], True), (['FALSE'], False)])
def test_correct_lt_to_surface_keyword(key_val, return_val):
    with patch('ale.base.data_naif.spice.gcpool', return_value=key_val) as gcpool, \
         patch('ale.base.data_naif.NaifSpice.ikid', new_callable=PropertyMock) as ikid:
        ikid.return_value = -12345
        assert NaifSpice().correct_lt_to_surface == return_val
        gcpool.assert_called_with('INS-12345_LT_SURFACE_CORRECT', 0, 1)
+6 −6
Original line number Diff line number Diff line
@@ -108,12 +108,12 @@ def test_load(test_kernels):
                                   [  193824.32093681,   210061.95495794, -1767367.56104995],
                                   [  193267.90484827,   209421.16305764, -1767500.49120063],
                                   [  192711.44397634,   208780.32318594, -1767633.01318365]]),
            'velocities': np.array([[-1069.71225785, -1231.97438089,  -258.37880523],
                                    [-1069.80205939, -1232.06556741,  -257.5939851 ],
                                    [-1069.89161639, -1232.15647191,  -256.80910187],
                                    [-1069.98092881, -1232.24709434,  -256.02415587],
                                    [-1070.06999666, -1232.33743471,  -255.2391471 ],
                                    [-1070.15881991, -1232.42749298,  -254.4540759 ]]),
            'velocities': np.array([[-1069.70946002, -1231.97108635,  -258.37361381],
                                    [-1069.79925825, -1232.06226912,  -257.58879787],
                                    [-1069.88881194, -1232.15316986,  -256.80391882],
                                    [-1069.97812106, -1232.24378854,  -256.01897702],
                                    [-1070.06718562, -1232.33412517,  -255.23397236],
                                    [-1070.15600557, -1232.42417969,  -254.44890536]]),
             'unit': 'm'},
         'sun_position': {
            'positions': np.array([[9.50465237e+10, 1.15903815e+11, 3.78729685e+09]]),
+2 −2
Original line number Diff line number Diff line
@@ -28,8 +28,8 @@ def usgscsm_compare_dict():
        '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]]),
        'positions': np.array([[-629657.4559945846, -1583350.7374122413, 1784408.773440049]]),
        'velocities': np.array([[1732.8734290653545, 2504.0213215928925, 2412.578186708735]]),
        'unit': 'm'},
    'sun_position': {
        'positions': np.array([[-4.68946673e+10, -5.36158427e+08,  2.71167863e+07]]),