Пример #1
0
 def obt2utc(self, obt_string):
     # Obt to Ephemeris time (seconds past J2000)
     ephemeris_time = spiceypy.scs2e(self.solar_orbiter_naif_id, obt_string)
     # Ephemeris time to Utc
     # Format of output epoch: ISOC (ISO Calendar format, UTC)
     # Digits of precision in fractional seconds: 3
     return spiceypy.et2utc(ephemeris_time, "ISOC", 3)
Пример #2
0
def sunDistanceAU(time: str, target: str) -> float:
    """Returns distance in AU between Sun and observed body from MRO."""

    base_kernel_path = Path(isis.environ["ISIS3DATA"]) / "base" / "kernels"
    lsk = sorted(Path(base_kernel_path / "lsk").glob("naif*.tls"))[-1]
    pck = sorted(Path(base_kernel_path / "spk").glob("de*.bsp"))[-1]
    sat = sorted(Path(base_kernel_path / "spk").glob("mar*.bsp"))[-1]

    sclk = sorted(
        Path(
            Path(isis.environ["ISIS3DATA"]) / "mro" / "kernels" / "sclk"
        ).glob("MRO_SCLKSCET.*.65536.tsc")
    )[-1]

    spiceypy.furnsh([str(lsk), str(pck), str(sat), str(sclk)])

    et = spiceypy.scs2e(-74999, time)

    targ = target.lower()
    if targ == "sky" or targ == "cal" or targ == "phobos" or targ == "deimos":
        targ = "mars"

    (sunv, lt) = spiceypy.spkpos(targ, et, "J2000", "LT+S", "sun")

    sunkm = spiceypy.vnorm(sunv)
    # Return in AU units
    return sunkm / 1.49597870691e8
Пример #3
0
 def ephemeris_stop_time(self):
     if self.spacecraft_clock_stop_count:
         return spice.scs2e(self.spacecraft_id,
                            self.spacecraft_clock_stop_count)
     else:
         return spice.str2et(
             self.utc_stop_time.strftime("%Y-%m-%d %H:%M:%S"))
Пример #4
0
 def ephemeris_start_time(self):
     if not hasattr(self, '_ephemeris_start_time'):
         sclock = self.label['IsisCube']['Instrument'][
             'SpacecraftClockCount']
         self._ephemeris_start_time = spice.scs2e(self.spacecraft_id,
                                                  sclock)
     return self._ephemeris_start_time
Пример #5
0
 def toUTC(self, sclk, fmt='ISOC', prec=5):
     '''Convert Spacecraft clock time to UTC'''
     if not self.loaded:
         self.load()
     if isinstance(sclk, (int, float)):
         sclk = '1/%f' % sclk
     elif '_' in sclk:
         sclk = '1/' + sclk.split('_')[0]
     return spice.et2utc(spice.scs2e(self.sc, sclk), fmt, prec)
Пример #6
0
 def ephemeris_start_time(self):
     """
     The starting ephemeris time for LRO is computed by taking the
     LRO:SPACECRAFT_CLOCK_PREROLL_COUNT, as defined in the label, and
     adding offsets that were taken from an IAK.
     -------
     : double
       Starting ephemeris time of the image
     """
     start_time = spice.scs2e(self.spacecraft_id, self.label['IsisCube']['Instrument']['SpacecraftClockPrerollCount'])
     return start_time + self.constant_time_offset + self.additional_preroll * self.exposure_duration
Пример #7
0
 def ephemeris_start_time(self):
     """
     Compute the center ephemeris time for a Dawn Frame camera. This is done
     via a spice call but 193 ms needs to be added to
     account for the CCD being discharged or cleared.
     """
     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 += 193.0 / 1000.0
     return self._ephemeris_start_time
Пример #8
0
    def ephemeris_stop_time(self):
        """
        Returns the ephemeris stop time of the image. Expects spacecraft_id to
        be defined. This must be the integer Naif Id code for the spacecraft.
        Expects spacecraft_clock_stop_count to be defined. This must be a string
        containing the stop clock count of the spacecraft

        Returns
        -------
        : double
          Ephemeris stop time of the image
        """
        return spice.scs2e(self.spacecraft_id,
                           self.spacecraft_clock_stop_count)
Пример #9
0
    def ephemeris_start_time(self):
        """
        Returns the ephemeris start time of the image.
        Expects spacecraft_id to be defined. This should be the integer
        Naif ID code for the spacecraft.

        Returns
        -------
        : float
          ephemeris start time of the image
        """
        if not hasattr(self, '_ephemeris_start_time'):
            sclock = self.label['IsisCube']['Instrument'][
                'SpacecraftClockCount']
            self._ephemeris_start_time = spice.scs2e(self.spacecraft_id,
                                                     sclock)
        return self._ephemeris_start_time
Пример #10
0
def scs2utc_spice(scs, sc, deltat):
    res = {}
    try:
        scid = sp.bods2c(sc)
        et = sp.scs2e(scid, scs)

        if deltat is not None:
            tai = sp.unitim(et, 'et', 'tai')
            tai += deltat
            et = sp.unitim(tai, 'tai', 'et')

        utc = sp.et2utc(et, 'isoc', 3)

        res[scs] = utc
    except sp.stypes.SpiceyError as ex:
        raise GeometrySpiceError(ex.value)
    else:
        return res
Пример #11
0
    def ephemeris_stop_time(self):
        """
        Returns the ephemeris stop time of the image. Expects spacecraft_id to
        be defined. This must be the integer Naif Id code for the spacecraft.
        Expects spacecraft_clock_stop_count to be defined. This must be a string
        containing the stop clock count of the spacecraft

        Returns
        -------
        : double
          Ephemeris stop time of the image
        """
        if self.spacecraft_clock_stop_count:
            return spice.scs2e(self.spacecraft_id,
                               self.spacecraft_clock_stop_count)
        else:
            return spice.str2et(
                self.utc_stop_time.strftime("%Y-%m-%d %H:%M:%S"))
Пример #12
0
    def ephemeris_start_time(self):
        """
        Returns the ephemeris_start_time of the image.
        Expects spacecraft_clock_start_count to be defined. This should be a float
        containing the start clock count of the spacecraft.
        Expects spacecraft_id to be defined. This should be the integer Naif ID code
        for the spacecraft.

        Returns
        -------
        : float
          ephemeris start time of the image.
        """
        if not hasattr(self, '_ephemeris_start_time'):
            sclock = self.spacecraft_clock_start_count
            self._starting_ephemeris_time = spice.scs2e(
                self.spacecraft_id, sclock)
        return self._starting_ephemeris_time
