From e1a3180050f8106acf788aa273b3c67e0ca63042 Mon Sep 17 00:00:00 2001 From: Tariq Soliman Date: Thu, 7 Mar 2024 14:41:37 -0800 Subject: [PATCH] #504 ShadeTool Improvements and Multi-missionize (#507) * #504 ShadeTool - User settable AzElRange * #504 SPICE kernel scheduled downloads * #504 update shadetool css * #504 Update docs for SPICE conf --- .gitignore | 5 + Missions/spice-kernels-conf.example.json | 82 +++++ docs/pages/Configure/SPICE/SPICE.md | 80 +++++ docs/pages/Setup/ENVs/ENVs.md | 12 + package-lock.json | 78 ++--- package.json | 2 +- private/api/BandsToProfile.py | 1 + private/api/chronice.py | 98 ++++++ private/api/ll2aerll.py | 179 ++++++++++ private/api/{spice => }/naif-about.txt | 0 private/api/spice/chronice.py | 71 ---- private/api/spice/chronos | Bin 1631040 -> 0 bytes private/api/spice/chronos.exe | Bin 1516544 -> 0 bytes private/api/spice/chronos.py | 61 ---- .../api/spice/chronosSetups/chronos-msl.setup | 29 -- .../spice/getKernelUtils/get-kernels-mro.bat | 7 - .../spice/getKernelUtils/get-kernels-msl.bat | 10 - .../spice/getKernelUtils/get-kernels-mvn.bat | 7 - .../spice/getKernelUtils/get-kernels-ody.bat | 7 - .../spice/getKernelUtils/get-kernels-tgo.bat | 7 - .../great_circle_calculator/__conversion.py | 28 -- .../great_circle_calculator/__conversion.pyc | Bin 1476 -> 0 bytes .../__error_checking.py | 18 - .../__error_checking.pyc | Bin 916 -> 0 bytes .../spice/great_circle_calculator/__init__.py | 2 - .../great_circle_calculator/__init__.pyc | Bin 220 -> 0 bytes .../great_circle_calculator/_constants.py | 59 ---- .../great_circle_calculator/_constants.pyc | Bin 2173 -> 0 bytes .../spice/great_circle_calculator/compass.py | 202 ----------- .../great_circle_calculator.py | 183 ---------- .../great_circle_calculator.pyc | Bin 7924 -> 0 bytes private/api/spice/ll2aerll.py | 129 ------- private/api/spice/lltarg2vistimes.py | 105 ------ python-requirements.txt | 3 +- sample.env | 9 +- scripts/server.js | 61 ++-- spice/getKernels.js | 176 ++++++++++ spice/kernels/.gitkeep | 0 src/essence/Tools/Shade/ShadeTool.css | 30 +- src/essence/Tools/Shade/ShadeTool.js | 314 +++++++++++++++--- src/essence/Tools/Shade/config.json | 6 +- src/pre/calls.js | 4 - 42 files changed, 1000 insertions(+), 1065 deletions(-) create mode 100644 Missions/spice-kernels-conf.example.json create mode 100644 docs/pages/Configure/SPICE/SPICE.md create mode 100644 private/api/chronice.py create mode 100644 private/api/ll2aerll.py rename private/api/{spice => }/naif-about.txt (100%) delete mode 100644 private/api/spice/chronice.py delete mode 100644 private/api/spice/chronos delete mode 100644 private/api/spice/chronos.exe delete mode 100644 private/api/spice/chronos.py delete mode 100644 private/api/spice/chronosSetups/chronos-msl.setup delete mode 100644 private/api/spice/getKernelUtils/get-kernels-mro.bat delete mode 100644 private/api/spice/getKernelUtils/get-kernels-msl.bat delete mode 100644 private/api/spice/getKernelUtils/get-kernels-mvn.bat delete mode 100644 private/api/spice/getKernelUtils/get-kernels-ody.bat delete mode 100644 private/api/spice/getKernelUtils/get-kernels-tgo.bat delete mode 100644 private/api/spice/great_circle_calculator/__conversion.py delete mode 100644 private/api/spice/great_circle_calculator/__conversion.pyc delete mode 100644 private/api/spice/great_circle_calculator/__error_checking.py delete mode 100644 private/api/spice/great_circle_calculator/__error_checking.pyc delete mode 100644 private/api/spice/great_circle_calculator/__init__.py delete mode 100644 private/api/spice/great_circle_calculator/__init__.pyc delete mode 100644 private/api/spice/great_circle_calculator/_constants.py delete mode 100644 private/api/spice/great_circle_calculator/_constants.pyc delete mode 100644 private/api/spice/great_circle_calculator/compass.py delete mode 100644 private/api/spice/great_circle_calculator/great_circle_calculator.py delete mode 100644 private/api/spice/great_circle_calculator/great_circle_calculator.pyc delete mode 100644 private/api/spice/ll2aerll.py delete mode 100644 private/api/spice/lltarg2vistimes.py create mode 100644 spice/getKernels.js create mode 100644 spice/kernels/.gitkeep diff --git a/.gitignore b/.gitignore index 3232928b..01f05385 100644 --- a/.gitignore +++ b/.gitignore @@ -17,6 +17,11 @@ /config/pre/toolConfigs.json /src/pre/tools.js +/spice/kernels/* +!/spice/kernels/.gitkeep +/Missions/spice-kernels-conf.json +!/Missions/spice-kernels-conf.example.json + /build/* /data/* *__pycache__ diff --git a/Missions/spice-kernels-conf.example.json b/Missions/spice-kernels-conf.example.json new file mode 100644 index 00000000..063ebbc2 --- /dev/null +++ b/Missions/spice-kernels-conf.example.json @@ -0,0 +1,82 @@ +{ + "body": { + "description": "If the MMGIS ENV 'SPICE_SCHEDULED_KERNEL_DOWNLOAD=true', then at every other midnight, MMGIS will read /Missions/spice-kernels-conf.json and re/download all the specified kernels to /spice/kernels.'body' names and 'target' names must be valid NAIF SPICE names/ids. Meta-kernels (.tm) can also be set for download by using an object instead of a string (see example below).", + "MARS": { + "description": "MARS", + "kernels": [ + "https://naif.jpl.nasa.gov/pub/naif/generic_kernels/lsk/naif0012.tls", + "https://naif.jpl.nasa.gov/pub/naif/generic_kernels/pck/pck00011.tpc", + "https://naif.jpl.nasa.gov/pub/naif/generic_kernels/spk/planets/de440.bsp", + "https://naif.jpl.nasa.gov/pub/naif/MARS2020/kernels/spk/mar097s.bsp", + "https://naif.jpl.nasa.gov/pub/naif/generic_kernels/pck/mars_iau2000_v1.tpc" + ], + "targets": { + "MRO": { + "description": "MRO - Mars Reconnaissance Orbiter", + "kernels": [ + "https://naif.jpl.nasa.gov/pub/naif/MRO/kernels/spk/mro_psp.bsp" + ] + }, + "MSL": { + "description": "MSL - Mars Science Laboratory", + "kernels": [ + "https://naif.jpl.nasa.gov/pub/naif/MSL/kernels/spk/msl_atls_ops120808_v1.bsp", + "https://naif.jpl.nasa.gov/pub/naif/MSL/kernels/spk/msl_ls_ops120808_iau2000_v1.bsp", + "https://naif.jpl.nasa.gov/pub/naif/MSL/kernels/sclk/MSL_76_SCLKSCET.00019.tsc", + "https://naif.jpl.nasa.gov/pub/naif/MSL/kernels/sclk/msl_lmst_ops120808_v1.tsc", + "https://naif.jpl.nasa.gov/pub/naif/MSL/kernels/fk/msl_v08.tf" + ] + }, + "-202": { + "description": "MVN - MAVEN - Mars Atmosphere and Volatile Evolution", + "kernels": [ + "https://naif.jpl.nasa.gov/pub/naif/MAVEN/kernels/spk/maven_orb.bsp" + ] + }, + "-53": { + "description": "ODY - 2001 Mars Odyssey", + "kernels": [ + "https://naif.jpl.nasa.gov/pub/naif/M01/kernels/spk/m01_map.bsp" + ] + }, + "-143": { + "description": "TGO - ExoMars Trace Gas Orbiter", + "kernels": [ + { + "url": "https://naif.jpl.nasa.gov/pub/naif/EXOMARS2016/kernels/mk/em16_ops.tm", + "mkRoot": "https://naif.jpl.nasa.gov/pub/naif/EXOMARS2016/kernels", + "mkRegex": ".*/spk/em16_tgo_fsp.*.bsp" + } + ] + } + } + }, + "MOON": { + "description": "MOON", + "kernels": [ + "https://naif.jpl.nasa.gov/pub/naif/generic_kernels/pck/pck00011.tpc" + ], + "targets": { + "LRO": { + "description": "LRO - Lunar Reconnaissance Orbiter", + "kernels": [ + "https://naif.jpl.nasa.gov/pub/naif/pds/data/lro-l-spice-6-v1.0/lrosp_1000/data/lsk/naif0012.tls", + "https://naif.jpl.nasa.gov/pub/naif/pds/data/lro-l-spice-6-v1.0/lrosp_1000/data/sclk/lro_clkcor_2023354_v00.tsc", + "https://naif.jpl.nasa.gov/pub/naif/pds/data/lro-l-spice-6-v1.0/lrosp_1000/data/pck/pck00010.tpc", + "https://naif.jpl.nasa.gov/pub/naif/pds/data/lro-l-spice-6-v1.0/lrosp_1000/data/pck/moon_pa_de421_1900_2050.bpc", + "https://naif.jpl.nasa.gov/pub/naif/pds/data/lro-l-spice-6-v1.0/lrosp_1000/data/fk/lro_dlre_frames_2010132_v04.tf", + "https://naif.jpl.nasa.gov/pub/naif/pds/data/lro-l-spice-6-v1.0/lrosp_1000/data/fk/lro_frames_2012255_v02.tf", + "https://naif.jpl.nasa.gov/pub/naif/pds/data/lro-l-spice-6-v1.0/lrosp_1000/data/fk/moon_assoc_me.tf", + "https://naif.jpl.nasa.gov/pub/naif/pds/data/lro-l-spice-6-v1.0/lrosp_1000/data/fk/moon_080317.tf", + "https://naif.jpl.nasa.gov/pub/naif/pds/data/lro-l-spice-6-v1.0/lrosp_1000/data/spk/de421.bsp", + { + "url": "https://naif.jpl.nasa.gov/pub/naif/pds/data/lro-l-spice-6-v1.0/lrosp_1000/extras/mk/lro_2023_v04.tm", + "mkRoot": "https://naif.jpl.nasa.gov/pub/naif/pds/data/lro-l-spice-6-v1.0/lrosp_1000/data", + "mkRegex": ".*/spk/lrorg.*.bsp" + } + ] + } + } + } + } +} diff --git a/docs/pages/Configure/SPICE/SPICE.md b/docs/pages/Configure/SPICE/SPICE.md new file mode 100644 index 00000000..cd7ec24f --- /dev/null +++ b/docs/pages/Configure/SPICE/SPICE.md @@ -0,0 +1,80 @@ +--- +layout: page +title: SPICE +permalink: /configure/spice +parent: Configure +nav_order: 3 +--- + +# SPICE + +> SPICE (Spacecraft Planet Instrument C-matrix Events) is a NASA ancillary information system used to compute geometric information used in planning and analyzing science observations obtained from robotic spacecraft. It is also used in planning missions and conducting numerous engineering functions needed to carry out those missions. + +[Link to NAIF SPICE](https://naif.jpl.nasa.gov/naif/) + +MMGIS utilizes SPICE through [spiceypy](https://github.com/AndrewAnnex/SpiceyPy). Some of MMGIS' tools may need to be configured properly with regards to SPICE. The following tools require relevant SPICE kernels (mission-specific files that SPICE needs to perform certain computations and transformations) to be set: + +- ShadeTool + +## Configuring + +MMGIS has a SPICE kernel download scheduler that, when configured, periodically downloads all the latest specified kernels (because they are regularly updated). + +- To begin, set the ENV `SPICE_SCHEDULED_KERNEL_DOWNLOAD=true`. +- Next there is a sample SPICE kernel configuration file under the `/Missions/` directory called `spice-kernels-conf.example.json`. +- Copy `spice-kernels-conf.example.json` to `spice-kernels-conf.json` in the same directory. + +### ENVs + +#### `SPICE_SCHEDULED_KERNEL_DOWNLOAD=` + +If true, then at every other midnight, MMGIS will read /Missions/spice-kernels-conf.json and re/download all the specified kernels. See /Missions/spice-kernels-conf.example.json | boolean | default `false` + +#### `SPICE_SCHEDULED_KERNEL_DOWNLOAD_ON_START=` + +If true, then also triggers the kernel download when MMGIS starts | boolean | default `false` + +#### `SPICE_SCHEDULED_KERNEL_CRON_EXPR=` + +A cron schedule expression for use in the [node-schedule npm library](https://www.npmjs.com/package/node-schedule) | string | default `"0 0 */2 * *"` (every other day) + +### spice-kernels-conf.json + +- If the MMGIS ENV 'SPICE_SCHEDULED_KERNEL_DOWNLOAD=true' MMGIS will read /Missions/spice-kernels-conf.json and re/download all the specified kernels to `/spice/kernels`. + +- 'body' names and 'targets' names must be valid NAIF SPICE names/ids. Meta-kernels (.tm) can also be set for download by using an object instead of a string. + +The schema works as follows: + +```json +{ + "body": { + "{NAIF_BODY_NAME_OR_ID}": { + "desciption": "If a function uses this BODY, it will furnsh() all these direct kernels.", + "kernels": [ + "Full URL to kernel to download", + "Or an object that indicates a meta-kernel (a kernel that lists out other kernels to download):", + { + "url": "Full URL to a meta-kernel to download (file extension .tm)", + "mkRoot": "Root path to replace the meta-kernel's '$KERNELS' prefixes with.", + "mkRegex": "A JavaScript regular expression to filter down which meta-kernel kernels to download. For instance '.*/spk/.*.bsp'" + } + ], + "targets": { + "{NAIF_TARGET_NAME_OR_ID}": { + "description": "If a function uses this BODY and TARGET, it will also furnsh() all these kernels.", + "kernels": [ + "Full URL to kernel to download", + "Or an object that indicates a meta-kernel (a kernel that lists out other kernels to download):", + { + "url": "Full URL to a meta-kernel to download (file extension .tm)", + "mkRoot": "Root path to replace the meta-kernel's '$KERNELS' prefixes with.", + "mkRegex": "A JavaScript regular expression to filter down which meta-kernel kernels to download. For instance '.*/spk/.*.bsp'" + } + ] + } + } + } + } +} +``` diff --git a/docs/pages/Setup/ENVs/ENVs.md b/docs/pages/Setup/ENVs/ENVs.md index 718997d1..885bbd7c 100644 --- a/docs/pages/Setup/ENVs/ENVs.md +++ b/docs/pages/Setup/ENVs/ENVs.md @@ -139,3 +139,15 @@ If true, MMGIS will not auto-login returning users. This can be useful when logi #### `GENERATE_SOURCEMAP=` If true at build-time, JavaScript source maps will also be built | boolean | default `false` + +#### `SPICE_SCHEDULED_KERNEL_DOWNLOAD=` + +If true, then at every other midnight, MMGIS will read /Missions/spice-kernels-conf.json and re/download all the specified kernels. See /Missions/spice-kernels-conf.example.json | boolean | default `false` + +#### `SPICE_SCHEDULED_KERNEL_DOWNLOAD_ON_START=` + +If true, then also triggers the kernel download when MMGIS starts | boolean | default `false` + +#### `SPICE_SCHEDULED_KERNEL_CRON_EXPR=` + +A cron schedule expression for use in the [node-schedule npm library](https://www.npmjs.com/package/node-schedule) | string | default `"0 0 */2 * *"` (every other day) diff --git a/package-lock.json b/package-lock.json index 550006ab..b32c7d96 100644 --- a/package-lock.json +++ b/package-lock.json @@ -51,7 +51,7 @@ "memorystore": "^1.6.2", "nipplejs": "^0.8.5", "node-fetch": "^2.6.1", - "node-schedule": "^1.3.2", + "node-schedule": "^2.1.1", "pg-promise": "^10.6.1", "png-js": "^1.0.0", "proj4": "^2.8.1", @@ -8705,15 +8705,14 @@ } }, "node_modules/cron-parser": { - "version": "2.18.0", - "resolved": "https://registry.npmjs.org/cron-parser/-/cron-parser-2.18.0.tgz", - "integrity": "sha512-s4odpheTyydAbTBQepsqd2rNWGa2iV3cyo8g7zbI2QQYGLVsfbhmwukayS1XHppe02Oy1fg7mg6xoaraVJeEcg==", + "version": "4.9.0", + "resolved": "https://registry.npmjs.org/cron-parser/-/cron-parser-4.9.0.tgz", + "integrity": "sha512-p0SaNjrHOnQeR8/VnfGbmg9te2kfyYSQ7Sc/j/6DtPL3JQvKxmjO9TSjNFpujqV3vEYYBvNNvXSxzyksBWAx1Q==", "dependencies": { - "is-nan": "^1.3.0", - "moment-timezone": "^0.5.31" + "luxon": "^3.2.1" }, "engines": { - "node": ">=0.8" + "node": ">=12.0.0" } }, "node_modules/cross-env": { @@ -14160,21 +14159,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/is-nan": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/is-nan/-/is-nan-1.3.2.tgz", - "integrity": "sha512-E+zBKpQ2t6MEo1VsonYmluk9NxGrbzpeeLC2xIViuO2EjU2xsXsBPwTr3Ykv9l08UYEVEdWeRZNouaZqF6RN0w==", - "dependencies": { - "call-bind": "^1.0.0", - "define-properties": "^1.1.3" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/is-negative-zero": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.2.tgz", @@ -18114,6 +18098,14 @@ "yallist": "^3.0.2" } }, + "node_modules/luxon": { + "version": "3.4.4", + "resolved": "https://registry.npmjs.org/luxon/-/luxon-3.4.4.tgz", + "integrity": "sha512-zobTr7akeGHnv7eBOXcRgMeCP6+uyYsczwmeRCauvpvaAltgNyTbLH/+VaEAPUeWBT+1GuNmz4wC/6jtQzbbVA==", + "engines": { + "node": ">=12" + } + }, "node_modules/lz-string": { "version": "1.5.0", "resolved": "https://registry.npmjs.org/lz-string/-/lz-string-1.5.0.tgz", @@ -18774,13 +18766,16 @@ "dev": true }, "node_modules/node-schedule": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/node-schedule/-/node-schedule-1.3.3.tgz", - "integrity": "sha512-uF9Ubn6luOPrcAYKfsXWimcJ1tPFtQ8I85wb4T3NgJQrXazEzojcFZVk46ZlLHby3eEJChgkV/0T689IsXh2Gw==", + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/node-schedule/-/node-schedule-2.1.1.tgz", + "integrity": "sha512-OXdegQq03OmXEjt2hZP33W2YPs/E5BcFQks46+G2gAxs4gHOIVD1u7EqlYLYSKsaIpyKCK9Gbk0ta1/gjRSMRQ==", "dependencies": { - "cron-parser": "^2.18.0", + "cron-parser": "^4.2.0", "long-timeout": "0.1.1", "sorted-array-functions": "^1.3.0" + }, + "engines": { + "node": ">=6" } }, "node_modules/normalize-package-data": { @@ -33484,12 +33479,11 @@ } }, "cron-parser": { - "version": "2.18.0", - "resolved": "https://registry.npmjs.org/cron-parser/-/cron-parser-2.18.0.tgz", - "integrity": "sha512-s4odpheTyydAbTBQepsqd2rNWGa2iV3cyo8g7zbI2QQYGLVsfbhmwukayS1XHppe02Oy1fg7mg6xoaraVJeEcg==", + "version": "4.9.0", + "resolved": "https://registry.npmjs.org/cron-parser/-/cron-parser-4.9.0.tgz", + "integrity": "sha512-p0SaNjrHOnQeR8/VnfGbmg9te2kfyYSQ7Sc/j/6DtPL3JQvKxmjO9TSjNFpujqV3vEYYBvNNvXSxzyksBWAx1Q==", "requires": { - "is-nan": "^1.3.0", - "moment-timezone": "^0.5.31" + "luxon": "^3.2.1" } }, "cross-env": { @@ -37511,15 +37505,6 @@ "integrity": "sha512-cOZFQQozTha1f4MxLFzlgKYPTyj26picdZTx82hbc/Xf4K/tZOOXSCkMvU4pKioRXGDLJRn0GM7Upe7kR721yg==", "dev": true }, - "is-nan": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/is-nan/-/is-nan-1.3.2.tgz", - "integrity": "sha512-E+zBKpQ2t6MEo1VsonYmluk9NxGrbzpeeLC2xIViuO2EjU2xsXsBPwTr3Ykv9l08UYEVEdWeRZNouaZqF6RN0w==", - "requires": { - "call-bind": "^1.0.0", - "define-properties": "^1.1.3" - } - }, "is-negative-zero": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.2.tgz", @@ -40639,6 +40624,11 @@ "yallist": "^3.0.2" } }, + "luxon": { + "version": "3.4.4", + "resolved": "https://registry.npmjs.org/luxon/-/luxon-3.4.4.tgz", + "integrity": "sha512-zobTr7akeGHnv7eBOXcRgMeCP6+uyYsczwmeRCauvpvaAltgNyTbLH/+VaEAPUeWBT+1GuNmz4wC/6jtQzbbVA==" + }, "lz-string": { "version": "1.5.0", "resolved": "https://registry.npmjs.org/lz-string/-/lz-string-1.5.0.tgz", @@ -41152,11 +41142,11 @@ "dev": true }, "node-schedule": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/node-schedule/-/node-schedule-1.3.3.tgz", - "integrity": "sha512-uF9Ubn6luOPrcAYKfsXWimcJ1tPFtQ8I85wb4T3NgJQrXazEzojcFZVk46ZlLHby3eEJChgkV/0T689IsXh2Gw==", + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/node-schedule/-/node-schedule-2.1.1.tgz", + "integrity": "sha512-OXdegQq03OmXEjt2hZP33W2YPs/E5BcFQks46+G2gAxs4gHOIVD1u7EqlYLYSKsaIpyKCK9Gbk0ta1/gjRSMRQ==", "requires": { - "cron-parser": "^2.18.0", + "cron-parser": "^4.2.0", "long-timeout": "0.1.1", "sorted-array-functions": "^1.3.0" } diff --git a/package.json b/package.json index c693c1d3..42966e54 100644 --- a/package.json +++ b/package.json @@ -88,7 +88,7 @@ "memorystore": "^1.6.2", "nipplejs": "^0.8.5", "node-fetch": "^2.6.1", - "node-schedule": "^1.3.2", + "node-schedule": "^2.1.1", "pg-promise": "^10.6.1", "png-js": "^1.0.0", "proj4": "^2.8.1", diff --git a/private/api/BandsToProfile.py b/private/api/BandsToProfile.py index 7c87a604..f0d78cd9 100755 --- a/private/api/BandsToProfile.py +++ b/private/api/BandsToProfile.py @@ -117,6 +117,7 @@ def latLonsToPixel(latLonPairs): type = str(sys.argv[4]) # xyorll bands = ast.literal_eval(unquote(sys.argv[5])) # bands + latLonPair = [[lat, lon]] # Open the image diff --git a/private/api/chronice.py b/private/api/chronice.py new file mode 100644 index 00000000..473c791e --- /dev/null +++ b/private/api/chronice.py @@ -0,0 +1,98 @@ +# chronice: chronos + spice (but without chronos since spice-alone offered more controll) +# chronice.py