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