Пример #13
0
    def sclk2jd(self, sclk):
        """
		Convert spacecraft time to TDB Julian Dates (JD).

		Parameters:
			sclk (ndarray): Timestamps in TESS Spacecraft Time.

		Returns:
			ndarray: Timestamps in TDB Julian Dates (TDB).
		"""

        sclk = np.atleast_1d(sclk)
        N = len(sclk)
        jd = np.empty(N, dtype='float64')
        for k in range(N):
            et = spiceypy.scs2e(-95, sclk[k])
            jd[k] = spiceypy.unitim(et, 'ET', 'JDTDB')

        return jd
Пример #14
0
    def ephemeris_start_time(self):
        """
        Overridden to use the alternate instrument ID. Also computes an offset to match
        what is being done in ISIS code.
        Expects spacecraft_clock_start_count to be defined.

        Returns
        -------
        : float
          ephemeris start time of the image
        """
        ephemeris_start_time = spice.scs2e(self.alt_ikid, str(self.spacecraft_clock_start_count))

        if self.exposure_duration <= .420:
            offset1 = 7.0 / 8.0 * 4.48
        else:
            offset1 = 3.0 / 8.0 * 4.48
        offset2 = 1.0 / 64.0 * 4.48

        return ephemeris_start_time + offset1 + offset2
Пример #15
0
    def scet_to_datetime(self, scet):
        """
        Convert SCET to datetime.

        Parameters
        ----------
        scet : `str`, `int`, `float`
            SCET time as number or spacecraft clock string e.g. `1.0` or `'625237315:44104'`

        Returns
        -------
        `datetime.datetime`
            Datetime of SCET

        """
        ephemeris_time = None
        if isinstance(scet, (float, int)):
            ephemeris_time = spiceypy.sct2e(SOLAR_ORBITER_ID, scet)
        elif isinstance(scet, str):
            ephemeris_time = spiceypy.scs2e(SOLAR_ORBITER_ID, scet)
        return spiceypy.et2datetime(ephemeris_time)
Пример #16
0
    def scet_to_utc(self, scet):
        """
        Convert SCET to UTC time string in ISO format.

        Parameters
        ----------
        scet : `str`, `int`, `float`
            SCET time as a number or spacecraft clock string e.g. `1.0` or `625237315:44104`

        Returns
        -------
        `str`
            UTC time string in ISO format
        """
        # Obt to Ephemeris time (seconds past J2000)
        ephemeris_time = None
        if isinstance(scet, (float, int)):
            ephemeris_time = spiceypy.sct2e(SOLAR_ORBITER_ID, scet)
        elif isinstance(scet, str):
            ephemeris_time = spiceypy.scs2e(SOLAR_ORBITER_ID, scet)
        # Ephemeris time to Utc
        # Format of output epoch: ISOC (ISO Calendar format, UTC)
        # Digits of precision in fractional seconds: 6
        return spiceypy.et2utc(ephemeris_time, "ISOC", 3)
Пример #17
0
def get_isd(label):
    """
    TODO: This function (and all like it) needs to open with some robust method to make sure this is
          in fact an MDIS label.

    """

    instrument_name = {
        'MDIS-NAC': 'MSGR_MDIS_NAC',
        'MERCURY DUAL IMAGING SYSTEM NARROW ANGLE CAMERA': 'MSGR_MDIS_NAC',
        'MERCURY DUAL IMAGING SYSTEM WIDE ANGLE CAMERA': 'MSGR_MDIS_WAC'
    }

    metakernel_dir = config.mdis
    mks = sorted(glob(os.path.join(metakernel_dir, '*.tm')))

    instrument_id = instrument_name[label['INSTRUMENT_ID']]
    spacecraft_name = label['MISSION_NAME']
    target_name = label['TARGET_NAME']
    time = label['START_TIME']

    messenger_mk = None
    for mk in mks:
        if str(time.year) in os.path.basename(mk):
            messenger_mk = mk

    spice.furnsh(messenger_mk)

    # Spice likes ids over names, so grab the ids from the names
    spacecraft_id = spice.bods2c(spacecraft_name)
    ikid = spice.bods2c(instrument_id)

    # Load the instrument and target metadata into the ISD
    reference_frame = 'IAU_{}'.format(target_name)

    isd = {}

    rad = spice.bodvrd(target_name, 'RADII', 3)
    isd['radii'] = {}
    isd['radii']['semimajor'] = rad[1][0]
    isd['radii']['semiminor'] = rad[1][1]

    isd['optical_distortion'] = {}
    odk_mssgr_x = spice.gdpool('INS{}_OD_T_X'.format(ikid), 0, 10)
    odk_mssgr_y = spice.gdpool('INS{}_OD_T_Y'.format(ikid), 0, 10)

    isd['optical_distortion']['x'] = list(odk_mssgr_x)
    isd['optical_distortion']['y'] = list(odk_mssgr_y)

    isd['focal2pixel_samples'] = list(
        spice.gdpool('INS{}_TRANSX'.format(ikid), 0, 3))
    isd['focal2pixel_lines'] = list(
        spice.gdpool('INS{}_TRANSY'.format(ikid), 0, 3))

    # Load information from the IK kernel
    isd['focal_length_model'] = {}

    focal_legnth_coeffs = spice.gdpool('INS{}_FL_TEMP_COEFFS '.format(ikid), 0,
                                       5)
    isd['focal_length_model']['focal_length'] = focal_length_from_temp(
        label['FOCAL_PLANE_TEMPERATURE'].value, focal_legnth_coeffs)

    isd['focal_length_model']['focal_length_epsilon'] = float(
        spice.gdpool('INS{}_FL_UNCERTAINTY'.format(ikid), 0, 1)[0])

    isd['image_lines'] = int(
        spice.gipool('INS{}_PIXEL_LINES'.format(ikid), 0, 1)[0])
    isd['image_samples'] = int(
        spice.gipool('INS{}_PIXEL_SAMPLES'.format(ikid), 0, 1)[0])

    isd['starting_detector_sample'] = int(
        spice.gdpool('INS{}_FPUBIN_START_SAMPLE'.format(ikid), 0, 1)[0])
    isd['starting_detector_line'] = int(
        spice.gdpool('INS{}_FPUBIN_START_LINE'.format(ikid), 0, 1)[0])

    # Now time
    sclock = label['SPACECRAFT_CLOCK_START_COUNT']
    exposure_duration = label['EXPOSURE_DURATION'].value
    exposure_duration = exposure_duration * 0.001  # Scale to seconds

    # Get the instrument id, and, since this is a framer, set the time to the middle of the exposure
    start_et = spice.scs2e(spacecraft_id, sclock)
    start_et += (exposure_duration / 2.0)

    end_et = spice.scs2e(
        spacecraft_id,
        label['SPACECRAFT_CLOCK_STOP_COUNT']) + (exposure_duration / 2.0)
    del_et = end_et - start_et
    et = (start_et + end_et) / 2

    isd['starting_ephemeris_time'] = start_et
    isd['dt_ephemeris'] = del_et
    isd['number_of_ephemerides'] = 1
    isd['interpolation_method'] = 'lagrange'
    isd['center_ephemeris_time'] = et

    # Get the rotation angles from MDIS NAC frame to Mercury body-fixed frame
    camera2bodyfixed = spice.pxform(instrument_id, reference_frame, et)
    quat = spice.m2q(camera2bodyfixed)

    isd['sensor_orientation'] = list(quat)

    # Get the Sensor Position
    loc, _ = spice.spkpos(target_name, et, reference_frame, 'LT+S',
                          spacecraft_name)

    isd['sensor_location'] = {}
    isd['sensor_location']['x'] = loc[0]
    isd['sensor_location']['y'] = loc[1]
    isd['sensor_location']['z'] = loc[2]
    isd['sensor_location']['unit'] = 'm'

    # Get the velocity
    v_state, lt = spice.spkezr(spacecraft_name, et, reference_frame, 'NONE',
                               target_name)

    isd['sensor_velocity'] = {}
    isd['sensor_velocity']['x'] = v_state[3]
    isd['sensor_velocity']['y'] = v_state[4]
    isd['sensor_velocity']['z'] = v_state[5]
    isd['sensor_velocity']['unit'] = 'm'
    isd['reference_height'] = {}
    isd['reference_height']['minheight'] = label.get('min_valid_height', -8000)
    isd['reference_height']['maxheight'] = label.get('max_valid_height', 8000)
    isd['reference_height']['unit'] = 'KM'

    # Get the sun position
    sun_state, lt = spice.spkezr("SUN", et, reference_frame, 'NONE',
                                 target_name)

    # Get the sun position, convert to meters
    xpos, ypos, zpos = [e.value for e in label['SC_SUN_POSITION_VECTOR']]
    xvel, yvel, zvel = [e.value for e in label['SC_SUN_VELOCITY_VECTOR']]

    # lighttime should always be off
    isd['sun_position'] = {}
    isd['sun_position']['x'] = sun_state[0]
    isd['sun_position']['y'] = sun_state[1]
    isd['sun_position']['z'] = sun_state[2]

    isd['sun_velocity'] = {}
    isd['sun_velocity']['x'] = sun_state[3]
    isd['sun_velocity']['y'] = sun_state[4]
    isd['sun_velocity']['z'] = sun_state[5]
    return isd
