From 1c4c8fed3cf14db316264455ecfef5f64107a0f3 Mon Sep 17 00:00:00 2001
From: Austin Sanders <austinsanders1993@gmail.com>
Date: Thu, 2 Jun 2022 11:09:51 -0700
Subject: [PATCH] Initial spiceql integration

---
 ale/base/data_naif.py            | 218 +++++++++++++++++++------------
 ale/drivers/co_drivers.py        |   9 +-
 ale/drivers/dawn_drivers.py      |  14 +-
 ale/drivers/galileo_drivers.py   |  10 +-
 ale/drivers/hayabusa2_drivers.py |   2 -
 ale/drivers/lro_drivers.py       |  56 ++++----
 ale/drivers/mess_drivers.py      |  15 ++-
 ale/drivers/mex_drivers.py       |  17 +--
 ale/drivers/mro_drivers.py       |   3 +-
 ale/drivers/nh_drivers.py        |   5 +-
 ale/drivers/selene_drivers.py    | 182 ++++++++++++++++++++++----
 ale/drivers/tgo_drivers.py       |   4 +-
 ale/drivers/viking_drivers.py    |   5 +-
 ale/drivers/voyager_drivers.py   |   2 +-
 14 files changed, 364 insertions(+), 178 deletions(-)

diff --git a/ale/base/data_naif.py b/ale/base/data_naif.py
index dad57ad..a04378d 100644
--- a/ale/base/data_naif.py
+++ b/ale/base/data_naif.py
@@ -1,4 +1,5 @@
 import spiceypy as spice
+from pyspiceql import pyspiceql
 import numpy as np
 import scipy.constants
 
@@ -19,7 +20,7 @@ class NaifSpice():
         to get the kernels furnished.
         """
         if self.kernels:
-            [spice.furnsh(k) for k in self.kernels]
+            [pyspiceql.KernelPool.getInstance().load(k) for k in self.kernels]
         return self
 
     def __exit__(self, exc_type, exc_val, exc_tb):
@@ -29,7 +30,7 @@ class NaifSpice():
         kernels can be unloaded.
         """
         if self.kernels:
-            [spice.unload(k) for k in self.kernels]
+            [pyspiceql.KernelPool.getInstance().unload(k) for k in self.kernels]
 
     @property
     def kernels(self):
@@ -93,10 +94,12 @@ 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'
+        if not hasattr(self, "_light_time_correction"):
+            try:
+                self._light_time_correction = pyspiceql.getKernelStringValue('INS{}_LIGHTTIME_CORRECTION'.format(self.ikid))[0]
+            except:
+                self._light_time_correction = 'LT+S'
+        return self._light_time_correction
 
     @property
     def odtx(self):
@@ -109,7 +112,9 @@ class NaifSpice():
         : list
           Optical distortion x coefficients
         """
-        return spice.gdpool('INS{}_OD_T_X'.format(self.ikid),0, 10).tolist()
+        if not hasattr(self, "_odtx"):
+            self._odtx = pyspiceql.getKernelVectorValue('INS{}_OD_T_X'.format(self.ikid)).toList()
+        return self._odtx
 
     @property
     def odty(self):
@@ -122,7 +127,9 @@ class NaifSpice():
         : list
           Optical distortion y coefficients
         """
-        return spice.gdpool('INS{}_OD_T_Y'.format(self.ikid), 0, 10).tolist()
+        if not hasattr(self, "_odty"):
+            self._odty = pyspiceql.getKernelVectorValue('INS{}_OD_T_Y'.format(self.ikid)).toList()
+        return self._odty
 
     @property
     def odtk(self):
@@ -135,7 +142,9 @@ class NaifSpice():
         : list
           Radial distortion coefficients
         """
-        return spice.gdpool('INS{}_OD_K'.format(self.ikid),0, 3).tolist()
+        if not hasattr(self, "_odtk"):
+            self._odtk = pyspiceql.getKernelVectorValue('INS{}_OD_K'.format(self.ikid)).toList()
+        return self._odtk
 
     @property
     def ikid(self):
@@ -149,7 +158,9 @@ class NaifSpice():
         : int
           Naif ID used to for identifying the instrument in Spice kernels
         """
-        return spice.bods2c(self.instrument_id)
+        if not hasattr(self, "_ikid"):
+            self._ikid = pyspiceql.Kernel_translateFrame(self.instrument_id)
+        return self._ikid
 
     @property
     def spacecraft_id(self):
@@ -163,7 +174,9 @@ class NaifSpice():
         : int
           Naif ID code for the spacecraft
         """
-        return spice.bods2c(self.spacecraft_name)
+        if not hasattr(self, "_spacecraft_id"):
+            self._spacecraft_id = pyspiceql.Kernel_translateFrame(self.spacecraft_name)
+        return self._spacecraft_id
 
     @property
     def target_id(self):
@@ -177,7 +190,9 @@ class NaifSpice():
         : int
           Naif ID code for the target body
         """
-        return spice.bods2c(self.target_name)
+        if not hasattr(self, "_target_id"):
+            self._target_id = pyspiceql.Kernel_translateFrame(self.target_name)
+        return self._target_id
 
     @property
     def target_frame_id(self):
@@ -191,8 +206,10 @@ class NaifSpice():
         : int
           Naif ID code for the target frame
         """
-        frame_info = spice.cidfrm(self.target_id)
-        return frame_info[0]
+        if not hasattr(self, "_target_frame_id"):
+            frame_info = spice.cidfrm(self.target_id)
+            self._target_frame_id = frame_info[0]
+        return self._target_frame_id
 
     @property
     def sensor_frame_id(self):
@@ -205,7 +222,9 @@ class NaifSpice():
         : int
           Naif ID code for the sensor frame
         """
-        return self.ikid
+        if not hasattr(self, "_sensor_frame_id"):
+            self._sensor_frame_id = self.ikid
+        return self._sensor_frame_id
 
     @property
     def focal2pixel_lines(self):
@@ -217,7 +236,9 @@ class NaifSpice():
         : list<double>
           focal plane to detector lines
         """
-        return list(spice.gdpool('INS{}_ITRANSL'.format(self.ikid), 0, 3))
+        if not hasattr(self, "_focal2pixel_lines"):
+            self._focal2pixel_lines = list(pyspiceql.getKernelVectorValue('INS{}_ITRANSL'.format(self.ikid)))
+        return self._focal2pixel_lines
 
     @property
     def focal2pixel_samples(self):
@@ -229,7 +250,9 @@ class NaifSpice():
         : list<double>
           focal plane to detector samples
         """
-        return list(spice.gdpool('INS{}_ITRANSS'.format(self.ikid), 0, 3))
+        if not hasattr(self, "_focal2pixel_lines"):
+            self._focal2pixel_samples = list(pyspiceql.getKernelVectorValue('INS{}_ITRANSS'.format(self.ikid)))
+        return self._focal2pixel_samples
 
     @property
     def pixel2focal_x(self):
@@ -241,7 +264,9 @@ class NaifSpice():
         : list<double>
         detector to focal plane x
         """
-        return list(spice.gdpool('INS{}_TRANSX'.format(self.ikid), 0, 3))
+        if not hasattr(self, "_pixel2focal_x"):
+            self._pixel2focal_x = list(pyspiceql.getKernelVectorValue('INS{}_ITRANSX'.format(self.ikid)))
+        return self._pixel2focal_x
 
     @property
     def pixel2focal_y(self):
@@ -253,7 +278,9 @@ class NaifSpice():
         : list<double>
         detector to focal plane y
         """
-        return list(spice.gdpool('INS{}_TRANSY'.format(self.ikid), 0, 3))
+        if not hasattr(self, "_pixel2focal_x"):
+            self._pixel2focal_y = list(pyspiceql.getKernelVectorValue('INS{}_ITRANSY'.format(self.ikid)))
+        return self._pixel2focal_y
 
     @property
     def focal_length(self):
@@ -266,7 +293,9 @@ class NaifSpice():
         : float
           focal length
         """
-        return float(spice.gdpool('INS{}_FOCAL_LENGTH'.format(self.ikid), 0, 1)[0])
+        if not hasattr(self, "_focal_length"):
+            self._focal_length = float(pyspiceql.getKernelStringValue('INS{}_FOCAL_LENGTH'.format(self.ikid))[0])
+        return self._focal_length
 
     @property
     def pixel_size(self):
@@ -277,7 +306,9 @@ class NaifSpice():
         -------
         : float pixel size
         """
-        return spice.gdpool('INS{}_PIXEL_SIZE'.format(self.ikid), 0, 1)[0] * 0.001
+        if not hasattr(self, "_pixel_size"):
+            self._pixel_size = pyspiceql.getKernelStringValue('INS{}_PIXEL_SIZE'.format(self.ikid), 0, 1)[0] * 0.001
+        return self._pixel_size
 
     @property
     def target_body_radii(self):
@@ -291,8 +322,9 @@ class NaifSpice():
         : list<double>
           Radius of all three axis of the target body
         """
-        rad = spice.bodvrd(self.target_name, 'RADII', 3)
-        return rad[1]
+        if not hasattr(self, "_target_body_radii"):
+            self._target_body_radii = spice.bodvrd(self.target_name, 'RADII', 3)[1]
+        return self._target_body_radii
 
     @property
     def reference_frame(self):
@@ -328,22 +360,25 @@ class NaifSpice():
         : (sun_positions, sun_velocities)
           a tuple containing a list of sun positions, a list of sun velocities
         """
