Loading notebooks/ISIS Serial Numbers.ipynb 0 → 100644 +290 −0 Original line number Diff line number Diff line %% Cell type:code id: tags: ``` python import os import sys print(os.path.abspath('../')) sys.path.insert(0, os.path.abspath('../')) from functools import reduce import glob import re from autocnet.graph import network from autocnet.fileio.sqlalchemy_json.alchemy import NestedJsonObject from autocnet.utils.utils import find_in_dict import sqlalchemy from sqlalchemy.ext import declarative from sqlalchemy import orm import json import warnings import pvl from pvl._collections import PVLModule ``` %% Output /Users/jlaura/github/autocnet %% Cell type:markdown id: tags: ## Generate the data The next three cells take a directory of cleaned `.trn` files (extra values like AUTO or OPTIONAL removed) and generate a `data.db` database of ISIS serial number translations. %% Cell type:code id: tags: ``` python # Database population and a declared class Base = declarative.declarative_base() class Translations(Base): __tablename__ = 'isis_translations' id = sqlalchemy.Column(sqlalchemy.INTEGER, primary_key=True) mission = sqlalchemy.Column(sqlalchemy.String) instrument = sqlalchemy.Column(sqlalchemy.String) translation = sqlalchemy.Column(NestedJsonObject) def __init__(self, mission, instrument, translation): self.mission = mission self.instrument = instrument self.translation = translation class StringToMission(Base): __tablename__ = 'isis_mission_to_standard' id = sqlalchemy.Column(sqlalchemy.INTEGER, primary_key=True) key = sqlalchemy.Column(sqlalchemy.String) value = sqlalchemy.Column(sqlalchemy.String) def __init__(self, key, value): self.key = key self.value = value engine = sqlalchemy.create_engine('sqlite:///data.db') Base.metadata.bind = engine Base.metadata.create_all() session = orm.sessionmaker(bind=engine)() ``` %% Cell type:code id: tags: ``` python files = glob.glob('../autocnet/examples/serial_number_translations/*.trn') for f in files: p = pvl.load(f) name = os.path.basename(f[:-16]) try: v = re.findall("([a-z, 0-9]*)([A-Z, a-z, 0-9]*)", name)[0] mission, instrument = v except: v = re.findall("[a-z, 0-9]*", name) mission = v[0] instrument = None r = Translations(mission, instrument, p) session.add(r) session.commit() ``` %% Cell type:code id: tags: ``` python # Build the mission names lookup table v = """ Group = MissionName InputKey = SpacecraftName InputGroup = "IsisCube,Instrument" InputPosition = (IsisCube, Instrument) Translation = (Aircraft, "Aircraft") Translation = (Apollo15, "APOLLO 15") Translation = (Apollo15, "APOLLO15") Translation = (Apollo16, "APOLLO 16") Translation = (Apollo16, "APOLLO16") Translation = (Apollo17, "APOLLO 17") Translation = (Apollo17, "APOLLO17") Translation = (Cassini, Cassini-Huygens) # Translation = (Chan1, "CHANDRAYAAN-1 ORBITER") # Translation = (Chan1, CHANDRAYAAN1_ORBITER) # Translation = (Chan1, CHANDRAYAAN-1) Translation = (Chandrayaan1, "CHANDRAYAAN-1 ORBITER") Translation = (Chandrayaan1, CHANDRAYAAN1_ORBITER) Translation = (Chandrayaan1, CHANDRAYAAN-1) Translation = (Clementine1, CLEMENTINE_1) Translation = (Clementine1, "CLEMENTINE 1") Translation = (Dawn, "DAWN") Translation = (Galileo, "Galileo Orbiter") Translation = (Hayabusa, HAYABUSA) Translation = (Ideal, IdealSpacecraft) Translation = (Kaguya, KAGUYA) Translation = (Kaguya, SELENE-M) Translation = (Lo, "Lunar Orbiter 3") Translation = (Lo, "Lunar Orbiter 4") Translation = (Lo, "Lunar Orbiter 5") Translation = (Lro, "LUNAR RECONNAISSANCE ORBITER") Translation = (Lro, "Lunar Reconnaissance Orbiter") Translation = (Mariner10, Mariner_10) Translation = (Mariner10, MARINER_10) Translation = (Mer, "MARS EXPLORATION ROVER 1") Translation = (Mer, MARS_EXPLORATION_ROVER_1) Translation = (Mer, "MARS EXPLORATION ROVER 2") Translation = (Mer, "SIMULATED MARS EXPLORATION ROVER 1") Translation = (Mer, "SIMULATED MARS EXPLORATION ROVER 2") Translation = (Messenger, MESSENGER) Translation = (Messenger, Messenger) Translation = (Mex, "MARS EXPRESS") Translation = (Mex, "Mars Express") Translation = (Mgs, MARSGLOBALSURVEYOR) Translation = (Mgs, "MARS GLOBAL SURVEYOR") Translation = (Mro, "MARS RECONNAISSANCE ORBITER") Translation = (Mro, Mars_Reconnaissance_Orbiter) Translation = (NewHorizons, "NEW HORIZONS") Translation = (Near, NEAR) Translation = (Near, "NEAR EARTH ASTEROID RENDEZVOUS") Translation = (Odyssey, MARS_ODYSSEY) Translation = (OsirisRex, OSIRIS-REX) Translation = (Smart1, SMART1) Translation = (Viking1, VIKING_ORBITER_1) Translation = (Viking2, VIKING_ORBITER_2) Translation = (Voyager1, VOYAGER_1) Translation = (Voyager2, VOYAGER_2) End_Group End """ p = pvl.loads(v) for k, v in p['MissionName'].items(): if k == 'Translation': r = StringToMission(v[1], v[0]) session.add(r) session.commit() ``` %% Cell type:markdown id: tags: ## Sample Query %% Cell type:code id: tags: ``` python # Sample querying the database for i, j, t in session.query(Translations.mission, Translations.instrument, Translations.translation): print(i,j) d = PVLModule(t) print(d) break ``` %% Cell type:markdown id: tags: ## Testing code to prototype the functionality now in autocnet %% Cell type:code id: tags: ``` python class SerialNumberDecoder(pvl.decoder.PVLDecoder): """ A PVL Decoder class to handle cube label parsing for the purpose of creating a valid ISIS serial number. Inherits from the PVLDecoder in planetarypy's pvl module. """ def cast_unquoated_string(self, value): """ Overrides the parent class's method so that any un-quoted string type value found in the parsed pvl will just return the original value. This is needed so that keyword values are not re-formatted from what is originally in the ISIS cube label. Note: This affects value types that are recognized as null, boolean, number, datetime, et at. """ return value.decode('utf-8') def get_isis_translation(label): """ Compute the ISIS serial number for a given image using the input cube or the label extracted from the cube. Parameters ---------- label : dict or str A PVL dict object or file name to extract the PVL object from Returns ------- translation : dict A PVLModule object containing the extracted translation file """ if not isinstance(label, PVLModule): label = pvl.load(label) cube_obj = find_in_dict(label, 'Instrument') # Grab the spacecraft name and run it through the ISIS lookup spacecraft_name = find_in_dict(cube_obj, 'SpacecraftName') for row in session.query(StringToMission).filter(StringToMission.key==spacecraft_name): spacecraft_name = row.value.lower() #Try and pull an instrument identifier try: instrumentid = find_in_dict(cube_obj, 'InstrumentId').capitalize() except: instrumentid = None # Grab the translation PVL object using the lookup for row in session.query(Translations).filter(Translations.mission==spacecraft_name, Translations.instrument==instrumentid): # Convert the JSON back to a PVL object translation = PVLModule(row.translation) return translation def extract_subgroup(data, key_list): return reduce(lambda d, k: d[k], key_list, data) def generate_serial_number(label): if not isinstance(label, PVLModule): label = pvl.load(label, cls=SerialNumberDecoder) # Get the translation information translation = get_isis_translation(label) serial_number = [] # Sort the keys to ensure proper iteration order keys = sorted(translation.keys()) for k in keys: group = translation[k] search_key = group['InputKey'] search_position = group['InputPosition'] search_translation = {group['Translation'][1]:group['Translation'][0]} print(search_key, search_position, search_translation) sub_group = extract_subgroup(label, search_position) serial_entry = sub_group[search_key] if serial_entry in search_translation.keys(): serial_entry = search_translation[serial_entry] elif '*' in search_translation.keys() and search_translation['*'] != '*': serial_entry = search_translation['*'] serial_number.append(serial_entry) return '/'.join(serial_number) serial = generate_serial_number('/Users/jlaura/Desktop/Apollo15/AS15-M-0296_sub4.cub') print(serial) ``` %% Output SpacecraftName ['IsisCube', 'Instrument'] {'*': 'APOLLO15'} InstrumentId ['IsisCube', 'Instrument'] {'*': '*'} StartTime ['IsisCube', 'Instrument'] {'*': '*'} APOLLO15/METRIC/1971-07-31T01:24:36.970 Loading
notebooks/ISIS Serial Numbers.ipynb 0 → 100644 +290 −0 Original line number Diff line number Diff line %% Cell type:code id: tags: ``` python import os import sys print(os.path.abspath('../')) sys.path.insert(0, os.path.abspath('../')) from functools import reduce import glob import re from autocnet.graph import network from autocnet.fileio.sqlalchemy_json.alchemy import NestedJsonObject from autocnet.utils.utils import find_in_dict import sqlalchemy from sqlalchemy.ext import declarative from sqlalchemy import orm import json import warnings import pvl from pvl._collections import PVLModule ``` %% Output /Users/jlaura/github/autocnet %% Cell type:markdown id: tags: ## Generate the data The next three cells take a directory of cleaned `.trn` files (extra values like AUTO or OPTIONAL removed) and generate a `data.db` database of ISIS serial number translations. %% Cell type:code id: tags: ``` python # Database population and a declared class Base = declarative.declarative_base() class Translations(Base): __tablename__ = 'isis_translations' id = sqlalchemy.Column(sqlalchemy.INTEGER, primary_key=True) mission = sqlalchemy.Column(sqlalchemy.String) instrument = sqlalchemy.Column(sqlalchemy.String) translation = sqlalchemy.Column(NestedJsonObject) def __init__(self, mission, instrument, translation): self.mission = mission self.instrument = instrument self.translation = translation class StringToMission(Base): __tablename__ = 'isis_mission_to_standard' id = sqlalchemy.Column(sqlalchemy.INTEGER, primary_key=True) key = sqlalchemy.Column(sqlalchemy.String) value = sqlalchemy.Column(sqlalchemy.String) def __init__(self, key, value): self.key = key self.value = value engine = sqlalchemy.create_engine('sqlite:///data.db') Base.metadata.bind = engine Base.metadata.create_all() session = orm.sessionmaker(bind=engine)() ``` %% Cell type:code id: tags: ``` python files = glob.glob('../autocnet/examples/serial_number_translations/*.trn') for f in files: p = pvl.load(f) name = os.path.basename(f[:-16]) try: v = re.findall("([a-z, 0-9]*)([A-Z, a-z, 0-9]*)", name)[0] mission, instrument = v except: v = re.findall("[a-z, 0-9]*", name) mission = v[0] instrument = None r = Translations(mission, instrument, p) session.add(r) session.commit() ``` %% Cell type:code id: tags: ``` python # Build the mission names lookup table v = """ Group = MissionName InputKey = SpacecraftName InputGroup = "IsisCube,Instrument" InputPosition = (IsisCube, Instrument) Translation = (Aircraft, "Aircraft") Translation = (Apollo15, "APOLLO 15") Translation = (Apollo15, "APOLLO15") Translation = (Apollo16, "APOLLO 16") Translation = (Apollo16, "APOLLO16") Translation = (Apollo17, "APOLLO 17") Translation = (Apollo17, "APOLLO17") Translation = (Cassini, Cassini-Huygens) # Translation = (Chan1, "CHANDRAYAAN-1 ORBITER") # Translation = (Chan1, CHANDRAYAAN1_ORBITER) # Translation = (Chan1, CHANDRAYAAN-1) Translation = (Chandrayaan1, "CHANDRAYAAN-1 ORBITER") Translation = (Chandrayaan1, CHANDRAYAAN1_ORBITER) Translation = (Chandrayaan1, CHANDRAYAAN-1) Translation = (Clementine1, CLEMENTINE_1) Translation = (Clementine1, "CLEMENTINE 1") Translation = (Dawn, "DAWN") Translation = (Galileo, "Galileo Orbiter") Translation = (Hayabusa, HAYABUSA) Translation = (Ideal, IdealSpacecraft) Translation = (Kaguya, KAGUYA) Translation = (Kaguya, SELENE-M) Translation = (Lo, "Lunar Orbiter 3") Translation = (Lo, "Lunar Orbiter 4") Translation = (Lo, "Lunar Orbiter 5") Translation = (Lro, "LUNAR RECONNAISSANCE ORBITER") Translation = (Lro, "Lunar Reconnaissance Orbiter") Translation = (Mariner10, Mariner_10) Translation = (Mariner10, MARINER_10) Translation = (Mer, "MARS EXPLORATION ROVER 1") Translation = (Mer, MARS_EXPLORATION_ROVER_1) Translation = (Mer, "MARS EXPLORATION ROVER 2") Translation = (Mer, "SIMULATED MARS EXPLORATION ROVER 1") Translation = (Mer, "SIMULATED MARS EXPLORATION ROVER 2") Translation = (Messenger, MESSENGER) Translation = (Messenger, Messenger) Translation = (Mex, "MARS EXPRESS") Translation = (Mex, "Mars Express") Translation = (Mgs, MARSGLOBALSURVEYOR) Translation = (Mgs, "MARS GLOBAL SURVEYOR") Translation = (Mro, "MARS RECONNAISSANCE ORBITER") Translation = (Mro, Mars_Reconnaissance_Orbiter) Translation = (NewHorizons, "NEW HORIZONS") Translation = (Near, NEAR) Translation = (Near, "NEAR EARTH ASTEROID RENDEZVOUS") Translation = (Odyssey, MARS_ODYSSEY) Translation = (OsirisRex, OSIRIS-REX) Translation = (Smart1, SMART1) Translation = (Viking1, VIKING_ORBITER_1) Translation = (Viking2, VIKING_ORBITER_2) Translation = (Voyager1, VOYAGER_1) Translation = (Voyager2, VOYAGER_2) End_Group End """ p = pvl.loads(v) for k, v in p['MissionName'].items(): if k == 'Translation': r = StringToMission(v[1], v[0]) session.add(r) session.commit() ``` %% Cell type:markdown id: tags: ## Sample Query %% Cell type:code id: tags: ``` python # Sample querying the database for i, j, t in session.query(Translations.mission, Translations.instrument, Translations.translation): print(i,j) d = PVLModule(t) print(d) break ``` %% Cell type:markdown id: tags: ## Testing code to prototype the functionality now in autocnet %% Cell type:code id: tags: ``` python class SerialNumberDecoder(pvl.decoder.PVLDecoder): """ A PVL Decoder class to handle cube label parsing for the purpose of creating a valid ISIS serial number. Inherits from the PVLDecoder in planetarypy's pvl module. """ def cast_unquoated_string(self, value): """ Overrides the parent class's method so that any un-quoted string type value found in the parsed pvl will just return the original value. This is needed so that keyword values are not re-formatted from what is originally in the ISIS cube label. Note: This affects value types that are recognized as null, boolean, number, datetime, et at. """ return value.decode('utf-8') def get_isis_translation(label): """ Compute the ISIS serial number for a given image using the input cube or the label extracted from the cube. Parameters ---------- label : dict or str A PVL dict object or file name to extract the PVL object from Returns ------- translation : dict A PVLModule object containing the extracted translation file """ if not isinstance(label, PVLModule): label = pvl.load(label) cube_obj = find_in_dict(label, 'Instrument') # Grab the spacecraft name and run it through the ISIS lookup spacecraft_name = find_in_dict(cube_obj, 'SpacecraftName') for row in session.query(StringToMission).filter(StringToMission.key==spacecraft_name): spacecraft_name = row.value.lower() #Try and pull an instrument identifier try: instrumentid = find_in_dict(cube_obj, 'InstrumentId').capitalize() except: instrumentid = None # Grab the translation PVL object using the lookup for row in session.query(Translations).filter(Translations.mission==spacecraft_name, Translations.instrument==instrumentid): # Convert the JSON back to a PVL object translation = PVLModule(row.translation) return translation def extract_subgroup(data, key_list): return reduce(lambda d, k: d[k], key_list, data) def generate_serial_number(label): if not isinstance(label, PVLModule): label = pvl.load(label, cls=SerialNumberDecoder) # Get the translation information translation = get_isis_translation(label) serial_number = [] # Sort the keys to ensure proper iteration order keys = sorted(translation.keys()) for k in keys: group = translation[k] search_key = group['InputKey'] search_position = group['InputPosition'] search_translation = {group['Translation'][1]:group['Translation'][0]} print(search_key, search_position, search_translation) sub_group = extract_subgroup(label, search_position) serial_entry = sub_group[search_key] if serial_entry in search_translation.keys(): serial_entry = search_translation[serial_entry] elif '*' in search_translation.keys() and search_translation['*'] != '*': serial_entry = search_translation['*'] serial_number.append(serial_entry) return '/'.join(serial_number) serial = generate_serial_number('/Users/jlaura/Desktop/Apollo15/AS15-M-0296_sub4.cub') print(serial) ``` %% Output SpacecraftName ['IsisCube', 'Instrument'] {'*': 'APOLLO15'} InstrumentId ['IsisCube', 'Instrument'] {'*': '*'} StartTime ['IsisCube', 'Instrument'] {'*': '*'} APOLLO15/METRIC/1971-07-31T01:24:36.970