Пример #18
0
 def ephemeris_start_time(self):
     if not hasattr(self, '_ephemeris_start_time'):
         sclock = self.spacecraft_clock_start_count
         self._starting_ephemeris_time = spice.scs2e(self.spacecraft_id, sclock)
     return self._starting_ephemeris_time
Пример #19
0
    def get_fits_headers(self, *, start_time, average_time):

        try:
            et = spiceypy.scs2e(-144, str(average_time))
        except (SpiceBADPARTNUMBER, SpiceINVALIDSCLKSTRING):
            et = spiceypy.utc2et(average_time.isot)

        # HeliographicStonyhurst
        solo_sun_hg, sun_solo_lt = spiceypy.spkezr('SOLO', et, 'SUN_EARTH_CEQU', 'None', 'Sun')

        # Convert to spherical and add units
        hg_rad, hg_lon, hg_lat = spiceypy.reclat(solo_sun_hg[:3])
        hg_rad = hg_rad * u.km
        hg_lat, hg_lon = (hg_lat * u.rad).to('deg'), (hg_lon * u.rad).to('deg')
        # Calculate radial velocity add units
        rad_vel, *_ = spiceypy.reclat(solo_sun_hg[3:])
        rad_vel = rad_vel * (u.km / u.s)

        rsun_arc = np.arcsin((1 * u.R_sun) / hg_rad).decompose().to('arcsec')

        solo_sun_hee, _ = spiceypy.spkezr('SOLO', et, 'SOLO_HEE', 'None', 'Sun')
        solo_sun_hci, _ = spiceypy.spkezr('SOLO', et, 'SOLO_HCI', 'None', 'Sun')
        solo_sun_hae, _ = spiceypy.spkezr('SOLO', et, 'SUN_ARIES_ECL', 'None', 'Sun')
        solo_sun_heeq, _ = spiceypy.spkezr('SOLO', et, 'SOLO_HEEQ', 'None', 'Sun')
        solo_sun_gse, earth_solo_lt = spiceypy.spkezr('SOLO', et, 'EARTH_SUN_ECL', 'None', 'Earth')
        sun_earth_hee, sun_earth_lt = spiceypy.spkezr('Earth', et, 'SOLO_HEE', 'None', 'Sun')

        precision = 2
        headers = (
            ('SPICE_MK', self.meta_kernel_path.name, 'SPICE meta kernel file'),
            ('RSUN_ARC', rsun_arc.to_value('arcsec'),
             '[arcsec] Apparent photospheric solar radius'),
            # ('CAR_ROT', ,), Doesn't make sense as we don't have a crpix
            ('HGLT_OBS', np.around(hg_lat.to_value('deg'), precision),
             '[deg] s/c heliographic latitude (B0 angle)'),
            ('HGLN_OBS', np.around(hg_lon.to_value('deg'), precision),
             '[deg] s/c heliographic longitude'),
            # Not mistake same values know by different terms
            ('CRLT_OBS', np.around(hg_lat.to_value('deg'), precision),
             '[deg] s/c Carrington latitude (B0 angle)'),
            ('CRLN_OBS', np.around(hg_lon.to_value('deg'), precision),
             '[deg] s/c Carrington longitude (L0 angle)'),
            ('DSUN_OBS', np.around(hg_rad.to_value('m'), precision),
             '[m] s/c distance from Sun'),
            ('HEEX_OBS', np.around((solo_sun_hee[0]*u.km).to_value('m'), precision),
             '[m] s/c Heliocentric Earth Ecliptic X'),
            ('HEEY_OBS', np.around((solo_sun_hee[1]*u.km).to_value('m'), precision),
             '[m] s/c Heliocentric Earth Ecliptic Y'),
            ('HEEZ_OBS', np.around((solo_sun_hee[2]*u.km).to_value('m'), precision),
             '[m] s/c Heliocentric Earth Ecliptic Z'),
            ('HCIX_OBS', np.around((solo_sun_hci[0]*u.km).to_value('m'), precision),
             '[m] s/c Heliocentric Inertial X'),
            ('HCIY_OBS', np.around((solo_sun_hci[1]*u.km).to_value('m'), precision),
             '[m] s/c Heliocentric Inertial Y'),
            ('HCIZ_OBS', np.around((solo_sun_hci[2]*u.km).to_value('m'), precision),
             '[m] s/c Heliocentric Inertial Z'),
            ('HCIX_VOB', np.around((solo_sun_hci[3]*(u.km/u.s)).to_value('m/s'), precision),
             '[m/s] s/c Heliocentric Inertial X Velocity'),
            ('HCIY_VOB', np.around((solo_sun_hci[4]*(u.km/u.s)).to_value('m/s'), precision),
             '[m/s] s/c Heliocentric Inertial Y Velocity'),
            ('HCIZ_VOB', np.around((solo_sun_hci[5]*(u.km/u.s)).to_value('m/s'), precision),
             '[m/s] s/c Heliocentric Inertial Z Velocity'),
            ('HAEX_OBS', np.around((solo_sun_hae[0]*u.km).to_value('m'), precision),
             '[m] s/c Heliocentric Aries Ecliptic X'),
            ('HAEY_OBS', np.around((solo_sun_hae[1]*u.km).to_value('m'), precision),
             '[m] s/c Heliocentric Aries Ecliptic Y'),
            ('HAEZ_OBS', np.around((solo_sun_hae[0]*u.km).to_value('m'), precision),
             '[m] s/c Heliocentric Aries Ecliptic Z'),
            ('HEQX_OBS', np.around((solo_sun_heeq[0]*u.km).to_value('m'), precision),
             '[m] s/c Heliocentric Earth Equatorial X'),
            ('HEQY_OBS', np.around((solo_sun_heeq[1]*u.km).to_value('m'), precision),
             '[m] s/c Heliocentric Earth Equatorial Y'),
            ('HEQZ_OBS', np.around((solo_sun_heeq[2]*u.km).to_value('m'), precision),
             '[m] s/c Heliocentric Earth Equatorial Z'),
            ('GSEX_OBS', np.around((solo_sun_gse[0]*u.km).to_value('m'), precision),
             '[m] s/c Geocentric Solar Ecliptic X'),
            ('GSEY_OBS', np.around((solo_sun_gse[1]*u.km).to_value('m'), precision),
             '[m] s/c Geocentric Solar Ecliptic Y'),
            ('GSEZ_OBS', np.around((solo_sun_gse[2]*u.km).to_value('m'), precision),
             '[m] s/c Geocentric Solar Ecliptic Y'),
            ('OBS_VR', np.around(rad_vel.to_value('m/s'), precision),
             '[m/s] Radial velocity of spacecraft relative to Sun'),
            ('EAR_TDEL', np.around(sun_earth_lt - sun_solo_lt, precision),
             '[s] Time(Sun to Earth) - Time(Sun to S/C)'),
            ('SUN_TIME', np.around(sun_solo_lt, precision),
             '[s] Time(Sun to s/c)'),
            ('DATE_EAR', (start_time + np.around((sun_earth_lt - sun_solo_lt), precision)*u.s).fits,
             'Start time of observation, corrected to Earth'),
            ('DATE_SUN', (start_time - np.around(sun_solo_lt, precision)*u.s).fits,
             'Start time of observation, corrected to Su'),
        )

        return headers