-        times = [self.center_ephemeris_time]
-        positions = []
-        velocities = []
-
-        for time in times:
-            sun_state, _ = spice.spkezr("SUN",
-                                         time,
-                                         self.reference_frame,
-                                         'LT+S',
-                                         self.target_name)
-            positions.append(sun_state[:3])
-            velocities.append(sun_state[3:6])
-        positions = 1000 * np.asarray(positions)
-        velocities = 1000 * np.asarray(velocities)
-
-        return positions, velocities, times
+        if not hasattr(self, "_sun_position"):
+            times = [self.center_ephemeris_time]
+            positions = []
+            velocities = []
+
+            for time in times:
+                sun_lt_state = pyspiceql.getTargetState(time,
+                                                        self.target_name,
+                                                        self.spacecraft_name,
+                                                        'J2000',
+                                                        self.light_time_correction)
+                sun_state = sun_lt_state.starg
+                positions.append(sun_state[:3])
+                velocities.append(sun_state[3:6])
+            positions = 1000 * np.asarray(positions)
+            velocities = 1000 * np.asarray(velocities)
+
+            self._sun_position = positions, velocities, times
+        return self._sun_position
 
     @property
     def sensor_position(self):
@@ -378,45 +413,55 @@ class NaifSpice():
                 # location of the target. For more information, see:
                 # https://naif.jpl.nasa.gov/pub/naif/toolkit_docs/FORTRAN/spicelib/spkezr.html
                 if self.correct_lt_to_surface and self.light_time_correction.upper() == 'LT+S':
-                    obs_tar_state, obs_tar_lt = spice.spkezr(target,
-                                                             time,
-                                                             'J2000',
-                                                             self.light_time_correction,
-                                                             observer)
+                    obs_tar = pyspiceql.getTargetState(time,
+                                                       target,
+                                                       observer,
+                                                       'J2000',
+                                                       self.light_time_correction)
+                    obs_tar_state = obs_tar.starg
+                    obs_tar_lt = obs_tar.lt
+
                     # ssb to spacecraft
-                    ssb_obs_state, ssb_obs_lt = spice.spkezr(observer,
-                                                             time,
-                                                             'J2000',
-                                                             'NONE',
-                                                             'SSB')
+                    ssb_obs = pyspiceql.getTargetState(time,
+                                                       target,
+                                                       'SSB',
+                                                       'J2000',
+                                                       "NONE")
+                    ssb_obs_state = ssb_obs.starg
+                    ssb_obs_lt = ssb_obs.lt
 
                     radius_lt = (self.target_body_radii[2] + self.target_body_radii[0]) / 2 / (scipy.constants.c/1000.0)
                     adjusted_time = time - obs_tar_lt + radius_lt
-                    ssb_tar_state, ssb_tar_lt = spice.spkezr(target,
-                                                             adjusted_time,
-                                                             'J2000',
-                                                             'NONE',
-                                                             'SSB')
+
+                    ssb_tar = pyspiceql.getTargetState(adjusted_time,
+                                                       target,
+                                                       'SSB',
+                                                       'J2000',
+                                                       "NONE")
+                    ssb_tar_state = ssb_tar.starg
+                    ssb_tar_lt = ssb_tar.lt
                     state = ssb_tar_state - ssb_obs_state
+
                     matrix = spice.sxform("J2000", self.reference_frame, time)
                     state = spice.mxvg(matrix, state)
                 else:
-                    state, _ = spice.spkezr(target,
-                                            time,
-                                            self.reference_frame,
-                                            self.light_time_correction,
-                                            observer)
+                    state = pyspiceql.getTargetState(time,
+                                                     target,
+                                                     observer,
+                                                     self.reference_frame,
+                                                     self.light_time_correction)
 
                 if self.swap_observer_target:
-                    pos.append(-state[:3])
-                    vel.append(-state[3:])
+                    pos.append(-state.starg[:3])
+                    vel.append(-state.starg[3:])
                 else:
