Commit 0e0f0650 authored by Jesse Mapel's avatar Jesse Mapel Committed by acpaquette
Browse files

Updated LRO test (#262)

* Moved SPK dependency tree logic to utils

* More tests

* Added ck frame function

* updated notebook

* Updated notebook

* Added LRO NAC data

* Updated notebook

* Added new LRO test

* Updated kernel slicing and sun LT

* Updated tests and regenerates kaguya and MRO kernels

* moved comparison ISD to fixture and fixed patch
parent bf1ace64
Loading
Loading
Loading
Loading
+7 −0
Original line number Diff line number Diff line
@@ -211,7 +211,14 @@ dmypy.json

# Binary Kernels
*.bsp
*.BSP
*.bc
*.BC
*.bpc
*.BPC

# Binary Images
*.cub
*.CUB
*.img
*.IMG
+1 −1
Original line number Diff line number Diff line
@@ -289,7 +289,7 @@ class NaifSpice():
        sun_state, _ = spice.spkezr("SUN",
                                     self.center_ephemeris_time,
                                     self.reference_frame,
                                     'NONE',
                                     'LT+S',
                                     self.target_name)
        positions = 1000 * np.asarray([sun_state[:3]])
        velocities = 1000 * np.asarray([sun_state[3:6]])
+112 −73
Original line number Diff line number Diff line
%% Cell type:code id: tags:

``` python
import spiceypy as spice
import pvl
import os
import re
import subprocess
from ale import util
from itertools import chain
import io
import networkx as nx


# These should be provided when running this script.
cube = "/work/users/sgstapleton/kernel_split/EN1072174528M.cub"
cube = "/home/acpaquette/B10_013341_1010_XN_79S172W.cub"
output_dir = "/Users/jmapel/ale/nb_test" # Output dir for created kernel files
data_dir = "/usgs/cpkgs/isis3/data/" # Dir of where to pull original kernels from
ckslicer_loc = "/Users/jmapel/ale/ckslicer"

def add_light_time_correction(cube_info):

def merge_intervals(intervals):
    """
    Merge a set of intervals. The intervals are assumed to be closed, that is they include the end-points.

    Parameters
    ----------
    intervals : list
                The input list of intrvals where each interval is a tuple of (start, end)

    Returns
    -------
    : list
      A sorted list of the merged intervals
    """
    sorted_intervals = sorted(intervals, key=lambda tup: tup[0])
    merged = [sorted_intervals[0]]
    for interval in sorted_intervals[1:]:
        # No intersection
        if interval[0] > merged[-1][1]:
            merged.append(interval)
        # Intersection, but new interval isn't wholey contained
        elif interval[1] > merged[-1][1]:
            merged[-1] = (merged[-1][0], interval[1])
    return merged

def add_light_time_correction(cube_info, padding=5):
    """
    Compute the time intervals for the image and any light time correction

    Parameters
    ----------
    cube_info : ordered dict
                The cube info from ale.util.generate_kernels_from_cube
    padding : float
              Time padding in seconds to add to each interval

    Returns
    -------
    : list
      A sorted list of the intervals as (start_et, stop_et)
    """
    image_start_et = spice.scs2e(cube_info['SpacecraftID'], cube_info['SpacecraftClockCount'])
    image_end_et = image_start_et + cube_info['ExposureDuration']

    inst_state, inst_lt = spice.spkez(cube_info['SpacecraftID'], (image_start_et + image_end_et)/2, 'J2000', 'LT+S', 0)
    target_state, target_lt = spice.spkez(cube_info['TargetID'], (image_start_et + image_end_et)/2, 'J2000', 'LT+S', 0)
    image_end_et = image_start_et + cube_info['ExposureDuration'] * cube_info['Lines']

    lt_pad = max(abs(inst_lt), abs(target_lt)) + 15
    inst_state, inst_lt = spice.spkez(cube_info['SpacecraftID'], image_start_et, 'J2000', 'LT+S', 0)
    target_state, target_lt = spice.spkez(cube_info['TargetID'], image_start_et, 'J2000', 'LT+S', 0)
    sun_state, sun_lt = spice.spkez(10, image_start_et, 'J2000', 'LT+S', cube_info['TargetID'])

    intervals = [
        (image_start_et - padding, image_end_et + padding),
        (image_start_et - padding - inst_lt, image_end_et + padding - inst_lt),
        (image_start_et - padding - target_lt, image_end_et + padding - target_lt),
        (image_start_et - padding - sun_lt, image_end_et + padding - sun_lt)]

    # Eph time
    padded_start_et = image_start_et - lt_pad
    padded_end_et = image_end_et + lt_pad

    # Padded times
    padded_start_sclk = spice.sce2s(cube_info['SpacecraftID'], padded_start_et)
    padded_end_sclk = spice.sce2s(cube_info['SpacecraftID'], padded_end_et)
    padded_start_utc = spice.et2utc(padded_start_et, 'c', 3)
    padded_end_utc = spice.et2utc(padded_end_et, 'c', 3)

    cube_info.update(PaddedStartTimeSCLK = padded_start_sclk)
    cube_info.update(PaddedEndTimeSCLK = padded_end_sclk)
    cube_info.update(PaddedStartTimeUTC = padded_start_utc)
    cube_info.update(PaddedEndTimeUTC = padded_end_utc)
    return merge_intervals(intervals)
```

%% Cell type:code id: tags:

``` python
# These are the processing steps. This will make use of the cube provided further up to create smaller,
# more manageable kernel files for ale testing purposes. This currently only handles ck and spk files.

# Get dictionary of kernel lists from cube
cube_info = util.generate_kernels_from_cube(cube, format_as = 'dict')

# Replace path variables with absolute paths for kernels
for kernel_list in cube_info:
    for index, kern in enumerate(cube_info[kernel_list]):
        if kern is not None:
            cube_info[kernel_list][index] = data_dir + kern.strip('$')

# Create ordered list of kernels for furnishing
kernels = [kernel for kernel in chain.from_iterable(cube_info.values()) if isinstance(kernel, str)]
spice.furnsh(kernels)

# Loads cube as pvl to extract rest of data
cube_pvl = pvl.load(cube)

# Save other necesary info in cube_info dict
cube_info.update(Lines = cube_pvl['IsisCube']['Core']['Dimensions']['Lines'])
cube_info.update(Lines = 400)
cube_info.update(SpacecraftClockCount = cube_pvl['IsisCube']['Instrument']['SpacecraftClockCount'])
cube_info.update(ExposureDuration = cube_pvl['IsisCube']['Instrument']['ExposureDuration'].value * 0.001)
cube_info.update(ExposureDuration = cube_pvl['IsisCube']['Instrument']['LineExposureDuration'].value * 0.001)
cube_info.update(TargetID = spice.bods2c(cube_pvl['IsisCube']['Instrument']['TargetName']))
cube_info.update(SpacecraftID = spice.bods2c(cube_pvl['IsisCube']['Instrument']['SpacecraftName']))

# Add lighttime-corrected SCLK values to cube_info
add_light_time_correction(cube_info)
# Account for light time correction
intervals = add_light_time_correction(cube_info)

# For each binary ck kernel specified in cube, run the ckslicer, comment and to-transfer commands
for ck in [k for k in kernels if k.lower().endswith('.bc')]:
    ck_path, ck_file_extension = os.path.splitext(ck)
    ck_basename = os.path.basename(ck_path)
    for frame in util.get_ck_frames(ck):
        output_basename = os.path.join(output_dir, ck_basename + '_sliced' + str(frame))
        output_kern = output_basename + ck_file_extension
        output_comments = output_basename + '.cmt'

        # Create new sliced ck kernel
        ckslicer_command = [ckslicer_loc,
                                '-LSK {}'.format(cube_info['LeapSecond'][0]),
                                '-SCLK {}'.format(cube_info['SpacecraftClock'][0]),
                                '-INPUTCK {}'.format(ck),
                                '-OUTPUTCK {}'.format(output_kern),
                                '-ID {}'.format(frame),
                                '-TIMETYPE {}'.format('SCLK'),
                                '-START {}'.format(cube_info['PaddedStartTimeSCLK']),
                                '-STOP {}'.format(cube_info['PaddedEndTimeSCLK'])]
        subprocess.run(ckslicer_command, check=True)

        # Remove old comments from new ck kernel
        commnt_command = ['commnt', '-d {}'.format(output_kern)]
        subprocess.run(commnt_command, check=True)

        with open(output_comments, 'w+') as comment_file:
            comment_file.write("This CK is for testing with the image: {}\n".format(cube))
            comment_file.write("\nThis CK was generated using the following command: {}\n")
            comment_file.write(" ".join(ckslicer_command))

        # Add new comments to new ck kernel
        new_commnts_command = ["commnt", "-a {}".format(output_kern), output_comments]
        subprocess.run(new_commnts_command, check=True)
    for index, interval in enumerate(intervals):
        for frame in util.get_ck_frames(ck):
            output_basename = os.path.join(output_dir, ck_basename + '_' + str(index) + '_sliced_' + str(frame))
            output_kern = output_basename + ck_file_extension
            output_comments = output_basename + '.cmt'
            start_sclk = spice.sce2s(cube_info['SpacecraftID'], interval[0])
            end_sclk = spice.sce2s(cube_info['SpacecraftID'], interval[1])

            # Create new sliced ck kernel
            ckslicer_command = [ckslicer_loc,
                                    '-LSK {}'.format(cube_info['LeapSecond'][0]),
                                    '-SCLK {}'.format(cube_info['SpacecraftClock'][0]),
                                    '-INPUTCK {}'.format(ck),
                                    '-OUTPUTCK {}'.format(output_kern),
                                    '-ID {}'.format(frame),
                                    '-TIMETYPE {}'.format('SCLK'),
                                    '-START {}'.format(start_sclk),
                                    '-STOP {}'.format(end_sclk)]
            subprocess.run(ckslicer_command, check=True)

            # Remove old comments from new ck kernel
            commnt_command = ['commnt', '-d {}'.format(output_kern)]
            subprocess.run(commnt_command, check=True)

            with open(output_comments, 'w+') as comment_file:
                comment_file.write("This CK is for testing with the image: {}\n".format(cube))
                comment_file.write("\nThis CK was generated using the following command: {}\n")
                comment_file.write(" ".join(ckslicer_command))

            # Add new comments to new ck kernel
            new_commnts_command = ["commnt", "-a {}".format(output_kern), output_comments]
            subprocess.run(new_commnts_command, check=True)

        # Create the transfer file of the new ck kernel
        subprocess.run(["toxfr", output_kern], check=True)
            # Create the transfer file of the new ck kernel
            subprocess.run(["toxfr", output_kern], check=True)

# Create the config file for the spkmerge command
output_spk_basename = os.path.join(output_dir, os.path.basename(os.path.splitext(cube)[0]))
output_spk = output_spk_basename + '.bsp'
spk_dep_tree = util.create_spk_dependency_tree([k for k in kernels if k.lower().endswith('.bsp')])
config_string = util.spkmerge_config_string(spk_dep_tree,
                                            output_spk,
                                            [cube_info['TargetID'], cube_info['SpacecraftID'], 10],
                                            cube_info['LeapSecond'][0],
                                            cube_info['PaddedStartTimeUTC'],
                                            cube_info['PaddedEndTimeUTC'])
with open(output_spk_basename + '.conf', 'w+') as spk_config:
    spk_config.write(config_string)

# Create the new SPK
spkmerge_command = ["spkmerge", spk_config.name]
subprocess.run(spkmerge_command, check=True)
for index, interval in enumerate(intervals):
    output_spk_basename = os.path.join(output_dir, os.path.basename(os.path.splitext(cube)[0]) + '_' + str(index))
    output_spk = output_spk_basename + '.bsp'
    start_utc = spice.et2utc(interval[0], 'c', 3)
    end_utc = spice.et2utc(interval[1], 'c', 3)
    spk_dep_tree = util.create_spk_dependency_tree([k for k in kernels if k.lower().endswith('.bsp')])
    config_string = util.spkmerge_config_string(spk_dep_tree,
                                                output_spk,
                                                [cube_info['TargetID'], cube_info['SpacecraftID'], 10],
                                                cube_info['LeapSecond'][0],
                                                start_utc,
                                                end_utc)
    with open(output_spk_basename + '.conf', 'w+') as spk_config:
        spk_config.write(config_string)

    # Create the new SPK
    spkmerge_command = ["spkmerge", spk_config.name]
    subprocess.run(spkmerge_command, check=True)

# Create the transfer file of the new SPK kernel
subprocess.run(["toxfr", output_spk], check=True)
    # Create the transfer file of the new SPK kernel
    subprocess.run(["toxfr", output_spk], check=True)
```

%% Cell type:code id: tags:

``` python
```
+0 −1227

File deleted.

Preview size limit exceeded, changes collapsed.

+238 −0
Original line number Diff line number Diff line
DAFETF NAIF DAF ENCODED TRANSFER FILE
'DAF/SPK '
'2'
'6'
'SPKMERGE                                                    '
BEGIN_ARRAY 1 39
'DE-0721LE-0721                          '
'11B5343E19100B^8'
'11B5344A3D6A28^8'
'A'
'0'
'1'
'2'
39
'11B67F4^8'
'A8C^5'
'-6A6A4E6EFBEC4^5'
'-16A5738DB2D721^4'
'116F9301E6CBB7^2'
'3BB342EF417074^0'
'-143EA1D5B06BCA^-2'
'4D71A9D28478FC^-4'
'A3F6F3E73A3DA8^-5'
'-3F86DFA205EE34^-5'
'-A0E656DBD4F968^-6'
'-12BC5CA973CF2C^-6'
'-16000276227541^-7'
'85899355DA66C8^5'
'-1233A0B32FBED3^4'
'-159729DD948514^2'
'10D48A928A157D^0'
'121402417C6B81^-1'
'299B9095B4E934^-3'
'7FFCBC7C9DC124^-4'
'73A28EFAC28F5C^-5'
'8A8210B6B7DE28^-6'
'1D67E18ABAC61D^-7'
'-5B014ADB4150E4^-8'
'395D4561F94A8C^5'
'-76166D30998704^3'
'-9D434CD950477^1'
'470183DFA00594^-1'
'865C61D95415F^-2'
'145DD211F7C747^-3'
'451D2183A9FA4^-4'
'4460D56AC45F78^-5'
'5A8EC394F7674C^-6'
'2E7B940C6FF5AA^-7'
'-CD572D2D95E658^-9'
'11ABF34^8'
'1518^6'
'23^2'
'1^1'
END_ARRAY 1 39
BEGIN_ARRAY 2 39
'DE-0721LE-0721                          '
'11B5343E19100B^8'
'11B5344A3D6A28^8'
'4'
'0'
'1'
'2'
39
'11ABF34^8'
'1518^6'
'C422D83940519^7'
'2B742584C925EA^6'
'-164B6C7084B299^6'
'258F29C5EB554A^3'
'43E6E269C9768^3'
'-6BBC5C04995FA4^1'
'-AAE2302E872B6^0'
'2A795B0FFCE838^-1'
'1CC9C4DBDD31C4^-2'
'-D00738FF4B924^-4'
'-46F8761103D114^-5'
'-5F0168A66662D8^6'
'1F65663892BC37^7'
'BDB732DA3325F8^4'
'-97F3809A470678^4'
'7A3B6AB47BF9A4^2'
'1826499044A212^2'
'-428E74408B86D8^0'
'-3F25454754FCD8^-1'
'16026832FB20DD^-2'
'A888E7B0F65A38^-4'
'-649CCEB96F843C^-5'
'-80C37ED4D23708^6'
'E53CD34955D98^6'
'F1318026EE0C38^4'
'-45C27A702C7F8^4'
'1AB80649559E43^2'
'B4238C7C7A6A38^1'
'-19E9B5295B41AD^0'
'-1E1C2011271F09^-1'
'952115AF483AA8^-3'
'530827AEE151EC^-4'
'-2C026380E7B77C^-5'
'1196DB4^8'
'2A3^6'
'23^2'
'1^1'
END_ARRAY 2 39
BEGIN_ARRAY 3 54
'MAR097                                  '
'11B5343E19100B^8'
'11B5344A3D6A28^8'
'1F3'
'4'
'1'
'3'
54
'11B557F^8'
'2A3^4'
'21517E31EA0FAC^-3'
'5D8DE96A3A4A6C^-3'
'4D9CC8490BA58^-3'
'-2E71B42D807D98^-3'
'-DAD49E37C541E^-4'
'3DFAC64801A17^-4'
'E627A49E175318^-5'
'-1C8B9FA7C2FC^-5'
'2C8897BB184AE6^-3'
'-33CC0033E7D6BE^-3'
'71E4FA55E352A8^-3'
'1CDD058543A157^-3'
'-129B58FEA2A5D1^-3'
'-30990BFB38E1E2^-4'
'F52C5CE95C617^-5'
'322A88D9957058^-5'
'4F386A19CC801^-4'
'-4D36658ACC30E8^-3'
'B3A2AB45D47618^-4'
'285604EFFD0438^-3'
'-14DB020970E306^-4'
'-3AC0C22B4631C^-4'
'-B1855628B66C8^-6'
'2893D6C8A301B^-5'
'-A4FE421E450B4^-7'
'5055F851CF184^-6'
'-5B963BDFD4FCC^-6'
'-2567B56F4D9268^-6'
'E19729C30AE1F8^-7'
'41775D79330204^-7'
'-9790C66B33E02^-8'
'0^0'
'7F4C61BCF979E^-7'
'78AFAD390B2A58^-6'
'373380FE48363E^-6'
'-341889E643D4C^-6'
'-A7AA00C8F1FDE8^-7'
'45BCF96EC06488^-7'
'10A5D1A2170B1D^-7'
'0^0'
'A113E600085FA^-7'
'CE149E0F20501^-7'
'4EB3AA4B09EA2^-6'
'-426EDCDAFF7C8^-7'
'-D15C3EDD2DA128^-7'
'-327EAC6B275FB8^-8'
'D77393E68EA2F^-8'
'0^0'
'11B52DC^8'
'546^4'
'32^2'
'1^1'
END_ARRAY 3 54
BEGIN_ARRAY 4 37
'spkwarp'ed; p_29-MAY-2009.nio           '
'11B5343E19100B^8'
'11B5344A3D6A28^8'
'-4A'
'4'
'1'
'D'
37
'-B32A7A9903DCC8^2'
'A0634CD455EFE^3'
'-A0320C7C7CAA78^3'
'-2A58ACE89BC61C^1'
'-1A8A654200B1CB^1'
'-173AA70BF2918A^1'
'-CD9FB05F2A7DD^2'
'9F581203E7A538^3'
'-A11881A144AD7^3'
'-2A516FA1D41742^1'
'-1AE7AAB8573855^1'
'-16DCB01880739F^1'
'-E81012BB551658^2'
'9E493583BE3FD8^3'
'-A1FB487DB89EC^3'
'-2A493B9C20D856^1'
'-1B4454D786098A^1'
'-167E328AEF7ADC^1'
'-1027B0783F70CE^3'
'9D36BD701168C^3'
'-A2DA5BDAB80E1^3'
'-2A4011059E9EAA^1'
'-1BA061773F5736^1'
'-161F30920A190C^1'
'-11CDFF4AED92A1^3'
'9C20AFFA90BE38^3'
'-A3B5B697099208^3'
'-2A35F012CF156A^1'
'-1BFBCE73A1B1A5^1'
'-15BFAC5F7729AF^1'
'11B53432^8'
'11B5343C^8'
'11B53446^8'
'11B5345^8'
'11B5345A^8'
'3^1'
'5^1'
END_ARRAY 4 37
TOTAL_ARRAYS 4
 ~NAIF/SPC BEGIN COMMENTS~
; /Users/jmapel/ale/nb_test/B10_013341_1010_XN_79S172W_0.bsp LOG FILE

; Created 2019-09-04/13:08:37.00.
;
; BEGIN SPKMERGE COMMANDS

LEAPSECONDS_KERNEL   = /usgs/cpkgs/isis3/data/base/kernels/lsk/naif0012.tls

SPK_KERNEL         = /Users/jmapel/ale/nb_test/B10_013341_1010_XN_79S172W_0.bsp
  SOURCE_SPK_KERNEL  = /usgs/cpkgs/isis3/data/base/kernels/spk/mar097.bsp
    INCLUDE_COMMENTS = NO
    BODIES           = 4, 10, 499
    BEGIN_TIME       = 2009 JUN 01 00:26:35.913
    END_TIME         = 2009 JUN 01 00:26:48.055
SOURCE_SPK_KERNEL = /usgs/cpkgs/isis3/data/mro/kernels/spk/mro_psp11_ssd_mro110c.bsp
    INCLUDE_COMMENTS = NO
    BODIES           = -74
    BEGIN_TIME       = 2009 JUN 01 00:26:35.913
    END_TIME         = 2009 JUN 01 00:26:48.055

; END SPKMERGE COMMANDS
 ~NAIF/SPC END COMMENTS~
Loading