Пример #20
0
def ctx_isd_from_json(data, meta):
    time = parser.parse(data['START_TIME'])
    for k in meta:
        if k.year.year == time.year:
            obs_kernels = k.path

    # Load the meta kernel
    spice.furnsh(obs_kernels)

    isd = {}
    spacecraft_name = data['SPACECRAFT_NAME']
    spacecraft_id = spice.bods2c('MRO')

    # Need to map CONTEXT CAMERA to what spice wants - MRO_CTX
    instrument_name = data['INSTRUMENT_NAME']
    ikid = isd['IKCODE'] = spice.bods2c('MRO_CTX')

    # Instrument / Spacecraft Metadata
    isd['OPTICAL_DIST_COEF'] = spice.gdpool('INS{}_OD_K'.format(ikid), 0, 3)
    isd['ITRANSL'] = spice.gdpool('INS{}_ITRANSL'.format(ikid), 0, 3)
    isd['ITRANSS'] = spice.gdpool('INS{}_ITRANSS'.format(ikid), 0, 3)
    isd['DETECTOR_SAMPLE_ORIGIN'] = spice.gdpool(
        'INS{}_BORESIGHT_SAMPLE'.format(ikid), 0, 1)
    isd['DETECTOR_LINE_ORIGIN'] = spice.gdpool(
        'INS{}_BORESIGHT_LINE'.format(ikid), 0, 1)
    isd['DETECTOR_SAMPLE_SUMMING'] = data['SAMPLING_FACTOR']
    isd['DETECTOR_SAMPLE_SUMMING'] = data['SAMPLING_FACTOR']
    isd['STARTING_SAMPLE'] = data['SAMPLE_FIRST_PIXEL']
    isd['TOTAL_LINES'] = nlines = data['IMAGE']['LINES']
    isd['TOTAL_SAMPLES'] = spice.gdpool('INS{}_PIXEL_SAMPLES'.format(ikid), 0,
                                        1)
    isd['SENSOR_TYPE'] = 'USGSAstroLineScanner'
    isd['MOUNTING_ANGLES'] = np.zeros(3)
    isd['ISIS_Z_DIRECTION'] = 1
    isd['STARTING_LINE'] = 1.0
    isd['DETECTOR_LINE_OFFSET'] = 0.0

    # Body Parameters
    target_name = find_in_dict(data, 'TARGET_NAME')
    rad = spice.bodvrd(target_name, 'RADII', 3)
    a = rad[1][1]
    b = rad[1][2]
    isd['SEMI_MAJOR_AXIS'] = a * 1000  # Scale to meters
    isd['ECCENTRICITY'] = sqrt(1 - (b**2 / a**2))  # Standard eccentricity

    isd['FOCAL'] = spice.gdpool('INS{}_FOCAL_LENGTH'.format(ikid), 0, 1)

    isd['ABERR'] = 0
    isd['ATMREF'] = 0
    isd['PLATFORM'] = 1

    # It really is hard coded this way...
    isd['TRI_PARAMETERS'] = np.zeros(18)
    isd['TRI_PARAMETERS'][15] = isd['FOCAL']

    # Time
    sclock = find_in_dict(data, 'SPACECRAFT_CLOCK_START_COUNT')
    et = spice.scs2e(spacecraft_id, sclock)
    isd['STARTING_EPHEMERIS_TIME'] = et

    half_lines = nlines / 2
    isd['INT_TIME'] = line_rate = data['LINE_EXPOSURE_DURATION'][
        0] * 0.001  # Scale to seconds
    center_sclock = et + half_lines * line_rate
    isd['CENTER_EPHEMERIS_TIME'] = center_sclock
    isd['SCAN_DURATION'] = line_rate * nlines
    # The socetlinekeywords code is pushing ephemeris and quaternion off of either side of the image.  Therefore,
    # the code needs to know when the start time is.  Since we are not pushing off the edge of the image, the start-time
    # should be identical to the actual image start time.
    isd['T0_QUAT'] = isd['T0_EPHEM'] = isd['STARTING_EPHEMERIS_TIME'] - isd[
        'CENTER_EPHEMERIS_TIME']
    isd['DT_EPHEM'] = 80 * isd['INT_TIME']  # This is every 300 lines

    # Determine how many ephemeris points to compute
    n_ephemeris = int(isd['SCAN_DURATION'] / isd['DT_EPHEM'])
    if n_ephemeris % 2 == 0:
        n_ephemeris += 1
    isd['NUMBER_OF_EPHEM'] = n_ephemeris
    eph = np.empty((n_ephemeris, 3))
    eph_rates = np.empty(eph.shape)
    current_et = et
    for i in range(n_ephemeris):
        loc_direct, _ = spice.spkpos(target_name, current_et, 'IAU_MARS',
                                     'LT+S', 'MRO')
        state, _ = spice.spkezr(target_name, current_et, 'IAU_MARS', 'LT+S',
                                'MRO')
        eph[i] = loc_direct
        eph_rates[i] = state[3:]
        current_et += isd[
            'DT_EPHEM']  # Increment the time by the number of lines being stepped
    eph *= -1000  # Reverse to be from body center and convert to meters
    eph_rates *= -1000  # Same, reverse and convert
    isd['EPHEM_PTS'] = eph.flatten()
    isd['EPHEM_RATES'] = eph_rates.flatten()

    # Why should / should not the n_quaternions equal the number of ephemeris pts?
    n_quaternions = n_ephemeris
    isd['NUMBER_OF_QUATERNIONS'] = n_quaternions

    isd['DT_QUAT'] = isd['SCAN_DURATION'] / n_quaternions
    qua = np.empty((n_quaternions, 4))
    current_et = et
    for i in range(n_quaternions):
        # Find the rotation matrix
        camera2bodyfixed = spice.pxform('MRO_CTX', 'IAU_MARS', current_et)
        q = spice.m2q(camera2bodyfixed)
        qua[i][:3] = q[1:]
        qua[i][-1] = q[0]
        current_et += isd['DT_QUAT']
    isd['QUATERNIONS'] = qua.flatten()

    # Now the 'optional' stuff
    isd['REFERENCE_HEIGHT'] = data.get('reference_height', 30)
    isd['MIN_VALID_HT'] = data.get('min_valid_height', -8000)
    isd['MAX_VALID_HT'] = data.get('max_valid_height', 8000)
    isd['IMAGE_ID'] = data.get('image_id', 'UNKNOWN')
    isd['SENSOR_ID'] = data.get('sensor_id', 'USGS_LINE_SCANNER')
    isd['PLATFORM_ID'] = data.get('platform_id', 'UNKNOWN')
    isd['TRAJ_ID'] = data.get('traj_id', 'UNKNOWN')
    isd['COLL_ID'] = data.get('coll_id', 'UNKNOWN')
    isd['REF_DATE_TIME'] = data.get('ref_date_time', 'UNKNOWN')

    spice.unload(obs_kernels)

    return json.dumps(isd, cls=NumpyEncoder)
