From 396524c2d13f6c383f05b78b396008f9762e32ae Mon Sep 17 00:00:00 2001 From: Trent Hare <thare@usgs.gov> Date: Mon, 28 Oct 2024 09:00:11 -0700 Subject: [PATCH] Update to isd_generate.py to allow for a NAIF radius override (#486) * Update to isd_generate.py to allow for a NAIF radius override Based on this RFC, we want to change our Mars pipeline to use a sphere. https://astrodiscuss.usgs.gov/t/appl-rfc-use-iau-sphere-for-hirise-dtm-projects-in-socet-set/428 Currently ALE uses the Mars elliptical defaults from the NAIF kernels. This update allows the user to override the kernels and set a spherical radius for both semimajor and semiminor in the ISD. This is not only needed for Mars. For triaxial bodies, the IAU recommends a best-fit sphere should also be set for map products. References (DOI) are listed in the updated help for the current IAU values. * remove extra file write if new radius is sent * update to allow ellipse, minor help update Add --semimajor and --semiminor parameters. I tried nargs="+" for --radius but fought for too long with argparse to do all the checking (like checking it is float). I am fine with these options but happy to hear better ways to use argparse. * Update isd_generate.py (#619) add in PROJ like options for radius names ("-a", "-r", "--radius", "-b") * Radius update with changes to address original PR and review comments (#620) * Update isd_generate.py add in PROJ like options for radius names ("-a", "-r", "--radius", "-b") * Update isd_generate.py updated required statement for --semimajor to catch if only --semiminor or -b is sent. Request that radius is sent in meters and updated some typos. --------- Co-authored-by: Austin Sanders <arsanders@usgs.gov> --------- Co-authored-by: Austin Sanders <arsanders@usgs.gov> --- ale/isd_generate.py | 58 ++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 55 insertions(+), 3 deletions(-) diff --git a/ale/isd_generate.py b/ale/isd_generate.py index 67d39fe..3581517 100755 --- a/ale/isd_generate.py +++ b/ale/isd_generate.py @@ -17,7 +17,7 @@ import os import pvl from pathlib import Path, PurePath import sys - +import json import ale import brotli import json @@ -55,6 +55,34 @@ def main(): "and the default strategy of replacing their final suffix with " ".json will be used to generate the output file paths." ) + parser.add_argument( + "--semimajor", "-a", "-r", "--radius", + required="--semiminor" in sys.argv or "-b" in sys.argv, + type=float, + default=None, + help="Optional spherical radius (m) override. Setting " + " '--semimajor 3396190.0' " + "will override both semi-major and semi-minor radius values with the same value. " + "An ellipsoid can be defined if '--semiminor' is also sent. " + "If not specified, the default radius values " + "(e.g.; from NAIF kernels or the ISIS Cube) will be used. " + "When is a semimajor specification needed? Beyond a specialized need, it is common " + "that planetary bodies are defined as a triaxial body. " + "In most of these cases, the IAU WGCCRE report recommends the use of a " + "best-fit sphere for a derived map product. " + "For current IAU spherical recommendations see: " + "https://doi.org/10.1007/s10569-017-9805-5 or " + "http://voparis-vespa-crs.obspm.fr:8080/web/ ." + "Make sure radius values are in meters (not kilometers)." + ) + parser.add_argument( + "--semiminor", "-b", + type=float, + default=None, + help="Optional semi-minor radius (m) override. When using this parameter, you must also define the semi-major radius. For example: " + " '--semimajor 3396190.0 --semiminor 3376200.0' " + "will override the semi-major and semi-minor radii to define an ellipsoid. " + ) parser.add_argument( "-v", "--verbose", action="store_true", @@ -117,9 +145,17 @@ def main(): except (KeyError, pvl.exceptions.LexerError): k = [args.kernel, ] + if args.semimajor is None: + radii = None + else: + if args.semiminor is None: # set a sphere + radii = [args.semimajor, args.semimajor] + else: # set as ellipsoid + radii = [args.semimajor, args.semiminor] + if len(args.input) == 1: try: - file_to_isd(args.input[0], args.out, kernels=k, log_level=log_level, compress=args.compress, only_isis_spice=args.only_isis_spice, only_naif_spice=args.only_naif_spice, local=args.local) + file_to_isd(args.input[0], args.out, radii, kernels=k, log_level=log_level, compress=args.compress, only_isis_spice=args.only_isis_spice, only_naif_spice=args.only_naif_spice, local=args.local) except Exception as err: # Seriously, this just throws a generic Exception? sys.exit(f"File {args.input[0]}: {err}") @@ -129,7 +165,8 @@ def main(): ) as executor: futures = { executor.submit( - file_to_isd, f, **{"kernels": k, + file_to_isd, f, **{"radii": radii, + "kernels": k, "log_level": log_level, "only_isis_spice": args.only_isis_spice, "only_naif_spice": args.only_naif_spice, @@ -151,6 +188,7 @@ def main(): def file_to_isd( file: os.PathLike, out: os.PathLike = None, + radii: list = None, kernels: list = None, log_level=logging.WARNING, compress=False, @@ -196,6 +234,18 @@ def file_to_isd( else: usgscsm_str = ale.loads(file, props=props, verbose=log_level>logging.INFO, only_isis_spice=only_isis_spice, only_naif_spice=only_naif_spice) + if radii is not None: + # first convert to kilometers for ISD + radii = [x / 1000.0 for x in radii] + + usgscsm_json = json.loads(usgscsm_str) + usgscsm_json["radii"]["semimajor"] = radii[0] + usgscsm_json["radii"]["semiminor"] = radii[1] + logger.info(f"Overriding radius to (km):") + logger.info(usgscsm_json["radii"]) + usgscsm_str = json.dumps(usgscsm_json, indent=2) + + logger.info(f"Writing: {isd_file}") if compress: logger.info(f"Writing: {os.path.splitext(isd_file)[0] + '.br'}") compress_json(usgscsm_str, os.path.splitext(isd_file)[0] + '.br') @@ -203,6 +253,7 @@ def file_to_isd( logger.info(f"Writing: {isd_file}") isd_file.write_text(usgscsm_str) + return def compress_json(json_data, output_file): @@ -257,3 +308,4 @@ if __name__ == "__main__": sys.exit(main()) except ValueError as err: sys.exit(err) + -- GitLab