From 0100f1644ecff8516a87b0b35a223ad2eeab68df Mon Sep 17 00:00:00 2001 From: antonhibl Date: Mon, 6 Feb 2023 14:39:15 -0700 Subject: [PATCH 01/13] initial UVVIS Driver notebook and code commit --- ale/drivers/uvvis_drivers.py | 95 +++++++++ write_UvvisIsisLabelNaifSpiceDriver.ipynb | 225 ++++++++++++++++++++++ 2 files changed, 320 insertions(+) create mode 100644 ale/drivers/uvvis_drivers.py create mode 100644 write_UvvisIsisLabelNaifSpiceDriver.ipynb diff --git a/ale/drivers/uvvis_drivers.py b/ale/drivers/uvvis_drivers.py new file mode 100644 index 000000000..f6e834325 --- /dev/null +++ b/ale/drivers/uvvis_drivers.py @@ -0,0 +1,95 @@ +import os +import spiceypy as spice +import json +import numpy as np +import pvl + +import ale +from ale.base import Driver +from ale.base.label_isis import IsisLabel +from ale.base.data_naif import NaifSpice +from ale.base.type_distortion import RadialDistortion, NoDistortion +from ale.base.type_sensor import Framer, LineScanner +from ale.util import generate_kernels_from_cube +from ale.base.type_sensor import Framer +from ale.base.type_distortion import NoDistortion + +from ale import util + + +class UvvisIsisLabelNaifSpiceDriver(Framer, IsisLabel, NaifSpice, NoDistortion, Driver): + """ + Driver for reading Ultra-violet Invisible Spectrum ISIS3 Labels + """ + + @property + def sensor_name(self): + """ + Returns the name of the instrument + + Returns + ------- + : str + instrument name + """ + return "UVVIS" + + @property + def sensor_model_version(self): + """ + Returns ISIS sensor model version + + Returns + ------- + : int + ISIS sensor model version + """ + return 1 + + @property + def spacecraft_clock_start_count(self): + """ + The spacecraft clock start count, frequently used to determine the start time + of the image. + + Returns + ------- + : str + spacecraft clock start count + """ + if "SpacecraftClockStartCount" in self.label["IsisCube"]["Instrument"]: + return str( + self.label["IsisCube"]["Instrument"]["SpacecraftClockStartCount"]) + else: + return None + + @property + def spacecraft_clock_stop_count(self): + """ + The spacecraft clock stop count, frequently used to determine the stop time + of the image. + + Returns + ------- + : str + spacecraft clock stop count + """ + if "SpacecraftClockStopCount" in self.label["IsisCube"]["Instrument"]: + return str( + self.label["IsisCube"]["Instrument"]["SpacecraftClockStopCount"]) + else: + return None + + @property + def ikid(self): + """ + Overridden to grab the ikid from the Isis Cube since there is no way to + obtain this value with a spice bods2c call. Isis sets this value during + ingestion, based on the original fits file. + + Returns + ------- + : int + Naif ID used to for identifying the instrument in Spice kernels + """ + return self.label["IsisCube"]["Kernels"]["NaifFrameCode"] diff --git a/write_UvvisIsisLabelNaifSpiceDriver.ipynb b/write_UvvisIsisLabelNaifSpiceDriver.ipynb new file mode 100644 index 000000000..395ec3376 --- /dev/null +++ b/write_UvvisIsisLabelNaifSpiceDriver.ipynb @@ -0,0 +1,225 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": 1, + "id": "accb1a2f", + "metadata": {}, + "outputs": [], + "source": [ + "import os\n", + "import spiceypy as spice\n", + "import json\n", + "import numpy as np\n", + "import pvl\n", + "\n", + "import ale\n", + "from ale.base import Driver\n", + "from ale.base.label_isis import IsisLabel\n", + "from ale.base.data_naif import NaifSpice\n", + "from ale.base.type_distortion import RadialDistortion, NoDistortion\n", + "from ale.base.type_sensor import Framer, LineScanner\n", + "from ale.util import generate_kernels_from_cube\n", + "from ale.base.type_sensor import Framer\n", + "from ale.base.type_distortion import NoDistortion\n", + "\n", + "from ale import util" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "id": "35b2500e", + "metadata": {}, + "outputs": [], + "source": [ + "class UvvisIsisLabelNaifSpiceDriver(Framer, IsisLabel, NaifSpice, NoDistortion, Driver):\n", + " \"\"\"\n", + " Driver for reading Ultra-violet Invisible Spectrum ISIS3 Labels\n", + " \"\"\"\n", + "\n", + " @property\n", + " def sensor_name(self):\n", + " \"\"\"\n", + " Returns the name of the instrument\n", + "\n", + " Returns\n", + " -------\n", + " : str\n", + " instrument name\n", + " \"\"\"\n", + " return \"UVVIS\"\n", + "\n", + " @property\n", + " def sensor_model_version(self):\n", + " \"\"\"\n", + " Returns ISIS sensor model version\n", + "\n", + " Returns\n", + " -------\n", + " : int\n", + " ISIS sensor model version\n", + " \"\"\"\n", + " return 1\n", + "\n", + " @property\n", + " def spacecraft_clock_start_count(self):\n", + " \"\"\"\n", + " The spacecraft clock start count, frequently used to determine the start time\n", + " of the image.\n", + "\n", + " Returns\n", + " -------\n", + " : str\n", + " spacecraft clock start count\n", + " \"\"\"\n", + " if \"SpacecraftClockStartCount\" in self.label[\"IsisCube\"][\"Instrument\"]:\n", + " return str(\n", + " self.label[\"IsisCube\"][\"Instrument\"][\"SpacecraftClockStartCount\"])\n", + " else:\n", + " return None\n", + "\n", + " @property\n", + " def spacecraft_clock_stop_count(self):\n", + " \"\"\"\n", + " The spacecraft clock stop count, frequently used to determine the stop time\n", + " of the image.\n", + "\n", + " Returns\n", + " -------\n", + " : str\n", + " spacecraft clock stop count\n", + " \"\"\"\n", + " if \"SpacecraftClockStopCount\" in self.label[\"IsisCube\"][\"Instrument\"]:\n", + " return str(\n", + " self.label[\"IsisCube\"][\"Instrument\"][\"SpacecraftClockStopCount\"])\n", + " else:\n", + " return None\n", + "\n", + " @property\n", + " def ikid(self):\n", + " \"\"\"\n", + " Overridden to grab the ikid from the Isis Cube since there is no way to\n", + " obtain this value with a spice bods2c call. Isis sets this value during\n", + " ingestion, based on the original fits file.\n", + "\n", + " Returns\n", + " -------\n", + " : int\n", + " Naif ID used to for identifying the instrument in Spice kernels\n", + " \"\"\"\n", + " return self.label[\"IsisCube\"][\"Kernels\"][\"NaifFrameCode\"]" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "id": "0d88ed00", + "metadata": {}, + "outputs": [], + "source": [ + "os.environ[\"ISISDATA\"] = \"/Users/ahibl/astro_efs\"\n", + "os.environ[\"ISISTESTDATA\"] = \"Volumes/pkgs/isis3_old/isis_testData/\"\n", + "os.environ[\"ISISROOT\"] = \"/Users/ahibl/working/astro/ISIS3/build/\"" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "id": "4e3f8e49", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "False False\n", + "Banana False False\n", + "Group = Kernels\n", + " NaifFrameCode = -40022\n", + " LeapSecond = $base/kernels/lsk/naif0012.tls\n", + " TargetAttitudeShape = Null\n", + " TargetPosition = $base/kernels/spk/de430.bsp\n", + " InstrumentPointing = ($Clementine1/kernels/ck/clem_2mn.bck,\n", + " $Clementine1/kernels/ck/clem_5sc.bck,\n", + " $clementine1/kernels/fk/clem_v12.tf)\n", + " Instrument = $Clementine1/kernels/ik/clem_uvvis_beta_ik_v04.-\n", + " ti\n", + " SpacecraftClock = $Clementine1/kernels/sclk/dspse002.tsc\n", + " InstrumentPosition = $Clementine1/kernels/spk/SPKMERGE_940219_940504-\n", + " _CLEMV001b.bsp\n", + " InstrumentAddendum = $Clementine1/kernels/iak/uvvisAddendum004.ti\n", + " ShapeModel = $base/dems/ldem_128ppd_Mar2011_clon180_radius_p-\n", + " ad.cub\n", + " InstrumentPositionQuality = Reconstructed\n", + " InstrumentPointingQuality = Reconstructed\n", + " CameraVersion = 1\n", + " Error = \"Can not find [BODY301_RADII] in text kernels\"\n", + "End_Group\n", + "**ERROR** Unable to initialize camera model.\n" + ] + } + ], + "source": [ + "!spiceinit from=/Users/ahibl/astro_efs/test_imgs/lub0322a.054.cub" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "id": "7cd23481", + "metadata": {}, + "outputs": [ + { + "ename": "TypeError", + "evalue": "argument of type 'NoneType' is not iterable", + "output_type": "error", + "traceback": [ + "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", + "\u001b[0;31mTypeError\u001b[0m Traceback (most recent call last)", + "Cell \u001b[0;32mIn[5], line 3\u001b[0m\n\u001b[1;32m 1\u001b[0m \u001b[38;5;66;03m# Generate kernels from an ISIS spiceinit'd label\u001b[39;00m\n\u001b[1;32m 2\u001b[0m cube \u001b[38;5;241m=\u001b[39m \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124m/Users/ahibl/astro_efs/test_imgs/lua0048a.054.cub\u001b[39m\u001b[38;5;124m\"\u001b[39m\n\u001b[0;32m----> 3\u001b[0m kernels \u001b[38;5;241m=\u001b[39m \u001b[43mgenerate_kernels_from_cube\u001b[49m\u001b[43m(\u001b[49m\u001b[43mcube\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mexpand\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[38;5;28;43;01mTrue\u001b[39;49;00m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mformat_as\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[38;5;124;43m'\u001b[39;49m\u001b[38;5;124;43mlist\u001b[39;49m\u001b[38;5;124;43m'\u001b[39;49m\u001b[43m)\u001b[49m\n\u001b[1;32m 4\u001b[0m kernels\n", + "File \u001b[0;32m~/working/astro/ale/ale/util.py:231\u001b[0m, in \u001b[0;36mgenerate_kernels_from_cube\u001b[0;34m(cube, expand, format_as)\u001b[0m\n\u001b[1;32m 228\u001b[0m \u001b[38;5;28;01mexcept\u001b[39;00m \u001b[38;5;167;01mKeyError\u001b[39;00m:\n\u001b[1;32m 229\u001b[0m \u001b[38;5;28;01mraise\u001b[39;00m \u001b[38;5;167;01mKeyError\u001b[39;00m(\u001b[38;5;124mf\u001b[39m\u001b[38;5;124m'\u001b[39m\u001b[38;5;132;01m{\u001b[39;00mcubelabel\u001b[38;5;132;01m}\u001b[39;00m\u001b[38;5;124m, Could not find kernels group, input cube [\u001b[39m\u001b[38;5;132;01m{\u001b[39;00mcube\u001b[38;5;132;01m}\u001b[39;00m\u001b[38;5;124m] may not be spiceinited\u001b[39m\u001b[38;5;124m'\u001b[39m)\n\u001b[0;32m--> 231\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[43mget_kernels_from_isis_pvl\u001b[49m\u001b[43m(\u001b[49m\u001b[43mkernel_group\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mexpand\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mformat_as\u001b[49m\u001b[43m)\u001b[49m\n", + "File \u001b[0;32m~/working/astro/ale/ale/util.py:254\u001b[0m, in \u001b[0;36mget_kernels_from_isis_pvl\u001b[0;34m(kernel_group, expand, format_as)\u001b[0m\n\u001b[1;32m 251\u001b[0m \u001b[38;5;28;01mwhile\u001b[39;00m \u001b[38;5;124m'\u001b[39m\u001b[38;5;124mTable\u001b[39m\u001b[38;5;124m'\u001b[39m \u001b[38;5;129;01min\u001b[39;00m mk_paths[key]: mk_paths[key]\u001b[38;5;241m.\u001b[39mremove(\u001b[38;5;124m'\u001b[39m\u001b[38;5;124mTable\u001b[39m\u001b[38;5;124m'\u001b[39m)\n\u001b[1;32m 252\u001b[0m \u001b[38;5;28;01mwhile\u001b[39;00m \u001b[38;5;124m'\u001b[39m\u001b[38;5;124mNadir\u001b[39m\u001b[38;5;124m'\u001b[39m \u001b[38;5;129;01min\u001b[39;00m mk_paths[key]: mk_paths[key]\u001b[38;5;241m.\u001b[39mremove(\u001b[38;5;124m'\u001b[39m\u001b[38;5;124mNadir\u001b[39m\u001b[38;5;124m'\u001b[39m)\n\u001b[0;32m--> 254\u001b[0m \u001b[43mload_table_data\u001b[49m\u001b[43m(\u001b[49m\u001b[38;5;124;43m'\u001b[39;49m\u001b[38;5;124;43mTargetPosition\u001b[39;49m\u001b[38;5;124;43m'\u001b[39;49m\u001b[43m)\u001b[49m\n\u001b[1;32m 255\u001b[0m load_table_data(\u001b[38;5;124m'\u001b[39m\u001b[38;5;124mInstrumentPosition\u001b[39m\u001b[38;5;124m'\u001b[39m)\n\u001b[1;32m 256\u001b[0m load_table_data(\u001b[38;5;124m'\u001b[39m\u001b[38;5;124mInstrumentPointing\u001b[39m\u001b[38;5;124m'\u001b[39m)\n", + "File \u001b[0;32m~/working/astro/ale/ale/util.py:251\u001b[0m, in \u001b[0;36mget_kernels_from_isis_pvl..load_table_data\u001b[0;34m(key)\u001b[0m\n\u001b[1;32m 249\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m \u001b[38;5;28misinstance\u001b[39m(mk_paths[key], \u001b[38;5;28mstr\u001b[39m):\n\u001b[1;32m 250\u001b[0m mk_paths[key] \u001b[38;5;241m=\u001b[39m [mk_paths[key]]\n\u001b[0;32m--> 251\u001b[0m \u001b[38;5;28;01mwhile\u001b[39;00m \u001b[38;5;124;43m'\u001b[39;49m\u001b[38;5;124;43mTable\u001b[39;49m\u001b[38;5;124;43m'\u001b[39;49m\u001b[43m \u001b[49m\u001b[38;5;129;43;01min\u001b[39;49;00m\u001b[43m \u001b[49m\u001b[43mmk_paths\u001b[49m\u001b[43m[\u001b[49m\u001b[43mkey\u001b[49m\u001b[43m]\u001b[49m: mk_paths[key]\u001b[38;5;241m.\u001b[39mremove(\u001b[38;5;124m'\u001b[39m\u001b[38;5;124mTable\u001b[39m\u001b[38;5;124m'\u001b[39m)\n\u001b[1;32m 252\u001b[0m \u001b[38;5;28;01mwhile\u001b[39;00m \u001b[38;5;124m'\u001b[39m\u001b[38;5;124mNadir\u001b[39m\u001b[38;5;124m'\u001b[39m \u001b[38;5;129;01min\u001b[39;00m mk_paths[key]: mk_paths[key]\u001b[38;5;241m.\u001b[39mremove(\u001b[38;5;124m'\u001b[39m\u001b[38;5;124mNadir\u001b[39m\u001b[38;5;124m'\u001b[39m)\n", + "\u001b[0;31mTypeError\u001b[0m: argument of type 'NoneType' is not iterable" + ] + } + ], + "source": [ + "# Generate kernels from an ISIS spiceinit'd label\n", + "cube = \"/Users/ahibl/astro_efs/test_imgs/lua0048a.054.cub\"\n", + "kernels = generate_kernels_from_cube(cube, expand=True, format_as='list')\n", + "kernels" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "a06a7928", + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "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.10.9" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} From 8395baa574fa1728d1caded265a453f1bcd836c6 Mon Sep 17 00:00:00 2001 From: antonhibl Date: Mon, 6 Feb 2023 14:58:49 -0700 Subject: [PATCH 02/13] build fixes --- ale/drivers/uvvis_drivers.py | 20 +++++++++++++++++++ .../write_UvvisIsisLabelNaifSpiceDriver.ipynb | 19 ++++++++++++++++++ 2 files changed, 39 insertions(+) rename write_UvvisIsisLabelNaifSpiceDriver.ipynb => notebooks/write_UvvisIsisLabelNaifSpiceDriver.ipynb (93%) diff --git a/ale/drivers/uvvis_drivers.py b/ale/drivers/uvvis_drivers.py index f6e834325..8ae785f3c 100644 --- a/ale/drivers/uvvis_drivers.py +++ b/ale/drivers/uvvis_drivers.py @@ -22,6 +22,26 @@ class UvvisIsisLabelNaifSpiceDriver(Framer, IsisLabel, NaifSpice, NoDistortion, Driver for reading Ultra-violet Invisible Spectrum ISIS3 Labels """ + @property + def instrument_id(self): + """ + Returns an instrument id for uniquely identifying the instrument, + but often also used to be piped into Spice Kernels to acquire + IKIDS. Therefor they are the same ID that Spice expects in bods2c + calls. Expect instrument_id to be defined in the IsisLabel mixin. + This should be a string of the form NEAR EARTH ASTEROID RENDEZVOUS + + Returns + ------- + : str + instrument id + """ + lookup_table = { + "MSI": "NEAR EARTH ASTEROID RENDEZVOUS" + } + print(lookup_table[super().instrument_id]) + return lookup_table[super().instrument_id] + @property def sensor_name(self): """ diff --git a/write_UvvisIsisLabelNaifSpiceDriver.ipynb b/notebooks/write_UvvisIsisLabelNaifSpiceDriver.ipynb similarity index 93% rename from write_UvvisIsisLabelNaifSpiceDriver.ipynb rename to notebooks/write_UvvisIsisLabelNaifSpiceDriver.ipynb index 395ec3376..bde05ad81 100644 --- a/write_UvvisIsisLabelNaifSpiceDriver.ipynb +++ b/notebooks/write_UvvisIsisLabelNaifSpiceDriver.ipynb @@ -37,6 +37,25 @@ " \"\"\"\n", " Driver for reading Ultra-violet Invisible Spectrum ISIS3 Labels\n", " \"\"\"\n", + " \n", + " @property\n", + " def instrument_id(self):\n", + " \"\"\"\n", + " Returns an instrument id for uniquely identifying the instrument,\n", + " but often also used to be piped into Spice Kernels to acquire\n", + " IKIDS. Therefor they are the same ID that Spice expects in bods2c\n", + " calls. Expect instrument_id to be defined in the IsisLabel mixin.\n", + " This should be a string of the form NEAR EARTH ASTEROID RENDEZVOUS\n", + "\n", + " Returns\n", + " -------\n", + " : str\n", + " instrument id\n", + " \"\"\"\n", + " lookup_table = {\n", + " \"UVVIS\": \"UVVIS\"\n", + " }\n", + " return lookup_table[super().instrument_id]\n", "\n", " @property\n", " def sensor_name(self):\n", From 6222813d38c6a0c2bd5efb917da1e9fe01430417 Mon Sep 17 00:00:00 2001 From: antonhibl Date: Tue, 7 Nov 2023 15:35:32 -0700 Subject: [PATCH 03/13] adding initial draft of the driver verification script --- ale/driver_verification.py | 89 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 89 insertions(+) create mode 100644 ale/driver_verification.py diff --git a/ale/driver_verification.py b/ale/driver_verification.py new file mode 100644 index 000000000..84c9093c4 --- /dev/null +++ b/ale/driver_verification.py @@ -0,0 +1,89 @@ +import argparse +import os +import shutil +import subprocess +from pathlib import Path + +# Define the function to run spiceinit with ISIS +def run_spiceinit_isis(image_path): + # Move ALE drivers to a temporary subfolder + ale_drivers_path = Path('path/to/ale/drivers') + temp_folder = ale_drivers_path.parent / 'temp_drivers' + temp_folder.mkdir(exist_ok=True) + for driver in ale_drivers_path.glob('*'): + shutil.move(str(driver), str(temp_folder)) + + # Run spiceinit with ISIS + subprocess.run(['spiceinit', f'from={image_path}']) + + # Move the drivers back + for driver in temp_folder.glob('*'): + shutil.move(str(driver), str(ale_drivers_path)) + temp_folder.rmdir() + +# Define the function to run spiceinit with ALE +def run_spiceinit_ale(image_path): + # Run spiceinit with ALE + subprocess.run(['spiceinit', f'from={image_path}']) + +# Define the function to generate ISD using the provided script +def generate_isd(image_path, driver_type): + isd_path = f"{image_path.stem}-{driver_type}.isd" + subprocess.run(['python', 'isd_generate_script.py', '-o', isd_path, 'input', str(image_path)]) + +# Define the function to compare ISDs +def compare_isds(isd1, isd2): + # Implement the comparison logic here + pass + +# Define the main function +def main(mission_name, images_list): + # Map mission names to drivers + mission_to_driver = { + 'mission1': 'driver1', + 'mission2': 'driver2', + # Add more mappings as needed + } + + # Check if the mission name is valid + if mission_name not in mission_to_driver: + raise ValueError("Invalid mission name provided.") + + # Process each image + for image_path in images_list: + # Duplicate the image for ALE and ISIS processing + image_ale_path = Path(f"{image_path.stem}_ALE{image_path.suffix}") + image_isis_path = Path(f"{image_path.stem}_ISIS{image_path.suffix}") + shutil.copy(image_path, image_ale_path) + shutil.copy(image_path, image_isis_path) + + # Run spiceinit with ISIS + run_spiceinit_isis(image_isis_path) + + # Run spiceinit with ALE + run_spiceinit_ale(image_ale_path) + + # Generate ISD for both ALE and ISIS + generate_isd(image_ale_path, 'ALE') + generate_isd(image_isis_path, 'ISIS') + + # Compare the ISDs + compare_isds(image_ale_path.with_suffix('.isd'), image_isis_path.with_suffix('.isd')) + + # Clean up duplicated images if needed + image_ale_path.unlink() + image_isis_path.unlink() + +# Set up argparse to handle command line arguments +if __name__ == "__main__": + parser = argparse.ArgumentParser(description="Script to compare ALE and ISIS3 drivers.") + parser.add_argument('mission_name', type=str, help='Name of the mission to determine the driver.') + parser.add_argument('images', type=str, nargs='+', help='List of image files to process.') #I am not convicned this is the best way to read images in yet + args = parser.parse_args() + + # Convert image paths to Path objects + images_list = [Path(image) for image in args.images] + + # Call the main function + main(args.mission_name, images_list) + From cb85d6d8ed0a34c2110bd704350b4ff6d7d7f071 Mon Sep 17 00:00:00 2001 From: antonhibl Date: Wed, 6 Dec 2023 16:05:58 -0700 Subject: [PATCH 04/13] script changes --- ale/driver_verification.py | 90 +++++++++++++++++++------------------- 1 file changed, 44 insertions(+), 46 deletions(-) diff --git a/ale/driver_verification.py b/ale/driver_verification.py index 84c9093c4..5d6cc1f4a 100644 --- a/ale/driver_verification.py +++ b/ale/driver_verification.py @@ -2,15 +2,16 @@ import os import shutil import subprocess +import difflib from pathlib import Path # Define the function to run spiceinit with ISIS def run_spiceinit_isis(image_path): # Move ALE drivers to a temporary subfolder - ale_drivers_path = Path('path/to/ale/drivers') + ale_drivers_path = Path('$ALEROOT/ale/drivers') temp_folder = ale_drivers_path.parent / 'temp_drivers' temp_folder.mkdir(exist_ok=True) - for driver in ale_drivers_path.glob('*'): + for driver in ale_drivers_path.glob('*'): # this globs wrong shutil.move(str(driver), str(temp_folder)) # Run spiceinit with ISIS @@ -26,64 +27,61 @@ def run_spiceinit_ale(image_path): # Run spiceinit with ALE subprocess.run(['spiceinit', f'from={image_path}']) -# Define the function to generate ISD using the provided script -def generate_isd(image_path, driver_type): - isd_path = f"{image_path.stem}-{driver_type}.isd" - subprocess.run(['python', 'isd_generate_script.py', '-o', isd_path, 'input', str(image_path)]) - # Define the function to compare ISDs def compare_isds(isd1, isd2): - # Implement the comparison logic here - pass + # Read the contents of the ISD files + with open(isd1, 'r') as file1: + isd1_content = file1.readlines() + + with open(isd2, 'r') as file2: + isd2_content = file2.readlines() + + # Use difflib to get the differences + diff = difflib.unified_diff(isd1_content, isd2_content, lineterm='') + + # Count the number of differing lines + diff_count = sum(1 for line in diff if line.startswith('+') or line.startswith('-')) + + return diff_count # Define the main function -def main(mission_name, images_list): - # Map mission names to drivers - mission_to_driver = { - 'mission1': 'driver1', - 'mission2': 'driver2', - # Add more mappings as needed - } +def main(driver, image): # Check if the mission name is valid - if mission_name not in mission_to_driver: - raise ValueError("Invalid mission name provided.") + if driver not in drivers: + raise ValueError("Invalid driver name provided.") - # Process each image - for image_path in images_list: - # Duplicate the image for ALE and ISIS processing - image_ale_path = Path(f"{image_path.stem}_ALE{image_path.suffix}") - image_isis_path = Path(f"{image_path.stem}_ISIS{image_path.suffix}") - shutil.copy(image_path, image_ale_path) - shutil.copy(image_path, image_isis_path) + # Duplicate the image for ALE and ISIS processing + image_ale_path = Path(f"{image.stem}_ALE{image.suffix}") + image_isis_path = Path(f"{image.stem}_ISIS{image.suffix}") + shutil.copy(image, image_ale_path) + shutil.copy(image, image_isis_path) - # Run spiceinit with ISIS - run_spiceinit_isis(image_isis_path) + # Run spiceinit with ISIS + run_spiceinit_isis(image_isis_path) - # Run spiceinit with ALE - run_spiceinit_ale(image_ale_path) + # Run spiceinit with ALE + run_spiceinit_ale(image_ale_path) - # Generate ISD for both ALE and ISIS - generate_isd(image_ale_path, 'ALE') - generate_isd(image_isis_path, 'ISIS') + # Generate ISD for both ALE and ISIS + subprocess.run(['python3 isd_generate.py', f'input={image_ale_path}']) + subprocess.run(['python3 isd_generate.py', f'input={image_isis_path}']) + # because there isn't isis spice drivers for every driver + # it is probably better to use tabledump - # Compare the ISDs - compare_isds(image_ale_path.with_suffix('.isd'), image_isis_path.with_suffix('.isd')) + # Compare the ISDs + compare_isds(image_ale_path.with_suffix('.json'), image_isis_path.with_suffix('.json')) - # Clean up duplicated images if needed - image_ale_path.unlink() - image_isis_path.unlink() + # Clean up duplicated images if needed + image_ale_path.unlink() + image_isis_path.unlink() # Set up argparse to handle command line arguments if __name__ == "__main__": - parser = argparse.ArgumentParser(description="Script to compare ALE and ISIS3 drivers.") - parser.add_argument('mission_name', type=str, help='Name of the mission to determine the driver.') - parser.add_argument('images', type=str, nargs='+', help='List of image files to process.') #I am not convicned this is the best way to read images in yet + parser = argparse.ArgumentParser(description="Script to compare ALE driver and ISIS3 driver against an image.") + parser.add_argument('driver', type=str, help='Name of the driver to utilize.') + parser.add_argument('image', type=str, nargs='+', help='Image to process.') args = parser.parse_args() - - # Convert image paths to Path objects - images_list = [Path(image) for image in args.images] - - # Call the main function - main(args.mission_name, images_list) + # Call the main function + main(args.driver, images) From b0fddd31b36546569ebb7649e12f444c7e10997f Mon Sep 17 00:00:00 2001 From: antonhibl Date: Wed, 6 Dec 2023 16:10:23 -0700 Subject: [PATCH 05/13] removing uvvis stuff that somehow got dragged in --- ale/drivers/uvvis_drivers.py | 115 --------- .../write_UvvisIsisLabelNaifSpiceDriver.ipynb | 244 ------------------ 2 files changed, 359 deletions(-) delete mode 100644 ale/drivers/uvvis_drivers.py delete mode 100644 notebooks/write_UvvisIsisLabelNaifSpiceDriver.ipynb diff --git a/ale/drivers/uvvis_drivers.py b/ale/drivers/uvvis_drivers.py deleted file mode 100644 index 8ae785f3c..000000000 --- a/ale/drivers/uvvis_drivers.py +++ /dev/null @@ -1,115 +0,0 @@ -import os -import spiceypy as spice -import json -import numpy as np -import pvl - -import ale -from ale.base import Driver -from ale.base.label_isis import IsisLabel -from ale.base.data_naif import NaifSpice -from ale.base.type_distortion import RadialDistortion, NoDistortion -from ale.base.type_sensor import Framer, LineScanner -from ale.util import generate_kernels_from_cube -from ale.base.type_sensor import Framer -from ale.base.type_distortion import NoDistortion - -from ale import util - - -class UvvisIsisLabelNaifSpiceDriver(Framer, IsisLabel, NaifSpice, NoDistortion, Driver): - """ - Driver for reading Ultra-violet Invisible Spectrum ISIS3 Labels - """ - - @property - def instrument_id(self): - """ - Returns an instrument id for uniquely identifying the instrument, - but often also used to be piped into Spice Kernels to acquire - IKIDS. Therefor they are the same ID that Spice expects in bods2c - calls. Expect instrument_id to be defined in the IsisLabel mixin. - This should be a string of the form NEAR EARTH ASTEROID RENDEZVOUS - - Returns - ------- - : str - instrument id - """ - lookup_table = { - "MSI": "NEAR EARTH ASTEROID RENDEZVOUS" - } - print(lookup_table[super().instrument_id]) - return lookup_table[super().instrument_id] - - @property - def sensor_name(self): - """ - Returns the name of the instrument - - Returns - ------- - : str - instrument name - """ - return "UVVIS" - - @property - def sensor_model_version(self): - """ - Returns ISIS sensor model version - - Returns - ------- - : int - ISIS sensor model version - """ - return 1 - - @property - def spacecraft_clock_start_count(self): - """ - The spacecraft clock start count, frequently used to determine the start time - of the image. - - Returns - ------- - : str - spacecraft clock start count - """ - if "SpacecraftClockStartCount" in self.label["IsisCube"]["Instrument"]: - return str( - self.label["IsisCube"]["Instrument"]["SpacecraftClockStartCount"]) - else: - return None - - @property - def spacecraft_clock_stop_count(self): - """ - The spacecraft clock stop count, frequently used to determine the stop time - of the image. - - Returns - ------- - : str - spacecraft clock stop count - """ - if "SpacecraftClockStopCount" in self.label["IsisCube"]["Instrument"]: - return str( - self.label["IsisCube"]["Instrument"]["SpacecraftClockStopCount"]) - else: - return None - - @property - def ikid(self): - """ - Overridden to grab the ikid from the Isis Cube since there is no way to - obtain this value with a spice bods2c call. Isis sets this value during - ingestion, based on the original fits file. - - Returns - ------- - : int - Naif ID used to for identifying the instrument in Spice kernels - """ - return self.label["IsisCube"]["Kernels"]["NaifFrameCode"] diff --git a/notebooks/write_UvvisIsisLabelNaifSpiceDriver.ipynb b/notebooks/write_UvvisIsisLabelNaifSpiceDriver.ipynb deleted file mode 100644 index bde05ad81..000000000 --- a/notebooks/write_UvvisIsisLabelNaifSpiceDriver.ipynb +++ /dev/null @@ -1,244 +0,0 @@ -{ - "cells": [ - { - "cell_type": "code", - "execution_count": 1, - "id": "accb1a2f", - "metadata": {}, - "outputs": [], - "source": [ - "import os\n", - "import spiceypy as spice\n", - "import json\n", - "import numpy as np\n", - "import pvl\n", - "\n", - "import ale\n", - "from ale.base import Driver\n", - "from ale.base.label_isis import IsisLabel\n", - "from ale.base.data_naif import NaifSpice\n", - "from ale.base.type_distortion import RadialDistortion, NoDistortion\n", - "from ale.base.type_sensor import Framer, LineScanner\n", - "from ale.util import generate_kernels_from_cube\n", - "from ale.base.type_sensor import Framer\n", - "from ale.base.type_distortion import NoDistortion\n", - "\n", - "from ale import util" - ] - }, - { - "cell_type": "code", - "execution_count": 2, - "id": "35b2500e", - "metadata": {}, - "outputs": [], - "source": [ - "class UvvisIsisLabelNaifSpiceDriver(Framer, IsisLabel, NaifSpice, NoDistortion, Driver):\n", - " \"\"\"\n", - " Driver for reading Ultra-violet Invisible Spectrum ISIS3 Labels\n", - " \"\"\"\n", - " \n", - " @property\n", - " def instrument_id(self):\n", - " \"\"\"\n", - " Returns an instrument id for uniquely identifying the instrument,\n", - " but often also used to be piped into Spice Kernels to acquire\n", - " IKIDS. Therefor they are the same ID that Spice expects in bods2c\n", - " calls. Expect instrument_id to be defined in the IsisLabel mixin.\n", - " This should be a string of the form NEAR EARTH ASTEROID RENDEZVOUS\n", - "\n", - " Returns\n", - " -------\n", - " : str\n", - " instrument id\n", - " \"\"\"\n", - " lookup_table = {\n", - " \"UVVIS\": \"UVVIS\"\n", - " }\n", - " return lookup_table[super().instrument_id]\n", - "\n", - " @property\n", - " def sensor_name(self):\n", - " \"\"\"\n", - " Returns the name of the instrument\n", - "\n", - " Returns\n", - " -------\n", - " : str\n", - " instrument name\n", - " \"\"\"\n", - " return \"UVVIS\"\n", - "\n", - " @property\n", - " def sensor_model_version(self):\n", - " \"\"\"\n", - " Returns ISIS sensor model version\n", - "\n", - " Returns\n", - " -------\n", - " : int\n", - " ISIS sensor model version\n", - " \"\"\"\n", - " return 1\n", - "\n", - " @property\n", - " def spacecraft_clock_start_count(self):\n", - " \"\"\"\n", - " The spacecraft clock start count, frequently used to determine the start time\n", - " of the image.\n", - "\n", - " Returns\n", - " -------\n", - " : str\n", - " spacecraft clock start count\n", - " \"\"\"\n", - " if \"SpacecraftClockStartCount\" in self.label[\"IsisCube\"][\"Instrument\"]:\n", - " return str(\n", - " self.label[\"IsisCube\"][\"Instrument\"][\"SpacecraftClockStartCount\"])\n", - " else:\n", - " return None\n", - "\n", - " @property\n", - " def spacecraft_clock_stop_count(self):\n", - " \"\"\"\n", - " The spacecraft clock stop count, frequently used to determine the stop time\n", - " of the image.\n", - "\n", - " Returns\n", - " -------\n", - " : str\n", - " spacecraft clock stop count\n", - " \"\"\"\n", - " if \"SpacecraftClockStopCount\" in self.label[\"IsisCube\"][\"Instrument\"]:\n", - " return str(\n", - " self.label[\"IsisCube\"][\"Instrument\"][\"SpacecraftClockStopCount\"])\n", - " else:\n", - " return None\n", - "\n", - " @property\n", - " def ikid(self):\n", - " \"\"\"\n", - " Overridden to grab the ikid from the Isis Cube since there is no way to\n", - " obtain this value with a spice bods2c call. Isis sets this value during\n", - " ingestion, based on the original fits file.\n", - "\n", - " Returns\n", - " -------\n", - " : int\n", - " Naif ID used to for identifying the instrument in Spice kernels\n", - " \"\"\"\n", - " return self.label[\"IsisCube\"][\"Kernels\"][\"NaifFrameCode\"]" - ] - }, - { - "cell_type": "code", - "execution_count": 3, - "id": "0d88ed00", - "metadata": {}, - "outputs": [], - "source": [ - "os.environ[\"ISISDATA\"] = \"/Users/ahibl/astro_efs\"\n", - "os.environ[\"ISISTESTDATA\"] = \"Volumes/pkgs/isis3_old/isis_testData/\"\n", - "os.environ[\"ISISROOT\"] = \"/Users/ahibl/working/astro/ISIS3/build/\"" - ] - }, - { - "cell_type": "code", - "execution_count": 6, - "id": "4e3f8e49", - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "False False\n", - "Banana False False\n", - "Group = Kernels\n", - " NaifFrameCode = -40022\n", - " LeapSecond = $base/kernels/lsk/naif0012.tls\n", - " TargetAttitudeShape = Null\n", - " TargetPosition = $base/kernels/spk/de430.bsp\n", - " InstrumentPointing = ($Clementine1/kernels/ck/clem_2mn.bck,\n", - " $Clementine1/kernels/ck/clem_5sc.bck,\n", - " $clementine1/kernels/fk/clem_v12.tf)\n", - " Instrument = $Clementine1/kernels/ik/clem_uvvis_beta_ik_v04.-\n", - " ti\n", - " SpacecraftClock = $Clementine1/kernels/sclk/dspse002.tsc\n", - " InstrumentPosition = $Clementine1/kernels/spk/SPKMERGE_940219_940504-\n", - " _CLEMV001b.bsp\n", - " InstrumentAddendum = $Clementine1/kernels/iak/uvvisAddendum004.ti\n", - " ShapeModel = $base/dems/ldem_128ppd_Mar2011_clon180_radius_p-\n", - " ad.cub\n", - " InstrumentPositionQuality = Reconstructed\n", - " InstrumentPointingQuality = Reconstructed\n", - " CameraVersion = 1\n", - " Error = \"Can not find [BODY301_RADII] in text kernels\"\n", - "End_Group\n", - "**ERROR** Unable to initialize camera model.\n" - ] - } - ], - "source": [ - "!spiceinit from=/Users/ahibl/astro_efs/test_imgs/lub0322a.054.cub" - ] - }, - { - "cell_type": "code", - "execution_count": 5, - "id": "7cd23481", - "metadata": {}, - "outputs": [ - { - "ename": "TypeError", - "evalue": "argument of type 'NoneType' is not iterable", - "output_type": "error", - "traceback": [ - "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", - "\u001b[0;31mTypeError\u001b[0m Traceback (most recent call last)", - "Cell \u001b[0;32mIn[5], line 3\u001b[0m\n\u001b[1;32m 1\u001b[0m \u001b[38;5;66;03m# Generate kernels from an ISIS spiceinit'd label\u001b[39;00m\n\u001b[1;32m 2\u001b[0m cube \u001b[38;5;241m=\u001b[39m \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124m/Users/ahibl/astro_efs/test_imgs/lua0048a.054.cub\u001b[39m\u001b[38;5;124m\"\u001b[39m\n\u001b[0;32m----> 3\u001b[0m kernels \u001b[38;5;241m=\u001b[39m \u001b[43mgenerate_kernels_from_cube\u001b[49m\u001b[43m(\u001b[49m\u001b[43mcube\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mexpand\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[38;5;28;43;01mTrue\u001b[39;49;00m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mformat_as\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[38;5;124;43m'\u001b[39;49m\u001b[38;5;124;43mlist\u001b[39;49m\u001b[38;5;124;43m'\u001b[39;49m\u001b[43m)\u001b[49m\n\u001b[1;32m 4\u001b[0m kernels\n", - "File \u001b[0;32m~/working/astro/ale/ale/util.py:231\u001b[0m, in \u001b[0;36mgenerate_kernels_from_cube\u001b[0;34m(cube, expand, format_as)\u001b[0m\n\u001b[1;32m 228\u001b[0m \u001b[38;5;28;01mexcept\u001b[39;00m \u001b[38;5;167;01mKeyError\u001b[39;00m:\n\u001b[1;32m 229\u001b[0m \u001b[38;5;28;01mraise\u001b[39;00m \u001b[38;5;167;01mKeyError\u001b[39;00m(\u001b[38;5;124mf\u001b[39m\u001b[38;5;124m'\u001b[39m\u001b[38;5;132;01m{\u001b[39;00mcubelabel\u001b[38;5;132;01m}\u001b[39;00m\u001b[38;5;124m, Could not find kernels group, input cube [\u001b[39m\u001b[38;5;132;01m{\u001b[39;00mcube\u001b[38;5;132;01m}\u001b[39;00m\u001b[38;5;124m] may not be spiceinited\u001b[39m\u001b[38;5;124m'\u001b[39m)\n\u001b[0;32m--> 231\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[43mget_kernels_from_isis_pvl\u001b[49m\u001b[43m(\u001b[49m\u001b[43mkernel_group\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mexpand\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mformat_as\u001b[49m\u001b[43m)\u001b[49m\n", - "File \u001b[0;32m~/working/astro/ale/ale/util.py:254\u001b[0m, in \u001b[0;36mget_kernels_from_isis_pvl\u001b[0;34m(kernel_group, expand, format_as)\u001b[0m\n\u001b[1;32m 251\u001b[0m \u001b[38;5;28;01mwhile\u001b[39;00m \u001b[38;5;124m'\u001b[39m\u001b[38;5;124mTable\u001b[39m\u001b[38;5;124m'\u001b[39m \u001b[38;5;129;01min\u001b[39;00m mk_paths[key]: mk_paths[key]\u001b[38;5;241m.\u001b[39mremove(\u001b[38;5;124m'\u001b[39m\u001b[38;5;124mTable\u001b[39m\u001b[38;5;124m'\u001b[39m)\n\u001b[1;32m 252\u001b[0m \u001b[38;5;28;01mwhile\u001b[39;00m \u001b[38;5;124m'\u001b[39m\u001b[38;5;124mNadir\u001b[39m\u001b[38;5;124m'\u001b[39m \u001b[38;5;129;01min\u001b[39;00m mk_paths[key]: mk_paths[key]\u001b[38;5;241m.\u001b[39mremove(\u001b[38;5;124m'\u001b[39m\u001b[38;5;124mNadir\u001b[39m\u001b[38;5;124m'\u001b[39m)\n\u001b[0;32m--> 254\u001b[0m \u001b[43mload_table_data\u001b[49m\u001b[43m(\u001b[49m\u001b[38;5;124;43m'\u001b[39;49m\u001b[38;5;124;43mTargetPosition\u001b[39;49m\u001b[38;5;124;43m'\u001b[39;49m\u001b[43m)\u001b[49m\n\u001b[1;32m 255\u001b[0m load_table_data(\u001b[38;5;124m'\u001b[39m\u001b[38;5;124mInstrumentPosition\u001b[39m\u001b[38;5;124m'\u001b[39m)\n\u001b[1;32m 256\u001b[0m load_table_data(\u001b[38;5;124m'\u001b[39m\u001b[38;5;124mInstrumentPointing\u001b[39m\u001b[38;5;124m'\u001b[39m)\n", - "File \u001b[0;32m~/working/astro/ale/ale/util.py:251\u001b[0m, in \u001b[0;36mget_kernels_from_isis_pvl..load_table_data\u001b[0;34m(key)\u001b[0m\n\u001b[1;32m 249\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m \u001b[38;5;28misinstance\u001b[39m(mk_paths[key], \u001b[38;5;28mstr\u001b[39m):\n\u001b[1;32m 250\u001b[0m mk_paths[key] \u001b[38;5;241m=\u001b[39m [mk_paths[key]]\n\u001b[0;32m--> 251\u001b[0m \u001b[38;5;28;01mwhile\u001b[39;00m \u001b[38;5;124;43m'\u001b[39;49m\u001b[38;5;124;43mTable\u001b[39;49m\u001b[38;5;124;43m'\u001b[39;49m\u001b[43m \u001b[49m\u001b[38;5;129;43;01min\u001b[39;49;00m\u001b[43m \u001b[49m\u001b[43mmk_paths\u001b[49m\u001b[43m[\u001b[49m\u001b[43mkey\u001b[49m\u001b[43m]\u001b[49m: mk_paths[key]\u001b[38;5;241m.\u001b[39mremove(\u001b[38;5;124m'\u001b[39m\u001b[38;5;124mTable\u001b[39m\u001b[38;5;124m'\u001b[39m)\n\u001b[1;32m 252\u001b[0m \u001b[38;5;28;01mwhile\u001b[39;00m \u001b[38;5;124m'\u001b[39m\u001b[38;5;124mNadir\u001b[39m\u001b[38;5;124m'\u001b[39m \u001b[38;5;129;01min\u001b[39;00m mk_paths[key]: mk_paths[key]\u001b[38;5;241m.\u001b[39mremove(\u001b[38;5;124m'\u001b[39m\u001b[38;5;124mNadir\u001b[39m\u001b[38;5;124m'\u001b[39m)\n", - "\u001b[0;31mTypeError\u001b[0m: argument of type 'NoneType' is not iterable" - ] - } - ], - "source": [ - "# Generate kernels from an ISIS spiceinit'd label\n", - "cube = \"/Users/ahibl/astro_efs/test_imgs/lua0048a.054.cub\"\n", - "kernels = generate_kernels_from_cube(cube, expand=True, format_as='list')\n", - "kernels" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "a06a7928", - "metadata": {}, - "outputs": [], - "source": [] - } - ], - "metadata": { - "kernelspec": { - "display_name": "Python 3 (ipykernel)", - "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.10.9" - } - }, - "nbformat": 4, - "nbformat_minor": 5 -} From 3944614ea4b79f46101261dca100164af4341e94 Mon Sep 17 00:00:00 2001 From: antonhibl Date: Thu, 14 Dec 2023 14:33:26 -0700 Subject: [PATCH 06/13] debugging isd_generate portion --- ale/driver_verification.py | 49 ++++++++++++++++++++++++++++---------- 1 file changed, 36 insertions(+), 13 deletions(-) diff --git a/ale/driver_verification.py b/ale/driver_verification.py index 5d6cc1f4a..3610a2262 100644 --- a/ale/driver_verification.py +++ b/ale/driver_verification.py @@ -1,21 +1,42 @@ +import ale.drivers import argparse +import importlib +import pkgutil import os import shutil import subprocess import difflib from pathlib import Path +# function to check if driver attribute exists in any given driver class file +def driver_exists(driver_name): + # Find the package path + package_path = ale.drivers.__path__ + + # Iterate over all modules in the ale.drivers package + for _, module_name, _ in pkgutil.iter_modules(package_path): + full_module_name = f"ale.drivers.{module_name}" + module = importlib.import_module(full_module_name) + # Check if the driver class exists in the module + if hasattr(module, driver_name): + return True + print(f"Driver {driver_name} does not exist.") + return False + # Define the function to run spiceinit with ISIS def run_spiceinit_isis(image_path): + ale_root = os.environ.get('ALEROOT') + if ale_root is None: + raise EnvironmentError("The environment variable 'ALEROOT' is not set.") # Move ALE drivers to a temporary subfolder - ale_drivers_path = Path('$ALEROOT/ale/drivers') + ale_drivers_path = Path(ale_root) / 'ale' / 'temp_drivers' temp_folder = ale_drivers_path.parent / 'temp_drivers' temp_folder.mkdir(exist_ok=True) for driver in ale_drivers_path.glob('*'): # this globs wrong shutil.move(str(driver), str(temp_folder)) # Run spiceinit with ISIS - subprocess.run(['spiceinit', f'from={image_path}']) + subprocess.run(['spiceinit', f'from={image_path}']) # I believe this is where the crashes are coming from # Move the drivers back for driver in temp_folder.glob('*'): @@ -30,11 +51,11 @@ def run_spiceinit_ale(image_path): # Define the function to compare ISDs def compare_isds(isd1, isd2): # Read the contents of the ISD files - with open(isd1, 'r') as file1: - isd1_content = file1.readlines() + with open(isd1, 'r') as file_1: + isd1_content = file_1.readlines() - with open(isd2, 'r') as file2: - isd2_content = file2.readlines() + with open(isd2, 'r') as file_2: + isd2_content = file_2.readlines() # Use difflib to get the differences diff = difflib.unified_diff(isd1_content, isd2_content, lineterm='') @@ -48,12 +69,14 @@ def compare_isds(isd1, isd2): def main(driver, image): # Check if the mission name is valid - if driver not in drivers: + if driver_exists(driver): + pass + else: raise ValueError("Invalid driver name provided.") # Duplicate the image for ALE and ISIS processing - image_ale_path = Path(f"{image.stem}_ALE{image.suffix}") - image_isis_path = Path(f"{image.stem}_ISIS{image.suffix}") + image_ale_path = Path(f"{image}_ALE.cub") + image_isis_path = Path(f"{image}_ISIS.cub") shutil.copy(image, image_ale_path) shutil.copy(image, image_isis_path) @@ -64,8 +87,8 @@ def main(driver, image): run_spiceinit_ale(image_ale_path) # Generate ISD for both ALE and ISIS - subprocess.run(['python3 isd_generate.py', f'input={image_ale_path}']) - subprocess.run(['python3 isd_generate.py', f'input={image_isis_path}']) + subprocess.run(['isd_generate', f'input={image_ale_path}']) + subprocess.run(['isd_generate', f'input={image_isis_path}']) # because there isn't isis spice drivers for every driver # it is probably better to use tabledump @@ -80,8 +103,8 @@ def main(driver, image): if __name__ == "__main__": parser = argparse.ArgumentParser(description="Script to compare ALE driver and ISIS3 driver against an image.") parser.add_argument('driver', type=str, help='Name of the driver to utilize.') - parser.add_argument('image', type=str, nargs='+', help='Image to process.') + parser.add_argument('image', type=str, help='Image to process.') args = parser.parse_args() # Call the main function - main(args.driver, images) + main(args.driver, args.image) From afe6a08e40dbca553f794d85e8e48720cb57b7e7 Mon Sep 17 00:00:00 2001 From: antonhibl Date: Mon, 8 Jan 2024 08:19:41 -0700 Subject: [PATCH 07/13] updated driver verification script --- ale/driver_verification.py | 170 +++++++++++++++++++++++++++++++------ 1 file changed, 144 insertions(+), 26 deletions(-) diff --git a/ale/driver_verification.py b/ale/driver_verification.py index 3610a2262..5e2898753 100644 --- a/ale/driver_verification.py +++ b/ale/driver_verification.py @@ -1,12 +1,26 @@ -import ale.drivers +#!/usr/bin/env python +import ale +from ale import drivers +from ale.base.base import Driver +from ale.base.data_isis import IsisSpice +from ale.base.label_isis import IsisLabel + +class ReadIsis(IsisSpice, IsisLabel, Driver): + def sensor_model_version(self): + return 0 + +from networkx.algorithms.shortest_paths.generic import shortest_path +from importlib import reload import argparse import importlib import pkgutil import os +ale_root = os.environ.get('ALEROOT') import shutil import subprocess import difflib from pathlib import Path +import numpy as np # function to check if driver attribute exists in any given driver class file def driver_exists(driver_name): @@ -19,24 +33,26 @@ def driver_exists(driver_name): module = importlib.import_module(full_module_name) # Check if the driver class exists in the module if hasattr(module, driver_name): - return True + return getattr(module, driver_name) print(f"Driver {driver_name} does not exist.") - return False + return None # Define the function to run spiceinit with ISIS def run_spiceinit_isis(image_path): - ale_root = os.environ.get('ALEROOT') if ale_root is None: raise EnvironmentError("The environment variable 'ALEROOT' is not set.") # Move ALE drivers to a temporary subfolder - ale_drivers_path = Path(ale_root) / 'ale' / 'temp_drivers' + ale_drivers_path = Path(ale_root) / 'ale' / 'drivers' temp_folder = ale_drivers_path.parent / 'temp_drivers' temp_folder.mkdir(exist_ok=True) for driver in ale_drivers_path.glob('*'): # this globs wrong shutil.move(str(driver), str(temp_folder)) # Run spiceinit with ISIS - subprocess.run(['spiceinit', f'from={image_path}']) # I believe this is where the crashes are coming from + try: + subprocess.run(['spiceinit', f'from={image_path}']) # I believe this is where the crashes are coming from + except: + pass # Move the drivers back for driver in temp_folder.glob('*'): @@ -48,30 +64,129 @@ def run_spiceinit_ale(image_path): # Run spiceinit with ALE subprocess.run(['spiceinit', f'from={image_path}']) -# Define the function to compare ISDs -def compare_isds(isd1, isd2): - # Read the contents of the ISD files - with open(isd1, 'r') as file_1: - isd1_content = file_1.readlines() +def generate_body_rotation(driver, target_frame_id): + frame_chain = driver.frame_chain + target_frame = target_frame_id + + J2000 = 1 # J2000 frame id + body_rotation = {} + source_frame, destination_frame, time_dependent_target_frame = frame_chain.last_time_dependent_frame_between(target_frame, J2000) + + if source_frame != J2000: + # Reverse the frame order because ISIS orders frames as + # (destination, intermediate, ..., intermediate, source) + body_rotation['time_dependent_frames'] = shortest_path(frame_chain, source_frame, J2000) + time_dependent_rotation = frame_chain.compute_rotation(J2000, source_frame) + body_rotation['ck_table_start_time'] = time_dependent_rotation.times[0] + body_rotation['ck_table_end_time'] = time_dependent_rotation.times[-1] + body_rotation['ck_table_original_size'] = len(time_dependent_rotation.times) + body_rotation['ephemeris_times'] = time_dependent_rotation.times + body_rotation['quaternions'] = time_dependent_rotation.quats[:, [3, 0, 1, 2]] + body_rotation['angular_velocities'] = time_dependent_rotation.av + + if source_frame != target_frame: + # Reverse the frame order because ISIS orders frames as + # (destination, intermediate, ..., intermediate, source) + body_rotation['constant_frames'] = shortest_path(frame_chain, target_frame, source_frame) + constant_rotation = frame_chain.compute_rotation(source_frame, target_frame) + body_rotation['constant_rotation'] = constant_rotation.rotation_matrix().flatten() + + body_rotation["reference_frame"] = destination_frame + return body_rotation - with open(isd2, 'r') as file_2: - isd2_content = file_2.readlines() +def generate_instrument_rotation(driver, sensor_frame_id): + # sensor orientation + frame_chain = driver.frame_chain + sensor_frame = sensor_frame_id - # Use difflib to get the differences - diff = difflib.unified_diff(isd1_content, isd2_content, lineterm='') + J2000 = 1 # J2000 frame id + instrument_pointing = {} + source_frame, destination_frame, _ = frame_chain.last_time_dependent_frame_between(J2000, sensor_frame) - # Count the number of differing lines - diff_count = sum(1 for line in diff if line.startswith('+') or line.startswith('-')) + # Reverse the frame order because ISIS orders frames as + # (destination, intermediate, ..., intermediate, source) + instrument_pointing['time_dependent_frames'] = shortest_path(frame_chain, destination_frame, J2000) + time_dependent_rotation = frame_chain.compute_rotation(J2000, destination_frame) + instrument_pointing['ck_table_start_time'] = time_dependent_rotation.times[0] + instrument_pointing['ck_table_end_time'] = time_dependent_rotation.times[-1] + instrument_pointing['ck_table_original_size'] = len(time_dependent_rotation.times) + instrument_pointing['ephemeris_times'] = time_dependent_rotation.times + instrument_pointing['quaternions'] = time_dependent_rotation.quats[:, [3, 0, 1, 2]] + instrument_pointing['angular_velocities'] = time_dependent_rotation.av - return diff_count + # reference frame should be the last frame in the chain + instrument_pointing["reference_frame"] = instrument_pointing['time_dependent_frames'][-1] + + # Reverse the frame order because ISIS orders frames as + # (destination, intermediate, ..., intermediate, source) + instrument_pointing['constant_frames'] = shortest_path(frame_chain, sensor_frame, destination_frame) + constant_rotation = frame_chain.compute_rotation(destination_frame, sensor_frame) + instrument_pointing['constant_rotation'] = constant_rotation.rotation_matrix().flatten() + + return instrument_pointing + +def generate_instrument_position(driver): + instrument_position = {} + positions, velocities, times = driver.sensor_position + instrument_position['spk_table_start_time'] = times[0] + instrument_position['spk_table_end_time'] = times[-1] + instrument_position['spk_table_original_size'] = len(times) + instrument_position['ephemeris_times'] = times + # Rotate positions and velocities into J2000 then scale into kilometers + # velocities = j2000_rotation.rotate_velocity_at(positions, velocities, times)/1000 + # positions = j2000_rotation.apply_at(positions, times)/1000 + instrument_position['positions'] = positions + instrument_position['velocities'] = velocities + return instrument_position + +def generate_sun_position(driver): + sun_position = {} + positions, velocities, times = driver.sun_position + sun_position['spk_table_start_time'] = times[0] + sun_position['spk_table_end_time'] = times[-1] + sun_position['spk_table_original_size'] = len(times) + sun_position['ephemeris_times'] = times + # Rotate positions and velocities into J2000 then scale into kilometers + # velocities = j2000_rotation.rotate_velocity_at(positions, velocities, times)/1000 + # positions = j2000_rotation.apply_at(positions, times)/1000 + sun_position['positions'] = positions + sun_position['velocities'] = velocities + # sun_position["reference_frame"] = j2000_rotation.dest + return sun_position + +def create_json_dump(driver, sensor_frame_id, target_frame_id): + json_dump = {} + json_dump["instrument_rotation"] = generate_instrument_rotation(driver, sensor_frame_id) + json_dump["body_rotation"] = generate_body_rotation(driver, target_frame_id) + json_dump["instrument_position"] = generate_instrument_position(driver) + json_dump["sun_position"] = generate_sun_position(driver) + return json_dump + +def diff_and_describe(json1, json2, key_array): + for key in key_array: + json1 = json1[key] + json2 = json2[key] + diff = json1 - json2 + print(len(diff), np.mean(diff, axis=(0)), np.median(diff, axis=(0))) + + +# Define the function to compare ISDs +def compare_isds(json1, json2): + diff_and_describe(json1, json2, ["instrument_position", "positions"]) + diff_and_describe(json1, json2, ["instrument_position", "velocities"]) + diff_and_describe(json1, json2, ["sun_position", "positions"]) + diff_and_describe(json1, json2, ["sun_position", "velocities"]) + diff_and_describe(json1, json2, ["instrument_rotation", "quaternions"]) + diff_and_describe(json1, json2, ["instrument_rotation", "angular_velocities"]) + diff_and_describe(json1, json2, ["body_rotation", "quaternions"]) + diff_and_describe(json1, json2, ["body_rotation", "angular_velocities"]) # Define the main function def main(driver, image): # Check if the mission name is valid - if driver_exists(driver): - pass - else: + driver_class = driver_exists(driver) + if driver_class == None: raise ValueError("Invalid driver name provided.") # Duplicate the image for ALE and ISIS processing @@ -87,17 +202,19 @@ def main(driver, image): run_spiceinit_ale(image_ale_path) # Generate ISD for both ALE and ISIS - subprocess.run(['isd_generate', f'input={image_ale_path}']) - subprocess.run(['isd_generate', f'input={image_isis_path}']) + read_ale_driver = ReadIsis(image_ale_path) + ale_json_dump = create_json_dump(read_ale_driver, read_ale_driver.sensor_frame_id, read_ale_driver.target_frame_id) + read_isis_driver = ReadIsis(image_isis_path) + isis_json_dump = create_json_dump(read_isis_driver, read_isis_driver.sensor_frame_id, read_isis_driver.target_frame_id) # because there isn't isis spice drivers for every driver # it is probably better to use tabledump # Compare the ISDs - compare_isds(image_ale_path.with_suffix('.json'), image_isis_path.with_suffix('.json')) + compare_isds(ale_json_dump, isis_json_dump) # Clean up duplicated images if needed - image_ale_path.unlink() - image_isis_path.unlink() + #image_ale_path.unlink() + #image_isis_path.unlink() # Set up argparse to handle command line arguments if __name__ == "__main__": @@ -108,3 +225,4 @@ def main(driver, image): # Call the main function main(args.driver, args.image) + From 4d1b1f756f8fb36868f08a5e7cb71400885dc945 Mon Sep 17 00:00:00 2001 From: antonhibl Date: Wed, 10 Jan 2024 15:21:59 -0700 Subject: [PATCH 08/13] adding ale.load(s) to test ISD generation --- ale/driver_verification.py | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/ale/driver_verification.py b/ale/driver_verification.py index 5e2898753..6e3ccabe2 100644 --- a/ale/driver_verification.py +++ b/ale/driver_verification.py @@ -13,6 +13,7 @@ def sensor_model_version(self): from importlib import reload import argparse import importlib +import pvl import pkgutil import os ale_root = os.environ.get('ALEROOT') @@ -194,13 +195,21 @@ def main(driver, image): image_isis_path = Path(f"{image}_ISIS.cub") shutil.copy(image, image_ale_path) shutil.copy(image, image_isis_path) - + # Run spiceinit with ISIS run_spiceinit_isis(image_isis_path) - + + # try ale.loads + isis_kerns = ale.util.generate_kernels_from_cube(image_isis_path, expand=True) + ale.loads(image_isis_path, props={"kernels": isis_kerns}, only_naif_spice=True) + # Run spiceinit with ALE run_spiceinit_ale(image_ale_path) - + + # try ale.loads + ale_kerns = ale.util.generate_kernels_from_cube(image_ale_path, expand=True) + ale.loads(image_ale_path, props={"kernels": ale_kerns}, only_naif_spice=True) + # Generate ISD for both ALE and ISIS read_ale_driver = ReadIsis(image_ale_path) ale_json_dump = create_json_dump(read_ale_driver, read_ale_driver.sensor_frame_id, read_ale_driver.target_frame_id) @@ -212,10 +221,6 @@ def main(driver, image): # Compare the ISDs compare_isds(ale_json_dump, isis_json_dump) - # Clean up duplicated images if needed - #image_ale_path.unlink() - #image_isis_path.unlink() - # Set up argparse to handle command line arguments if __name__ == "__main__": parser = argparse.ArgumentParser(description="Script to compare ALE driver and ISIS3 driver against an image.") From 902aa085f915adae093e6d7afc809d3a8a79bc43 Mon Sep 17 00:00:00 2001 From: antonhibl Date: Thu, 11 Jan 2024 14:38:20 -0700 Subject: [PATCH 09/13] fixed PVLModule loading with ale.load(s) --- ale/base/label_isis.py | 13 +++++++------ ale/driver_verification.py | 6 ++++-- ale/drivers/__init__.py | 12 ++++++++++-- 3 files changed, 21 insertions(+), 10 deletions(-) diff --git a/ale/base/label_isis.py b/ale/base/label_isis.py index 28d1642d2..2a42ec02d 100644 --- a/ale/base/label_isis.py +++ b/ale/base/label_isis.py @@ -12,12 +12,13 @@ def label(self): self._label = self._file grammar = pvl.grammar.ISISGrammar() grammar.comments+=(("#", "\n"), ) - try: - self._label = pvl.loads(self._file, grammar=grammar) - except Exception: - self._label = pvl.load(self._file, grammar=grammar) - except: - raise ValueError("{} is not a valid label".format(self._file)) + if not isinstance(self._file, pvl.PVLModule): + try: + self._label = pvl.loads(self._file, grammar=grammar) + except Exception: + self._label = pvl.load(self._file, grammar=grammar) + except: + raise ValueError("{} is not a valid label".format(self._file)) return self._label @property diff --git a/ale/driver_verification.py b/ale/driver_verification.py index 6e3ccabe2..6df268783 100644 --- a/ale/driver_verification.py +++ b/ale/driver_verification.py @@ -201,14 +201,16 @@ def main(driver, image): # try ale.loads isis_kerns = ale.util.generate_kernels_from_cube(image_isis_path, expand=True) - ale.loads(image_isis_path, props={"kernels": isis_kerns}, only_naif_spice=True) + isis_label = pvl.load(image_isis_path) + ale.loads(isis_label, props={"kernels": isis_kerns}, only_naif_spice=True) # Run spiceinit with ALE run_spiceinit_ale(image_ale_path) # try ale.loads ale_kerns = ale.util.generate_kernels_from_cube(image_ale_path, expand=True) - ale.loads(image_ale_path, props={"kernels": ale_kerns}, only_naif_spice=True) + ale_label = pvl.load(image_ale_path) + ale.loads(ale_label, props={"kernels": ale_kerns}, only_naif_spice=True) # Generate ISD for both ALE and ISIS read_ale_driver = ReadIsis(image_ale_path) diff --git a/ale/drivers/__init__.py b/ale/drivers/__init__.py index dbb2609c2..1de801697 100644 --- a/ale/drivers/__init__.py +++ b/ale/drivers/__init__.py @@ -73,8 +73,6 @@ def load(label, props={}, formatter='ale', verbose=False, only_isis_spice=False, when one has updated the ephemeris information on an ISIS cube. * ``only_naif_spice=True`` Used for example, when one has a data product or an ISIS cube, but not yet obtained ephemeris information. - - Parameters ---------- label : str String path to the given label file @@ -158,6 +156,16 @@ def load(label, props={}, formatter='ale', verbose=False, only_isis_spice=False, print("Success with: ", driver) print("ISD:\n", json.dumps(isd, indent=2, cls=AleJsonEncoder)) return isd + except AttributeError: + res = driver(label, props=props) + # get instrument_id to force early failure + res.instrument_id + with res as driver: + isd = formatter(driver) + if verbose: + print("Success with: ", driver) + print("ISD:\n", json.dumps(isd, indent=2, cls=AleJsonEncoder)) + return isd except Exception as e: if verbose: print(f'Failed: {e}\n') From 67c51dc6fa90893fb13daabcf505ce59729d20b8 Mon Sep 17 00:00:00 2001 From: antonhibl Date: Thu, 11 Jan 2024 14:41:51 -0700 Subject: [PATCH 10/13] removed conflicting driver verification script file, moving changes for that into the original PR adding it --- ale/driver_verification.py | 235 ------------------------------------- 1 file changed, 235 deletions(-) delete mode 100644 ale/driver_verification.py diff --git a/ale/driver_verification.py b/ale/driver_verification.py deleted file mode 100644 index 6df268783..000000000 --- a/ale/driver_verification.py +++ /dev/null @@ -1,235 +0,0 @@ -#!/usr/bin/env python -import ale -from ale import drivers -from ale.base.base import Driver -from ale.base.data_isis import IsisSpice -from ale.base.label_isis import IsisLabel - -class ReadIsis(IsisSpice, IsisLabel, Driver): - def sensor_model_version(self): - return 0 - -from networkx.algorithms.shortest_paths.generic import shortest_path -from importlib import reload -import argparse -import importlib -import pvl -import pkgutil -import os -ale_root = os.environ.get('ALEROOT') -import shutil -import subprocess -import difflib -from pathlib import Path -import numpy as np - -# function to check if driver attribute exists in any given driver class file -def driver_exists(driver_name): - # Find the package path - package_path = ale.drivers.__path__ - - # Iterate over all modules in the ale.drivers package - for _, module_name, _ in pkgutil.iter_modules(package_path): - full_module_name = f"ale.drivers.{module_name}" - module = importlib.import_module(full_module_name) - # Check if the driver class exists in the module - if hasattr(module, driver_name): - return getattr(module, driver_name) - print(f"Driver {driver_name} does not exist.") - return None - -# Define the function to run spiceinit with ISIS -def run_spiceinit_isis(image_path): - if ale_root is None: - raise EnvironmentError("The environment variable 'ALEROOT' is not set.") - # Move ALE drivers to a temporary subfolder - ale_drivers_path = Path(ale_root) / 'ale' / 'drivers' - temp_folder = ale_drivers_path.parent / 'temp_drivers' - temp_folder.mkdir(exist_ok=True) - for driver in ale_drivers_path.glob('*'): # this globs wrong - shutil.move(str(driver), str(temp_folder)) - - # Run spiceinit with ISIS - try: - subprocess.run(['spiceinit', f'from={image_path}']) # I believe this is where the crashes are coming from - except: - pass - - # Move the drivers back - for driver in temp_folder.glob('*'): - shutil.move(str(driver), str(ale_drivers_path)) - temp_folder.rmdir() - -# Define the function to run spiceinit with ALE -def run_spiceinit_ale(image_path): - # Run spiceinit with ALE - subprocess.run(['spiceinit', f'from={image_path}']) - -def generate_body_rotation(driver, target_frame_id): - frame_chain = driver.frame_chain - target_frame = target_frame_id - - J2000 = 1 # J2000 frame id - body_rotation = {} - source_frame, destination_frame, time_dependent_target_frame = frame_chain.last_time_dependent_frame_between(target_frame, J2000) - - if source_frame != J2000: - # Reverse the frame order because ISIS orders frames as - # (destination, intermediate, ..., intermediate, source) - body_rotation['time_dependent_frames'] = shortest_path(frame_chain, source_frame, J2000) - time_dependent_rotation = frame_chain.compute_rotation(J2000, source_frame) - body_rotation['ck_table_start_time'] = time_dependent_rotation.times[0] - body_rotation['ck_table_end_time'] = time_dependent_rotation.times[-1] - body_rotation['ck_table_original_size'] = len(time_dependent_rotation.times) - body_rotation['ephemeris_times'] = time_dependent_rotation.times - body_rotation['quaternions'] = time_dependent_rotation.quats[:, [3, 0, 1, 2]] - body_rotation['angular_velocities'] = time_dependent_rotation.av - - if source_frame != target_frame: - # Reverse the frame order because ISIS orders frames as - # (destination, intermediate, ..., intermediate, source) - body_rotation['constant_frames'] = shortest_path(frame_chain, target_frame, source_frame) - constant_rotation = frame_chain.compute_rotation(source_frame, target_frame) - body_rotation['constant_rotation'] = constant_rotation.rotation_matrix().flatten() - - body_rotation["reference_frame"] = destination_frame - return body_rotation - -def generate_instrument_rotation(driver, sensor_frame_id): - # sensor orientation - frame_chain = driver.frame_chain - sensor_frame = sensor_frame_id - - J2000 = 1 # J2000 frame id - instrument_pointing = {} - source_frame, destination_frame, _ = frame_chain.last_time_dependent_frame_between(J2000, sensor_frame) - - # Reverse the frame order because ISIS orders frames as - # (destination, intermediate, ..., intermediate, source) - instrument_pointing['time_dependent_frames'] = shortest_path(frame_chain, destination_frame, J2000) - time_dependent_rotation = frame_chain.compute_rotation(J2000, destination_frame) - instrument_pointing['ck_table_start_time'] = time_dependent_rotation.times[0] - instrument_pointing['ck_table_end_time'] = time_dependent_rotation.times[-1] - instrument_pointing['ck_table_original_size'] = len(time_dependent_rotation.times) - instrument_pointing['ephemeris_times'] = time_dependent_rotation.times - instrument_pointing['quaternions'] = time_dependent_rotation.quats[:, [3, 0, 1, 2]] - instrument_pointing['angular_velocities'] = time_dependent_rotation.av - - # reference frame should be the last frame in the chain - instrument_pointing["reference_frame"] = instrument_pointing['time_dependent_frames'][-1] - - # Reverse the frame order because ISIS orders frames as - # (destination, intermediate, ..., intermediate, source) - instrument_pointing['constant_frames'] = shortest_path(frame_chain, sensor_frame, destination_frame) - constant_rotation = frame_chain.compute_rotation(destination_frame, sensor_frame) - instrument_pointing['constant_rotation'] = constant_rotation.rotation_matrix().flatten() - - return instrument_pointing - -def generate_instrument_position(driver): - instrument_position = {} - positions, velocities, times = driver.sensor_position - instrument_position['spk_table_start_time'] = times[0] - instrument_position['spk_table_end_time'] = times[-1] - instrument_position['spk_table_original_size'] = len(times) - instrument_position['ephemeris_times'] = times - # Rotate positions and velocities into J2000 then scale into kilometers - # velocities = j2000_rotation.rotate_velocity_at(positions, velocities, times)/1000 - # positions = j2000_rotation.apply_at(positions, times)/1000 - instrument_position['positions'] = positions - instrument_position['velocities'] = velocities - return instrument_position - -def generate_sun_position(driver): - sun_position = {} - positions, velocities, times = driver.sun_position - sun_position['spk_table_start_time'] = times[0] - sun_position['spk_table_end_time'] = times[-1] - sun_position['spk_table_original_size'] = len(times) - sun_position['ephemeris_times'] = times - # Rotate positions and velocities into J2000 then scale into kilometers - # velocities = j2000_rotation.rotate_velocity_at(positions, velocities, times)/1000 - # positions = j2000_rotation.apply_at(positions, times)/1000 - sun_position['positions'] = positions - sun_position['velocities'] = velocities - # sun_position["reference_frame"] = j2000_rotation.dest - return sun_position - -def create_json_dump(driver, sensor_frame_id, target_frame_id): - json_dump = {} - json_dump["instrument_rotation"] = generate_instrument_rotation(driver, sensor_frame_id) - json_dump["body_rotation"] = generate_body_rotation(driver, target_frame_id) - json_dump["instrument_position"] = generate_instrument_position(driver) - json_dump["sun_position"] = generate_sun_position(driver) - return json_dump - -def diff_and_describe(json1, json2, key_array): - for key in key_array: - json1 = json1[key] - json2 = json2[key] - diff = json1 - json2 - print(len(diff), np.mean(diff, axis=(0)), np.median(diff, axis=(0))) - - -# Define the function to compare ISDs -def compare_isds(json1, json2): - diff_and_describe(json1, json2, ["instrument_position", "positions"]) - diff_and_describe(json1, json2, ["instrument_position", "velocities"]) - diff_and_describe(json1, json2, ["sun_position", "positions"]) - diff_and_describe(json1, json2, ["sun_position", "velocities"]) - diff_and_describe(json1, json2, ["instrument_rotation", "quaternions"]) - diff_and_describe(json1, json2, ["instrument_rotation", "angular_velocities"]) - diff_and_describe(json1, json2, ["body_rotation", "quaternions"]) - diff_and_describe(json1, json2, ["body_rotation", "angular_velocities"]) - -# Define the main function -def main(driver, image): - - # Check if the mission name is valid - driver_class = driver_exists(driver) - if driver_class == None: - raise ValueError("Invalid driver name provided.") - - # Duplicate the image for ALE and ISIS processing - image_ale_path = Path(f"{image}_ALE.cub") - image_isis_path = Path(f"{image}_ISIS.cub") - shutil.copy(image, image_ale_path) - shutil.copy(image, image_isis_path) - - # Run spiceinit with ISIS - run_spiceinit_isis(image_isis_path) - - # try ale.loads - isis_kerns = ale.util.generate_kernels_from_cube(image_isis_path, expand=True) - isis_label = pvl.load(image_isis_path) - ale.loads(isis_label, props={"kernels": isis_kerns}, only_naif_spice=True) - - # Run spiceinit with ALE - run_spiceinit_ale(image_ale_path) - - # try ale.loads - ale_kerns = ale.util.generate_kernels_from_cube(image_ale_path, expand=True) - ale_label = pvl.load(image_ale_path) - ale.loads(ale_label, props={"kernels": ale_kerns}, only_naif_spice=True) - - # Generate ISD for both ALE and ISIS - read_ale_driver = ReadIsis(image_ale_path) - ale_json_dump = create_json_dump(read_ale_driver, read_ale_driver.sensor_frame_id, read_ale_driver.target_frame_id) - read_isis_driver = ReadIsis(image_isis_path) - isis_json_dump = create_json_dump(read_isis_driver, read_isis_driver.sensor_frame_id, read_isis_driver.target_frame_id) - # because there isn't isis spice drivers for every driver - # it is probably better to use tabledump - - # Compare the ISDs - compare_isds(ale_json_dump, isis_json_dump) - -# Set up argparse to handle command line arguments -if __name__ == "__main__": - parser = argparse.ArgumentParser(description="Script to compare ALE driver and ISIS3 driver against an image.") - parser.add_argument('driver', type=str, help='Name of the driver to utilize.') - parser.add_argument('image', type=str, help='Image to process.') - args = parser.parse_args() - - # Call the main function - main(args.driver, args.image) - From cb9e6e514595cbcbc4654d622af278670c3fe504 Mon Sep 17 00:00:00 2001 From: antonhibl Date: Thu, 11 Jan 2024 14:48:09 -0700 Subject: [PATCH 11/13] accidentally removed 2 lines --- ale/drivers/__init__.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/ale/drivers/__init__.py b/ale/drivers/__init__.py index 1de801697..40cb4355e 100644 --- a/ale/drivers/__init__.py +++ b/ale/drivers/__init__.py @@ -73,6 +73,8 @@ def load(label, props={}, formatter='ale', verbose=False, only_isis_spice=False, when one has updated the ephemeris information on an ISIS cube. * ``only_naif_spice=True`` Used for example, when one has a data product or an ISIS cube, but not yet obtained ephemeris information. + + Parameters ---------- label : str String path to the given label file From cac3c9d5da175eaafc4353ba911da4a4c044ee79 Mon Sep 17 00:00:00 2001 From: antonhibl Date: Thu, 11 Jan 2024 14:52:35 -0700 Subject: [PATCH 12/13] removing extra spaces --- ale/drivers/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ale/drivers/__init__.py b/ale/drivers/__init__.py index 40cb4355e..3d0763dcf 100644 --- a/ale/drivers/__init__.py +++ b/ale/drivers/__init__.py @@ -73,7 +73,7 @@ def load(label, props={}, formatter='ale', verbose=False, only_isis_spice=False, when one has updated the ephemeris information on an ISIS cube. * ``only_naif_spice=True`` Used for example, when one has a data product or an ISIS cube, but not yet obtained ephemeris information. - + Parameters ---------- label : str From 6bb46f4fc0adc6745223b1f64f1a46089fed3342 Mon Sep 17 00:00:00 2001 From: antonhibl Date: Thu, 11 Jan 2024 14:57:16 -0700 Subject: [PATCH 13/13] removed unneccesary AttributeError exception handler --- ale/drivers/__init__.py | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/ale/drivers/__init__.py b/ale/drivers/__init__.py index 3d0763dcf..dbb2609c2 100644 --- a/ale/drivers/__init__.py +++ b/ale/drivers/__init__.py @@ -158,16 +158,6 @@ def load(label, props={}, formatter='ale', verbose=False, only_isis_spice=False, print("Success with: ", driver) print("ISD:\n", json.dumps(isd, indent=2, cls=AleJsonEncoder)) return isd - except AttributeError: - res = driver(label, props=props) - # get instrument_id to force early failure - res.instrument_id - with res as driver: - isd = formatter(driver) - if verbose: - print("Success with: ", driver) - print("ISD:\n", json.dumps(isd, indent=2, cls=AleJsonEncoder)) - return isd except Exception as e: if verbose: print(f'Failed: {e}\n')