Пример #21
0
 def ephemeris_start_time(self):
     return spice.scs2e(self.spacecraft_id,
                        self.spacecraft_clock_start_count)
Пример #22
0
def get_isd(label):

    mission_name = {"CASSINI-HUYGENS": "CASSINI"}

    instrument_names = {"ISSNA": "CASSINI_ISS_NAC", "ISSWA": "CASSINI_ISS_WAC"}

    metakernal_dir = config.cassini
    mks = sorted(glob(metakernal_dir + '/*.tm'))

    instrument_name = instrument_names[label['INSTRUMENT_ID']]
    spacecraft_name = mission_name[label['MISSION_NAME']]
    target_name = label['TARGET_NAME']
    time = label['START_TIME']

    cassini_mk = None
    for mk in mks:
        if str(time.year) in os.path.basename(mk):
            cassini_mk = mk

    spice.furnsh(cassini_mk)

    # Spice likes ids over names, so grab the ids from the names
    spacecraft_id = spice.bods2c(spacecraft_name)
    instrument_id = spice.bods2c(instrument_name)

    # Load the instrument and target metadata into the ISD
    reference_frame = 'IAU_{}'.format(target_name)

    isd = {}

    rad = spice.bodvrd(target_name, 'RADII', 3)
    isd['semimajor'] = rad[1][0] * 1000
    isd['semiminor'] = rad[1][1] * 1000

    # transx and transy are unavailable so fill in with pixel_size after conversion to millimeters from microns
    # assuming pixels are square
    pixel_size = int(
        spice.gipool('INS{}_PIXEL_SIZE'.format(instrument_id), 0,
                     1)[0]) * 0.001
    isd['focal2pixel_samples'] = [0.0, pixel_size, 0.0]
    isd['focal2pixel_lines'] = [0.0, 0.0, pixel_size]

    # unavailable so default to 0
    isd['starting_detector_sample'] = 0.0
    isd['starting_detector_line'] = 0.0

    isd['image_lines'] = float(
        spice.gipool('INS{}_PIXEL_LINES'.format(instrument_id), 0, 1)[0])
    isd['image_samples'] = float(
        spice.gipool('INS{}_PIXEL_SAMPLES'.format(instrument_id), 0, 1)[0])

    isd['focal_length_model'] = {}
    isd['focal_length_model']['focal_length'] = float(
        spice.gdpool('INS{}_FOCAL_LENGTH'.format(instrument_id), 0, 1)[0])
    isd['focal_length_model']['focal_length_epsilon'] = float(
        spice.gdpool('INS{}_FL_UNCERTAINTY'.format(instrument_id), 0, 1)[0])

    # this following part is ripped from the mdis driver. Since they are both framers this code should be able to be applied to both
    # Now time
    sclock = label['SPACECRAFT_CLOCK_START_COUNT']
    exposure_duration = label['EXPOSURE_DURATION'].value
    exposure_duration = exposure_duration * 0.001  # Scale to seconds

    # Get the instrument id, and, since this is a framer, set the time to the middle of the exposure
    start_et = spice.scs2e(spacecraft_id, sclock)
    start_et += (exposure_duration / 2.0)

    end_et = spice.scs2e(
        spacecraft_id,
        label['SPACECRAFT_CLOCK_STOP_COUNT']) + (exposure_duration / 2.0)
    del_et = end_et - start_et
    et = (start_et + end_et) / 2

    isd['starting_ephemeris_time'] = start_et
    isd['dt_ephemeris'] = del_et
    isd['number_of_ephemerides'] = 1
    isd['interpolation_method'] = 'lagrange'
    isd['center_ephemeris_time'] = et

    # Get the rotation angles from MDIS NAC frame to Mercury body-fixed frame
    camera2bodyfixed = spice.pxform(instrument_name, reference_frame, et)
    quat = spice.m2q(camera2bodyfixed)
    # cassini follows spice style for quaternions so no transformation is needed
    isd['sensor_orientation'] = list(quat)

    # Get the Sensor Position
    loc, _ = spice.spkpos(target_name, et, reference_frame, 'None',
                          spacecraft_name)
    loc *= -1000

    isd['sensor_location'] = {}
    isd['sensor_location']['x'] = loc[0]
    isd['sensor_location']['y'] = loc[1]
    isd['sensor_location']['z'] = loc[2]
    isd['sensor_location']['unit'] = 'm'

    # Get the velocity
    v_state, lt = spice.spkezr(spacecraft_name, et, reference_frame, 'NONE',
                               target_name)

    isd['sensor_velocity'] = {}
    isd['sensor_velocity']['x'] = v_state[3] * 1000
    isd['sensor_velocity']['y'] = v_state[4] * 1000
    isd['sensor_velocity']['z'] = v_state[5] * 1000
    isd['sensor_velocity']['unit'] = 'm'
    isd['reference_height'] = {}
    isd['reference_height']['minheight'] = label.get('min_valid_height', -8000)
    isd['reference_height']['maxheight'] = label.get('max_valid_height', 8000)
    isd['reference_height']['unit'] = 'KM'

    # Get the sun position
    sun_state, lt = spice.spkezr("SUN", et, reference_frame, 'NONE',
                                 target_name)

    # lighttime should always be off
    isd['sun_position'] = {}
    isd['sun_position']['x'] = sun_state[0] * 1000
    isd['sun_position']['y'] = sun_state[1] * 1000
    isd['sun_position']['z'] = sun_state[2] * 1000

    isd['sun_velocity'] = {}
    isd['sun_velocity']['x'] = sun_state[3] * 1000
    isd['sun_velocity']['y'] = sun_state[4] * 1000
    isd['sun_velocity']['z'] = sun_state[5] * 1000

    # cassini has no optical distortion model
    isd['optical_distortion'] = None

    return isd
