From f349ddeb1f13ae997a2b13fa95cff68271c7dbca Mon Sep 17 00:00:00 2001 From: Summer Stapleton <sgstapleton@usgs.gov> Date: Wed, 28 Aug 2019 10:00:53 -0700 Subject: [PATCH] Functioning Kernel Split Notebook (#255) * Notebook for CK/SPK Kernel Slicing * Initial spkmerged configuration file output * Functioning kernel split script --- notebooks/KernelSlice.ipynb | 236 ++++++++++++++++++++++++++++++++++++ 1 file changed, 236 insertions(+) create mode 100644 notebooks/KernelSlice.ipynb diff --git a/notebooks/KernelSlice.ipynb b/notebooks/KernelSlice.ipynb new file mode 100644 index 0000000..ebb8963 --- /dev/null +++ b/notebooks/KernelSlice.ipynb @@ -0,0 +1,236 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [], + "source": [ + "import spiceypy as spice\n", + "import pvl\n", + "import os\n", + "import re\n", + "import subprocess\n", + "from ale import util\n", + "from itertools import chain\n", + "import io\n", + "import networkx as nx\n", + "\n", + "\n", + "# These should be provided when running this script. \n", + "cube = \"/work/users/sgstapleton/kernel_split/EN1072174528M.cub\"\n", + "output_dir = \"/work/users/sgstapleton/kernel_split/\" # Output dir for created kernel files\n", + "data_dir = \"/usgs/cpkgs/isis3/data/\" # Dir of where to pull original kernels from\n", + "\n", + " \n", + "def get_reference_id(bc_filename):\n", + " brief = subprocess.check_output([\"ckbrief\", bc_filename])\n", + " reference = None\n", + "\n", + " for line in brief.splitlines():\n", + " line = str(line)\n", + " if('Object:' in line):\n", + " reference = int(line.strip(\"''\").split()[1])\n", + " \n", + " return reference\n", + "\n", + "\n", + "def add_light_time_correction(cube_info, kernels):\n", + " \n", + " furnished_kerns = spice.furnsh(kernels)\n", + " \n", + " image_start_et = spice.scs2e(cube_info['SpacecraftID'], cube_info['SpacecraftClockCount'])\n", + " image_end_et = image_start_et + cube_info['ExposureDuration']\n", + " \n", + " inst_state, inst_lt = spice.spkez(cube_info['SpacecraftID'], (image_start_et + image_end_et)/2, 'J2000', 'LT+S', 0)\n", + " target_state, target_lt = spice.spkez(cube_info['TargetID'], (image_start_et + image_end_et)/2, 'J2000', 'LT+S', 0)\n", + " \n", + " lt_pad = max(abs(inst_lt), abs(target_lt)) + 15\n", + " \n", + " # Eph time\n", + " padded_start_et = image_start_et - lt_pad\n", + " padded_end_et = image_end_et + lt_pad\n", + " \n", + " # Padded times\n", + " padded_start_sclk = spice.sce2s(cube_info['SpacecraftID'], padded_start_et)\n", + " padded_end_sclk = spice.sce2s(cube_info['SpacecraftID'], padded_end_et)\n", + " padded_start_utc = spice.et2utc(padded_start_et, 'c', 3)\n", + " padded_end_utc = spice.et2utc(padded_end_et, 'c', 3)\n", + "\n", + " cube_info.update(PaddedStartTimeSCLK = padded_start_sclk)\n", + " cube_info.update(PaddedEndTimeSCLK = padded_end_sclk)\n", + " cube_info.update(PaddedStartTimeUTC = padded_start_utc)\n", + " cube_info.update(PaddedEndTimeUTC = padded_end_utc)\n", + " \n", + "\n", + "def get_body_ids(spk_file, body_id):\n", + " brief = subprocess.check_output([\"brief\", \"-c {}\".format(spk_file)])\n", + " \n", + " # Convert from bytes\n", + " brief = brief.decode(\"utf-8\")\n", + " brief_io = io.StringIO(brief)\n", + " line = brief_io.readline()\n", + " edge_list = []\n", + " \n", + " while(line):\n", + " \n", + " if(\"w.r.t\" in line):\n", + " bodies_results = re.findall('\\((.*?)\\)', line)\n", + " edge_list.append(bodies_results)\n", + " \n", + " line = brief_io.readline()\n", + " \n", + " G = nx.DiGraph()\n", + " G.add_edges_from(edge_list)\n", + " \n", + " body_ids = []\n", + " for path in nx.all_simple_paths(G, body_id, '0'):\n", + " body_ids = body_ids + path\n", + " \n", + " body_ids = set(body_ids)\n", + "\n", + " return body_ids\n", + "\n", + "\n", + "def output_spkmerge_config(config_file, cube_info, output_dir):\n", + " \n", + " with open(config_file, \"w+\") as config:\n", + " config.write('''LEAPSECONDS_KERNEL = {}\\n'''.format(cube_info['LeapSecond'][0]))\n", + " \n", + " for kern in cube_info['InstrumentPosition']:\n", + " \n", + " basename = os.path.basename(kern).split('.')[0]\n", + " filename, file_extension = os.path.splitext(kern)\n", + " new_kern = output_dir + basename + \"_merged\" + file_extension\n", + " \n", + " config.write(''' SPK_KERNEL = {}\\n'''.format(new_kern))\n", + "\n", + " body_ids = get_body_ids(kern, str(cube_info['SpacecraftID']))\n", + "\n", + " for body in body_ids:\n", + "\n", + " if body != '0':\n", + "\n", + " config.write(''' SOURCE_SPK_KERNEL = {}\\n'''.format(kern))\n", + " config.write(''' INCLUDE_COMMENTS = no\\n''')\n", + " config.write(''' BODIES = {}\\n'''.format(body))\n", + " config.write(''' BEGIN_TIME = {}\\n'''.format(cube_info['PaddedStartTimeUTC']))\n", + " config.write(''' END_TIME = {}\\n'''.format(cube_info['PaddedEndTimeUTC']))\n", + " \n", + " config.close()\n", + " " + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": {}, + "outputs": [], + "source": [ + "# These are the processing steps. This will make use of the cube provided further up to create smaller, \n", + "# more manageable kernel files for ale testing purposes. This currently only handles ck and spk files.\n", + "\n", + "# Get dictionary of kernel lists from cube\n", + "cube_info = util.generate_kernels_from_cube(cube, 'dict')\n", + "\n", + "# Replace path variables with absolute paths for kernels\n", + "for kernel_list in cube_info:\n", + " for index, kern in enumerate(cube_info[kernel_list]):\n", + " if kern is not None:\n", + " cube_info[kernel_list][index] = data_dir + kern.strip('$')\n", + " \n", + "# Create ordered list of kernels for furnishing\n", + "kernels = [kernel for kernel in chain.from_iterable(cube_info.values()) if isinstance(kernel, str)]\n", + " \n", + "# Loads cube as pvl to extract rest of data\n", + "cube_pvl = pvl.load(cube)\n", + " \n", + "# Save other necesary info in cube_info dict\n", + "cube_info.update(SpacecraftClockCount = cube_pvl['IsisCube']['Instrument']['SpacecraftClockCount'])\n", + "cube_info.update(ExposureDuration = cube_pvl['IsisCube']['Instrument']['ExposureDuration'].value * 0.001)\n", + "cube_info.update(TargetID = spice.bods2c(cube_pvl['IsisCube']['Instrument']['TargetName']))\n", + "cube_info.update(SpacecraftID = spice.bods2c(cube_pvl['IsisCube']['Instrument']['SpacecraftName']))\n", + "\n", + "# Add lighttime-corrected SCLK values to cube_info\n", + "add_light_time_correction(cube_info, kernels)\n", + "\n", + "# For each binary ck kernel specified in cube, run the ckslicer, comment and to-transfer commands\n", + "for ck in cube_info['InstrumentPointing']:\n", + " if ck.endswith('.bc'):\n", + " \n", + " # Get reference id associated with ck\n", + " reference_id = get_reference_id(ck)\n", + " \n", + " ck_filename = os.path.basename(ck).split('.')[0]\n", + " ck_path, ck_file_extension = os.path.splitext(ck)\n", + " output_kern = output_dir + ck_filename + '_sliced' + ck_file_extension\n", + " \n", + " # Create new sliced ck kernel\n", + " ckslicer_command = [\"./ckslicer\", \n", + " '-LSK {}'.format(cube_info['LeapSecond'][0]), \n", + " '-SCLK {}'.format(cube_info['SpacecraftClock'][0]), \n", + " '-INPUTCK {}'.format(ck), \n", + " '-OUTPUTCK {}'.format(output_kern),\n", + " '-ID {}'.format(reference_id),\n", + " '-TIMETYPE {}'.format('SCLK'),\n", + " '-START {}'.format(cube_info['PaddedStartTimeSCLK']),\n", + " '-STOP {}'.format(cube_info['PaddedEndTimeSCLK'])]\n", + " subprocess.call(ckslicer_command)\n", + " \n", + " # Remove old comments from new ck kernel\n", + " commnt_command = ['commnt', '-d {}'.format(output_kern)]\n", + " subprocess.call(commnt_command)\n", + " \n", + " # Makes a new txt file for the only comments that should be stored in the new ck file\n", + " with open(\"temp_commnts.txt\",\"w+\") as f:\n", + " f.write(\"This CK is for testing with the image: {}\\n\".format(cube))\n", + " f.write(\"\\nThis CK was generated using the following command: {}\\n\".format(\" \".join(ckslicer_command)))\n", + " \n", + " # Add new comments to new ck kernel\n", + " new_commnts_command = [\"commnt\", \"-a {}\".format(output_kern), \"temp_commnts.txt\"]\n", + " subprocess.call(new_commnts_command)\n", + " \n", + " # Create the transfer file of the new ck kernel\n", + " subprocess.call([\"toxfr\", output_kern])\n", + "\n", + "# Create the config file for the spkmerge command\n", + "output_spkmerge_config(output_dir + \"spk.config\", cube_info, output_dir)\n", + "\n", + "# Run the spkmerge command\n", + "spkmerge_command = [\"spkmerge\", output_dir + \"spk.config\"]\n", + "subprocess.call(spkmerge_command)\n", + "\n", + "# Clean up temp config file\n", + "os.remove(output_dir + \"spk.config\")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.7.1" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} -- GitLab