-                    pos.append(state[:3])
-                    vel.append(state[3:])
+                    pos.append(state.starg[:3])
+                    vel.append(state.starg[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]
+            self._position = 1000 * np.asarray(pos)
+            self._velocity = 1000 * np.asarray(vel)
         return self._position, self._velocity, self.ephemeris_time
 
     @property
@@ -444,7 +489,7 @@ class NaifSpice():
                 velocity_axis = 2
                 # 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)))
+                trans_x = np.array(self.focal2pixel_lines)
 
                 if (trans_x[0] < trans_x[1]):
                     velocity_axis = 1
@@ -489,7 +534,9 @@ class NaifSpice():
         : double
           Starting ephemeris time of the image
         """
-        return spice.scs2e(self.spacecraft_id, self.spacecraft_clock_start_count)
+        if not hasattr(self, "_ephemeris_start_time"):
+            self._ephemeris_start_time = pyspiceql.sclkToEt(str(self.spacecraft_name), self.spacecraft_clock_start_count)
+        return self._ephemeris_start_time
 
     @property
     def ephemeris_stop_time(self):
@@ -504,7 +551,9 @@ class NaifSpice():
         : double
           Ephemeris stop time of the image
         """
-        return spice.scs2e(self.spacecraft_id, self.spacecraft_clock_stop_count)
+        if not hasattr(self, "_ephemeris_stop_time"):
+            self._ephemeris_stop_time = pyspiceql.sclkToEt(self.spacecraft_name, self.spacecraft_clock_stop_count)
+        return self._ephemeris_stop_time
 
     @property
     def detector_center_sample(self):
@@ -517,7 +566,9 @@ class NaifSpice():
         : float
           Detector sample of the principal point
         """
-        return float(spice.gdpool('INS{}_BORESIGHT_SAMPLE'.format(self.ikid), 0, 1)[0])
+        if not hasattr(self, "_detector_center_sample"):
+            self._detector_center_sample = float(pyspiceql.getKernelStringValue('INS{}_BORESIGHT_SAMPLE'.format(self.ikid))[0])
+        return self._detector_center_sample
 
     @property
     def detector_center_line(self):
@@ -530,8 +581,9 @@ class NaifSpice():
         : float
           Detector line of the principal point
         """
-        return float(spice.gdpool('INS{}_BORESIGHT_LINE'.format(self.ikid), 0, 1)[0])
-
+        if not hasattr(self, "_detector_center_line"):
+            self._detector_center_line = float(pyspiceql.getKernelStringValue('INS{}_BORESIGHT_LINE'.format(self.ikid))[0])
+        return self._detector_center_line
 
     @property
     def swap_observer_target(self):
@@ -544,11 +596,13 @@ class NaifSpice():
         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
+        if not hasattr(self, "_swap_observer_target"):
+            try:
+                swap = pyspiceql.getKernelStringValue('INS{}_SWAP_OBSERVER_TARGET'.format(self.ikid))[0]
+                self._swap_observer_target = swap.upper() == "TRUE"
+            except:
+                self._swap_observer_target = False
+        return self._swap_observer_target
 
     @property
     def correct_lt_to_surface(self):
@@ -560,11 +614,13 @@ class NaifSpice():
         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
+        if not hasattr(self, "_correct_lt_to_surface"):
+            try:
+                surface_correct = pyspiceql.getKernelStringValue('INS{}_LT_SURFACE_CORRECT'.format(self.ikid))[0]
+                self._correct_lt_to_surface = surface_correct.upper() == "TRUE"
+            except:
+                self._correct_lt_to_surface = False
+        return self._correct_lt_to_surface
 
     @property
     def naif_keywords(self):
diff --git a/ale/drivers/co_drivers.py b/ale/drivers/co_drivers.py
index f800c06..97f5405 100644
--- a/ale/drivers/co_drivers.py
+++ b/ale/drivers/co_drivers.py
@@ -5,6 +5,7 @@ import numpy as np
 
 import pvl
 import spiceypy as spice
+from pyspiceql import pyspiceql
 from ale.base import Driver
 from ale.base.data_naif import NaifSpice
 from ale.base.data_isis import IsisSpice
@@ -326,7 +327,7 @@ class CassiniIssPds3LabelNaifSpiceDriver(Framer, Pds3Label, NaifSpice, RadialDis
         : float
           focal epsilon
         """
-        return float(spice.gdpool('INS{}_FL_UNCERTAINTY'.format(self.ikid), 0, 1)[0])
+        return float(pyspiceql.getKernelVectorValue('INS{}_FL_UNCERTAINTY'.format(self.ikid))[0])
 
     @property
     def spacecraft_name(self):
@@ -353,7 +354,7 @@ class CassiniIssPds3LabelNaifSpiceDriver(Framer, Pds3Label, NaifSpice, RadialDis
           focal plane to detector samples
         """
         # Microns to mm
-        pixel_size = spice.gdpool('INS{}_PIXEL_SIZE'.format(self.ikid), 0, 1)[0] * 0.001
+        pixel_size = float(pyspiceql.getKernelVectorValue('INS{}_PIXEL_SIZE'.format(self.ikid))[0]) * .001
         return [0.0, 1/pixel_size, 0.0]
 
     @property
@@ -367,7 +368,7 @@ class CassiniIssPds3LabelNaifSpiceDriver(Framer, Pds3Label, NaifSpice, RadialDis
         : list<double>
           focal plane to detector lines
         """
-        pixel_size = spice.gdpool('INS{}_PIXEL_SIZE'.format(self.ikid), 0, 1)[0] * 0.001
+        pixel_size = float(pyspiceql.getKernelVectorValue('INS{}_PIXEL_SIZE'.format(self.ikid))[0]) * .001
         return [0.0, 0.0, 1/pixel_size]
 
     @property
@@ -443,7 +444,7 @@ class CassiniIssPds3LabelNaifSpiceDriver(Framer, Pds3Label, NaifSpice, RadialDis
         try:
             default_focal_len = super(CassiniIssPds3LabelNaifSpiceDriver, self).focal_length
         except:
-            default_focal_len = float(spice.gdpool('INS{}_FOV_CENTER_PIXEL'.format(self.ikid), 0, 2)[0])
+            default_focal_len = float(pyspiceql.getKernelVectorValue('INS{}_FOV_CENTER_PIXEL'.format(self.ikid))[0])
 
         filters = tuple(self.label['FILTER_NAME'])
 
diff --git a/ale/drivers/dawn_drivers.py b/ale/drivers/dawn_drivers.py
index ceb14f5..36ac3b3 100644
--- a/ale/drivers/dawn_drivers.py
+++ b/ale/drivers/dawn_drivers.py
@@ -1,5 +1,4 @@
 import pvl
-import spiceypy as spice
 import os
 
 from glob import glob
@@ -9,6 +8,7 @@ from ale.base import Driver
 from ale.base.data_naif import NaifSpice
 from ale.base.label_pds3 import Pds3Label
 from ale.base.type_sensor import Framer
+from pyspiceql import pyspiceql
 
 ID_LOOKUP = {
     "FC1" : "DAWN_FC1",
@@ -83,7 +83,7 @@ class DawnFcPds3NaifSpiceDriver(Framer, Pds3Label, NaifSpice, Driver):
         """
         if not hasattr(self, '_ephemeris_start_time'):
             sclock = self.spacecraft_clock_start_count
-            self._ephemeris_start_time = spice.scs2e(self.spacecraft_id, sclock)
+            self._ephemeris_start_time = pyspiceql.sclkToEt(self.spacecraft_id, sclock)
             self._ephemeris_start_time += 193.0 / 1000.0
         return self._ephemeris_start_time
 
@@ -118,7 +118,7 @@ class DawnFcPds3NaifSpiceDriver(Framer, Pds3Label, NaifSpice, Driver):
         : list
           Radial distortion coefficients
         """
-        return spice.gdpool('INS{}_RAD_DIST_COEFF'.format(self.ikid),0, 1).tolist()
+        return pyspiceql.getKernelVectorValue('INS{}_RAD_DIST_COEFF'.format(self.ikid)).tolist()
 
     # TODO: Update focal2pixel samples and lines to reflect the rectangular
     #       nature of dawn pixels
@@ -134,7 +134,7 @@ class DawnFcPds3NaifSpiceDriver(Framer, Pds3Label, NaifSpice, Driver):
           focal plane to detector samples
         """
         # Microns to mm
-        pixel_size = spice.gdpool('INS{}_PIXEL_SIZE'.format(self.ikid), 0, 1)[0] * 0.001
+        pixel_size = float(pyspiceql.getKernelVectorValue('INS{}_PIXEL_SIZE'.format(self.ikid))[0]) * .001
         return [0.0, 1/pixel_size, 0.0]
 
     @property
@@ -149,7 +149,7 @@ class DawnFcPds3NaifSpiceDriver(Framer, Pds3Label, NaifSpice, Driver):
           focal plane to detector lines
         """
         # Microns to mm
-        pixel_size = spice.gdpool('INS{}_PIXEL_SIZE'.format(self.ikid), 0, 1)[0] * 0.001
+        pixel_size = float(pyspiceql.getKernelVectorValue('INS{}_PIXEL_SIZE'.format(self.ikid))[0]) * .001
         return [0.0, 0.0, 1/pixel_size]
 
     @property
@@ -180,7 +180,7 @@ class DawnFcPds3NaifSpiceDriver(Framer, Pds3Label, NaifSpice, Driver):
         : float
           center detector sample
         """
-        return float(spice.gdpool('INS{}_CCD_CENTER'.format(self.ikid), 0, 2)[0]) + 0.5
+        return float(pyspiceql.getKernelVectorValue('INS{}_CCD_CENTER'.format(self.ikid))[0]) + 0.5
 
     @property
     def detector_center_line(self):
@@ -198,4 +198,4 @@ class DawnFcPds3NaifSpiceDriver(Framer, Pds3Label, NaifSpice, Driver):
         : float
           center detector line
         """
-        return float(spice.gdpool('INS{}_CCD_CENTER'.format(self.ikid), 0, 2)[1]) + 0.5
+        return float(pyspiceql.getKernelVectorValue('INS{}_CCD_CENTER'.format(self.ikid))[1]) + 0.5
diff --git a/ale/drivers/galileo_drivers.py b/ale/drivers/galileo_drivers.py
index c4b2d34..4a7cab4 100644
--- a/ale/drivers/galileo_drivers.py
+++ b/ale/drivers/galileo_drivers.py
@@ -1,13 +1,12 @@
 import datetime
 
-import spiceypy as spice
-
 import ale
 from ale.base.data_naif import NaifSpice
 from ale.base.label_isis import IsisLabel
 from ale.base.type_sensor import Framer
 from ale.base.type_distortion import RadialDistortion
 from ale.base.base import Driver
+from pyspiceql import pyspiceql
 
 ssi_id_lookup = {
     "SOLID STATE IMAGING SYSTEM" : "GLL_SSI_PLATFORM"
@@ -62,8 +61,7 @@ class GalileoSsiIsisLabelNaifSpiceDriver(Framer, IsisLabel, NaifSpice, RadialDis
             key_str = "_K1_COVER"
         else:
             key_str = "_K1"
-        k1 = spice.gdpool("INS" + str(self.ikid) + key_str, 0, 1);
-        return k1
+        return pyspiceql.getKernelVectorValue("INS" + str(self.ikid) + key_str)
 
     @property
     def naif_keywords(self):
@@ -76,7 +74,7 @@ class GalileoSsiIsisLabelNaifSpiceDriver(Framer, IsisLabel, NaifSpice, RadialDis
           Dictionary of keywords and values that ISIS creates and attaches to the label
         """
         key = "INS" + str(self.ikid) + "_FOCAL_LENGTH_COVER";
-        return {**super().naif_keywords, key: spice.gdpool(key, 0, 1)}
+        return {**super().naif_keywords, key: pyspiceql.getKernelStringValue(key)}
 
     @property
     def ephemeris_start_time(self):
@@ -88,7 +86,7 @@ class GalileoSsiIsisLabelNaifSpiceDriver(Framer, IsisLabel, NaifSpice, RadialDis
         : float
           start time
         """
-        return spice.str2et(self.utc_start_time.strftime("%Y-%m-%d %H:%M:%S.%f"))
+        return pyspiceql.utc2et(self.utc_start_time)
 
     @property
     def center_ephemeris_time(self):
diff --git a/ale/drivers/hayabusa2_drivers.py b/ale/drivers/hayabusa2_drivers.py
index d2ab85f..a392a5e 100644
--- a/ale/drivers/hayabusa2_drivers.py
+++ b/ale/drivers/hayabusa2_drivers.py
@@ -1,5 +1,3 @@
-import spiceypy as spice
-
 import ale
 from ale.base.data_naif import NaifSpice
 from ale.base.label_isis import IsisLabel
diff --git a/ale/drivers/lro_drivers.py b/ale/drivers/lro_drivers.py
index 80a72af..bd68da5 100644
--- a/ale/drivers/lro_drivers.py
+++ b/ale/drivers/lro_drivers.py
@@ -5,6 +5,7 @@ import pvl
 import spiceypy as spice
 from glob import glob
 
+from pyspiceql import pyspiceql
 from ale.util import get_metakernels, query_kernel_pool
 from ale.base import Driver
 from ale.base.data_naif import NaifSpice
@@ -97,7 +98,7 @@ class LroLrocNacPds3LabelNaifSpiceDriver(LineScanner, NaifSpice, Pds3Label, Driv
         : list
           Radial distortion coefficients. There is only one coefficient for LROC NAC l/r
         """
-        return spice.gdpool('INS{}_OD_K'.format(self.ikid), 0, 1).tolist()
+        return pyspiceql.getKernelVectorValue('INS{}_OD_K'.format(self.ikid)).tolist()
 
     @property
     def light_time_correction(self):
@@ -143,7 +144,7 @@ class LroLrocNacPds3LabelNaifSpiceDriver(LineScanner, NaifSpice, Pds3Label, Driv
         : list<double>
           focal plane to detector lines
         """
-        focal2pixel_lines = np.array(list(spice.gdpool('INS{}_ITRANSL'.format(self.ikid), 0, 3))) / self.sampling_factor
+        focal2pixel_lines = np.array(list(pyspiceql.getKernelVectorValue('INS{}_ITRANSL'.format(self.ikid)))) / self.sampling_factor
         if self.spacecraft_direction < 0:
             return -focal2pixel_lines
         else:
@@ -161,7 +162,7 @@ class LroLrocNacPds3LabelNaifSpiceDriver(LineScanner, NaifSpice, Pds3Label, Driv
         : double
           Starting ephemeris time of the image
         """
-        start_time = spice.scs2e(self.spacecraft_id, self.label['LRO:SPACECRAFT_CLOCK_PREROLL_COUNT'])
+        start_time = pyspiceql.sclkToEt(self.spacecraft_id, self.label['LRO:SPACECRAFT_CLOCK_PREROLL_COUNT'])
         return start_time + self.constant_time_offset + self.additional_preroll * self.exposure_duration
 
     @property
@@ -267,9 +268,10 @@ class LroLrocNacPds3LabelNaifSpiceDriver(LineScanner, NaifSpice, Pds3Label, Driv
                     X value of the first velocity relative to the sensor
         """
         frame_chain = self.frame_chain
-        lro_bus_id = spice.bods2c('LRO_SC_BUS')
+        lro_bus_id = pyspiceql.Kernel_translateFrame('LRO_SC_BUS')
         time = self.ephemeris_start_time
-        state, _ = spice.spkezr(self.spacecraft_name, time, 'J2000', 'None', self.target_name)
+        lt_state = pyspiceql.getTargetState(time, self.target_name, self.spacecraft_name, 'J2000', 'None')
+        state = lt_state.starg
         position = state[:3]
         velocity = state[3:]
         rotation = frame_chain.compute_rotation(1, lro_bus_id)
@@ -338,7 +340,7 @@ class LroLrocNacIsisLabelNaifSpiceDriver(LineScanner, NaifSpice, IsisLabel, Driv
         : list
           Radial distortion coefficients. There is only one coefficient for LROC NAC l/r
         """
-        return spice.gdpool('INS{}_OD_K'.format(self.ikid), 0, 1).tolist()
+        return pyspiceql.getKernelVectorValue('INS{}_OD_K'.format(self.ikid)).tolist()
 
     @property
     def light_time_correction(self):
@@ -384,7 +386,7 @@ class LroLrocNacIsisLabelNaifSpiceDriver(LineScanner, NaifSpice, IsisLabel, Driv
         : double
           Starting ephemeris time of the image
         """
-        start_time = spice.scs2e(self.spacecraft_id, self.label['IsisCube']['Instrument']['SpacecraftClockPrerollCount'])
+        start_time = pyspiceql.sclkToEt(self.spacecraft_id, self.label['IsisCube']['Instrument']['SpacecraftClockPrerollCount'])
         return start_time + self.constant_time_offset + self.additional_preroll * self.exposure_duration
 
     @property
@@ -412,7 +414,7 @@ class LroLrocNacIsisLabelNaifSpiceDriver(LineScanner, NaifSpice, IsisLabel, Driv
         : list<double>
           focal plane to detector lines
         """
-        focal2pixel_lines = np.array(list(spice.gdpool('INS{}_ITRANSL'.format(self.ikid), 0, 3))) / self.sampling_factor
+        focal2pixel_lines = np.array(list(pyspiceql.getKernelVectorValue('INS{}_ITRANSL'.format(self.ikid)))) / self.sampling_factor
         if self.spacecraft_direction < 0:
             return -focal2pixel_lines
         else:
@@ -503,9 +505,10 @@ class LroLrocNacIsisLabelNaifSpiceDriver(LineScanner, NaifSpice, IsisLabel, Driv
                     X value of the first velocity relative to the sensor
         """
         frame_chain = self.frame_chain
-        lro_bus_id = spice.bods2c('LRO_SC_BUS')
+        lro_bus_id = pyspiceql.Kernel_translateFrame('LRO_SC_BUS')
         time = self.ephemeris_start_time
-        state, _ = spice.spkezr(self.spacecraft_name, time, 'J2000', 'None', self.target_name)
+        lt_state = pyspiceql.getTargetState(time, self.target_name, self.spacecraft_name, 'J2000', 'None')
+        state = lt_state.starg
         position = state[:3]
         velocity = state[3:]
         rotation = frame_chain.compute_rotation(1, lro_bus_id)
@@ -742,7 +745,8 @@ class LroMiniRfIsisLabelNaifSpiceDriver(Radar, NaifSpice, IsisLabel, Driver):
 
         # Get float value of frequency in GHz
         frequency = self.label['IsisCube']['Instrument']['Frequency'].value
-        wavelength = spice.clight() / frequency / 1000.0
+        #wavelength = spice.clight() / frequency / 1000.0
+        wavelength = 299792.458 / frequency / 1000.0
         return wavelength
 
     @property
@@ -800,7 +804,7 @@ class LroMiniRfIsisLabelNaifSpiceDriver(Radar, NaifSpice, IsisLabel, Driver):
           times for range conversion coefficients
         """
         range_coefficients_utc = self.label['IsisCube']['Instrument']['RangeCoefficientSet']
-        range_coefficients_et = [spice.str2et(elt[0]) for elt in range_coefficients_utc]
+        range_coefficients_et = [pyspiceql.utcToEt(elt[0]) for elt in range_coefficients_utc]
         return range_coefficients_et
 
 
@@ -814,7 +818,7 @@ class LroMiniRfIsisLabelNaifSpiceDriver(Radar, NaifSpice, IsisLabel, Driver):
         : float
           start time
         """
-        return spice.str2et(self.utc_start_time.strftime("%Y-%m-%d %H:%M:%S.%f"))
+        return pyspiceql.utcToEt(self.utc_start_time.strftime("%Y-%m-%d %H:%M:%S.%f"))
 
     @property
     def ephemeris_stop_time(self):
@@ -826,7 +830,7 @@ class LroMiniRfIsisLabelNaifSpiceDriver(Radar, NaifSpice, IsisLabel, Driver):
         : float
           stop time
         """
-        return spice.str2et(self.utc_stop_time.strftime("%Y-%m-%d %H:%M:%S.%f"))
+        return pyspiceql.utcToEt(self.utc_stop_time.strftime("%Y-%m-%d %H:%M:%S.%f"))
 
     @property
     def look_direction(self):
@@ -947,7 +951,7 @@ class LroLrocWacIsisLabelIsisSpiceDriver(PushFrame, IsisLabel, IsisSpice, Radial
         ans = self.naif_keywords.get(key, None)
         if ans is None:
             raise Exception('Could not parse the distortion model coefficients using key: ' + key)
-        
+
         ans = [x * -1 for x in ans]
         return ans
 
@@ -1010,7 +1014,7 @@ class LroLrocWacIsisLabelIsisSpiceDriver(PushFrame, IsisLabel, IsisSpice, Radial
         if ans is None:
             raise Exception('Could not parse the focal length using key: ' + key)
         return ans
-    
+
     @property
     def detector_center_sample(self):
         """
@@ -1090,7 +1094,7 @@ class LroLrocWacIsisLabelNaifSpiceDriver(PushFrame, IsisLabel, NaifSpice, Radial
         """
         if not hasattr(self, '_ephemeris_start_time'):
             sclock = self.label['IsisCube']['Instrument']['SpacecraftClockStartCount']
-            self._ephemeris_start_time = spice.scs2e(self.spacecraft_id, sclock)
+            self._ephemeris_start_time = pyspiceql.sclkToEt(self.spacecraft_id, sclock)
         return self._ephemeris_start_time
 
 
@@ -1115,7 +1119,7 @@ class LroLrocWacIsisLabelNaifSpiceDriver(PushFrame, IsisLabel, NaifSpice, Radial
         : list
           Radial distortion coefficients.
         """
-        coeffs = spice.gdpool('INS{}_OD_K'.format(self.fikid), 0, 3).tolist()
+        coeffs = pyspiceql.getKernelVectorValue('INS{}_OD_K'.format(self.fikid)).tolist()
         coeffs = [x * -1 for x in coeffs]
         return coeffs
 
@@ -1251,7 +1255,7 @@ class LroLrocWacIsisLabelNaifSpiceDriver(PushFrame, IsisLabel, NaifSpice, Radial
         : list<double>
         detector to focal plane x
         """
-        return list(spice.gdpool('INS{}_TRANSX'.format(self.fikid), 0, 3))
+        return list(pyspiceql.getKernelVectorValue('INS{}_TRANSX'.format(self.fikid)))
 
 
     @property
@@ -1264,7 +1268,7 @@ class LroLrocWacIsisLabelNaifSpiceDriver(PushFrame, IsisLabel, NaifSpice, Radial
         : list<double>
         detector to focal plane y
         """
-        return list(spice.gdpool('INS{}_TRANSY'.format(self.fikid), 0, 3))
+        return list(pyspiceql.getKernelVectorValue('INS{}_TRANSY'.format(self.fikid)))
 
     @property
     def focal2pixel_lines(self):
@@ -1276,7 +1280,7 @@ class LroLrocWacIsisLabelNaifSpiceDriver(PushFrame, IsisLabel, NaifSpice, Radial
         : list<double>
           focal plane to detector lines
         """
-        return list(spice.gdpool('INS{}_ITRANSL'.format(self.fikid), 0, 3))
+        return list(pyspiceql.getKernelVectorValue('INS{}_ITRANSL'.format(self.fikid)))
 
     @property
     def focal2pixel_samples(self):
@@ -1288,7 +1292,7 @@ class LroLrocWacIsisLabelNaifSpiceDriver(PushFrame, IsisLabel, NaifSpice, Radial
         : list<double>
           focal plane to detector samples
         """
-        return list(spice.gdpool('INS{}_ITRANSS'.format(self.fikid), 0, 3))
+        return list(pyspiceql.getKernelVectorValue('INS{}_ITRANSS'.format(self.fikid)))
 
 
     @property
@@ -1301,7 +1305,7 @@ class LroLrocWacIsisLabelNaifSpiceDriver(PushFrame, IsisLabel, NaifSpice, Radial
         : int
           Zero based Detector line corresponding to the first image line
         """
-        offset = list(spice.gdpool('INS{}_FILTER_OFFSET'.format(self.fikid), 0, 3))
+        offset = list(pyspiceql.getKernelVectorValue('INS{}_FILTER_OFFSET'.format(self.fikid)))
         try:
             # If multiple items are present, use the first one
             offset = offset[0]
@@ -1321,7 +1325,7 @@ class LroLrocWacIsisLabelNaifSpiceDriver(PushFrame, IsisLabel, NaifSpice, Radial
         : float
           focal length
         """
-        return float(spice.gdpool('INS{}_FOCAL_LENGTH'.format(self.fikid), 0, 1)[0])
+        return float(pyspiceql.getKernelVectorValue('INS{}_FOCAL_LENGTH'.format(self.fikid))[0])
 
     @property
     def detector_center_sample(self):
@@ -1334,7 +1338,7 @@ class LroLrocWacIsisLabelNaifSpiceDriver(PushFrame, IsisLabel, NaifSpice, Radial
         : float
           Detector sample of the principal point
         """
-        return float(spice.gdpool('INS{}_BORESIGHT_SAMPLE'.format(self.fikid), 0, 1)[0]) - 0.5
+        return float(pyspiceql.getKernelVectorValue('INS{}_BORESIGHT_SAMPLE'.format(self.fikid))[0]) - 0.5
 
     @property
     def detector_center_line(self):
@@ -1347,4 +1351,4 @@ class LroLrocWacIsisLabelNaifSpiceDriver(PushFrame, IsisLabel, NaifSpice, Radial
         : float
           Detector line of the principal point
         """
-        return float(spice.gdpool('INS{}_BORESIGHT_LINE'.format(self.fikid), 0, 1)[0]) - 0.5
+        return float(pyspiceql.getKernelVectorValue('INS{}_BORESIGHT_LINE'.format(self.fikid))[0]) - 0.5
diff --git a/ale/drivers/mess_drivers.py b/ale/drivers/mess_drivers.py
index e537351..31df9fe 100644
--- a/ale/drivers/mess_drivers.py
+++ b/ale/drivers/mess_drivers.py
@@ -5,6 +5,7 @@ import pvl
 import spiceypy as spice
 import numpy as np
 
+from pyspiceql import pyspiceql
 from ale.base import Driver
 from ale.base.data_naif import NaifSpice
 from ale.base.label_pds3 import Pds3Label
@@ -164,7 +165,7 @@ class MessengerMdisPds3NaifSpiceDriver(Framer, Pds3Label, NaifSpice, NoDistortio
         : double
           focal length in meters
         """
-        coeffs = spice.gdpool('INS{}_FL_TEMP_COEFFS'.format(self.fikid), 0, 6)
+        coeffs = pyspiceql.getKernelVectorValue('INS{}_FL_TEMP_COEFFS'.format(self.fikid))
 
         # 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
@@ -246,7 +247,7 @@ class MessengerMdisPds3NaifSpiceDriver(Framer, Pds3Label, NaifSpice, NoDistortio
         -------
         : float pixel size
         """
-        return spice.gdpool('INS{}_PIXEL_PITCH'.format(self.ikid), 0, 1)
+        return pyspiceql.getKernelStringValue('INS{}_PIXEL_PITCH'.format(self.ikid))
 
 
 class MessengerMdisIsisLabelNaifSpiceDriver(IsisLabel, NaifSpice, Framer, NoDistortion, Driver):
@@ -303,7 +304,7 @@ class MessengerMdisIsisLabelNaifSpiceDriver(IsisLabel, NaifSpice, Framer, NoDist
         """
         if not hasattr(self, '_ephemeris_start_time'):
             sclock = self.spacecraft_clock_start_count
-            self._starting_ephemeris_time = spice.scs2e(self.spacecraft_id, sclock)
+            self._starting_ephemeris_time = pyspiceql.sclkToEt(self.spacecraft_id, sclock)
         return self._starting_ephemeris_time
 
     @property
@@ -360,7 +361,7 @@ class MessengerMdisIsisLabelNaifSpiceDriver(IsisLabel, NaifSpice, Framer, NoDist
         : double
           focal length in meters
         """
-        coeffs = spice.gdpool('INS{}_FL_TEMP_COEFFS'.format(self.fikid), 0, 6)
+        coeffs = pyspiceql.getKernelVectorValue('INS{}_FL_TEMP_COEFFS'.format(self.fikid))
         # 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])
@@ -383,7 +384,7 @@ class MessengerMdisIsisLabelNaifSpiceDriver(IsisLabel, NaifSpice, Framer, NoDist
         : float
           detector center sample
         """
-        return float(spice.gdpool('INS{}_CCD_CENTER'.format(self.ikid), 0, 3)[0]) - 0.5
+        return float(pyspiceql.getKernelVectorValue('INS{}_CCD_CENTER'.format(self.ikid)[0])) - 0.5
 
 
     @property
@@ -401,7 +402,7 @@ class MessengerMdisIsisLabelNaifSpiceDriver(IsisLabel, NaifSpice, Framer, NoDist
         : float
           detector center line
         """
-        return float(spice.gdpool('INS{}_CCD_CENTER'.format(self.ikid), 0, 3)[1]) - 0.5
+        return float(pyspiceql.getKernelVectorValue('INS{}_CCD_CENTER'.format(self.ikid)[1])) - 0.5
 
     @property
     def sensor_model_version(self):
@@ -423,7 +424,7 @@ class MessengerMdisIsisLabelNaifSpiceDriver(IsisLabel, NaifSpice, Framer, NoDist
         -------
         : float pixel size
         """
-        return spice.gdpool('INS{}_PIXEL_PITCH'.format(self.ikid), 0, 1)
+        return pyspiceql.getKernelStringValue('INS{}_PIXEL_PITCH'.format(self.ikid))
 
     @property
     def sampling_factor(self):
diff --git a/ale/drivers/mex_drivers.py b/ale/drivers/mex_drivers.py
index fde25ff..a33e991 100644
--- a/ale/drivers/mex_drivers.py
+++ b/ale/drivers/mex_drivers.py
@@ -8,6 +8,7 @@ import struct
 import spiceypy as spice
 import warnings
 
+from pyspiceql import pyspiceql
 from ale.base import Driver
 from ale.base.data_isis import read_table_data
 from ale.base.data_isis import parse_table
@@ -115,7 +116,7 @@ class MexHrscPds3NaifSpiceDriver(LineScanner, Pds3Label, NaifSpice, RadialDistor
         : int
           Naif ID used to for identifying the instrument in Spice kernels
         """
-        return spice.bods2c("MEX_HRSC_HEAD")
+        return pyspiceql.Kernel_translateFrame("MEX_HRSC_HEAD")
 
 
     @property
@@ -133,7 +134,7 @@ class MexHrscPds3NaifSpiceDriver(LineScanner, Pds3Label, NaifSpice, RadialDistor
         : int
           Naif ID code used in calculating focal length
         """
-        return spice.bods2c(self.instrument_id)
+        return pyspiceql.Kernel_translateFrame(self.instrument_id)
 
 
     # TODO Since HRSC has different frames based on filters, need to check that
@@ -483,7 +484,7 @@ class MexHrscPds3NaifSpiceDriver(LineScanner, Pds3Label, NaifSpice, RadialDistor
 
 
 class MexHrscIsisLabelNaifSpiceDriver(LineScanner, IsisLabel, NaifSpice, RadialDistortion, Driver):
-  
+
   @property
   def instrument_id(self):
       """
@@ -611,7 +612,7 @@ class MexHrscIsisLabelNaifSpiceDriver(LineScanner, IsisLabel, NaifSpice, RadialD
       : int
         Naif ID used to for identifying the instrument in Spice kernels
       """
-      return spice.bods2c("MEX_HRSC_HEAD")
+      return pyspiceql.Kernel_translateFrame("MEX_HRSC_HEAD")
 
 
   @property
@@ -629,7 +630,7 @@ class MexHrscIsisLabelNaifSpiceDriver(LineScanner, IsisLabel, NaifSpice, RadialD
       : int
         Naif ID code used in calculating focal length
       """
-      return spice.bods2c(self.instrument_id)
+      return pyspiceql.Kernel_translateFrame(self.instrument_id)
 
   @property
   def focal2pixel_lines(self):
@@ -658,7 +659,7 @@ class MexHrscIsisLabelNaifSpiceDriver(LineScanner, IsisLabel, NaifSpice, RadialD
 
 class MexSrcPds3NaifSpiceDriver(Framer, Pds3Label, NaifSpice, RadialDistortion, Driver):
     """
-    Driver for a PDS3 Mars Express (Mex) High Resolution Stereo Camera (HRSC) - Super Resolution 
+    Driver for a PDS3 Mars Express (Mex) High Resolution Stereo Camera (HRSC) - Super Resolution
     Channel (SRC) image.
     """
 
@@ -678,14 +679,14 @@ class MexSrcPds3NaifSpiceDriver(Framer, Pds3Label, NaifSpice, RadialDistortion,
     @property
     def ikid(self):
         """
-        Returns the Naif ID code for HRSC SRC. 
+        Returns the Naif ID code for HRSC SRC.
 
         Returns
         -------
         : int
           Naif ID used to for identifying the instrument in Spice kernels
         """
-        return spice.bods2c("MEX_HRSC_SRC")
+        return pyspiceql.Kernel_translateFrame("MEX_HRSC_HEAD")
 
 
     @property
diff --git a/ale/drivers/mro_drivers.py b/ale/drivers/mro_drivers.py
index 5b481ed..710a957 100644
--- a/ale/drivers/mro_drivers.py
+++ b/ale/drivers/mro_drivers.py
@@ -1,5 +1,6 @@
 import spiceypy as spice
 
+from pyspiceql import pyspiceql
 from ale.base import Driver
 from ale.base.data_naif import NaifSpice
 from ale.base.data_isis import IsisSpice
@@ -357,7 +358,7 @@ class MroCtxIsisLabelNaifSpiceDriver(LineScanner, IsisLabel, NaifSpice, RadialDi
         """
         if not hasattr(self, '_ephemeris_start_time'):
             sclock = self.label['IsisCube']['Instrument']['SpacecraftClockCount']
-            self._ephemeris_start_time = spice.scs2e(self.spacecraft_id, sclock)
+            self._ephemeris_start_time = pyspiceql.sclkToEt(self.spacecraft_id, sclock)
         return self._ephemeris_start_time
 
     @property
diff --git a/ale/drivers/nh_drivers.py b/ale/drivers/nh_drivers.py
index 4fd7eb4..8fae575 100644
--- a/ale/drivers/nh_drivers.py
+++ b/ale/drivers/nh_drivers.py
@@ -4,6 +4,7 @@ import pvl
 
 from ale import util
 
+from pyspiceql import pyspiceql
 from ale.base import Driver
 from ale.base.type_distortion import NoDistortion, LegendreDistortion
 from ale.base.data_naif import NaifSpice
@@ -67,7 +68,7 @@ class NewHorizonsLorriIsisLabelNaifSpiceDriver(Framer, IsisLabel, NaifSpice, NoD
         list :
             The center of the CCD formatted as line, sample
         """
-        return float(spice.gdpool('INS{}_BORESIGHT'.format(self.ikid), 0, 3)[0])
+        return float(pyspiceql.getKernelVectorValue('INS{}_BORESIGHT'.format(self.ikid))[0])
 
     @property
     def detector_center_sample(self):
@@ -81,7 +82,7 @@ class NewHorizonsLorriIsisLabelNaifSpiceDriver(Framer, IsisLabel, NaifSpice, NoD
         list :
             The center of the CCD formatted as line, sample
         """
-        return float(spice.gdpool('INS{}_BORESIGHT'.format(self.ikid), 0, 3)[1])
+        return float(pyspiceql.getKernelVectorValue('INS{}_BORESIGHT'.format(self.ikid))[1])
 
     @property
     def sensor_name(self):
diff --git a/ale/drivers/selene_drivers.py b/ale/drivers/selene_drivers.py
index e73e92d..0892c2d 100644
--- a/ale/drivers/selene_drivers.py
+++ b/ale/drivers/selene_drivers.py
@@ -1,4 +1,5 @@
 import spiceypy as spice
+from pyspiceql import pyspiceql
 
 from ale.base import Driver
 from ale.base.data_naif import NaifSpice
@@ -243,9 +244,9 @@ class KaguyaTcPds3NaifSpiceDriver(LineScanner, Pds3Label, NaifSpice, KaguyaSelen
           ikid of LISM_TC1 or LISM_TC2
         """
         if not hasattr(self, "_ikid"):
-          self._ikid = spice.bods2c("LISM_{}".format(super().instrument_id))
+          return pyspiceql.Kernel_translateFrame("LISM_{}".format(super().instrument_id))
         return self._ikid
-
+        
     @property
     def spacecraft_name(self):
         """
@@ -300,7 +301,7 @@ class KaguyaTcPds3NaifSpiceDriver(LineScanner, Pds3Label, NaifSpice, KaguyaSelen
           ephemeris start time of the image
         """
         if not hasattr(self, "_ephemeris_start_time"):
-          self._ephemeris_start_time = spice.sct2e(self.spacecraft_id, self.spacecraft_clock_start_count)
+          return pyspiceql.sclkToEt(self.spacecraft_id, self.spacecraft_clock_start_count)
         return self._ephemeris_start_time
 
     @property
@@ -317,7 +318,7 @@ class KaguyaTcPds3NaifSpiceDriver(LineScanner, Pds3Label, NaifSpice, KaguyaSelen
           focal plane to detector samples
         """
         if not hasattr(self, "_focal2pixel_samples"):
-          pixel_size = spice.gdpool('INS{}_PIXEL_SIZE'.format(self.ikid), 0, 1)[0]
+          pixel_size = pyspiceql.getKernelVectorValue('INS{}_PIXEL_SIZE'.format(self.ikid)[0])
           self._focal2pixel_samples = [0, 0, -1/pixel_size]
         return self._focal2pixel_samples
 
@@ -335,7 +336,7 @@ class KaguyaTcPds3NaifSpiceDriver(LineScanner, Pds3Label, NaifSpice, KaguyaSelen
           focal plane to detector lines
         """
         if not hasattr(self, "_focal2pixel_lines"):
-          pixel_size = spice.gdpool('INS{}_PIXEL_SIZE'.format(self.ikid), 0, 1)[0]
+          pixel_size = pyspiceql.getKernelVectorValue('INS{}_PIXEL_SIZE'.format(self.ikid)[0])
           self._focal2pixel_lines = [0, 1/pixel_size, 0]
         return self._focal2pixel_lines
 
@@ -352,7 +353,7 @@ class KaguyaTcPds3NaifSpiceDriver(LineScanner, Pds3Label, NaifSpice, KaguyaSelen
           Optical distortion x coefficients
         """
         if not hasattr(self, "__odkx"):
-          self.__odkx = spice.gdpool('INS{}_DISTORTION_COEF_X'.format(self.ikid),0, 4).tolist()
+          self.__odkx = pyspiceql.getKernelVectorValue('INS{}_DISTORTION_COEF_X'.format(self.ikid)).tolist()
         return self.__odkx
 
     @property
@@ -368,7 +369,7 @@ class KaguyaTcPds3NaifSpiceDriver(LineScanner, Pds3Label, NaifSpice, KaguyaSelen
           Optical distortion y coefficients
         """
         if not hasattr(self, "__odky"):
-          self.__odky = spice.gdpool('INS{}_DISTORTION_COEF_Y'.format(self.ikid), 0, 4).tolist()
+          self.__odky = pyspiceql.getKernelVectorValue('INS{}_DISTORTION_COEF_Y'.format(self.ikid)).tolist()
         return self.__odky
 
     @property
@@ -384,7 +385,7 @@ class KaguyaTcPds3NaifSpiceDriver(LineScanner, Pds3Label, NaifSpice, KaguyaSelen
           Boresight focal plane x coordinate
         """
         if not hasattr(self, "_boresight_x"):
-          self._boresight_x = spice.gdpool('INS{}_BORESIGHT'.format(self.ikid), 0, 1)[0]
+          self._boresight_x = pyspiceql.getKernelVectorValue('INS{}_BORESIGHT'.format(self.ikid))[0]
         return self._boresight_x
 
     @property
@@ -400,7 +401,11 @@ class KaguyaTcPds3NaifSpiceDriver(LineScanner, Pds3Label, NaifSpice, KaguyaSelen
           Boresight focal plane x coordinate
         """
         if not hasattr(self, "_boresight_y"):
-          self._boresight_y = spice.gdpool('INS{}_BORESIGHT'.format(self.ikid), 1, 1)[0]
+          # TODO is this the right way to access this value?
+          # original:
+          #   return spice.gdpool('INS{}_BORESIGHT'.format(self.ikid), 1, 1)[0]
+
+          self._boresight_y = pyspiceql.getKernelVectorValue('INS{}_BORESIGHT'.format(self.ikid))[1]
         return self._boresight_y
 
     @property
@@ -426,6 +431,46 @@ class KaguyaTcPds3NaifSpiceDriver(LineScanner, Pds3Label, NaifSpice, KaguyaSelen
         except:
             return self.label['CORRECTED_SAMPLING_INTERVAL'].value * 0.001  # Scale to seconds
 
+    @property
+    def usgscsm_distortion_model(self):
+        """
+        Kaguya uses a unique radial distortion model so we need to overwrite the
+        method packing the distortion model into the ISD.
+
+        from the IK:
+
+        Line-of-sight vector of pixel no. n can be expressed as below.
+
+        Distortion coefficients information:
+        INS<INSTID>_DISTORTION_COEF_X  = ( a0, a1, a2, a3)
+        INS<INSTID>_DISTORTION_COEF_Y  = ( b0, b1, b2, b3),
+
+        Distance r from the center:
+        r = - (n - INS<INSTID>_CENTER) * INS<INSTID>_PIXEL_SIZE.
+
+        Line-of-sight vector v is calculated as
+        v[X] = INS<INSTID>BORESIGHT[X] + a0 + a1*r + a2*r^2 + a3*r^3 ,
+        v[Y] = INS<INSTID>BORESIGHT[Y] + r+a0 + a1*r +a2*r^2 + a3*r^3 ,
+        v[Z] = INS<INSTID>BORESIGHT[Z]
+
+        Expects odkx and odky to be defined. These should be a list of optical
+        distortion x and y coefficients respectively.
+
+        Returns
+        -------
+        : dict
+          radial distortion model
+
+        """
+        return {
+            "kaguyalism": {
+                "x" : self._odkx,
+                "y" : self._odky,
+                "boresight_x" : self.boresight_x,
+                "boresight_y" : self.boresight_y
+            }
+        }
+
     @property
     def detector_start_sample(self):
         """
@@ -930,7 +975,7 @@ class KaguyaMiPds3NaifSpiceDriver(LineScanner, Pds3Label, NaifSpice, KaguyaSelen
           ephemeris start time of the image
         """
         if not hasattr(self, "_ephemeris_start_time"):
-          self._ephemeris_start_time = spice.scs2e(self.spacecraft_id, self.spacecraft_clock_start_count)
+          self._ephemeris_start_time = pyspiceql.sclkToEt(self.spacecraft_id, self.spacecraft_clock_start_count)
         return self._ephemeris_start_time
 
     @property
@@ -948,7 +993,7 @@ class KaguyaMiPds3NaifSpiceDriver(LineScanner, Pds3Label, NaifSpice, KaguyaSelen
           The detector line of the principle point
         """
         if not hasattr(self, "_detector_center_line"):
-          self._detector_center_line = spice.gdpool('INS{}_CENTER'.format(self.ikid), 0, 2)[1] - 0.5
+          self._detector_center_line = pyspiceql.getKernelVectorValue('INS{}_CENTER'.format(self.ikid))[1] - 0.5
         return self._detector_center_line
 
     @property
@@ -966,7 +1011,7 @@ class KaguyaMiPds3NaifSpiceDriver(LineScanner, Pds3Label, NaifSpice, KaguyaSelen
           The detector sample of the principle point
         """
         if not hasattr(self, "_detector_center_sample"):
-          self._detector_center_sample = spice.gdpool('INS{}_CENTER'.format(self.ikid), 0, 2)[0] - 0.5
+          self._detector_center_sample = pyspiceql.getKernelVectorValue('INS{}_CENTER'.format(self.ikid))[0] - 0.5
         return self._detector_center_sample
 
     @property
@@ -983,7 +1028,7 @@ class KaguyaMiPds3NaifSpiceDriver(LineScanner, Pds3Label, NaifSpice, KaguyaSelen
           focal plane to detector samples
         """
         if not hasattr(self, "_focal2pixel_samples"):
-          pixel_size = spice.gdpool('INS{}_PIXEL_SIZE'.format(self.ikid), 0, 1)[0]
+          pixel_size = pyspiceql.getKernelVectorValue('INS{}_PIXEL_SIZE'.format(self.ikid))[0]
           self._focal2pixel_samples = [0, 0, -1/pixel_size]
         return self._focal2pixel_samples
 
@@ -1001,7 +1046,7 @@ class KaguyaMiPds3NaifSpiceDriver(LineScanner, Pds3Label, NaifSpice, KaguyaSelen
           focal plane to detector lines
         """
         if not hasattr(self, "_focal2pixel_lines"):
-          pixel_size = spice.gdpool('INS{}_PIXEL_SIZE'.format(self.ikid), 0, 1)[0]
+          pixel_size = pyspiceql.getKernelVectorValue('INS{}_PIXEL_SIZE'.format(self.ikid))[0]
           self._focal2pixel_lines = [0, 1/pixel_size, 0]
         return self._focal2pixel_lines
 
@@ -1018,7 +1063,7 @@ class KaguyaMiPds3NaifSpiceDriver(LineScanner, Pds3Label, NaifSpice, KaguyaSelen
           Optical distortion x coefficients
         """
         if not hasattr(self, "__odkx"):
-          self.__odkx = spice.gdpool('INS{}_DISTORTION_COEF_X'.format(self.ikid),0, 4).tolist()
+          self.__odkx = pyspiceql.getKernelVectorValue('INS{}_DISTORTION_COEF_X'.format(self.ikid),0, 4).tolist()
         return self.__odkx
 
     @property
@@ -1034,7 +1079,7 @@ class KaguyaMiPds3NaifSpiceDriver(LineScanner, Pds3Label, NaifSpice, KaguyaSelen
           Optical distortion y coefficients
         """
         if not hasattr(self, "__odky"):
-          self.__odky = spice.gdpool('INS{}_DISTORTION_COEF_Y'.format(self.ikid), 0, 4).tolist()
+          self.__odky = pyspiceql.getKernelVectorValue('INS{}_DISTORTION_COEF_Y'.format(self.ikid),0, 4).tolist()
         return self.__odky
 
     @property
@@ -1050,7 +1095,7 @@ class KaguyaMiPds3NaifSpiceDriver(LineScanner, Pds3Label, NaifSpice, KaguyaSelen
           Boresight focal plane x coordinate
         """
         if not hasattr(self, "_boresight_x"):
-          self._boresight_x = spice.gdpool('INS{}_BORESIGHT'.format(self.ikid), 0, 1)[0]
+          self._boresight_x = pyspiceql.getKernelVectorValue('INS{}_BORESIGHT'.format(self.ikid))[0]
         return self._boresight_x
 
     @property
@@ -1066,7 +1111,7 @@ class KaguyaMiPds3NaifSpiceDriver(LineScanner, Pds3Label, NaifSpice, KaguyaSelen
           Boresight focal plane x coordinate
         """
         if not hasattr(self, "_boresight_y"):
-          self._boresight_y = spice.gdpool('INS{}_BORESIGHT'.format(self.ikid), 1, 1)[0]
+          self._boresight_y = pyspiceql.getKernelVectorValue('INS{}_BORESIGHT'.format(self.ikid))[1]
         return self._boresight_y
 
     @property
@@ -1092,6 +1137,46 @@ class KaguyaMiPds3NaifSpiceDriver(LineScanner, Pds3Label, NaifSpice, KaguyaSelen
         except:
             return self.label['CORRECTED_SAMPLING_INTERVAL'].value * 0.001  # Scale to seconds
 
+    @property
+    def usgscsm_distortion_model(self):
+        """
+        Kaguya uses a unique radial distortion model so we need to overwrite the
+        method packing the distortion model into the ISD.
+
+        from the IK:
+
+        Line-of-sight vector of pixel no. n can be expressed as below.
+
+        Distortion coefficients information:
+        INS<INSTID>_DISTORTION_COEF_X  = ( a0, a1, a2, a3)
+        INS<INSTID>_DISTORTION_COEF_Y  = ( b0, b1, b2, b3),
+
+        Distance r from the center:
+        r = - (n - INS<INSTID>_CENTER) * INS<INSTID>_PIXEL_SIZE.
+
+        Line-of-sight vector v is calculated as
+        v[X] = INS<INSTID>BORESIGHT[X] + a0 + a1*r + a2*r^2 + a3*r^3 ,
+        v[Y] = INS<INSTID>BORESIGHT[Y] + r+a0 + a1*r +a2*r^2 + a3*r^3 ,
+        v[Z] = INS<INSTID>BORESIGHT[Z]
+
+        Expects odkx and odky to be defined. These should be a list of optical
+        distortion x and y coefficients respectively.
+
+        Returns
+        -------
+        : dict
+          radial distortion model
+
+        """
+        return {
+            "kaguyalism": {
+                "x" : self._odkx,
+                "y" : self._odky,
+                "boresight_x" : self.boresight_x,
+                "boresight_y" : self.boresight_y
+            }
+        }
+
     @property
     def sensor_model_version(self):
         """
@@ -1192,7 +1277,7 @@ class KaguyaMiIsisLabelNaifSpiceDriver(LineScanner, NaifSpice, IsisLabel, Kaguya
           ephemeris start time of the image
         """
         if not hasattr(self, "_ephemeris_start_time"):
-          self._ephemeris_start_time = spice.sct2e(self.spacecraft_id, self.spacecraft_clock_start_count)
+          self._ephemeris_start_time = pyspiceql.sclkToEt(self.spacecraft_id, self.spacecraft_clock_start_count)
         return self._ephemeris_start_time
 
     @property
@@ -1207,7 +1292,7 @@ class KaguyaMiIsisLabelNaifSpiceDriver(LineScanner, NaifSpice, IsisLabel, Kaguya
           ephemeris start time of the image
         """
         if not hasattr(self, "_ephemeris_stop_time"):
-          self._ephemeris_stop_time = spice.sct2e(self.spacecraft_id, self.spacecraft_clock_stop_count)
+          self._ephemeris_stop_time = pyspiceql.sclkToEt(self.spacecraft_id, self.spacecraft_clock_stop_count)
         return self._ephemeris_stop_time
 
     @property
@@ -1242,7 +1327,7 @@ class KaguyaMiIsisLabelNaifSpiceDriver(LineScanner, NaifSpice, IsisLabel, Kaguya
           The detector line of the principle point
         """
         if not hasattr(self, "_detector_center_line"):
-          self._detector_center_line = spice.gdpool('INS{}_CENTER'.format(self.ikid), 0, 2)[1] - 0.5
+          self._detector_center_line = pyspiceql.getKernelVectorValue('INS{}_CENTER'.format(self.ikid))[1] - 0.5
         return self._detector_center_line
 
     @property
@@ -1260,7 +1345,7 @@ class KaguyaMiIsisLabelNaifSpiceDriver(LineScanner, NaifSpice, IsisLabel, Kaguya
           The detector sample of the principle point
         """
         if not hasattr(self, "_detector_center_sample"):
-          self._detector_center_sample = spice.gdpool('INS{}_CENTER'.format(self.ikid), 0, 2)[0] - 0.5
+          self._detector_center_sample = pyspiceql.getKernelVectorValue('INS{}_CENTER'.format(self.ikid))[0] - 0.5
         return self._detector_center_sample
 
     @property
@@ -1276,7 +1361,7 @@ class KaguyaMiIsisLabelNaifSpiceDriver(LineScanner, NaifSpice, IsisLabel, Kaguya
           Optical distortion x coefficients
         """
         if not hasattr(self, "__odkx"):
-          self.__odkx = spice.gdpool('INS{}_DISTORTION_COEF_X'.format(self.ikid),0, 4).tolist()
+          self.__odkx = pyspiceql.getKernelVectorValue('INS{}_DISTORTION_COEF_X'.format(self.ikid)).tolist()
         return self.__odkx
 
     @property
@@ -1292,7 +1377,7 @@ class KaguyaMiIsisLabelNaifSpiceDriver(LineScanner, NaifSpice, IsisLabel, Kaguya
           Optical distortion y coefficients
         """
         if not hasattr(self, "__odky"):
-          self.__odky = spice.gdpool('INS{}_DISTORTION_COEF_Y'.format(self.ikid), 0, 4).tolist()
+          self.__odky = pyspiceql.getKernelVectorValue('INS{}_DISTORTION_COEF_Y'.format(self.ikid), 0, 4).tolist()
         return self.__odky
 
     @property
@@ -1308,7 +1393,7 @@ class KaguyaMiIsisLabelNaifSpiceDriver(LineScanner, NaifSpice, IsisLabel, Kaguya
           Boresight focal plane x coordinate
         """
         if not hasattr(self, "_boresight_x"):
-          self._boresight_x = spice.gdpool('INS{}_BORESIGHT'.format(self.ikid), 0, 1)[0]
+          self._boresight_x = pyspiceql.getKernelVectorValue('INS{}_BORESIGHT'.format(self.ikid))[0]
         return self._boresight_x
 
     @property
@@ -1324,9 +1409,50 @@ class KaguyaMiIsisLabelNaifSpiceDriver(LineScanner, NaifSpice, IsisLabel, Kaguya
           Boresight focal plane x coordinate
         """
         if not hasattr(self, "_boresight_y"):
-          self._boresight_y = spice.gdpool('INS{}_BORESIGHT'.format(self.ikid), 1, 1)[0]
+          self._boresight_y = pyspiceql.getKernelVectorValue('INS{}_BORESIGHT'.format(self.ikid))[1]
         return self._boresight_y
 
+    @property
+    def usgscsm_distortion_model(self):
+        """
+        Kaguya uses a unique radial distortion model so we need to overwrite the
+        method packing the distortion model into the ISD.
+
+        from the IK:
+
+        Line-of-sight vector of pixel no. n can be expressed as below.
+
+        Distortion coefficients information:
+        INS<INSTID>_DISTORTION_COEF_X  = ( a0, a1, a2, a3)
+        INS<INSTID>_DISTORTION_COEF_Y  = ( b0, b1, b2, b3),
+
+        Distance r from the center:
+        r = - (n - INS<INSTID>_CENTER) * INS<INSTID>_PIXEL_SIZE.
+
+        Line-of-sight vector v is calculated as
+        v[X] = INS<INSTID>BORESIGHT[X] + a0 + a1*r + a2*r^2 + a3*r^3 ,
+        v[Y] = INS<INSTID>BORESIGHT[Y] + r+a0 + a1*r +a2*r^2 + a3*r^3 ,
+        v[Z] = INS<INSTID>BORESIGHT[Z]
+
+        Expects odkx and odky to be defined. These should be a list of optical
+        distortion x and y coefficients respectively.
+
+        Returns
+        -------
+        : dict
+          radial distortion model
+
+        """
+        return {
+            "kaguyalism": {
+                "x" : self._odkx,
+                "y" : self._odky,
+                "boresight_x" : self.boresight_x,
+                "boresight_y" : self.boresight_y
+            }
+        }
+
+
     @property
     def line_exposure_duration(self):
         """
@@ -1364,7 +1490,7 @@ class KaguyaMiIsisLabelNaifSpiceDriver(LineScanner, NaifSpice, IsisLabel, Kaguya
           focal plane to detector samples
         """
         if not hasattr(self, "_focal2pixel_samples"):
-          pixel_size = spice.gdpool('INS{}_PIXEL_SIZE'.format(self.ikid), 0, 1)[0]
+          pixel_size = pyspiceql.getKernelVectorValue('INS{}_PIXEL_SIZE'.format(self.ikid))[0]
           self._focal2pixel_samples = [0, 0, -1/pixel_size]
         return self._focal2pixel_samples
 
@@ -1382,6 +1508,6 @@ class KaguyaMiIsisLabelNaifSpiceDriver(LineScanner, NaifSpice, IsisLabel, Kaguya
           focal plane to detector lines
         """
         if not hasattr(self, "_focal2pixel_lines"):
-          pixel_size = spice.gdpool('INS{}_PIXEL_SIZE'.format(self.ikid), 0, 1)[0]
+          pixel_size = pyspiceql.getKernelVectorValue('INS{}_PIXEL_SIZE'.format(self.ikid))[0]
           self._focal2pixel_lines = [0, 1/pixel_size, 0]
         return self._focal2pixel_lines
diff --git a/ale/drivers/tgo_drivers.py b/ale/drivers/tgo_drivers.py
index 1f98023..574d9e5 100644
--- a/ale/drivers/tgo_drivers.py
+++ b/ale/drivers/tgo_drivers.py
@@ -3,9 +3,9 @@ import os
 
 import struct
 import pvl
-import spiceypy as spice
 import numpy as np
 
+from pyspiceql import pyspiceql
 from ale.base import Driver
 from ale.base.data_naif import NaifSpice
 from ale.base.label_isis import IsisLabel
@@ -50,7 +50,7 @@ class TGOCassisIsisLabelNaifSpiceDriver(Framer, IsisLabel, NaifSpice, NoDistorti
         : float
           ephemeris start time of the image.
         """
-        return spice.utc2et(self.utc_start_time.strftime("%Y-%m-%d %H:%M:%S.%f"))
+        return pyspiceql.utc2et(self.utc_start_time.strftime("%Y-%m-%d %H:%M:%S.%f")))
 
     @property
     def sensor_frame_id(self):
diff --git a/ale/drivers/viking_drivers.py b/ale/drivers/viking_drivers.py
index a0f1a11..5577fe1 100644
--- a/ale/drivers/viking_drivers.py
+++ b/ale/drivers/viking_drivers.py
@@ -1,5 +1,3 @@
-import spiceypy as spice
-
 import ale
 from ale.base.data_naif import NaifSpice
 from ale.base.data_isis import IsisSpice
@@ -7,6 +5,7 @@ from ale.base.label_isis import IsisLabel
 from ale.base.type_sensor import Framer
 from ale.base.type_distortion import NoDistortion
 from ale.base.base import Driver
+from pyspiceql import pyspiceql
 
 sensor_name_lookup = {
     "VISUAL_IMAGING_SUBSYSTEM_CAMERA_A" : "Visual Imaging Subsystem Camera A",
@@ -109,7 +108,7 @@ class VikingIsisLabelNaifSpiceDriver(Framer, IsisLabel, NaifSpice, NoDistortion,
         : float
           ephemeris start time of the image
         """
-        ephemeris_start_time = spice.scs2e(self.alt_ikid, str(self.spacecraft_clock_start_count))
+        ephemeris_start_time = pyspiceql.sclkToEt(self.alt_ikid, str(self.spacecraft_clock_start_count))
 
         if self.exposure_duration <= .420:
             offset1 = 7.0 / 8.0 * 4.48
diff --git a/ale/drivers/voyager_drivers.py b/ale/drivers/voyager_drivers.py
index 17f6afc..9674d1a 100644
--- a/ale/drivers/voyager_drivers.py
+++ b/ale/drivers/voyager_drivers.py
@@ -62,7 +62,7 @@ class VoyagerCameraIsisLabelNaifSpiceDriver(Framer, IsisLabel, NaifSpice, NoDist
 
     @property
     def ephemeris_start_time(self):
-        inital_time = spice.utc2et(self.utc_start_time.strftime("%Y-%m-%d %H:%M:%S.%f"))
+        inital_time = pyspiceql.utcToEt(self.utc_start_time.strftime("%Y-%m-%d %H:%M:%S.%f"))
         # To get shutter end (close) time, subtract 2 seconds from the start time
         updated_time = inital_time - 2
         # To get shutter start (open) time, take off the exposure duration from the end time.
-- 
GitLab