Пример #23
0
def get_isd(label):

    metakernel_dir = config.mro
    mks = sorted(glob(os.path.join(config.mro, '*.tm')))
    time = label['START_TIME']

    mro_mk = None
    for mk in mks:
        if str(time.year) in os.path.basename(mk):
            mro_mk = mk
    spice.furnsh(mro_mk)

    isd = {}

    instrument_name = label['INSTRUMENT_NAME']
    spacecraft_name = label['SPACECRAFT_NAME']
    target_name = label['TARGET_NAME']

    # Spice likes ids over names, so grab the ids from the names
    spacecraft_id = spice.bods2c(
        'MRO')  # Label specifies: MARS_RECONNAISSANCE_ORBITER
    ikid = spice.bods2c('MRO_CTX')  # Label specifies: CONTEXT CAMERA

    # Load the instrument and target metadata into the ISD
    reference_frame = 'IAU_{}'.format(target_name)

    # Instrument / Spacecraft Metadata
    isd['OPTICAL_DIST_COEF'] = [
        0, 0, 0
    ]  # spice.gdpool('INS{}_OD_K'.format(ikid),0, 3)
    isd['ITRANSL'] = spice.gdpool('INS{}_ITRANSL'.format(ikid), 0, 3)
    isd['ITRANSS'] = spice.gdpool('INS{}_ITRANSS'.format(ikid), 0, 3)
    isd['DETECTOR_SAMPLE_ORIGIN'] = spice.gdpool(
        'INS{}_BORESIGHT_SAMPLE'.format(ikid), 0, 1)
    isd['DETECTOR_LINE_ORIGIN'] = spice.gdpool(
        'INS{}_BORESIGHT_LINE'.format(ikid), 0, 1)
    isd['DETECTOR_SAMPLE_SUMMING'] = label['SAMPLING_FACTOR']
    isd['STARTING_SAMPLE'] = 0  # label['SAMPLE_FIRST_PIXEL']
    isd['TOTAL_LINES'] = nlines = label['IMAGE']['LINES']
    isd['TOTAL_SAMPLES'] = label['IMAGE'][
        'LINE_SAMPLES']  # spice.gdpool('INS{}_PIXEL_SAMPLES'.format(ikid), 0, 1)
    isd['SENSOR_TYPE'] = 'USGSAstroLineScanner'
    isd['MOUNTING_ANGLES'] = np.zeros(3)
    isd['ISIS_Z_DIRECTION'] = 1
    isd['STARTING_LINE'] = 1.0
    isd['DETECTOR_LINE_OFFSET'] = 0.0
    # Body Parameters
    target_name = label['TARGET_NAME']
    rad = spice.bodvrd(target_name, 'RADII', 3)
    a = rad[1][1]
    b = rad[1][2]
    isd['SEMI_MAJOR_AXIS'] = a * 1000  # Scale to meters
    isd['ECCENTRICITY'] = np.sqrt(1 - (b**2 / a**2))  # Standard eccentricity

    isd['FOCAL'] = spice.gdpool('INS{}_FOCAL_LENGTH'.format(ikid), 0, 1)

    isd['ABERR'] = 0
    isd['ATMREF'] = 0
    isd['PLATFORM'] = 1

    # It really is hard coded this way...
    isd['TRI_PARAMETERS'] = np.zeros(18)
    isd['TRI_PARAMETERS'][15] = isd['FOCAL']

    # Time
    sclock = label['SPACECRAFT_CLOCK_START_COUNT']
    et = spice.scs2e(spacecraft_id, sclock)
    isd['STARTING_EPHEMERIS_TIME'] = et

    half_lines = nlines / 2
    isd['INT_TIME'] = line_rate = label['LINE_EXPOSURE_DURATION'][
        0] * 0.001  # Scale to seconds
    center_sclock = et + half_lines * line_rate
    isd['CENTER_EPHEMERIS_TIME'] = center_sclock
    isd['SCAN_DURATION'] = line_rate * nlines
    # The socetlinekeywords code is pushing ephemeris and quaternion off of either side of the image.  Therefore,
    # the code needs to know when the start time is.  Since we are not pushing off the edge of the image, the start-time
    # should be identical to the actual image start time.
    isd['T0_QUAT'] = isd['T0_EPHEM'] = isd['STARTING_EPHEMERIS_TIME'] - isd[
        'CENTER_EPHEMERIS_TIME']
    isd['DT_EPHEM'] = 80 * isd['INT_TIME']  # This is every 300 lines

    # Determine how many ephemeris points to compute
    n_ephemeris = int(isd['SCAN_DURATION'] / isd['DT_EPHEM'])
    if n_ephemeris % 2 == 0:
        n_ephemeris += 1
    isd['NUMBER_OF_EPHEM'] = n_ephemeris
    eph = np.empty((n_ephemeris, 3))
    eph_rates = np.empty(eph.shape)
    current_et = et
    for i in range(n_ephemeris):
        loc_direct, _ = spice.spkpos(target_name, current_et, 'IAU_MARS',
                                     'NONE', 'MRO')
        state, _ = spice.spkezr(target_name, current_et, 'IAU_MARS', 'NONE',
                                'MRO')
        eph[i] = loc_direct
        eph_rates[i] = state[3:]
        current_et += isd[
            'DT_EPHEM']  # Increment the time by the number of lines being stepped
    eph *= -1000  # Reverse to be from body center and convert to meters
    eph_rates *= -1000  # Same, reverse and convert
    isd['EPHEM_PTS'] = eph.flatten()
    isd['EPHEM_RATES'] = eph_rates.flatten()

    # Why should / should not the n_quaternions equal the number of ephemeris pts?
    n_quaternions = n_ephemeris
    isd['NUMBER_OF_QUATERNIONS'] = n_quaternions

    isd['DT_QUAT'] = isd['SCAN_DURATION'] / n_quaternions
    qua = np.empty((n_quaternions, 4))
    current_et = et
    for i in range(n_quaternions):
        # Find the rotation matrix
        camera2bodyfixed = spice.pxform('MRO_CTX', 'IAU_MARS', current_et)
        q = spice.m2q(camera2bodyfixed)
        qua[i, :3] = q[1:]
        qua[i, 3] = q[0]
        current_et += isd['DT_QUAT']
    isd['QUATERNIONS'] = qua.flatten()

    # Now the 'optional' stuff
    isd['REFERENCE_HEIGHT'] = label.get('reference_height', 30)
    isd['MIN_VALID_HT'] = label.get('min_valid_height', -8000)
    isd['MAX_VALID_HT'] = label.get('max_valid_height', 8000)
    isd['IMAGE_ID'] = label.get('image_id', 'UNKNOWN')
    isd['SENSOR_ID'] = label.get('sensor_id', 'USGS_LINE_SCANNER')
    isd['PLATFORM_ID'] = label.get('platform_id', 'UNKNOWN')
    isd['TRAJ_ID'] = label.get('traj_id', 'UNKNOWN')
    isd['COLL_ID'] = label.get('coll_id', 'UNKNOWN')
    isd['REF_DATE_TIME'] = label.get('ref_date_time', 'UNKNOWN')

    spice.unload(mro_mk)

    return isd
