Skip to content
Snippets Groups Projects
Unverified Commit 396524c2 authored by Trent Hare's avatar Trent Hare Committed by GitHub
Browse files

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: default avatarAustin Sanders <arsanders@usgs.gov>

---------

Co-authored-by: default avatarAustin Sanders <arsanders@usgs.gov>
parent d8994dea
No related branches found
No related tags found
No related merge requests found
...@@ -17,7 +17,7 @@ import os ...@@ -17,7 +17,7 @@ import os
import pvl import pvl
from pathlib import Path, PurePath from pathlib import Path, PurePath
import sys import sys
import json
import ale import ale
import brotli import brotli
import json import json
...@@ -55,6 +55,34 @@ def main(): ...@@ -55,6 +55,34 @@ def main():
"and the default strategy of replacing their final suffix with " "and the default strategy of replacing their final suffix with "
".json will be used to generate the output file paths." ".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( parser.add_argument(
"-v", "--verbose", "-v", "--verbose",
action="store_true", action="store_true",
...@@ -117,9 +145,17 @@ def main(): ...@@ -117,9 +145,17 @@ def main():
except (KeyError, pvl.exceptions.LexerError): except (KeyError, pvl.exceptions.LexerError):
k = [args.kernel, ] 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: if len(args.input) == 1:
try: 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: except Exception as err:
# Seriously, this just throws a generic Exception? # Seriously, this just throws a generic Exception?
sys.exit(f"File {args.input[0]}: {err}") sys.exit(f"File {args.input[0]}: {err}")
...@@ -129,7 +165,8 @@ def main(): ...@@ -129,7 +165,8 @@ def main():
) as executor: ) as executor:
futures = { futures = {
executor.submit( executor.submit(
file_to_isd, f, **{"kernels": k, file_to_isd, f, **{"radii": radii,
"kernels": k,
"log_level": log_level, "log_level": log_level,
"only_isis_spice": args.only_isis_spice, "only_isis_spice": args.only_isis_spice,
"only_naif_spice": args.only_naif_spice, "only_naif_spice": args.only_naif_spice,
...@@ -151,6 +188,7 @@ def main(): ...@@ -151,6 +188,7 @@ def main():
def file_to_isd( def file_to_isd(
file: os.PathLike, file: os.PathLike,
out: os.PathLike = None, out: os.PathLike = None,
radii: list = None,
kernels: list = None, kernels: list = None,
log_level=logging.WARNING, log_level=logging.WARNING,
compress=False, compress=False,
...@@ -196,6 +234,18 @@ def file_to_isd( ...@@ -196,6 +234,18 @@ def file_to_isd(
else: 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) 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: if compress:
logger.info(f"Writing: {os.path.splitext(isd_file)[0] + '.br'}") logger.info(f"Writing: {os.path.splitext(isd_file)[0] + '.br'}")
compress_json(usgscsm_str, 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( ...@@ -203,6 +253,7 @@ def file_to_isd(
logger.info(f"Writing: {isd_file}") logger.info(f"Writing: {isd_file}")
isd_file.write_text(usgscsm_str) isd_file.write_text(usgscsm_str)
return return
def compress_json(json_data, output_file): def compress_json(json_data, output_file):
...@@ -257,3 +308,4 @@ if __name__ == "__main__": ...@@ -257,3 +308,4 @@ if __name__ == "__main__":
sys.exit(main()) sys.exit(main())
except ValueError as err: except ValueError as err:
sys.exit(err) sys.exit(err)
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment