From 334cfb1b68b30f2d5ba2cdfb4ece5b1c72bc89a5 Mon Sep 17 00:00:00 2001 From: Ylva Selling Date: Mon, 30 Mar 2026 13:41:36 +0200 Subject: [PATCH] Add moon scripts --- generate-moon-assets/README.md | 49 +++ generate-moon-assets/generatemoonassets.py | 392 +++++++++++++++++++++ generate-moon-assets/lookuptable.py | 310 ++++++++++++++++ 3 files changed, 751 insertions(+) create mode 100644 generate-moon-assets/README.md create mode 100644 generate-moon-assets/generatemoonassets.py create mode 100644 generate-moon-assets/lookuptable.py diff --git a/generate-moon-assets/README.md b/generate-moon-assets/README.md new file mode 100644 index 0000000..f4dc639 --- /dev/null +++ b/generate-moon-assets/README.md @@ -0,0 +1,49 @@ +# Generate Moon Assets + +Python scripts that generate [OpenSpace](https://www.openspaceproject.com/) `.asset` files for Saturn's minor moons, using SPICE kernel data from JPL. + +## Scripts + +### `generatemoonassets.py` + +Generates OpenSpace asset files for recently discovered Saturn moons. For each moon it creates: + +- A **RenderableGlobe** scene graph node (body) +- A **RenderableTrailOrbit** (orbital trail) +- A **RenderableLabel** (text label, disabled by default) + +All objects are parented to `SaturnBarycenter` and placed under `/Solar System/Planets/Saturn/Minor Moons/ Group/` in the GUI. + +The script contains two ID blocks mapping provisional moon designations to SPICE kernel IDs: + +| Block | IDs | SPICE Kernel | Description | +|-------|-----|--------------|-------------| +| `id_block2` | 65094 -- 65157 | `kernels454` (SAT453) | May 2023 discoveries | +| `id_block` | 65158 -- 65285 | `kernels455` | March 2025 discoveries | + +The active block (`id_block`, parsed on line 225) is split into two output files to keep asset sizes manageable (e.g. `march_2025_discoveries-1.asset` and `march_2025_discoveries-2.asset`). To switch batches, change line 225 to parse `id_block2` instead. + +### `lookuptable.py` + +A data module exporting a `saturn_moons` dictionary with physical and orbital properties for ~288 Saturn moons. Each entry contains: + +- **group** -- dynamical family (e.g. Norse (Mundilfari), Inuit (Kiviuq), Gallic, inner ring) +- **orbital_period_days** -- orbital period in days (negative values indicate retrograde orbits) +- **diameter_km** -- approximate diameter in km + +Groups covered: inner/regular moons, co-orbital, ring-embedded, trojans, Inuit, Gallic, and Norse (with sub-groups Mundilfari, Phoebe, Kari, low-inclination). + +When run standalone it prints a summary table of all moons sorted by orbital period. + +## Usage + +```bash +python generatemoonassets.py +``` + +This writes two `.asset` files in the current directory. Place them in the appropriate OpenSpace data folder alongside the referenced SPICE kernel and transforms assets. + +## Dependencies + +- Python 3.6+ (f-strings) +- No external packages diff --git a/generate-moon-assets/generatemoonassets.py b/generate-moon-assets/generatemoonassets.py new file mode 100644 index 0000000..fdd1828 --- /dev/null +++ b/generate-moon-assets/generatemoonassets.py @@ -0,0 +1,392 @@ +import re +from lookuptable import saturn_moons + +id_block2 = """ + S2019S2 = 65094, + S2019S3 = 65095, + S2020S1 = 65096, + S2020S2 = 65097, + S2004S40 = 65098, + S2006S9 = 65100, + S2007S5 = 65101, + S2020S3 = 65102, + S2019S4 = 65103, + S2004S41 = 65104, + S2020S4 = 65105, + S2020S5 = 65106, + S2007S6 = 65107, + S2004S42 = 65108, + S2006S10 = 65109, + S2019S5 = 65110, + S2004S43 = 65111, + S2004S44 = 65112, + S2004S45 = 65113, + S2006S11 = 65114, + S2006S12 = 65115, + S2019S6 = 65116, + S2006S13 = 65117, + S2019S7 = 65118, + S2019S8 = 65119, + S2019S9 = 65120, + S2004S46 = 65121, + S2019S10 = 65122, + S2004S47 = 65123, + S2019S11 = 65124, + S2006S14 = 65125, + S2019S12 = 65126, + S2020S6 = 65127, + S2019S13 = 65128, + S2005S4 = 65129, + S2007S7 = 65130, + S2007S8 = 65131, + S2020S7 = 65132, + S2019S14 = 65133, + S2019S15 = 65134, + S2005S5 = 65135, + S2006S15 = 65136, + S2006S16 = 65137, + S2006S17 = 65138, + S2004S48 = 65139, + S2020S8 = 65140, + S2004S49 = 65141, + S2004S50 = 65142, + S2006S18 = 65143, + S2019S16 = 65144, + S2019S17 = 65145, + S2019S18 = 65146, + S2019S19 = 65147, + S2019S20 = 65148, + S2006S19 = 65149, + S2004S51 = 65150, + S2020S9 = 65151, + S2004S52 = 65152, + S2007S9 = 65153, + S2004S53 = 65154, + S2020S10 = 65155, + S2019S21 = 65156, + S2006S20 = 65157 +""" + +id_block = """ + S2004S54 = 65158, + S2004S55 = 65159, + S2004S56 = 65160, + S2004S57 = 65161, + S2004S58 = 65162, + S2004S59 = 65163, + S2004S60 = 65164, + S2004S61 = 65165, + S2005S6 = 65166, + S2005S7 = 65167, + S2006S21 = 65168, + S2006S22 = 65169, + S2006S23 = 65170, + S2006S24 = 65171, + S2006S25 = 65172, + S2006S26 = 65173, + S2006S27 = 65174, + S2006S28 = 65175, + S2006S29 = 65176, + S2007S10 = 65177, + S2007S11 = 65178, + S2019S22 = 65179, + S2019S23 = 65180, + S2019S24 = 65181, + S2019S25 = 65182, + S2019S26 = 65183, + S2019S27 = 65184, + S2019S28 = 65185, + S2019S29 = 65186, + S2019S30 = 65187, + S2019S31 = 65188, + S2019S32 = 65189, + S2019S33 = 65190, + S2019S34 = 65191, + S2019S35 = 65192, + S2019S36 = 65193, + S2019S37 = 65194, + S2019S38 = 65195, + S2019S39 = 65196, + S2019S40 = 65197, + S2019S41 = 65198, + S2019S42 = 65199, + S2019S43 = 65200, + S2019S44 = 65201, + S2020S11 = 65202, + S2020S12 = 65203, + S2020S13 = 65204, + S2020S14 = 65205, + S2020S15 = 65206, + S2020S16 = 65207, + S2020S17 = 65208, + S2020S18 = 65209, + S2020S19 = 65210, + S2020S20 = 65211, + S2020S21 = 65212, + S2020S22 = 65213, + S2020S23 = 65214, + S2020S24 = 65215, + S2020S25 = 65216, + S2020S26 = 65217, + S2020S27 = 65218, + S2020S28 = 65219, + S2020S29 = 65220, + S2020S30 = 65221, + S2020S31 = 65222, + S2020S32 = 65223, + S2020S33 = 65224, + S2020S34 = 65225, + S2020S35 = 65226, + S2020S36 = 65227, + S2020S37 = 65228, + S2020S38 = 65229, + S2020S39 = 65230, + S2020S40 = 65231, + S2020S41 = 65232, + S2020S42 = 65233, + S2020S43 = 65234, + S2020S44 = 65235, + S2023S1 = 65236, + S2023S2 = 65237, + S2023S3 = 65238, + S2023S4 = 65239, + S2023S5 = 65240, + S2023S6 = 65241, + S2023S7 = 65242, + S2023S8 = 65243, + S2023S9 = 65244, + S2023S10 = 65245, + S2023S11 = 65246, + S2023S12 = 65247, + S2023S13 = 65248, + S2023S14 = 65249, + S2023S15 = 65250, + S2023S16 = 65251, + S2023S17 = 65252, + S2023S18 = 65253, + S2023S19 = 65254, + S2023S20 = 65255, + S2023S21 = 65256, + S2023S22 = 65257, + S2023S23 = 65258, + S2023S24 = 65259, + S2023S25 = 65260, + S2023S26 = 65261, + S2023S27 = 65262, + S2023S28 = 65263, + S2023S29 = 65264, + S2023S30 = 65265, + S2023S31 = 65266, + S2023S32 = 65267, + S2023S33 = 65268, + S2023S34 = 65269, + S2023S35 = 65270, + S2023S36 = 65271, + S2023S37 = 65272, + S2023S38 = 65273, + S2023S39 = 65274, + S2023S40 = 65275, + S2023S41 = 65276, + S2023S42 = 65277, + S2023S43 = 65278, + S2023S44 = 65279, + S2023S45 = 65280, + S2023S46 = 65281, + S2023S47 = 65282, + S2023S48 = 65283, + S2023S49 = 65284, + S2023S50 = 65285 +""" + +def may2023(kernel, nBodies): + return f""" +asset.meta = {{ + Name = "Saturn Spice Kernels ({kernel} - May 2023 Discoveries)", + Description = [[{nBodies} newly discovered satellites [65094-65098], 65100-65157] + based on the SAT453 solution from R. Jacobson (JPL).]], + Author = "OpenSpace Team", + URL = "https://naif.jpl.nasa.gov/pub/naif/pds/wgc/kernels/spk/", + License = "NASA" +}} +""" + +def march2025(kernel, nBodies): + return f""" +asset.meta = {{ + Name = \"Saturn Spice Kernels ({kernel} - March 2025 Discoveries)\", + Description = [[SPICE kernels for {nBodies} Saturn moons discovered and announced March 2025. + (M. Brozović & R. A. Jacobson, JPL, Apr 2025)]], + Author = "OpenSpace Team", + URL = "https://naif.jpl.nasa.gov/pub/naif/pds/wgc/kernels/spk/", + License = "NASA" +}} +""" + +ids = dict(re.findall(r"(\w+)\s*=\s*(\d+)", id_block)) + +def format_gui_name(name): + match = re.match(r"S(\d{4})S0?(\d+)", name) + if match: + return f"S/{match.group(1)} S {match.group(2)}" + return name + +def get_group(name): + if format_gui_name(name) in saturn_moons: + return saturn_moons[format_gui_name(name)]["group"] + print(name, "not found in lookup table") + return "Unclassified" + +def get_orbit_time(name): + if format_gui_name(name) in saturn_moons: + return abs(saturn_moons[format_gui_name(name)]["orbital_period_days"]) + print(name, "not found in lookup table") + return 365 + +def get_radius(name): + if format_gui_name(name) in saturn_moons: + return saturn_moons[format_gui_name(name)]["diameter_km"] / 2 + print(name, "not found in lookup table") + return 1000 + + +# ---- Body generator ---- +def generate_body(name, kernel, orbit_time, radius): + + group = get_group(name) + gui_name = format_gui_name(name) + path = f"/Solar System/Planets/Saturn/Minor Moons/{group} Group/{name}" + + return f""" +local {name} = {{ + Identifier = "{name}", + Parent = transforms.SaturnBarycenter.Identifier, + Transform = {{ + Translation = {{ + Type = "SpiceTranslation", + Target = {kernel}.ID.{name}, + Observer = coreKernels.ID.SaturnBarycenter + }} + }}, + Renderable = {{ + Type = "RenderableGlobe", + Radii = {{ {radius}, {radius}, {radius} }} + }}, + GUI = {{ + Name = "{gui_name}", + Path = "{path}" + }} +}} + +local {name}Trail = {{ + Identifier = "{name}Trail", + Parent = transforms.SaturnBarycenter.Identifier, + Renderable = {{ + Type = "RenderableTrailOrbit", + Translation = {{ + Type = "SpiceTranslation", + Target = {kernel}.ID.{name}, + Observer = coreKernels.ID.SaturnBarycenter + }}, + Color = {{ 0.5, 0.3, 0.3 }}, + Period = {orbit_time}, + Resolution = 1000 + }}, + GUI = {{ + Name = "{gui_name} Trail", + Path = "{path}", + Focusable = false + }} +}} + +local {name}Label = {{ + Identifier = "{name}Label", + Parent = {name}.Identifier, + Renderable = {{ + Type = "RenderableLabel", + Enabled = false, + Text = "{gui_name}", + FontSize = 70.0, + Size = 7.0, + MinMaxSize = {{ 1, 25 }}, + OrientationOption = "Camera View Direction" + }}, + GUI = {{ + Name = "{gui_name} Label", + Path = "{path}", + Focusable = false + }} +}} +""" + +def generate_initialize(name): + return f""" + openspace.addSceneGraphNode({name}) + openspace.addSceneGraphNode({name}Trail) + openspace.addSceneGraphNode({name}Label) +""" + +def generate_deinitialize(name): + return f""" + openspace.removeSceneGraphNode({name}Label) + openspace.removeSceneGraphNode({name}Trail) + openspace.removeSceneGraphNode({name}) +""" + +kernel = "kernels454" if len(ids.keys()) <= 63 else "kernels455" +nBodies = str(len(ids.keys())) + +def print_ids(selected_ids, filename): + # ---- Write full asset file ---- + with open(filename + ".asset", "w", encoding="utf-8") as f: + f.write(f""" +local transforms = asset.require("../transforms") +local {kernel} = asset.require("../{kernel}") +local coreKernels = asset.require("spice/core") + """) + + # All bodies + for name in selected_ids: + orbit_time = get_orbit_time(name) + radius = get_radius(name) + f.write(generate_body(name, kernel, orbit_time, radius)) + + # Kernel calls + export + f.write(f""" + asset.onInitialize(function() + """) + # All bodies + for name in selected_ids: + f.write(generate_initialize(name)) + + f.write(f""" + end) + """) + f.write(f""" + asset.onDeinitialize(function() + """) + # All bodies + for name in selected_ids: + f.write(generate_deinitialize(name)) + + f.write(f""" + end) + """) + + for name in selected_ids: + f.write(f"asset.export({name})\n") + f.write(f"asset.export({name}Trail)\n") + f.write(f"asset.export({name}Label)\n\n") + + metadata = may2023(kernel, nBodies) if ids.keys().__len__() <= 63 else march2025(kernel, nBodies) + f.write(metadata) + +filename = "may_2023_discoveries" if len(ids.keys()) <= 63 else "march_2025_discoveries" + +keys_list = list(ids.keys()) +mid = len(keys_list) // 2 +print_ids(keys_list[:mid], filename + "-1") +print_ids(keys_list[mid:], filename + "-2") + +print("Full asset file generated: " + filename) +print("Generated bodies for:" + nBodies + " moons") + diff --git a/generate-moon-assets/lookuptable.py b/generate-moon-assets/lookuptable.py new file mode 100644 index 0000000..205c7b8 --- /dev/null +++ b/generate-moon-assets/lookuptable.py @@ -0,0 +1,310 @@ +# Saturn Moon Lookup Table (Complete - including provisional designations) +# Data: group, orbital_period_days, diameter_km +# Note: Negative orbital periods indicate retrograde orbits. +# Diameter values are approximate for most irregular/provisional moons. + +saturn_moons = { + # --- Inner / Regular Moons --- + "S/2009 S 1": {"group": "inner ring", "orbital_period_days": 0.47150, "diameter_km": 0.3}, + "Pan": {"group": "inner ring", "orbital_period_days": 0.57505, "diameter_km": 28.2}, + "Daphnis": {"group": "inner ring", "orbital_period_days": 0.59408, "diameter_km": 7.6}, + "Atlas": {"group": "inner ring", "orbital_period_days": 0.60460, "diameter_km": 30.2}, + "Prometheus": {"group": "inner ring", "orbital_period_days": 0.61588, "diameter_km": 86.2}, + "Pandora": {"group": "inner ring", "orbital_period_days": 0.63137, "diameter_km": 81.4}, + "Epimetheus": {"group": "co-orbital (with Janus)", "orbital_period_days": 0.69701, "diameter_km": 116.2}, + "Janus": {"group": "co-orbital (with Epimetheus)", "orbital_period_days": 0.69735, "diameter_km": 179.0}, + "Aegaeon": {"group": "ring-embedded", "orbital_period_days": 0.80812, "diameter_km": 0.66}, + "Mimas": {"group": "regular (round)", "orbital_period_days": 0.94242, "diameter_km": 396.4}, + "Methone": {"group": "ring-embedded", "orbital_period_days": 1.00955, "diameter_km": 2.9}, + "Anthe": {"group": "ring-embedded", "orbital_period_days": 1.03890, "diameter_km": 1.8}, + "Pallene": {"group": "ring-embedded", "orbital_period_days": 1.15606, "diameter_km": 4.44}, + "Enceladus": {"group": "regular (round)", "orbital_period_days": 1.37022, "diameter_km": 504.2}, + "Tethys": {"group": "regular (round)", "orbital_period_days": 1.88780, "diameter_km": 1062.2}, + "Telesto": {"group": "trojan (Tethys L4)", "orbital_period_days": 1.88780, "diameter_km": 24.8}, + "Calypso": {"group": "trojan (Tethys L5)", "orbital_period_days": 1.88780, "diameter_km": 21.4}, + "Helene": {"group": "trojan (Dione L4)", "orbital_period_days": 2.73692, "diameter_km": 35.2}, + "Polydeuces": {"group": "trojan (Dione L5)", "orbital_period_days": 2.73692, "diameter_km": 2.6}, + "Dione": {"group": "regular (round)", "orbital_period_days": 2.73692, "diameter_km": 1122.8}, + "Rhea": {"group": "regular (round)", "orbital_period_days": 4.51750, "diameter_km": 1527.6}, + "Titan": {"group": "regular (round)", "orbital_period_days": 15.9454, "diameter_km": 5149.46}, + "Hyperion": {"group": "regular", "orbital_period_days": 21.2767, "diameter_km": 270.0}, + "Iapetus": {"group": "regular (round)", "orbital_period_days": 79.3310, "diameter_km": 1468.6}, + + # --- Inuit Group --- + "S/2023 S 1": {"group": "Inuit (Kiviuq)", "orbital_period_days": 442.86, "diameter_km": 3.0}, + "S/2019 S 1": {"group": "Inuit (Kiviuq)", "orbital_period_days": 445.17, "diameter_km": 5.0}, + "S/2004 S 54": {"group": "Inuit (Kiviuq)", "orbital_period_days": 447.14, "diameter_km": 4.0}, + "S/2004 S 55": {"group": "Inuit (Kiviuq)", "orbital_period_days": 448.16, "diameter_km": 3.0}, + "S/2020 S 11": {"group": "Inuit (Kiviuq)", "orbital_period_days": 448.21, "diameter_km": 3.0}, + "S/2019 S 22": {"group": "Inuit (Kiviuq)", "orbital_period_days": 448.48, "diameter_km": 3.0}, + "Kiviuq": {"group": "Inuit (Kiviuq)", "orbital_period_days": 448.91, "diameter_km": 17.0}, + "S/2023 S 2": {"group": "Inuit (Kiviuq)", "orbital_period_days": 449.05, "diameter_km": 3.0}, + "S/2019 S 23": {"group": "Inuit (Kiviuq)", "orbital_period_days": 449.08, "diameter_km": 3.0}, + "S/2020 S 12": {"group": "Inuit (Kiviuq)", "orbital_period_days": 449.33, "diameter_km": 3.0}, + "S/2005 S 4": {"group": "Inuit (Kiviuq)", "orbital_period_days": 449.93, "diameter_km": 5.0}, + "S/2019 S 25": {"group": "Inuit (Kiviuq)", "orbital_period_days": 450.22, "diameter_km": 4.0}, + "S/2020 S 1": {"group": "Inuit (Kiviuq)", "orbital_period_days": 450.77, "diameter_km": 4.0}, + "Ijiraq": {"group": "Inuit (Kiviuq)", "orbital_period_days": 451.12, "diameter_km": 13.0}, + "S/2019 S 24": {"group": "Inuit (Kiviuq)", "orbital_period_days": 452.07, "diameter_km": 4.0}, + "S/2007 S 10": {"group": "Inuit (Kiviuq)", "orbital_period_days": 452.36, "diameter_km": 4.0}, + "S/2019 S 26": {"group": "Inuit (Kiviuq)", "orbital_period_days": 453.89, "diameter_km": 3.0}, + "S/2020 S 13": {"group": "Inuit (Kiviuq)", "orbital_period_days": 455.39, "diameter_km": 3.0}, + "S/2023 S 6": {"group": "Inuit (Kiviuq)", "orbital_period_days": 487.91, "diameter_km": 3.0}, + "S/2023 S 7": {"group": "Inuit (Kiviuq)", "orbital_period_days": 499.01, "diameter_km": 4.0}, + "Paaliaq": {"group": "Inuit", "orbital_period_days": 685.72, "diameter_km": 25.0}, + "S/2004 S 31": {"group": "Inuit (Siarnaq)", "orbital_period_days": 863.92, "diameter_km": 5.0}, + "S/2019 S 14": {"group": "Inuit (Siarnaq)", "orbital_period_days": 890.59, "diameter_km": 4.0}, + "S/2023 S 19": {"group": "Inuit (Siarnaq)", "orbital_period_days": 870.92, "diameter_km": 3.0}, + "S/2023 S 3": {"group": "Inuit (Siarnaq)", "orbital_period_days": 875.00, "diameter_km": 3.0}, + "S/2020 S 19": {"group": "Inuit (Siarnaq)", "orbital_period_days": 881.04, "diameter_km": 3.0}, + "Tarqeq": {"group": "Inuit (Siarnaq)", "orbital_period_days": 882.85, "diameter_km": 7.0}, + "Siarnaq": {"group": "Inuit (Siarnaq)", "orbital_period_days": 892.68, "diameter_km": 39.3}, + "S/2019 S 32": {"group": "Inuit (Siarnaq)", "orbital_period_days": 898.71, "diameter_km": 5.0}, + "S/2020 S 3": {"group": "Inuit (Siarnaq)", "orbital_period_days": 905.84, "diameter_km": 3.0}, + "S/2005 S 6": {"group": "Inuit (Siarnaq)", "orbital_period_days": 909.58, "diameter_km": 4.0}, + "S/2019 S 6": {"group": "Inuit (Siarnaq)", "orbital_period_days": 917.11, "diameter_km": 5.0}, + "S/2004 S 58": {"group": "Inuit (Siarnaq)", "orbital_period_days": 920.80, "diameter_km": 5.0}, + "S/2006 S 23": {"group": "Inuit (Siarnaq)", "orbital_period_days": 921.86, "diameter_km": 3.0}, + "S/2020 S 5": {"group": "Inuit (Siarnaq)", "orbital_period_days": 931.19, "diameter_km": 3.0}, + "S/2023 S 22": {"group": "Inuit (Siarnaq)", "orbital_period_days": 945.37, "diameter_km": 4.0}, + + # --- Gallic Group --- + "Albiorix": {"group": "Gallic", "orbital_period_days": 779.07, "diameter_km": 28.6}, + "S/2020 S 15": {"group": "Gallic", "orbital_period_days": 807.82, "diameter_km": 3.0}, + "Bebhionn": {"group": "Gallic", "orbital_period_days": 829.64, "diameter_km": 6.0}, + "S/2007 S 8": {"group": "Gallic", "orbital_period_days": 831.21, "diameter_km": 4.0}, + "S/2004 S 29": {"group": "Gallic", "orbital_period_days": 832.27, "diameter_km": 5.0}, + "S/2019 S 29": {"group": "Gallic", "orbital_period_days": 853.62, "diameter_km": 3.0}, + "S/2023 S 18": {"group": "Gallic", "orbital_period_days": 855.65, "diameter_km": 3.0}, + "S/2023 S 17": {"group": "Gallic", "orbital_period_days": 855.94, "diameter_km": 3.0}, + "S/2007 S 11": {"group": "Gallic", "orbital_period_days": 859.53, "diameter_km": 4.0}, + "Erriapus": {"group": "Gallic", "orbital_period_days": 864.92, "diameter_km": 10.0}, + "S/2019 S 31": {"group": "Gallic", "orbital_period_days": 882.24, "diameter_km": 3.0}, + "Tarvos": {"group": "Gallic", "orbital_period_days": 917.98, "diameter_km": 15.0}, + "S/2020 S 4": {"group": "Gallic", "orbital_period_days": 919.52, "diameter_km": 3.0}, + "S/2019 S 34": {"group": "Gallic", "orbital_period_days": 935.45, "diameter_km": 3.0}, + "S/2005 S 7": {"group": "Gallic", "orbital_period_days": 939.75, "diameter_km": 3.0}, + "S/2006 S 12": {"group": "Gallic", "orbital_period_days": 1022.29, "diameter_km": 4.0}, + "S/2004 S 24": {"group": "Gallic", "orbital_period_days": 1331.32, "diameter_km": 4.0}, + + # --- Norse Group --- + "S/2023 S 50": {"group": "Norse (Mundilfari)", "orbital_period_days": -469.82, "diameter_km": 3.0}, + "S/2023 S 38": {"group": "Norse (low-inclination)", "orbital_period_days": -546.31, "diameter_km": 3.0}, + "Phoebe": {"group": "Norse (Phoebe)", "orbital_period_days": -550.30, "diameter_km": 213.0}, + "S/2023 S 9": {"group": "Norse (Phoebe)", "orbital_period_days": -564.11, "diameter_km": 3.0}, + "S/2006 S 20": {"group": "Norse (Phoebe)", "orbital_period_days": -565.79, "diameter_km": 5.0}, + "S/2004 S 56": {"group": "Norse (Mundilfari)", "orbital_period_days": -596.69, "diameter_km": 5.0}, + "S/2023 S 8": {"group": "Norse (Mundilfari)", "orbital_period_days": -619.69, "diameter_km": 3.0}, + "S/2023 S 11": {"group": "Norse (Mundilfari)", "orbital_period_days": -621.49, "diameter_km": 3.0}, + "S/2006 S 9": {"group": "Norse (Phoebe)", "orbital_period_days": -645.58, "diameter_km": 3.0}, + "S/2006 S 21": {"group": "Norse (Mundilfari)", "orbital_period_days": -684.28, "diameter_km": 3.0}, + "S/2006 S 22": {"group": "Norse (Phoebe)", "orbital_period_days": -693.41, "diameter_km": 3.0}, + "S/2023 S 13": {"group": "Norse (Mundilfari)", "orbital_period_days": -699.18, "diameter_km": 3.0}, + "S/2023 S 10": {"group": "Norse (Mundilfari)", "orbital_period_days": -720.49, "diameter_km": 3.0}, + "Skathi": {"group": "Norse (low-inclination)", "orbital_period_days": -725.73, "diameter_km": 8.0}, + "S/2023 S 12": {"group": "Norse (Mundilfari)", "orbital_period_days": -741.92, "diameter_km": 3.0}, + "S/2007 S 5": {"group": "Norse (Mundilfari)", "orbital_period_days": -744.01, "diameter_km": 4.0}, + "S/2007 S 7": {"group": "Norse (Mundilfari)", "orbital_period_days": -750.80, "diameter_km": 4.0}, + "S/2007 S 2": {"group": "Norse (Phoebe)", "orbital_period_days": -751.33, "diameter_km": 5.0}, + "S/2004 S 37": {"group": "Norse (Mundilfari)", "orbital_period_days": -752.55, "diameter_km": 4.0}, + "S/2004 S 47": {"group": "Norse (Mundilfari)", "orbital_period_days": -759.22, "diameter_km": 4.0}, + "S/2004 S 40": {"group": "Norse (Mundilfari)", "orbital_period_days": -761.00, "diameter_km": 4.0}, + "S/2020 S 14": {"group": "Norse (Mundilfari)", "orbital_period_days": -768.86, "diameter_km": 3.0}, + "S/2019 S 27": {"group": "Norse (Mundilfari)", "orbital_period_days": -774.63, "diameter_km": 3.0}, + "S/2019 S 2": {"group": "Norse (Phoebe)", "orbital_period_days": -795.67, "diameter_km": 3.0}, + "S/2020 S 7": {"group": "Norse (Mundilfari)", "orbital_period_days": -856.53, "diameter_km": 3.0}, + "S/2023 S 14": {"group": "Norse (Mundilfari)", "orbital_period_days": -816.86, "diameter_km": 3.0}, + "S/2020 S 16": {"group": "Norse (Mundilfari)", "orbital_period_days": -824.92, "diameter_km": 3.0}, + "S/2023 S 16": {"group": "Norse (Mundilfari)", "orbital_period_days": -827.81, "diameter_km": 3.0}, + "Skoll": {"group": "Norse (Mundilfari)", "orbital_period_days": -873.57, "diameter_km": 5.0}, + "S/2019 S 30": {"group": "Norse (Mundilfari)", "orbital_period_days": -879.97, "diameter_km": 3.0}, + "S/2019 S 28": {"group": "Norse (Mundilfari)", "orbital_period_days": -864.09, "diameter_km": 4.0}, + "S/2019 S 4": {"group": "Norse (Mundilfari)", "orbital_period_days": -898.09, "diameter_km": 3.0}, + "S/2020 S 20": {"group": "Norse (Mundilfari)", "orbital_period_days": -901.53, "diameter_km": 3.0}, + "S/2004 S 41": {"group": "Norse (Mundilfari)", "orbital_period_days": -908.89, "diameter_km": 4.0}, + "S/2004 S 57": {"group": "Norse (Mundilfari)", "orbital_period_days": -913.07, "diameter_km": 4.0}, + "S/2006 S 24": {"group": "Norse (Mundilfari)", "orbital_period_days": -917.56, "diameter_km": 3.0}, + "S/2023 S 30": {"group": "Norse (low-inclination)", "orbital_period_days": -919.71, "diameter_km": 3.0}, + "S/2004 S 42": {"group": "Norse (Mundilfari)", "orbital_period_days": -919.88, "diameter_km": 4.0}, + "S/2023 S 15": {"group": "Norse (Mundilfari)", "orbital_period_days": -919.93, "diameter_km": 3.0}, + "Hyrrokkin": {"group": "Norse (low-inclination)", "orbital_period_days": -927.46, "diameter_km": 8.0}, + "S/2023 S 24": {"group": "Norse (Mundilfari)", "orbital_period_days": -928.25, "diameter_km": 3.0}, + "Greip": {"group": "Norse (Phoebe)", "orbital_period_days": -930.44, "diameter_km": 5.0}, + "S/2004 S 13": {"group": "Norse (Mundilfari)", "orbital_period_days": -936.09, "diameter_km": 4.0}, + "S/2007 S 6": {"group": "Norse (Mundilfari)", "orbital_period_days": -942.98, "diameter_km": 3.0}, + "S/2019 S 35": {"group": "Norse (Mundilfari)", "orbital_period_days": -944.00, "diameter_km": 3.0}, + "S/2006 S 25": {"group": "Norse (Mundilfari)", "orbital_period_days": -945.07, "diameter_km": 3.0}, + "Mundilfari": {"group": "Norse (Mundilfari)", "orbital_period_days": -946.29, "diameter_km": 7.0}, + "S/2006 S 26": {"group": "Norse (Mundilfari)", "orbital_period_days": -948.67, "diameter_km": 3.0}, + "S/2019 S 33": {"group": "Norse (Mundilfari)", "orbital_period_days": -954.53, "diameter_km": 4.0}, + "S/2006 S 1": {"group": "Norse (Kari)", "orbital_period_days": -958.32, "diameter_km": 5.0}, + "S/2023 S 23": {"group": "Norse (Mundilfari)", "orbital_period_days": -961.22, "diameter_km": 3.0}, + "S/2020 S 21": {"group": "Norse (Mundilfari)", "orbital_period_days": -967.26, "diameter_km": 3.0}, + "S/2004 S 43": {"group": "Norse (Mundilfari)", "orbital_period_days": -972.85, "diameter_km": 4.0}, + "S/2006 S 10": {"group": "Norse (Mundilfari)", "orbital_period_days": -976.34, "diameter_km": 3.0}, + "S/2019 S 5": {"group": "Norse (Mundilfari)", "orbital_period_days": -984.87, "diameter_km": 3.0}, + "S/2023 S 25": {"group": "Norse (Mundilfari)", "orbital_period_days": -988.53, "diameter_km": 3.0}, + "S/2004 S 59": {"group": "Norse (Mundilfari)", "orbital_period_days": -991.18, "diameter_km": 3.0}, + "S/2006 S 27": {"group": "Norse (Mundilfari)", "orbital_period_days": -993.79, "diameter_km": 4.0}, + "Gridr": {"group": "Norse (Mundilfari)", "orbital_period_days": -997.33, "diameter_km": 4.0}, + "Bergelmir": {"group": "Norse (Mundilfari)", "orbital_period_days": -998.62, "diameter_km": 5.0}, + "Jarnsaxa": {"group": "Norse (Mundilfari)", "orbital_period_days": -999.13, "diameter_km": 6.0}, + "Narvi": {"group": "Norse (low-inclination)", "orbital_period_days": -999.94, "diameter_km": 7.0}, + "S/2023 S 44": {"group": "Norse (Mundilfari)", "orbital_period_days": -1000.47, "diameter_km": 3.0}, + "Suttungr": {"group": "Norse (Phoebe)", "orbital_period_days": -1008.25, "diameter_km": 7.0}, + "S/2020 S 22": {"group": "Norse (Mundilfari)", "orbital_period_days": -1012.24, "diameter_km": 3.0}, + "S/2004 S 44": {"group": "Norse (Mundilfari)", "orbital_period_days": -1017.91, "diameter_km": 5.0}, + "S/2004 S 60": {"group": "Norse (Phoebe)", "orbital_period_days": -1018.13, "diameter_km": 3.0}, + "S/2007 S 3": {"group": "Norse (Phoebe)", "orbital_period_days": -1025.70, "diameter_km": 5.0}, + "S/2004 S 45": {"group": "Norse (Kari)", "orbital_period_days": -1031.86, "diameter_km": 4.0}, + "Hati": {"group": "Norse (Mundilfari)", "orbital_period_days": -1032.02, "diameter_km": 5.0}, + "S/2004 S 17": {"group": "Norse (Mundilfari)", "orbital_period_days": -1032.37, "diameter_km": 4.0}, + "S/2006 S 11": {"group": "Norse (Phoebe)", "orbital_period_days": -1033.35, "diameter_km": 3.0}, + "S/2004 S 12": {"group": "Norse (Mundilfari)", "orbital_period_days": -1040.39, "diameter_km": 4.0}, + "S/2020 S 23": {"group": "Norse (Mundilfari)", "orbital_period_days": -1040.38, "diameter_km": 3.0}, + "S/2023 S 27": {"group": "Norse (low-inclination)", "orbital_period_days": -1041.85, "diameter_km": 3.0}, + "Eggther": {"group": "Norse (Mundilfari)", "orbital_period_days": -1043.80, "diameter_km": 6.0}, + "S/2023 S 28": {"group": "Norse (Mundilfari)", "orbital_period_days": -1046.56, "diameter_km": 3.0}, + "S/2023 S 37": {"group": "Norse (Phoebe)", "orbital_period_days": -1047.39, "diameter_km": 3.0}, + "S/2023 S 26": {"group": "Norse (Mundilfari)", "orbital_period_days": -1047.76, "diameter_km": 3.0}, + "S/2019 S 36": {"group": "Norse (Mundilfari)", "orbital_period_days": -1048.42, "diameter_km": 3.0}, + "S/2006 S 13": {"group": "Norse (Mundilfari)", "orbital_period_days": -1052.32, "diameter_km": 4.0}, + "S/2019 S 37": {"group": "Norse (low-inclination)", "orbital_period_days": -1055.78, "diameter_km": 3.0}, + "S/2023 S 48": {"group": "Norse (Mundilfari)", "orbital_period_days": -1058.35, "diameter_km": 3.0}, + "S/2023 S 29": {"group": "Norse (Phoebe)", "orbital_period_days": -1059.42, "diameter_km": 3.0}, + "S/2007 S 9": {"group": "Norse (Mundilfari)", "orbital_period_days": -1069.81, "diameter_km": 4.0}, + "S/2019 S 7": {"group": "Norse (Phoebe)", "orbital_period_days": -1070.80, "diameter_km": 4.0}, + "S/2019 S 8": {"group": "Norse (Phoebe)", "orbital_period_days": -1078.86, "diameter_km": 4.0}, + "Farbauti": {"group": "Norse (Kari)", "orbital_period_days": -1079.12, "diameter_km": 5.0}, + "Thrymr": {"group": "Norse (Phoebe)", "orbital_period_days": -1082.23, "diameter_km": 8.0}, + "Bestla": {"group": "Norse (low-inclination)", "orbital_period_days": -1082.94, "diameter_km": 7.0}, + "S/2019 S 9": {"group": "Norse (Mundilfari)", "orbital_period_days": -1084.62, "diameter_km": 4.0}, + "S/2023 S 32": {"group": "Norse (Mundilfari)", "orbital_period_days": -1092.24, "diameter_km": 2.0}, + "S/2004 S 46": {"group": "Norse (Phoebe)", "orbital_period_days": -1096.99, "diameter_km": 3.0}, + "Angrboda": {"group": "Norse (Phoebe)", "orbital_period_days": -1103.20, "diameter_km": 4.0}, + "S/2020 S 24": {"group": "Norse (Mundilfari)", "orbital_period_days": -1105.41, "diameter_km": 3.0}, + "S/2019 S 11": {"group": "Norse (low-inclination)", "orbital_period_days": -1109.11, "diameter_km": 4.0}, + "Aegir": {"group": "Norse (Mundilfari)", "orbital_period_days": -1109.13, "diameter_km": 6.0}, + "S/2019 S 10": {"group": "Norse (Mundilfari)", "orbital_period_days": -1111.99, "diameter_km": 3.0}, + "Beli": {"group": "Norse (Mundilfari)", "orbital_period_days": -1112.27, "diameter_km": 4.0}, + "S/2023 S 31": {"group": "Norse (Mundilfari)", "orbital_period_days": -1114.29, "diameter_km": 3.0}, + "S/2020 S 25": {"group": "Norse (Mundilfari)", "orbital_period_days": -1117.09, "diameter_km": 3.0}, + "S/2023 S 34": {"group": "Norse (Mundilfari)", "orbital_period_days": -1120.38, "diameter_km": 3.0}, + "S/2023 S 39": {"group": "Norse (Mundilfari)", "orbital_period_days": -1121.99, "diameter_km": 3.0}, + "S/2019 S 12": {"group": "Norse (Mundilfari)", "orbital_period_days": -1127.60, "diameter_km": 4.0}, + "Gerd": {"group": "Norse (Phoebe)", "orbital_period_days": -1131.91, "diameter_km": 4.0}, + "S/2019 S 13": {"group": "Norse (Phoebe)", "orbital_period_days": -1133.27, "diameter_km": 3.0}, + "S/2004 S 61": {"group": "Norse (Mundilfari)", "orbital_period_days": -1135.06, "diameter_km": 4.0}, + "S/2006 S 14": {"group": "Norse (Mundilfari)", "orbital_period_days": -1141.27, "diameter_km": 3.0}, + "S/2023 S 40": {"group": "Norse (Mundilfari)", "orbital_period_days": -1141.48, "diameter_km": 3.0}, + "Gunnlod": {"group": "Norse (Mundilfari)", "orbital_period_days": -1147.74, "diameter_km": 4.0}, + "S/2019 S 15": {"group": "Norse (Mundilfari)", "orbital_period_days": -1151.66, "diameter_km": 3.0}, + "S/2020 S 6": {"group": "Norse (Mundilfari)", "orbital_period_days": -1156.81, "diameter_km": 3.0}, + "S/2020 S 26": {"group": "Norse (Mundilfari)", "orbital_period_days": -1157.77, "diameter_km": 3.0}, + "S/2023 S 41": {"group": "Norse (Phoebe)", "orbital_period_days": -1159.52, "diameter_km": 3.0}, + "S/2004 S 7": {"group": "Norse (Mundilfari)", "orbital_period_days": -1162.93, "diameter_km": 5.0}, + "S/2006 S 3": {"group": "Norse (Kari)", "orbital_period_days": -1165.02, "diameter_km": 5.0}, + "S/2005 S 5": {"group": "Norse (Mundilfari)", "orbital_period_days": -1165.96, "diameter_km": 3.0}, + "Skrymir": {"group": "Norse (Phoebe)", "orbital_period_days": -1172.72, "diameter_km": 4.0}, + "S/2023 S 33": {"group": "Norse (Kari)", "orbital_period_days": -1187.07, "diameter_km": 3.0}, + "S/2006 S 16": {"group": "Norse (Mundilfari)", "orbital_period_days": -1195.13, "diameter_km": 3.0}, + "S/2023 S 49": {"group": "Norse (Mundilfari)", "orbital_period_days": -1198.99, "diameter_km": 3.0}, + "S/2020 S 30": {"group": "Norse (Kari)", "orbital_period_days": -1201.02, "diameter_km": 3.0}, + "S/2006 S 15": {"group": "Norse (Mundilfari)", "orbital_period_days": -1201.69, "diameter_km": 4.0}, + "S/2020 S 27": {"group": "Norse (low-inclination)", "orbital_period_days": -1202.02, "diameter_km": 3.0}, + "S/2023 S 42": {"group": "Norse (Mundilfari)", "orbital_period_days": -1204.81, "diameter_km": 3.0}, + "S/2004 S 28": {"group": "Norse (Mundilfari)", "orbital_period_days": -1207.18, "diameter_km": 5.0}, + "S/2020 S 32": {"group": "Norse (Mundilfari)", "orbital_period_days": -1208.85, "diameter_km": 3.0}, + "S/2006 S 28": {"group": "Norse (Phoebe)", "orbital_period_days": -1214.53, "diameter_km": 4.0}, + "S/2020 S 8": {"group": "Norse (Mundilfari)", "orbital_period_days": -1215.61, "diameter_km": 3.0}, + "S/2020 S 28": {"group": "Norse (Mundilfari)", "orbital_period_days": -1217.81, "diameter_km": 3.0}, + "Alvaldi": {"group": "Norse (Phoebe)", "orbital_period_days": -1217.80, "diameter_km": 6.0}, + "S/2019 S 38": {"group": "Norse (Mundilfari)", "orbital_period_days": -1218.27, "diameter_km": 3.0}, + "Kari": {"group": "Norse (Kari)", "orbital_period_days": -1220.98, "diameter_km": 6.0}, + "S/2004 S 48": {"group": "Norse (Mundilfari)", "orbital_period_days": -1229.86, "diameter_km": 4.0}, + "S/2023 S 36": {"group": "Norse (Mundilfari)", "orbital_period_days": -1237.61, "diameter_km": 3.0}, + "Geirrod": {"group": "Norse (Kari)", "orbital_period_days": -1240.05, "diameter_km": 4.0}, + "S/2023 S 35": {"group": "Norse (Mundilfari)", "orbital_period_days": -1240.76, "diameter_km": 3.0}, + "S/2020 S 29": {"group": "Norse (Mundilfari)", "orbital_period_days": -1243.45, "diameter_km": 3.0}, + "Fenrir": {"group": "Norse (Mundilfari)", "orbital_period_days": -1245.92, "diameter_km": 4.0}, + "S/2004 S 50": {"group": "Norse (Mundilfari)", "orbital_period_days": -1247.19, "diameter_km": 3.0}, + "S/2006 S 17": {"group": "Norse (Mundilfari)", "orbital_period_days": -1250.46, "diameter_km": 4.0}, + "S/2004 S 49": {"group": "Norse (Mundilfari)", "orbital_period_days": -1251.68, "diameter_km": 4.0}, + "S/2020 S 34": {"group": "Norse (Mundilfari)", "orbital_period_days": -1254.61, "diameter_km": 3.0}, + "S/2020 S 31": {"group": "Norse (Mundilfari)", "orbital_period_days": -1256.50, "diameter_km": 3.0}, + "S/2023 S 43": {"group": "Norse (Mundilfari)", "orbital_period_days": -1265.57, "diameter_km": 3.0}, + "S/2019 S 17": {"group": "Norse (Kari)", "orbital_period_days": -1278.96, "diameter_km": 4.0}, + "Surtur": {"group": "Norse (Mundilfari)", "orbital_period_days": -1281.14, "diameter_km": 6.0}, + "S/2006 S 18": {"group": "Norse (Mundilfari)", "orbital_period_days": -1282.09, "diameter_km": 4.0}, + "S/2020 S 36": {"group": "Norse (Mundilfari)", "orbital_period_days": -1286.03, "diameter_km": 3.0}, + "Loge": {"group": "Norse (Mundilfari)", "orbital_period_days": -1295.52, "diameter_km": 5.0}, + "S/2020 S 33": {"group": "Norse (Mundilfari)", "orbital_period_days": -1295.85, "diameter_km": 3.0}, + "Ymir": {"group": "Norse (Phoebe)", "orbital_period_days": -1298.68, "diameter_km": 19.0}, + "S/2020 S 35": {"group": "Norse (Phoebe)", "orbital_period_days": -1304.97, "diameter_km": 3.0}, + "S/2019 S 19": {"group": "Norse (Kari)", "orbital_period_days": -1306.16, "diameter_km": 3.0}, + "S/2019 S 18": {"group": "Norse (Kari)", "orbital_period_days": -1314.27, "diameter_km": 3.0}, + "S/2004 S 21": {"group": "Norse (Kari)", "orbital_period_days": -1316.12, "diameter_km": 4.0}, + "S/2004 S 39": {"group": "Norse (Mundilfari)", "orbital_period_days": -1318.74, "diameter_km": 4.0}, + "S/2019 S 16": {"group": "Norse (Mundilfari)", "orbital_period_days": -1324.95, "diameter_km": 3.0}, + "S/2004 S 53": {"group": "Norse (Mundilfari)", "orbital_period_days": -1326.18, "diameter_km": 4.0}, + "S/2004 S 36": {"group": "Norse (Kari)", "orbital_period_days": -1335.80, "diameter_km": 4.0}, + "S/2023 S 45": {"group": "Norse (Mundilfari)", "orbital_period_days": -1339.85, "diameter_km": 3.0}, + "Thiazzi": {"group": "Norse (Mundilfari)", "orbital_period_days": -1351.83, "diameter_km": 4.0}, + "S/2020 S 38": {"group": "Norse (Mundilfari)", "orbital_period_days": -1352.43, "diameter_km": 4.0}, + "S/2019 S 20": {"group": "Norse (Kari)", "orbital_period_days": -1360.47, "diameter_km": 3.0}, + "S/2020 S 37": {"group": "Norse (Phoebe)", "orbital_period_days": -1366.82, "diameter_km": 3.0}, + "S/2019 S 39": {"group": "Norse (Phoebe)", "orbital_period_days": -1369.64, "diameter_km": 3.0}, + "S/2020 S 40": {"group": "Norse (Mundilfari)", "orbital_period_days": -1369.76, "diameter_km": 3.0}, + "S/2006 S 19": {"group": "Norse (Phoebe)", "orbital_period_days": -1371.02, "diameter_km": 4.0}, + "S/2019 S 40": {"group": "Norse (Mundilfari)", "orbital_period_days": -1395.88, "diameter_km": 3.0}, + "S/2019 S 42": {"group": "Norse (Mundilfari)", "orbital_period_days": -1397.98, "diameter_km": 4.0}, + "S/2004 S 34": {"group": "Norse (Mundilfari)", "orbital_period_days": -1400.93, "diameter_km": 4.0}, + "S/2020 S 39": {"group": "Norse (Mundilfari)", "orbital_period_days": -1411.15, "diameter_km": 3.0}, + "S/2019 S 41": {"group": "Norse (Mundilfari)", "orbital_period_days": -1431.30, "diameter_km": 3.0}, + "S/2023 S 46": {"group": "Norse (low-inclination)", "orbital_period_days": -1450.27, "diameter_km": 3.0}, + "Fornjot": {"group": "Norse (Mundilfari)", "orbital_period_days": -1470.36, "diameter_km": 6.0}, + "S/2023 S 47": {"group": "Norse (Mundilfari)", "orbital_period_days": -1485.04, "diameter_km": 3.0}, + "S/2004 S 51": {"group": "Norse (Mundilfari)", "orbital_period_days": -1494.41, "diameter_km": 4.0}, + "S/2006 S 29": {"group": "Norse (Kari)", "orbital_period_days": -1494.78, "diameter_km": 3.0}, + "S/2020 S 10": {"group": "Norse (Mundilfari)", "orbital_period_days": -1503.97, "diameter_km": 3.0}, + "S/2020 S 42": {"group": "Norse (Mundilfari)", "orbital_period_days": -1505.31, "diameter_km": 3.0}, + "S/2020 S 9": {"group": "Norse (Mundilfari)", "orbital_period_days": -1512.38, "diameter_km": 4.0}, + "S/2023 S 5": {"group": "Norse (Mundilfari)", "orbital_period_days": -1528.04, "diameter_km": 3.0}, + "S/2020 S 41": {"group": "Norse (Mundilfari)", "orbital_period_days": -1554.40, "diameter_km": 3.0}, + "S/2004 S 26": {"group": "Norse (Phoebe)", "orbital_period_days": -1574.25, "diameter_km": 5.0}, + "S/2019 S 21": {"group": "Norse (Mundilfari)", "orbital_period_days": -1605.28, "diameter_km": 4.0}, + "S/2004 S 52": {"group": "Norse (Mundilfari)", "orbital_period_days": -1605.89, "diameter_km": 3.0}, + "S/2020 S 43": {"group": "Norse (Mundilfari)", "orbital_period_days": -1625.29, "diameter_km": 3.0}, + "S/2019 S 43": {"group": "Norse (Mundilfari)", "orbital_period_days": -1625.90, "diameter_km": 3.0}, + "S/2019 S 44": {"group": "Norse (Phoebe)", "orbital_period_days": -1638.11, "diameter_km": 3.0}, + "S/2020 S 44": {"group": "Norse (Mundilfari)", "orbital_period_days": -1680.64, "diameter_km": 3.0}, + "S/2020 S 17": {"group": "Norse (low-inclination)", "orbital_period_days": -834.45, "diameter_km": 4.0}, + "S/2020 S 18": {"group": "Norse (Mundilfari)", "orbital_period_days": -885.12, "diameter_km": 3.0}, + "S/2023 S 4": {"group": "Norse (Mundilfari)", "orbital_period_days": -884.11, "diameter_km": 3.0}, + "S/2023 S 20": {"group": "Norse (low-inclination)", "orbital_period_days": -846.77, "diameter_km": 3.0}, + "S/2023 S 21": {"group": "Norse (Mundilfari)", "orbital_period_days": -883.31, "diameter_km": 3.0}, + "S/2019 S 3": {"group": "Norse (Mundilfari)", "orbital_period_days": -833.19, "diameter_km": 4.0}, + "S/2020 S 2": {"group": "Norse (Mundilfari)", "orbital_period_days": -891.86, "diameter_km": 3.0}, +} + +# Note: Negative orbital periods indicate retrograde orbits. +# Diameter values are approximate for most irregular/provisional moons. + +if __name__ == "__main__": + # Example lookup + name = "Titan" + moon = saturn_moons[name] + print(f"{name}: group={moon['group']}, period={moon['orbital_period_days']} days, diameter={moon['diameter_km']} km\n") + + # Summary stats + named = [k for k in saturn_moons if not k.startswith("S/")] + unnamed = [k for k in saturn_moons if k.startswith("S/")] + print(f"Total moons in table: {len(saturn_moons)}") + print(f" Named: {len(named)}") + print(f" Provisional: {len(unnamed)}") + + # Print all moons sorted by orbital period + print(f"\n{'Moon':<20} {'Group':<35} {'Period (days)':>14} {'Diameter (km)':>14}") + print("-" * 88) + for name, data in sorted(saturn_moons.items(), key=lambda x: x[1]["orbital_period_days"]): + print(f"{name:<20} {data['group']:<35} {data['orbital_period_days']:>14.2f} {data['diameter_km']:>14.2f}") \ No newline at end of file