Пример #24
0
def isd_from_json(data, meta):
    instrument_name = {
        'IMAGING SCIENCE SUBSYSTEM NARROW ANGLE': 'CASSINI_ISS_NAC',
        'IMAGING SCIENCE SUBSYSTEM WIDE ANGLE': 'CASSINI_ISS_WAC',
        'IMAGING SCIENCE SUBSYSTEM - NARROW ANGLE': 'CASSINI_ISS_NAC',
        'MDIS-NAC': 'MSGR_MDIS_NAC',
        'MERCURY DUAL IMAGING SYSTEM NARROW ANGLE CAMERA': 'MSGR_MDIS_NAC',
        'MERCURY DUAL IMAGING SYSTEM WIDE ANGLE CAMERA': 'MSGR_MDIS_WAC'
    }

    spacecraft_names = {'CASSINI ORBITER': 'CASSINI', 'MESSENGER': 'MESSENGER'}

    # This is the return dict
    isd = {}

    # Meta kernels are keyed by body, spacecraft, and year - grab from the data
    spacecraft_name = spacecraft_names[data['spacecraft_id']]
    target_name = data['target_name']
    time = parser.parse(data['capture_date'])

    for k in meta:
        if k.year.year == time.year:
            obs_kernels = k.path

    # Load the meta kernel
    spice.furnsh(obs_kernels)
    path, tpe, handle, found = spice.kdata(0, 'TEXT')
    if not found:
        directory = os.path.dirname(path)
        directory = os.path.abspath(os.path.join(directory, '../iak'))
        additional_ik = glob.glob(directory + '/*.ti')
        spice.furnsh(additional_ik)

    # Spice likes ids over names, so grab the ids from the names
    instrument_name = instrument_name[data['instrument']]
    spacecraft_id = spice.bods2c(spacecraft_name)
    ikid = spice.bods2c(instrument_name)

    # Load the instrument and target metadata into the ISD
    isd['instrument_id'] = instrument_name
    isd['target_name'] = target_name
    isd['spacecraft_name'] = spacecraft_name

    # Prepend IAU to all instances of the body name
    reference_frame = 'IAU_{}'.format(target_name)

    # Load information from the IK kernel
    isd['focal_length'] = spice.gdpool('INS{}_FOCAL_LENGTH'.format(ikid), 0, 1)
    isd['focal_length_epsilon'] = spice.gdpool(
        'INS{}_FL_UNCERTAINTY'.format(ikid), 0, 1)
    isd['nlines'] = spice.gipool('INS{}_PIXEL_LINES'.format(ikid), 0, 1)
    isd['nsamples'] = spice.gipool('INS{}_PIXEL_SAMPLES'.format(ikid), 0, 1)
    isd['original_half_lines'] = isd['nlines'] / 2.0
    isd['original_half_samples'] = isd['nsamples'] / 2.0
    isd['pixel_pitch'] = spice.gdpool('INS{}_PIXEL_PITCH'.format(ikid), 0, 1)
    isd['ccd_center'] = spice.gdpool('INS{}_CCD_CENTER'.format(ikid), 0, 2)
    isd['ifov'] = spice.gdpool('INS{}_IFOV'.format(ikid), 0, 1)
    isd['boresight'] = spice.gdpool('INS{}_BORESIGHT'.format(ikid), 0, 3)
    isd['transx'] = spice.gdpool('INS{}_TRANSX'.format(ikid), 0, 3)
    isd['transy'] = spice.gdpool('INS{}_TRANSY'.format(ikid), 0, 3)
    isd['itrans_sample'] = spice.gdpool('INS{}_ITRANSS'.format(ikid), 0, 3)
    isd['itrans_line'] = spice.gdpool('INS{}_ITRANSL'.format(ikid), 0, 3)
    try:
        isd['odt_x'] = spice.gdpool('INS-{}_OD_T_X'.format(ikid), 0, 10)
    except:
        isd['odt_x'] = np.zeros(10)
        isd['odt_x'][1] = 1
    try:
        isd['odt_y'] = spice.gdpool('INS-{}_OD_T_Y'.format(ikid), 0, 10)
    except:
        isd['odt_y'] = np.zeros(10)
        isd['odt_y'][2] = 1
    try:
        isd['starting_detector_sample'] = spice.gdpool(
            'INS{}_FPUBIN_START_SAMPLE'.format(ikid), 0, 1)
    except:
        isd['starting_detector_sample'] = 0
    try:
        isd['starting_detector_line'] = spice.gdpool(
            'INS{}_FPUBIN_START_LINE'.format(ikid), 0, 1)
    except:
        isd['starting_detector_line'] = 0

    # Get temperature from SPICE and adjust focal length
    if 'focal_plane_temperature' in data.keys():
        try:  # TODO: Remove once WAC temperature dependent is working
            temp_coeffs = spice.gdpool('INS-{}_FL_TEMP_COEFFS'.format(ikid), 0,
                                       6)
            temp = data['focal_plane_temperature']
            isd['focal_length'] = distort_focal_length(temp_coeffs, temp)
        except:
            isd['focal_length'] = spice.gdpool(
                'INS-{}_FOCAL_LENGTH'.format(ikid), 0, 1)
    else:
        isd['focal_length'] = spice.gdpool('INS-{}_FOCAL_LENGTH'.format(ikid),
                                           0, 1)

    # Get the radii from SPICE
    rad = spice.bodvrd(isd['target_name'], 'RADII', 3)
    radii = rad[1]
    isd['semi_major_axis'] = rad[1][0]
    isd['semi_minor_axis'] = rad[1][1]

    # Now time
    sclock = data['spacecraft_clock_count']
    exposure_duration = data['exposure_duration']
    exposure_duration = exposure_duration * 0.001  # Scale to seconds

    # Get the instrument id, and, since this is a framer, set the time to the middle of the exposure
    et = spice.scs2e(spacecraft_id, sclock)
    et += (exposure_duration / 2.0)

    isd['ephemeris_time'] = et

    # Get the Sensor Position
    loc, _ = spice.spkpos(isd['target_name'], et, reference_frame, 'LT+S',
                          spacecraft_name)
    loc *= -1000
    isd['x_sensor_origin'] = loc[0]
    isd['y_sensor_origin'] = loc[1]
    isd['z_sensor_origin'] = loc[2]

    # Get the rotation angles from MDIS NAC frame to Mercury body-fixed frame
    camera2bodyfixed = spice.pxform(instrument_name, reference_frame, et)
    opk = spice.m2eul(camera2bodyfixed, 3, 2, 1)

    isd['omega'] = opk[2]
    isd['phi'] = opk[1]
    isd['kappa'] = opk[0]

    # Get the sun position
    sun_state, lt = spice.spkezr("SUN", et, reference_frame,
                                 data['lighttime_correction'], target_name)

    # Convert to meters
    isd['x_sun_position'] = sun_state[0] * 1000
    isd['y_sun_position'] = sun_state[1] * 1000
    isd['z_sun_position'] = sun_state[2] * 1000

    # Get the velocity
    v_state, lt = spice.spkezr(spacecraft_name, et, reference_frame,
                               data['lighttime_correction'], target_name)

    isd['x_sensor_velocity'] = v_state[3] * 1000
    isd['y_sensor_velocity'] = v_state[4] * 1000
    isd['z_sensor_velocity'] = v_state[5] * 1000

    # Misc. insertion
    # A lookup here would be smart - similar to the meta kernals, what is the newest model, etc.
    if 'model_name' not in data.keys():
        isd['model_name'] = 'ISIS_MDISNAC_USGSAstro_1_Linux64_csm30.so'
    isd['min_elevation'] = data['min_elevation']
    isd['max_elevation'] = data['max_elevation']

    spice.unload(obs_kernels)  # Also unload iak
    return isd
Пример #25
0
 def starting_ephemeris_time(self):
     if not hasattr(self, '_starting_ephemeris_time'):
         sclock = self.label['SPACECRAFT_CLOCK_START_COUNT']
         self._starting_ephemeris_time = spice.scs2e(
             self.spacecraft_id, sclock)
     return self._starting_ephemeris_time