diff --git a/.gitattributes b/.gitattributes index 292d92e5..9ef06974 100644 --- a/.gitattributes +++ b/.gitattributes @@ -1,7 +1,3 @@ data/*.bsp filter=lfs diff=lfs merge=lfs -text data/*.bpc filter=lfs diff=lfs merge=lfs -text -data/de421.anise filter=lfs diff=lfs merge=lfs -text -data/de430.anise filter=lfs diff=lfs merge=lfs -text -data/de438s.anise filter=lfs diff=lfs merge=lfs -text -data/de440.anise filter=lfs diff=lfs merge=lfs -text data/*.pca filter=lfs diff=lfs merge=lfs -text \ No newline at end of file diff --git a/.github/workflows/benchmarks.yml b/.github/workflows/benchmarks.yml index 894b354c..7a2dd0d5 100644 --- a/.github/workflows/benchmarks.yml +++ b/.github/workflows/benchmarks.yml @@ -16,8 +16,14 @@ jobs: steps: - name: Checkout sources uses: actions/checkout@v3 - with: - lfs: true + + - name: Download data + run: | + wget -O data/de421.bsp http://public-data.nyxspace.com/anise/de421.bsp + wget -O data/de430.bsp http://public-data.nyxspace.com/anise/de430.bsp + wget -O data/de440s.bsp http://public-data.nyxspace.com/anise/de440s.bsp + wget -O data/de440.bsp http://public-data.nyxspace.com/anise/de440.bsp + wget -O data/pck08.pca http://public-data.nyxspace.com/anise/pck08.pca - name: Install stable toolchain uses: actions-rs/toolchain@v1 diff --git a/.github/workflows/python.yml b/.github/workflows/python.yml index 0ad072ad..4812c5b1 100644 --- a/.github/workflows/python.yml +++ b/.github/workflows/python.yml @@ -26,8 +26,14 @@ jobs: target: [x86_64, x86, aarch64, armv7, s390x, ppc64le] steps: - uses: actions/checkout@v3 - with: - lfs: true + + - name: Download data + run: | + wget -O data/de421.bsp http://public-data.nyxspace.com/anise/de421.bsp + wget -O data/de430.bsp http://public-data.nyxspace.com/anise/de430.bsp + wget -O data/de440s.bsp http://public-data.nyxspace.com/anise/de440s.bsp + wget -O data/de440.bsp http://public-data.nyxspace.com/anise/de440.bsp + wget -O data/pck08.pca http://public-data.nyxspace.com/anise/pck08.pca - uses: actions/setup-python@v4 with: @@ -172,8 +178,14 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 - with: - lfs: true + + - name: Download data + run: | + wget -O data/de421.bsp http://public-data.nyxspace.com/anise/de421.bsp + wget -O data/de430.bsp http://public-data.nyxspace.com/anise/de430.bsp + wget -O data/de440s.bsp http://public-data.nyxspace.com/anise/de440s.bsp + wget -O data/de440.bsp http://public-data.nyxspace.com/anise/de440.bsp + wget -O data/pck08.pca http://public-data.nyxspace.com/anise/pck08.pca - name: Build sdist uses: PyO3/maturin-action@v1 diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml index 98643fdc..b5f85452 100644 --- a/.github/workflows/rust.yml +++ b/.github/workflows/rust.yml @@ -40,8 +40,14 @@ jobs: steps: - name: Checkout sources uses: actions/checkout@v2 - with: - lfs: true + + - name: Download data + run: | + wget -O data/de421.bsp http://public-data.nyxspace.com/anise/de421.bsp + wget -O data/de430.bsp http://public-data.nyxspace.com/anise/de430.bsp + wget -O data/de440s.bsp http://public-data.nyxspace.com/anise/de440s.bsp + wget -O data/de440.bsp http://public-data.nyxspace.com/anise/de440.bsp + wget -O data/pck08.pca http://public-data.nyxspace.com/anise/pck08.pca - name: Install stable toolchain uses: actions-rs/toolchain@v1 @@ -93,8 +99,14 @@ jobs: steps: - name: Checkout sources uses: actions/checkout@v2 - with: - lfs: true + + - name: Download data + run: | + wget -O data/de421.bsp http://public-data.nyxspace.com/anise/de421.bsp + wget -O data/de430.bsp http://public-data.nyxspace.com/anise/de430.bsp + wget -O data/de440s.bsp http://public-data.nyxspace.com/anise/de440s.bsp + wget -O data/de440.bsp http://public-data.nyxspace.com/anise/de440.bsp + wget -O data/pck08.pca http://public-data.nyxspace.com/anise/pck08.pca - name: Install stable toolchain uses: actions-rs/toolchain@v1 @@ -150,8 +162,14 @@ jobs: steps: - name: Checkout uses: actions/checkout@v3 - with: - lfs: true + + - name: Download data + run: | + wget -O data/de421.bsp http://public-data.nyxspace.com/anise/de421.bsp + wget -O data/de430.bsp http://public-data.nyxspace.com/anise/de430.bsp + wget -O data/de440s.bsp http://public-data.nyxspace.com/anise/de440s.bsp + wget -O data/de440.bsp http://public-data.nyxspace.com/anise/de440.bsp + wget -O data/pck08.pca http://public-data.nyxspace.com/anise/pck08.pca - name: Install stable toolchain uses: actions-rs/toolchain@v1 @@ -169,14 +187,15 @@ jobs: - name: Generate coverage report run: | + cd anise # Prevent the workspace flag cargo llvm-cov clean --workspace - cargo llvm-cov test --workspace --exclude anise-gui --exclude anise-py --no-report -- --test-threads=1 - cargo llvm-cov test --workspace --exclude anise-gui --exclude anise-py --no-report --tests -- compile_fail - cargo llvm-cov test --workspace --exclude anise-gui --exclude anise-py --no-report validate_iau_rotation_to_parent -- --nocapture --ignored - cargo llvm-cov test --workspace --exclude anise-gui --exclude anise-py --no-report validate_bpc_to_iau_rotations -- --nocapture --ignored - cargo llvm-cov test --workspace --exclude anise-gui --exclude anise-py --no-report validate_jplde_de440s_no_aberration --features spkezr_validation -- --nocapture --ignored - cargo llvm-cov test --workspace --exclude anise-gui --exclude anise-py --no-report validate_jplde_de440s_aberration_lt --features spkezr_validation -- --nocapture --ignored - cargo llvm-cov test --workspace --exclude anise-gui --exclude anise-py --no-report validate_hermite_type13_from_gmat --features spkezr_validation -- --nocapture --ignored + cargo llvm-cov test --no-report -- --test-threads=1 + cargo llvm-cov test --no-report --tests -- compile_fail + cargo llvm-cov test --no-report validate_iau_rotation_to_parent -- --nocapture --ignored + cargo llvm-cov test --no-report validate_bpc_to_iau_rotations -- --nocapture --ignored + cargo llvm-cov test --no-report validate_jplde_de440s_no_aberration --features spkezr_validation -- --nocapture --ignored + cargo llvm-cov test --no-report validate_jplde_de440s_aberration_lt --features spkezr_validation -- --nocapture --ignored + cargo llvm-cov test --no-report validate_hermite_type13_from_gmat --features spkezr_validation -- --nocapture --ignored cargo llvm-cov report --lcov > lcov.txt env: RUSTFLAGS: --cfg __ui_tests diff --git a/anise-py/src/lib.rs b/anise-py/src/lib.rs index 076f12ae..062f59dd 100644 --- a/anise-py/src/lib.rs +++ b/anise-py/src/lib.rs @@ -8,7 +8,7 @@ * Documentation: https://nyxspace.com/ */ -use ::anise::almanac::meta::MetaAlmanac; +use ::anise::almanac::meta::{MetaAlmanac, MetaFile}; use ::anise::almanac::Almanac; use ::anise::astro::Aberration; use hifitime::leap_seconds::{LatestLeapSeconds, LeapSecondsFile}; @@ -28,6 +28,7 @@ fn anise(py: Python, m: &PyModule) -> PyResult<()> { m.add_class::()?; m.add_class::()?; m.add_class::()?; + m.add_class::()?; Ok(()) } diff --git a/anise/src/almanac/meta.rs b/anise/src/almanac/meta.rs index 1fe95b33..bbb79067 100644 --- a/anise/src/almanac/meta.rs +++ b/anise/src/almanac/meta.rs @@ -17,6 +17,7 @@ use snafu::prelude::*; use std::fs::{create_dir_all, File}; use std::io::Write; use std::path::Path; +use std::time::Duration; use url::Url; #[cfg(feature = "python")] @@ -65,12 +66,13 @@ pub enum MetaAlmanacError { #[derive(Clone, Debug, Serialize, Deserialize, PartialEq)] #[cfg_attr(feature = "python", pyclass)] #[cfg_attr(feature = "python", pyo3(module = "anise"))] +#[cfg_attr(feature = "python", pyo3(get_all, set_all))] pub struct MetaAlmanac { - files: Vec, + pub files: Vec, } impl MetaAlmanac { - /// Loads the provided path as a Dhall file and processes each file. + /// Loads the provided path as a Dhall configuration file and processes each file. pub fn new(path: String) -> Result { match serde_dhall::from_file(&path).parse::() { Err(e) => Err(MetaAlmanacError::ParseDhall { @@ -84,11 +86,14 @@ impl MetaAlmanac { #[cfg_attr(feature = "python", pymethods)] impl MetaAlmanac { - /// Loads the provided path as a Dhall file and processes each file. + /// Loads the provided path as a Dhall file. If no path is provided, creates an empty MetaAlmanac that can store MetaFiles. #[cfg(feature = "python")] #[new] - pub fn py_new(path: String) -> Result { - Self::new(path) + pub fn py_new(maybe_path: Option) -> Result { + match maybe_path { + Some(path) => Self::new(path), + None => Ok(Self { files: Vec::new() }), + } } /// Fetch all of the data and return a loaded Almanac @@ -182,14 +187,50 @@ impl Default for MetaAlmanac { } } +#[cfg_attr(feature = "python", pyclass)] +#[cfg_attr(feature = "python", pyo3(module = "anise"))] +#[cfg_attr(feature = "python", pyo3(get_all, set_all))] #[derive(Clone, Debug, Default, Serialize, Deserialize, PartialEq, StaticType)] pub struct MetaFile { + /// URI of this meta file pub uri: String, /// Optionally specify the CRC32 of this file, which will be checked prior to loading. pub crc32: Option, } +#[cfg_attr(feature = "python", pymethods)] impl MetaFile { + /// Builds a new MetaFile from the provided URI and optionally its CRC32 checksum. + #[cfg(feature = "python")] + #[new] + pub fn py_new(uri: String, crc32: Option) -> Self { + Self { uri, crc32 } + } + + #[cfg(feature = "python")] + fn __str__(&self) -> String { + format!("{self:?}") + } + + #[cfg(feature = "python")] + fn __repr__(&self) -> String { + format!("{self:?} (@{self:p})") + } + + #[cfg(feature = "python")] + fn __richcmp__(&self, other: &Self, op: CompareOp) -> Result { + match op { + CompareOp::Eq => Ok(self == other), + CompareOp::Ne => Ok(self != other), + _ => Err(PyErr::new::(format!( + "{op:?} not available" + ))), + } + } + + /// Processes this MetaFile by downloading it if it's a URL. + /// + /// This function modified `self` and changes the URI to be the path to the downloaded file. fn process(&mut self) -> Result<(), MetaAlmanacError> { match Url::parse(&self.uri) { Err(e) => { @@ -240,7 +281,13 @@ impl MetaFile { } // At this stage, either the dest path does not exist, or the CRC32 check failed. - match reqwest::blocking::get(url.clone()) { + let client = reqwest::blocking::Client::builder() + .connect_timeout(Duration::from_secs(30)) + .timeout(Duration::from_secs(30)) + .build() + .unwrap(); + + match client.get(url.clone()).send() { Ok(resp) => { if resp.status().is_success() { // Downloaded the file, let's store it locally. @@ -279,6 +326,7 @@ impl MetaFile { } } } else { + println!("err"); let err = resp.error_for_status().unwrap(); Err(MetaAlmanacError::FetchError { status: err.status(), diff --git a/anise/src/astro/aberration.rs b/anise/src/astro/aberration.rs index 4d3e78de..5e06f09a 100644 --- a/anise/src/astro/aberration.rs +++ b/anise/src/astro/aberration.rs @@ -35,7 +35,7 @@ use crate::errors::PhysicsError; /// For deep space missions, preliminary analysis would likely require both light time correction and stellar aberration. Mission planning and operations will definitely need converged light-time calculations. /// /// For more details, . -#[derive(Copy, Clone, Debug, Default, PartialEq, Eq)] +#[derive(Copy, Clone, Default, PartialEq, Eq)] #[cfg_attr(feature = "python", pyclass)] #[cfg_attr(feature = "python", pyo3(module = "anise"))] #[cfg_attr(feature = "python", pyo3(get_all, set_all))] @@ -164,6 +164,24 @@ impl Aberration { } } +impl fmt::Debug for Aberration { + /// Prints this configuration as the SPICE name. + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + if self.transmit_mode { + write!(f, "X")?; + } + if self.converged { + write!(f, "CN")?; + } else { + write!(f, "LT")?; + } + if self.stellar { + write!(f, "+S")?; + } + Ok(()) + } +} + impl fmt::Display for Aberration { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { if self.converged { @@ -261,3 +279,21 @@ pub fn stellar_aberration( Ok(app_target_pos_km) } + +#[cfg(test)] +mod ut_aberration { + #[test] + fn test_display() { + use super::Aberration; + + assert_eq!(format!("{:?}", Aberration::LT.unwrap()), "LT"); + assert_eq!(format!("{:?}", Aberration::LT_S.unwrap()), "LT+S"); + assert_eq!(format!("{:?}", Aberration::CN.unwrap()), "CN"); + assert_eq!(format!("{:?}", Aberration::CN_S.unwrap()), "CN+S"); + + assert_eq!(format!("{:?}", Aberration::XLT.unwrap()), "XLT"); + assert_eq!(format!("{:?}", Aberration::XLT_S.unwrap()), "XLT+S"); + assert_eq!(format!("{:?}", Aberration::XCN.unwrap()), "XCN"); + assert_eq!(format!("{:?}", Aberration::XCN_S.unwrap()), "XCN+S"); + } +} diff --git a/anise/tests/ephemerides/validation/compare.rs b/anise/tests/ephemerides/validation/compare.rs index 6fa8ca60..04ed7988 100644 --- a/anise/tests/ephemerides/validation/compare.rs +++ b/anise/tests/ephemerides/validation/compare.rs @@ -257,8 +257,18 @@ impl CompareEphem { }; // Perform the same query in SPICE - let (spice_state, _) = - spice::spkezr(&targ, epoch.to_et_seconds(), "J2000", "NONE", &obs); + let spice_ab_corr = match self.aberration { + None => "NONE".to_string(), + Some(corr) => format!("{corr:?}"), + }; + + let (spice_state, _) = spice::spkezr( + &targ, + epoch.to_et_seconds(), + "J2000", + &spice_ab_corr, + &obs, + ); EphemValData { src_frame: format!("{from_frame:e}"),