Skip to content

Commit

Permalink
Merge pull request #1077 from dirac-institute/1044-get-rid-of-all-glo…
Browse files Browse the repository at this point in the history
…bal-variables-and-move-to-a-config-data-class

1044 get rid of all global variables and move to a config data class
  • Loading branch information
Little-Ryugu authored Dec 18, 2024
2 parents 26b85be + 914398b commit 6ff172b
Show file tree
Hide file tree
Showing 12 changed files with 341 additions and 144 deletions.
4 changes: 0 additions & 4 deletions src/sorcha/ephemeris/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,6 @@
create_ecl_to_eq_rotation_matrix,
)
from .simulation_data_files import (
DATA_FILE_LIST,
JPL_PLANETS,
JPL_SMALL_BODIES,
DE440S,
make_retriever,
)
from .simulation_geometry import (
Expand Down
77 changes: 5 additions & 72 deletions src/sorcha/ephemeris/simulation_data_files.py
Original file line number Diff line number Diff line change
@@ -1,75 +1,7 @@
import pooch

# Define variables for the file names

DE440S = "de440s.bsp"
EARTH_PREDICT = "earth_200101_990827_predict.bpc"
EARTH_HISTORICAL = "earth_620120_240827.bpc"
EARTH_HIGH_PRECISION = "earth_latest_high_prec.bpc"
JPL_PLANETS = "linux_p1550p2650.440"
JPL_SMALL_BODIES = "sb441-n16.bsp"
LEAP_SECONDS = "naif0012.tls"
META_KERNEL = "meta_kernel.txt"
OBSERVATORY_CODES = "ObsCodes.json"
OBSERVATORY_CODES_COMPRESSED = "ObsCodes.json.gz"
ORIENTATION_CONSTANTS = "pck00010.pck"

# Dictionary of filename: url
URLS = {
DE440S: "https://naif.jpl.nasa.gov/pub/naif/generic_kernels/spk/planets/de440s.bsp",
EARTH_PREDICT: "https://naif.jpl.nasa.gov/pub/naif/generic_kernels/pck/earth_200101_990827_predict.bpc",
EARTH_HISTORICAL: "https://naif.jpl.nasa.gov/pub/naif/generic_kernels/pck/earth_620120_240827.bpc",
EARTH_HIGH_PRECISION: "https://naif.jpl.nasa.gov/pub/naif/generic_kernels/pck/earth_latest_high_prec.bpc",
JPL_PLANETS: "https://ssd.jpl.nasa.gov/ftp/eph/planets/Linux/de440/linux_p1550p2650.440",
JPL_SMALL_BODIES: "https://ssd.jpl.nasa.gov/ftp/eph/small_bodies/asteroids_de441/sb441-n16.bsp",
LEAP_SECONDS: "https://naif.jpl.nasa.gov/pub/naif/generic_kernels/lsk/naif0012.tls",
OBSERVATORY_CODES_COMPRESSED: "https://minorplanetcenter.net/Extended_Files/obscodes_extended.json.gz",
ORIENTATION_CONSTANTS: "https://naif.jpl.nasa.gov/pub/naif/generic_kernels/pck/pck00010.tpc",
}

# Convenience list of all the file names
DATA_FILE_LIST = [
DE440S,
EARTH_PREDICT,
EARTH_HISTORICAL,
EARTH_HIGH_PRECISION,
JPL_PLANETS,
JPL_SMALL_BODIES,
LEAP_SECONDS,
META_KERNEL,
OBSERVATORY_CODES,
OBSERVATORY_CODES_COMPRESSED,
ORIENTATION_CONSTANTS,
]

# List of files that need to be downloaded
DATA_FILES_TO_DOWNLOAD = [
DE440S,
EARTH_PREDICT,
EARTH_HISTORICAL,
EARTH_HIGH_PRECISION,
JPL_PLANETS,
JPL_SMALL_BODIES,
LEAP_SECONDS,
OBSERVATORY_CODES_COMPRESSED,
ORIENTATION_CONSTANTS,
]

# List of kernels ordered from least to most precise - used to assemble META_KERNEL file
ORDERED_KERNEL_FILES = [
LEAP_SECONDS,
EARTH_HISTORICAL,
EARTH_PREDICT,
ORIENTATION_CONSTANTS,
DE440S,
EARTH_HIGH_PRECISION,
]

# Default Pooch registry to define which files will be tracked and retrievable
REGISTRY = {data_file: None for data_file in DATA_FILE_LIST}


def make_retriever(directory_path: str = None, registry: dict = REGISTRY) -> pooch.Pooch:
def make_retriever(auxconfigs, directory_path: str = None) -> pooch.Pooch:
"""Helper function that will create a Pooch object to track and retrieve files.
Parameters
Expand All @@ -79,7 +11,8 @@ def make_retriever(directory_path: str = None, registry: dict = REGISTRY) -> poo
registry : dictionary, optional
A dictionary of file names to SHA hashes. Generally we'll not use SHA=None
because the files we're tracking change frequently. Default = REGISTRY
auxconfigs: dataclass
Dataclass of auxiliary configuration file arguments.
Returns
-------
: pooch
Expand All @@ -92,7 +25,7 @@ def make_retriever(directory_path: str = None, registry: dict = REGISTRY) -> poo
return pooch.create(
path=dir_path,
base_url="",
urls=URLS,
registry=registry,
urls=auxconfigs.urls,
registry=auxconfigs.registry,
retry_if_failed=25,
)
6 changes: 3 additions & 3 deletions src/sorcha/ephemeris/simulation_driver.py
Original file line number Diff line number Diff line change
Expand Up @@ -116,13 +116,13 @@ def create_ephemeris(orbits_df, pointings_df, args, sconfigs):
ephemeris_csv_filename = os.path.join(args.outpath, args.output_ephemeris_file)

verboselog("Building ASSIST ephemeris object.")
ephem, gm_sun, gm_total = create_assist_ephemeris(args)
ephem, gm_sun, gm_total = create_assist_ephemeris(args, sconfigs.auxiliary)
verboselog("Furnishing SPICE kernels.")
furnish_spiceypy(args)
furnish_spiceypy(args, sconfigs.auxiliary)
verboselog("Generating ASSIST+REBOUND simulations.")
sim_dict = generate_simulations(ephem, gm_sun, gm_total, orbits_df, args)
pixel_dict = defaultdict(list)
observatories = Observatory(args)
observatories = Observatory(args, sconfigs.auxiliary)

output = StringIO()
in_memory_csv = writer(output)
Expand Down
22 changes: 10 additions & 12 deletions src/sorcha/ephemeris/simulation_parsing.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,9 @@
import numpy as np
import spiceypy as spice
from pooch import Decompress

from sorcha.ephemeris.simulation_constants import RADIUS_EARTH_KM
from sorcha.ephemeris.simulation_geometry import ecliptic_to_equatorial
from sorcha.ephemeris.simulation_data_files import (
OBSERVATORY_CODES,
OBSERVATORY_CODES_COMPRESSED,
make_retriever,
)
from sorcha.ephemeris.simulation_data_files import make_retriever
from sorcha.ephemeris.orbit_conversion_utilities import universal_cartesian


Expand Down Expand Up @@ -134,30 +129,33 @@ class Observatory:
Class containing various utility tools related to the calculation of the observatory position
"""

def __init__(self, args, oc_file=OBSERVATORY_CODES):
def __init__(self, args, auxconfigs, oc_file=None):
"""
Initialization method
Parameters
----------
args : dictionary or `sorchaArguments` object
dictionary of command-line arguments.
auxconfigs: dataclass
Dataclass of configuration file arguments.
oc_file : str
Path for the file with observatory codes
"""
self.observatoryPositionCache = {} # previously calculated positions to speed up the process

if oc_file == OBSERVATORY_CODES:
retriever = make_retriever(args.ar_data_file_path)
if oc_file == None:
retriever = make_retriever(auxconfigs, args.ar_data_file_path)

# is the file available locally, if so, return the full path
if os.path.isfile(os.path.join(retriever.abspath, OBSERVATORY_CODES)):
obs_file_path = retriever.fetch(OBSERVATORY_CODES)
if os.path.isfile(os.path.join(retriever.abspath, auxconfigs.observatory_codes)):
obs_file_path = retriever.fetch(auxconfigs.observatory_codes)

# if the file is not local, download, and decompress it, then return the path.
else:
obs_file_path = retriever.fetch(
OBSERVATORY_CODES_COMPRESSED, processor=Decompress(name=OBSERVATORY_CODES)
auxconfigs.observatory_codes_compressed,
processor=Decompress(name=auxconfigs.observatory_codes),
)

else:
Expand Down
43 changes: 22 additions & 21 deletions src/sorcha/ephemeris/simulation_setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,7 @@
import numpy as np

from sorcha.ephemeris.simulation_constants import *
from sorcha.ephemeris.simulation_data_files import (
make_retriever,
JPL_PLANETS,
JPL_SMALL_BODIES,
META_KERNEL,
ORDERED_KERNEL_FILES,
)
from sorcha.ephemeris.simulation_data_files import make_retriever

from sorcha.ephemeris.simulation_geometry import (
barycentricObservatoryRates,
Expand All @@ -32,9 +26,12 @@
from sorcha.utilities.generate_meta_kernel import build_meta_kernel_file


def create_assist_ephemeris(args) -> tuple:
def create_assist_ephemeris(args, auxconfigs) -> tuple:
"""Build the ASSIST ephemeris object
Parameter
---------
auxconfigs: dataclass
Dataclass of auxiliary configuration file arguments.
Returns
---------
Ephem : ASSIST ephemeris obejct
Expand All @@ -46,9 +43,9 @@ def create_assist_ephemeris(args) -> tuple:
"""
pplogger = logging.getLogger(__name__)

retriever = make_retriever(args.ar_data_file_path)
planets_file_path = retriever.fetch(JPL_PLANETS)
small_bodies_file_path = retriever.fetch(JPL_SMALL_BODIES)
retriever = make_retriever(auxconfigs, args.ar_data_file_path)
planets_file_path = retriever.fetch(auxconfigs.jpl_planets)
small_bodies_file_path = retriever.fetch(auxconfigs.jpl_small_bodies)
ephem = Ephem(planets_path=planets_file_path, asteroids_path=small_bodies_file_path)
gm_sun = ephem.get_particle("Sun", 0).m
gm_total = sum(sorted([ephem.get_particle(i, 0).m for i in range(27)]))
Expand All @@ -59,27 +56,31 @@ def create_assist_ephemeris(args) -> tuple:
return ephem, gm_sun, gm_total


def furnish_spiceypy(args):
def furnish_spiceypy(args, auxconfigs):
"""
Builds the SPICE kernel, downloading the required files if needed
Parameters
-----------
auxconfigs: dataclass
Dataclass of auxiliary configuration file arguments.
"""
# The goal here would be to download the spice kernel files (if needed)
# Then call spice.furnish(<filename>) on each of those files.

pplogger = logging.getLogger(__name__)

retriever = make_retriever(args.ar_data_file_path)
retriever = make_retriever(auxconfigs, args.ar_data_file_path)

for kernel_file in ORDERED_KERNEL_FILES:
for kernel_file in auxconfigs.ordered_kernel_files:
retriever.fetch(kernel_file)

# check if the META_KERNEL file exists. If it doesn't exist, create it.
if not os.path.exists(os.path.join(retriever.abspath, META_KERNEL)):
build_meta_kernel_file(retriever)
if not os.path.exists(os.path.join(retriever.abspath, auxconfigs.meta_kernel)):
build_meta_kernel_file(auxconfigs, retriever)

# try to get the META_KERNEL file. If it's not there, error out.
try:
meta_kernel = retriever.fetch(META_KERNEL)
meta_kernel = retriever.fetch(auxconfigs.meta_kernel)
except ValueError:
pplogger.error(
"ERROR: furnish_spiceypy: Must create meta_kernel.txt by running `bootstrap_sorcha_data_files` on the command line."
Expand Down Expand Up @@ -181,11 +182,11 @@ def precompute_pointing_information(pointings_df, args, sconfigs):
pointings_df : pandas dataframe
The original dataframe with several additional columns of precomputed values.
"""
ephem, _, _ = create_assist_ephemeris(args)
ephem, _, _ = create_assist_ephemeris(args, sconfigs.auxiliary)

furnish_spiceypy(args)
furnish_spiceypy(args, sconfigs.auxiliary)
obsCode = sconfigs.simulation.ar_obs_code
observatories = Observatory(args)
observatories = Observatory(args, sconfigs.auxiliary)

# vectorize the calculation to get x,y,z vector from ra/dec
vectors = ra_dec2vec(
Expand Down
13 changes: 5 additions & 8 deletions src/sorcha/utilities/generate_meta_kernel.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,6 @@
import os
import pooch

from sorcha.ephemeris.simulation_data_files import (
META_KERNEL,
ORDERED_KERNEL_FILES,
)

"""
An example output from running `build_meta_kernel_file` might look like
Expand All @@ -29,29 +25,30 @@
"""


def build_meta_kernel_file(retriever: pooch.Pooch) -> None:
def build_meta_kernel_file(auxconfigs, retriever: pooch.Pooch) -> None:
"""Builds a specific text file that will be fed into `spiceypy` that defines
the list of spice kernel to load, as well as the order to load them.
Parameters
----------
retriever : pooch
Pooch object that maintains the registry of files to download
auxconfigs: dataclass
Dataclass of auxiliary configuration file arguments.
Returns
---------
None
"""
# build meta_kernel file path
meta_kernel_file_path = os.path.join(retriever.abspath, META_KERNEL)
meta_kernel_file_path = os.path.join(retriever.abspath, auxconfigs.meta_kernel)

# build a meta_kernel.txt file
with open(meta_kernel_file_path, "w") as meta_file:
meta_file.write("\\begindata\n\n")
meta_file.write(f"PATH_VALUES = ('{retriever.abspath}')\n\n")
meta_file.write("PATH_SYMBOLS = ('A')\n\n")
meta_file.write("KERNELS_TO_LOAD=(\n")
for file_name in ORDERED_KERNEL_FILES:
for file_name in auxconfigs.ordered_kernel_files:
shortened_file_name = _build_file_name(retriever.abspath, retriever.fetch(file_name))
meta_file.write(f" '{shortened_file_name}',\n")
meta_file.write(")\n\n")
Expand Down
12 changes: 5 additions & 7 deletions src/sorcha/utilities/retrieve_ephemeris_data_files.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,7 @@
import pooch

from functools import partial
from sorcha.ephemeris.simulation_data_files import (
make_retriever,
DATA_FILES_TO_DOWNLOAD,
DATA_FILE_LIST,
)
from sorcha.ephemeris.simulation_data_files import make_retriever
from sorcha.utilities.generate_meta_kernel import build_meta_kernel_file


Expand All @@ -35,7 +31,7 @@ def _decompress(fname, action, pup): # pragma: no cover
pooch.Decompress(method="auto", name=os.path.splitext(fname)[0]).__call__(fname, action, pup)


def _remove_files(retriever: pooch.Pooch) -> None: # pragma: no cover
def _remove_files(auxconfigs, retriever: pooch.Pooch) -> None: # pragma: no cover
"""Utility to remove all the files tracked by the pooch retriever. This includes
the decompressed ObservatoryCodes.json file as well as the META_KERNEL file
that are created after downloading the files in the DATA_FILES_TO_DOWNLOAD
Expand All @@ -45,9 +41,11 @@ def _remove_files(retriever: pooch.Pooch) -> None: # pragma: no cover
------------
retriever : pooch
Pooch object that maintains the registry of files to download.
auxconfigs: dataclass
Dataclass of auxiliary configuration file arguments.
"""

for file_name in DATA_FILE_LIST:
for file_name in auxconfigs.data_file_list:
file_path = retriever.fetch(file_name)
print(f"Deleting file: {file_path}")
os.remove(file_path)
Expand Down
Loading

0 comments on commit 6ff172b

Please sign in to comment.