sidereon 3.0.4__tar.gz → 3.0.5__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {sidereon-3.0.4 → sidereon-3.0.5}/.github/workflows/ci.yml +2 -0
- {sidereon-3.0.4 → sidereon-3.0.5}/.github/workflows/release.yml +4 -4
- {sidereon-3.0.4 → sidereon-3.0.5}/CHANGELOG.md +14 -0
- {sidereon-3.0.4 → sidereon-3.0.5}/Cargo.lock +5 -5
- {sidereon-3.0.4 → sidereon-3.0.5}/Cargo.toml +3 -3
- {sidereon-3.0.4 → sidereon-3.0.5}/PKG-INFO +5 -2
- {sidereon-3.0.4 → sidereon-3.0.5}/README.md +4 -1
- {sidereon-3.0.4 → sidereon-3.0.5}/THIRD-PARTY-NOTICES.md +3 -3
- {sidereon-3.0.4 → sidereon-3.0.5}/docs/public-gnss-distribution-sources.md +5 -5
- {sidereon-3.0.4 → sidereon-3.0.5}/docs/sp3.md +15 -5
- {sidereon-3.0.4 → sidereon-3.0.5}/pyproject.toml +4 -4
- {sidereon-3.0.4 → sidereon-3.0.5}/python/sidereon/__init__.pyi +43 -7
- {sidereon-3.0.4 → sidereon-3.0.5}/python/sidereon/data.py +33 -7
- {sidereon-3.0.4 → sidereon-3.0.5}/python/sidereon/data.pyi +3 -0
- {sidereon-3.0.4 → sidereon-3.0.5}/scripts/check-release.py +3 -3
- {sidereon-3.0.4 → sidereon-3.0.5}/scripts/core_source_identity.rs +1 -1
- sidereon-3.0.5/scripts/smoke-release.py +154 -0
- {sidereon-3.0.4 → sidereon-3.0.5}/src/ephemeris.rs +96 -3
- {sidereon-3.0.4 → sidereon-3.0.5}/src/lnav.rs +7 -7
- {sidereon-3.0.4 → sidereon-3.0.5}/tests/fixtures/core_goldens.json +2 -2
- {sidereon-3.0.4 → sidereon-3.0.5}/tests/fixtures/ppp_esbc.json +2 -2
- {sidereon-3.0.4 → sidereon-3.0.5}/tests/test_core_revision.py +34 -25
- {sidereon-3.0.4 → sidereon-3.0.5}/tests/test_data.py +14 -0
- {sidereon-3.0.4 → sidereon-3.0.5}/tests/test_lnav.py +110 -2
- {sidereon-3.0.4 → sidereon-3.0.5}/tests/test_sp3_merge.py +28 -2
- {sidereon-3.0.4 → sidereon-3.0.5}/tests/test_sp3_write_and_records.py +34 -23
- sidereon-3.0.5/third_party_source/sidereon-core-3.0.5/tides/mod.rs +1501 -0
- sidereon-3.0.5/third_party_source/sidereon-core-3.0.5/tides/ocean.rs +987 -0
- sidereon-3.0.5/third_party_source/sidereon-core-3.0.5/tides/pole.rs +203 -0
- {sidereon-3.0.4 → sidereon-3.0.5}/uv.lock +1 -1
- sidereon-3.0.4/scripts/smoke-release.py +0 -52
- {sidereon-3.0.4 → sidereon-3.0.5}/.cargo/config.toml.disabled +0 -0
- {sidereon-3.0.4 → sidereon-3.0.5}/.gitattributes +0 -0
- {sidereon-3.0.4 → sidereon-3.0.5}/.gitignore +0 -0
- {sidereon-3.0.4 → sidereon-3.0.5}/COVERAGE.md +0 -0
- {sidereon-3.0.4 → sidereon-3.0.5}/LICENSE +0 -0
- {sidereon-3.0.4 → sidereon-3.0.5}/bench/README.md +0 -0
- {sidereon-3.0.4 → sidereon-3.0.5}/bench/bench_fleet.py +0 -0
- {sidereon-3.0.4 → sidereon-3.0.5}/docs/antex.md +0 -0
- {sidereon-3.0.4 → sidereon-3.0.5}/docs/observations.md +0 -0
- {sidereon-3.0.4 → sidereon-3.0.5}/docs/releasing.md +0 -0
- {sidereon-3.0.4 → sidereon-3.0.5}/docs/rinex-clock.md +0 -0
- {sidereon-3.0.4 → sidereon-3.0.5}/docs/tdm.md +0 -0
- {sidereon-3.0.4 → sidereon-3.0.5}/examples/clean_a_phone_track.ipynb +0 -0
- {sidereon-3.0.4 → sidereon-3.0.5}/examples/static_occupation_vs_cors.ipynb +0 -0
- {sidereon-3.0.4 → sidereon-3.0.5}/python/sidereon/__init__.py +0 -0
- {sidereon-3.0.4 → sidereon-3.0.5}/python/sidereon/_compression.py +0 -0
- {sidereon-3.0.4 → sidereon-3.0.5}/python/sidereon/_exact_cache.py +0 -0
- {sidereon-3.0.4 → sidereon-3.0.5}/python/sidereon/_ingress.py +0 -0
- {sidereon-3.0.4 → sidereon-3.0.5}/python/sidereon/distribution.py +0 -0
- {sidereon-3.0.4 → sidereon-3.0.5}/python/sidereon/distribution.pyi +0 -0
- {sidereon-3.0.4 → sidereon-3.0.5}/python/sidereon/exact_cache.py +0 -0
- {sidereon-3.0.4 → sidereon-3.0.5}/python/sidereon/exact_cache.pyi +0 -0
- {sidereon-3.0.4 → sidereon-3.0.5}/python/sidereon/exact_sp3.py +0 -0
- {sidereon-3.0.4 → sidereon-3.0.5}/python/sidereon/exact_sp3.pyi +0 -0
- {sidereon-3.0.4 → sidereon-3.0.5}/python/sidereon/ntrip.py +0 -0
- {sidereon-3.0.4 → sidereon-3.0.5}/python/sidereon/ntrip.pyi +0 -0
- {sidereon-3.0.4 → sidereon-3.0.5}/python/sidereon/py.typed +0 -0
- {sidereon-3.0.4 → sidereon-3.0.5}/rust-toolchain.toml +0 -0
- {sidereon-3.0.4 → sidereon-3.0.5}/scripts/coverage/bindmap.py +0 -0
- {sidereon-3.0.4 → sidereon-3.0.5}/scripts/coverage/pubapi.py +0 -0
- {sidereon-3.0.4 → sidereon-3.0.5}/scripts/coverage/render_coverage.py +0 -0
- {sidereon-3.0.4 → sidereon-3.0.5}/src/almanac.rs +0 -0
- {sidereon-3.0.4 → sidereon-3.0.5}/src/angles.rs +0 -0
- {sidereon-3.0.4 → sidereon-3.0.5}/src/anomaly.rs +0 -0
- {sidereon-3.0.4 → sidereon-3.0.5}/src/antex.rs +0 -0
- {sidereon-3.0.4 → sidereon-3.0.5}/src/araim.rs +0 -0
- {sidereon-3.0.4 → sidereon-3.0.5}/src/atmosphere.rs +0 -0
- {sidereon-3.0.4 → sidereon-3.0.5}/src/bias.rs +0 -0
- {sidereon-3.0.4 → sidereon-3.0.5}/src/bodies.rs +0 -0
- {sidereon-3.0.4 → sidereon-3.0.5}/src/body_observe.rs +0 -0
- {sidereon-3.0.4 → sidereon-3.0.5}/src/broadcast_comparison.rs +0 -0
- {sidereon-3.0.4 → sidereon-3.0.5}/src/cdm.rs +0 -0
- {sidereon-3.0.4 → sidereon-3.0.5}/src/clock_stability.rs +0 -0
- {sidereon-3.0.4 → sidereon-3.0.5}/src/conjunction.rs +0 -0
- {sidereon-3.0.4 → sidereon-3.0.5}/src/constellation.rs +0 -0
- {sidereon-3.0.4 → sidereon-3.0.5}/src/core_error_detail.rs +0 -0
- {sidereon-3.0.4 → sidereon-3.0.5}/src/covariance.rs +0 -0
- {sidereon-3.0.4 → sidereon-3.0.5}/src/coverage.rs +0 -0
- {sidereon-3.0.4 → sidereon-3.0.5}/src/data_catalog.rs +0 -0
- {sidereon-3.0.4 → sidereon-3.0.5}/src/defaults.rs +0 -0
- {sidereon-3.0.4 → sidereon-3.0.5}/src/dgnss.rs +0 -0
- {sidereon-3.0.4 → sidereon-3.0.5}/src/doppler.rs +0 -0
- {sidereon-3.0.4 → sidereon-3.0.5}/src/elements.rs +0 -0
- {sidereon-3.0.4 → sidereon-3.0.5}/src/emission.rs +0 -0
- {sidereon-3.0.4 → sidereon-3.0.5}/src/equinoctial.rs +0 -0
- {sidereon-3.0.4 → sidereon-3.0.5}/src/error_metrics.rs +0 -0
- {sidereon-3.0.4 → sidereon-3.0.5}/src/estimation.rs +0 -0
- {sidereon-3.0.4 → sidereon-3.0.5}/src/events.rs +0 -0
- {sidereon-3.0.4 → sidereon-3.0.5}/src/exact_cache.rs +0 -0
- {sidereon-3.0.4 → sidereon-3.0.5}/src/exact_time.rs +0 -0
- {sidereon-3.0.4 → sidereon-3.0.5}/src/fallback.rs +0 -0
- {sidereon-3.0.4 → sidereon-3.0.5}/src/forces.rs +0 -0
- {sidereon-3.0.4 → sidereon-3.0.5}/src/format_diagnostics.rs +0 -0
- {sidereon-3.0.4 → sidereon-3.0.5}/src/frame_catalog.rs +0 -0
- {sidereon-3.0.4 → sidereon-3.0.5}/src/frames.rs +0 -0
- {sidereon-3.0.4 → sidereon-3.0.5}/src/fusion.rs +0 -0
- {sidereon-3.0.4 → sidereon-3.0.5}/src/geodesic.rs +0 -0
- {sidereon-3.0.4 → sidereon-3.0.5}/src/geodetic_time_series.rs +0 -0
- {sidereon-3.0.4 → sidereon-3.0.5}/src/geofence.rs +0 -0
- {sidereon-3.0.4 → sidereon-3.0.5}/src/geoid.rs +0 -0
- {sidereon-3.0.4 → sidereon-3.0.5}/src/geometry.rs +0 -0
- {sidereon-3.0.4 → sidereon-3.0.5}/src/geometry_quality.rs +0 -0
- {sidereon-3.0.4 → sidereon-3.0.5}/src/ils.rs +0 -0
- {sidereon-3.0.4 → sidereon-3.0.5}/src/iod.rs +0 -0
- {sidereon-3.0.4 → sidereon-3.0.5}/src/ionex.rs +0 -0
- {sidereon-3.0.4 → sidereon-3.0.5}/src/lambert.rs +0 -0
- {sidereon-3.0.4 → sidereon-3.0.5}/src/leap.rs +0 -0
- {sidereon-3.0.4 → sidereon-3.0.5}/src/least_squares.rs +0 -0
- {sidereon-3.0.4 → sidereon-3.0.5}/src/lib.rs +0 -0
- {sidereon-3.0.4 → sidereon-3.0.5}/src/marshal.rs +0 -0
- {sidereon-3.0.4 → sidereon-3.0.5}/src/nmea.rs +0 -0
- {sidereon-3.0.4 → sidereon-3.0.5}/src/normality.rs +0 -0
- {sidereon-3.0.4 → sidereon-3.0.5}/src/ntrip.rs +0 -0
- {sidereon-3.0.4 → sidereon-3.0.5}/src/observables.rs +0 -0
- {sidereon-3.0.4 → sidereon-3.0.5}/src/observation.rs +0 -0
- {sidereon-3.0.4 → sidereon-3.0.5}/src/oem.rs +0 -0
- {sidereon-3.0.4 → sidereon-3.0.5}/src/omm.rs +0 -0
- {sidereon-3.0.4 → sidereon-3.0.5}/src/opm.rs +0 -0
- {sidereon-3.0.4 → sidereon-3.0.5}/src/orbit_determination.rs +0 -0
- {sidereon-3.0.4 → sidereon-3.0.5}/src/ppp.rs +0 -0
- {sidereon-3.0.4 → sidereon-3.0.5}/src/ppp_corrections.rs +0 -0
- {sidereon-3.0.4 → sidereon-3.0.5}/src/products.rs +0 -0
- {sidereon-3.0.4 → sidereon-3.0.5}/src/propagation.rs +0 -0
- {sidereon-3.0.4 → sidereon-3.0.5}/src/qc.rs +0 -0
- {sidereon-3.0.4 → sidereon-3.0.5}/src/reduced_orbit.rs +0 -0
- {sidereon-3.0.4 → sidereon-3.0.5}/src/relative.rs +0 -0
- {sidereon-3.0.4 → sidereon-3.0.5}/src/reliability.rs +0 -0
- {sidereon-3.0.4 → sidereon-3.0.5}/src/rf.rs +0 -0
- {sidereon-3.0.4 → sidereon-3.0.5}/src/rinex.rs +0 -0
- {sidereon-3.0.4 → sidereon-3.0.5}/src/rinex_clock.rs +0 -0
- {sidereon-3.0.4 → sidereon-3.0.5}/src/rtcm.rs +0 -0
- {sidereon-3.0.4 → sidereon-3.0.5}/src/rtk.rs +0 -0
- {sidereon-3.0.4 → sidereon-3.0.5}/src/sbas_pl.rs +0 -0
- {sidereon-3.0.4 → sidereon-3.0.5}/src/sbas_ssr.rs +0 -0
- {sidereon-3.0.4 → sidereon-3.0.5}/src/scenario.rs +0 -0
- {sidereon-3.0.4 → sidereon-3.0.5}/src/sidereal.rs +0 -0
- {sidereon-3.0.4 → sidereon-3.0.5}/src/signal_analysis.rs +0 -0
- {sidereon-3.0.4 → sidereon-3.0.5}/src/sky.rs +0 -0
- {sidereon-3.0.4 → sidereon-3.0.5}/src/solve_error_detail.rs +0 -0
- {sidereon-3.0.4 → sidereon-3.0.5}/src/source_localization.rs +0 -0
- {sidereon-3.0.4 → sidereon-3.0.5}/src/space_weather.rs +0 -0
- {sidereon-3.0.4 → sidereon-3.0.5}/src/spk.rs +0 -0
- {sidereon-3.0.4 → sidereon-3.0.5}/src/spp.rs +0 -0
- {sidereon-3.0.4 → sidereon-3.0.5}/src/spp_error_detail.rs +0 -0
- {sidereon-3.0.4 → sidereon-3.0.5}/src/staleness.rs +0 -0
- {sidereon-3.0.4 → sidereon-3.0.5}/src/static_positioning.rs +0 -0
- {sidereon-3.0.4 → sidereon-3.0.5}/src/tca.rs +0 -0
- {sidereon-3.0.4 → sidereon-3.0.5}/src/tdm.rs +0 -0
- {sidereon-3.0.4 → sidereon-3.0.5}/src/terrain.rs +0 -0
- {sidereon-3.0.4 → sidereon-3.0.5}/src/terrain_store.rs +0 -0
- {sidereon-3.0.4 → sidereon-3.0.5}/src/tides.rs +0 -0
- {sidereon-3.0.4 → sidereon-3.0.5}/src/time_model_error.rs +0 -0
- {sidereon-3.0.4 → sidereon-3.0.5}/src/tle_fit_error_detail.rs +0 -0
- {sidereon-3.0.4 → sidereon-3.0.5}/src/tropo.rs +0 -0
- {sidereon-3.0.4 → sidereon-3.0.5}/src/unix_compress.rs +0 -0
- {sidereon-3.0.4 → sidereon-3.0.5}/tests/_helpers.py +0 -0
- {sidereon-3.0.4 → sidereon-3.0.5}/tests/_sp3_merge.py +0 -0
- {sidereon-3.0.4 → sidereon-3.0.5}/tests/fixtures/README.md +0 -0
- {sidereon-3.0.4 → sidereon-3.0.5}/tests/fixtures/antex/igs20_pasa_scoa_gps.atx +0 -0
- {sidereon-3.0.4 → sidereon-3.0.5}/tests/fixtures/antex/igs20_wettzell_trim.atx +0 -0
- {sidereon-3.0.4 → sidereon-3.0.5}/tests/fixtures/batch_fleet.json +0 -0
- {sidereon-3.0.4 → sidereon-3.0.5}/tests/fixtures/bodies/observe_de.bsp +0 -0
- {sidereon-3.0.4 → sidereon-3.0.5}/tests/fixtures/cdm.json +0 -0
- {sidereon-3.0.4 → sidereon-3.0.5}/tests/fixtures/clk/lossless/rinex_clock304_table_a17.clk +0 -0
- {sidereon-3.0.4 → sidereon-3.0.5}/tests/fixtures/clk/lossless/rinex_clock304_table_a18.clk +0 -0
- {sidereon-3.0.4 → sidereon-3.0.5}/tests/fixtures/clk/synthetic_rinex_clock.clk +0 -0
- {sidereon-3.0.4 → sidereon-3.0.5}/tests/fixtures/conjunction.json +0 -0
- {sidereon-3.0.4 → sidereon-3.0.5}/tests/fixtures/constellation/gps_ops_sample.json +0 -0
- {sidereon-3.0.4 → sidereon-3.0.5}/tests/fixtures/constellation/navcen_forecast_cases.html +0 -0
- {sidereon-3.0.4 → sidereon-3.0.5}/tests/fixtures/constellation/navcen_gps_sample.html +0 -0
- {sidereon-3.0.4 → sidereon-3.0.5}/tests/fixtures/events_bodies_dop.json +0 -0
- {sidereon-3.0.4 → sidereon-3.0.5}/tests/fixtures/format_diagnostics_inputs.json +0 -0
- {sidereon-3.0.4 → sidereon-3.0.5}/tests/fixtures/frames_time.json +0 -0
- {sidereon-3.0.4 → sidereon-3.0.5}/tests/fixtures/geodesic/geodtest_row.dat +0 -0
- {sidereon-3.0.4 → sidereon-3.0.5}/tests/fixtures/geoid/egm2008_25_norcal_crop.bin +0 -0
- {sidereon-3.0.4 → sidereon-3.0.5}/tests/fixtures/gnss_data/igs22376.sp3.Z.b64 +0 -0
- {sidereon-3.0.4 → sidereon-3.0.5}/tests/fixtures/gnss_data/ncompress-current-b9-counter.Z.b64 +0 -0
- {sidereon-3.0.4 → sidereon-3.0.5}/tests/fixtures/listings/aiub-iono-prd-20260923.csv +0 -0
- {sidereon-3.0.4 → sidereon-3.0.5}/tests/fixtures/listings/gfz-ultra-w2430-20260804.html +0 -0
- {sidereon-3.0.4 → sidereon-3.0.5}/tests/fixtures/nav/BRDC00GOP_R_20210010000_01D_MN.rnx +0 -0
- {sidereon-3.0.4 → sidereon-3.0.5}/tests/fixtures/nav/ESBC00DNK_R_20201770000_01D_MN.rnx +0 -0
- {sidereon-3.0.4 → sidereon-3.0.5}/tests/fixtures/nav/KMS300DNK_R_20221591000_01H_MN.rnx +0 -0
- {sidereon-3.0.4 → sidereon-3.0.5}/tests/fixtures/numerical_propagation.json +0 -0
- {sidereon-3.0.4 → sidereon-3.0.5}/tests/fixtures/obs/ESBC00DNK_R_20201770000_01D_30S_MO_trim.crx +0 -0
- {sidereon-3.0.4 → sidereon-3.0.5}/tests/fixtures/obs/ESBC00DNK_R_20201770000_01D_30S_MO_trim.rnx +0 -0
- {sidereon-3.0.4 → sidereon-3.0.5}/tests/fixtures/obs/algo0010_2015001_v1_trim.crx +0 -0
- {sidereon-3.0.4 → sidereon-3.0.5}/tests/fixtures/obs/algo0010_2015001_v1_trim.rnx +0 -0
- {sidereon-3.0.4 → sidereon-3.0.5}/tests/fixtures/omm.json +0 -0
- {sidereon-3.0.4 → sidereon-3.0.5}/tests/fixtures/pass_finder.json +0 -0
- {sidereon-3.0.4 → sidereon-3.0.5}/tests/fixtures/rf_link_budget.json +0 -0
- {sidereon-3.0.4 → sidereon-3.0.5}/tests/fixtures/rtk_wtzr.json +0 -0
- {sidereon-3.0.4 → sidereon-3.0.5}/tests/fixtures/scenario_base.json +0 -0
- {sidereon-3.0.4 → sidereon-3.0.5}/tests/fixtures/sgp4_topocentric.json +0 -0
- {sidereon-3.0.4 → sidereon-3.0.5}/tests/fixtures/sp3/IGS0OPSFIN_20261200945_02H30M_15M_ORB.SP3 +0 -0
- {sidereon-3.0.4 → sidereon-3.0.5}/tests/fixtures/sp3-merge-input-v1.json +0 -0
- {sidereon-3.0.4 → sidereon-3.0.5}/tests/fixtures/sp3-merge-report-v3.json +0 -0
- {sidereon-3.0.4 → sidereon-3.0.5}/tests/fixtures/sp3_bodies.json +0 -0
- {sidereon-3.0.4 → sidereon-3.0.5}/tests/fixtures/spk/horizons_eros_type21.bsp +0 -0
- {sidereon-3.0.4 → sidereon-3.0.5}/tests/fixtures/tdm/annex_e_01.kvn +0 -0
- {sidereon-3.0.4 → sidereon-3.0.5}/tests/fixtures/tle_roundtrip.json +0 -0
- {sidereon-3.0.4 → sidereon-3.0.5}/tests/golden/sp3-terminal-record-v1.json +0 -0
- {sidereon-3.0.4 → sidereon-3.0.5}/tests/test_012_bindings.py +0 -0
- {sidereon-3.0.4 → sidereon-3.0.5}/tests/test_013_bindings.py +0 -0
- {sidereon-3.0.4 → sidereon-3.0.5}/tests/test_014_bindings.py +0 -0
- {sidereon-3.0.4 → sidereon-3.0.5}/tests/test_015_bindings.py +0 -0
- {sidereon-3.0.4 → sidereon-3.0.5}/tests/test_016_wave2_bindings.py +0 -0
- {sidereon-3.0.4 → sidereon-3.0.5}/tests/test_017_domain_exposure.py +0 -0
- {sidereon-3.0.4 → sidereon-3.0.5}/tests/test_018_domain_exposure.py +0 -0
- {sidereon-3.0.4 → sidereon-3.0.5}/tests/test_019_track.py +0 -0
- {sidereon-3.0.4 → sidereon-3.0.5}/tests/test_020_error_metrics.py +0 -0
- {sidereon-3.0.4 → sidereon-3.0.5}/tests/test_antex.py +0 -0
- {sidereon-3.0.4 → sidereon-3.0.5}/tests/test_antex_public_equality.py +0 -0
- {sidereon-3.0.4 → sidereon-3.0.5}/tests/test_antex_public_pcv_sample_fields.py +0 -0
- {sidereon-3.0.4 → sidereon-3.0.5}/tests/test_atmosphere.py +0 -0
- {sidereon-3.0.4 → sidereon-3.0.5}/tests/test_attested_open.py +0 -0
- {sidereon-3.0.4 → sidereon-3.0.5}/tests/test_batch.py +0 -0
- {sidereon-3.0.4 → sidereon-3.0.5}/tests/test_body_observe_reference.py +0 -0
- {sidereon-3.0.4 → sidereon-3.0.5}/tests/test_broadcast_comparison.py +0 -0
- {sidereon-3.0.4 → sidereon-3.0.5}/tests/test_broadcast_fallback.py +0 -0
- {sidereon-3.0.4 → sidereon-3.0.5}/tests/test_cdm.py +0 -0
- {sidereon-3.0.4 → sidereon-3.0.5}/tests/test_cdm_top_level.py +0 -0
- {sidereon-3.0.4 → sidereon-3.0.5}/tests/test_cdm_value_equality.py +0 -0
- {sidereon-3.0.4 → sidereon-3.0.5}/tests/test_codec_error_details.py +0 -0
- {sidereon-3.0.4 → sidereon-3.0.5}/tests/test_conjunction.py +0 -0
- {sidereon-3.0.4 → sidereon-3.0.5}/tests/test_constellation.py +0 -0
- {sidereon-3.0.4 → sidereon-3.0.5}/tests/test_constellation_fleet.py +0 -0
- {sidereon-3.0.4 → sidereon-3.0.5}/tests/test_core_defaults.py +0 -0
- {sidereon-3.0.4 → sidereon-3.0.5}/tests/test_core_public_api_parity.py +0 -0
- {sidereon-3.0.4 → sidereon-3.0.5}/tests/test_core_round3_surfaces.py +0 -0
- {sidereon-3.0.4 → sidereon-3.0.5}/tests/test_covariance.py +0 -0
- {sidereon-3.0.4 → sidereon-3.0.5}/tests/test_covariance_propagation.py +0 -0
- {sidereon-3.0.4 → sidereon-3.0.5}/tests/test_coverage.py +0 -0
- {sidereon-3.0.4 → sidereon-3.0.5}/tests/test_crinex.py +0 -0
- {sidereon-3.0.4 → sidereon-3.0.5}/tests/test_data_publication_resilience.py +0 -0
- {sidereon-3.0.4 → sidereon-3.0.5}/tests/test_dgnss.py +0 -0
- {sidereon-3.0.4 → sidereon-3.0.5}/tests/test_distribution.py +0 -0
- {sidereon-3.0.4 → sidereon-3.0.5}/tests/test_distribution_fallback.py +0 -0
- {sidereon-3.0.4 → sidereon-3.0.5}/tests/test_dop_at_epoch.py +0 -0
- {sidereon-3.0.4 → sidereon-3.0.5}/tests/test_dop_convention.py +0 -0
- {sidereon-3.0.4 → sidereon-3.0.5}/tests/test_doppler.py +0 -0
- {sidereon-3.0.4 → sidereon-3.0.5}/tests/test_dted_tile_error_details.py +0 -0
- {sidereon-3.0.4 → sidereon-3.0.5}/tests/test_egm96.py +0 -0
- {sidereon-3.0.4 → sidereon-3.0.5}/tests/test_elements.py +0 -0
- {sidereon-3.0.4 → sidereon-3.0.5}/tests/test_events_bodies_dop.py +0 -0
- {sidereon-3.0.4 → sidereon-3.0.5}/tests/test_exact_cache_atomicity.py +0 -0
- {sidereon-3.0.4 → sidereon-3.0.5}/tests/test_field_mode_bindings.py +0 -0
- {sidereon-3.0.4 → sidereon-3.0.5}/tests/test_forces.py +0 -0
- {sidereon-3.0.4 → sidereon-3.0.5}/tests/test_format_diagnostics.py +0 -0
- {sidereon-3.0.4 → sidereon-3.0.5}/tests/test_frames_time.py +0 -0
- {sidereon-3.0.4 → sidereon-3.0.5}/tests/test_ftp_transport.py +0 -0
- {sidereon-3.0.4 → sidereon-3.0.5}/tests/test_fusion_error_details.py +0 -0
- {sidereon-3.0.4 → sidereon-3.0.5}/tests/test_geoid.py +0 -0
- {sidereon-3.0.4 → sidereon-3.0.5}/tests/test_geometry.py +0 -0
- {sidereon-3.0.4 → sidereon-3.0.5}/tests/test_ils.py +0 -0
- {sidereon-3.0.4 → sidereon-3.0.5}/tests/test_import.py +0 -0
- {sidereon-3.0.4 → sidereon-3.0.5}/tests/test_inertial_mechanization.py +0 -0
- {sidereon-3.0.4 → sidereon-3.0.5}/tests/test_ionex.py +0 -0
- {sidereon-3.0.4 → sidereon-3.0.5}/tests/test_ionex_instant_queries.py +0 -0
- {sidereon-3.0.4 → sidereon-3.0.5}/tests/test_ionex_policies.py +0 -0
- {sidereon-3.0.4 → sidereon-3.0.5}/tests/test_ionex_public_equality.py +0 -0
- {sidereon-3.0.4 → sidereon-3.0.5}/tests/test_ionosphere_nequick.py +0 -0
- {sidereon-3.0.4 → sidereon-3.0.5}/tests/test_klobuchar_native.py +0 -0
- {sidereon-3.0.4 → sidereon-3.0.5}/tests/test_lambert_iod.py +0 -0
- {sidereon-3.0.4 → sidereon-3.0.5}/tests/test_leap_seconds.py +0 -0
- {sidereon-3.0.4 → sidereon-3.0.5}/tests/test_least_squares.py +0 -0
- {sidereon-3.0.4 → sidereon-3.0.5}/tests/test_misc_public_equality.py +0 -0
- {sidereon-3.0.4 → sidereon-3.0.5}/tests/test_moving_baseline.py +0 -0
- {sidereon-3.0.4 → sidereon-3.0.5}/tests/test_new_core_api.py +0 -0
- {sidereon-3.0.4 → sidereon-3.0.5}/tests/test_next_issue_due.py +0 -0
- {sidereon-3.0.4 → sidereon-3.0.5}/tests/test_nmea_finish_output.py +0 -0
- {sidereon-3.0.4 → sidereon-3.0.5}/tests/test_ntrip.py +0 -0
- {sidereon-3.0.4 → sidereon-3.0.5}/tests/test_numerical.py +0 -0
- {sidereon-3.0.4 → sidereon-3.0.5}/tests/test_obs_policies.py +0 -0
- {sidereon-3.0.4 → sidereon-3.0.5}/tests/test_observables.py +0 -0
- {sidereon-3.0.4 → sidereon-3.0.5}/tests/test_observables_broadcast.py +0 -0
- {sidereon-3.0.4 → sidereon-3.0.5}/tests/test_observables_error_details.py +0 -0
- {sidereon-3.0.4 → sidereon-3.0.5}/tests/test_observation.py +0 -0
- {sidereon-3.0.4 → sidereon-3.0.5}/tests/test_observation_qc.py +0 -0
- {sidereon-3.0.4 → sidereon-3.0.5}/tests/test_observe_batch.py +0 -0
- {sidereon-3.0.4 → sidereon-3.0.5}/tests/test_oem.py +0 -0
- {sidereon-3.0.4 → sidereon-3.0.5}/tests/test_oem_full_dto.py +0 -0
- {sidereon-3.0.4 → sidereon-3.0.5}/tests/test_omm.py +0 -0
- {sidereon-3.0.4 → sidereon-3.0.5}/tests/test_omm_full_dto.py +0 -0
- {sidereon-3.0.4 → sidereon-3.0.5}/tests/test_opm.py +0 -0
- {sidereon-3.0.4 → sidereon-3.0.5}/tests/test_opm_full_dto.py +0 -0
- {sidereon-3.0.4 → sidereon-3.0.5}/tests/test_parity_gaps.py +0 -0
- {sidereon-3.0.4 → sidereon-3.0.5}/tests/test_parse_tle_file.py +0 -0
- {sidereon-3.0.4 → sidereon-3.0.5}/tests/test_passes.py +0 -0
- {sidereon-3.0.4 → sidereon-3.0.5}/tests/test_ppp.py +0 -0
- {sidereon-3.0.4 → sidereon-3.0.5}/tests/test_ppp_corrections.py +0 -0
- {sidereon-3.0.4 → sidereon-3.0.5}/tests/test_ppp_range_corrections.py +0 -0
- {sidereon-3.0.4 → sidereon-3.0.5}/tests/test_precise_interpolant_public_values.py +0 -0
- {sidereon-3.0.4 → sidereon-3.0.5}/tests/test_precise_samples.py +0 -0
- {sidereon-3.0.4 → sidereon-3.0.5}/tests/test_precise_samples_errors.py +0 -0
- {sidereon-3.0.4 → sidereon-3.0.5}/tests/test_propagation.py +0 -0
- {sidereon-3.0.4 → sidereon-3.0.5}/tests/test_qc.py +0 -0
- {sidereon-3.0.4 → sidereon-3.0.5}/tests/test_reduced_orbit.py +0 -0
- {sidereon-3.0.4 → sidereon-3.0.5}/tests/test_reduced_orbit_piecewise.py +0 -0
- {sidereon-3.0.4 → sidereon-3.0.5}/tests/test_release_guard.py +0 -0
- {sidereon-3.0.4 → sidereon-3.0.5}/tests/test_residual_stats.py +0 -0
- {sidereon-3.0.4 → sidereon-3.0.5}/tests/test_rf.py +0 -0
- {sidereon-3.0.4 → sidereon-3.0.5}/tests/test_rinex_clock.py +0 -0
- {sidereon-3.0.4 → sidereon-3.0.5}/tests/test_rinex_clock_equality.py +0 -0
- {sidereon-3.0.4 → sidereon-3.0.5}/tests/test_rinex_clock_header_field_details.py +0 -0
- {sidereon-3.0.4 → sidereon-3.0.5}/tests/test_rinex_clock_lossless.py +0 -0
- {sidereon-3.0.4 → sidereon-3.0.5}/tests/test_rinex_nav.py +0 -0
- {sidereon-3.0.4 → sidereon-3.0.5}/tests/test_rinex_obs.py +0 -0
- {sidereon-3.0.4 → sidereon-3.0.5}/tests/test_rtcm.py +0 -0
- {sidereon-3.0.4 → sidereon-3.0.5}/tests/test_rtcm_departure_message_number_contract.py +0 -0
- {sidereon-3.0.4 → sidereon-3.0.5}/tests/test_rtk.py +0 -0
- {sidereon-3.0.4 → sidereon-3.0.5}/tests/test_rtk_unresolved_carriers.py +0 -0
- {sidereon-3.0.4 → sidereon-3.0.5}/tests/test_sbas_decoded_lists.py +0 -0
- {sidereon-3.0.4 → sidereon-3.0.5}/tests/test_sbas_unassigned_mask.py +0 -0
- {sidereon-3.0.4 → sidereon-3.0.5}/tests/test_scenario_external_sources.py +0 -0
- {sidereon-3.0.4 → sidereon-3.0.5}/tests/test_sky.py +0 -0
- {sidereon-3.0.4 → sidereon-3.0.5}/tests/test_sp3_bodies.py +0 -0
- {sidereon-3.0.4 → sidereon-3.0.5}/tests/test_sp3_catalog_exact.py +0 -0
- {sidereon-3.0.4 → sidereon-3.0.5}/tests/test_sp3_clock_reference.py +0 -0
- {sidereon-3.0.4 → sidereon-3.0.5}/tests/test_sp3_interpolation_policy.py +0 -0
- {sidereon-3.0.4 → sidereon-3.0.5}/tests/test_sp3_merge_coverage.py +0 -0
- {sidereon-3.0.4 → sidereon-3.0.5}/tests/test_sp3_merge_per_epoch_provenance.py +0 -0
- {sidereon-3.0.4 → sidereon-3.0.5}/tests/test_sp3_public_metadata.py +0 -0
- {sidereon-3.0.4 → sidereon-3.0.5}/tests/test_sp3_terminal_record.py +0 -0
- {sidereon-3.0.4 → sidereon-3.0.5}/tests/test_sp3_window_continuity.py +0 -0
- {sidereon-3.0.4 → sidereon-3.0.5}/tests/test_spk.py +0 -0
- {sidereon-3.0.4 → sidereon-3.0.5}/tests/test_spp.py +0 -0
- {sidereon-3.0.4 → sidereon-3.0.5}/tests/test_spp_error_details.py +0 -0
- {sidereon-3.0.4 → sidereon-3.0.5}/tests/test_spp_glonass.py +0 -0
- {sidereon-3.0.4 → sidereon-3.0.5}/tests/test_spp_robustness.py +0 -0
- {sidereon-3.0.4 → sidereon-3.0.5}/tests/test_staleness.py +0 -0
- {sidereon-3.0.4 → sidereon-3.0.5}/tests/test_stub_accuracy.py +0 -0
- {sidereon-3.0.4 → sidereon-3.0.5}/tests/test_tca.py +0 -0
- {sidereon-3.0.4 → sidereon-3.0.5}/tests/test_tdm_policies.py +0 -0
- {sidereon-3.0.4 → sidereon-3.0.5}/tests/test_terrain_unknown_elevation.py +0 -0
- {sidereon-3.0.4 → sidereon-3.0.5}/tests/test_tides.py +0 -0
- {sidereon-3.0.4 → sidereon-3.0.5}/tests/test_time_model_error_details.py +0 -0
- {sidereon-3.0.4 → sidereon-3.0.5}/tests/test_time_offset_error_details.py +0 -0
- {sidereon-3.0.4 → sidereon-3.0.5}/tests/test_tle_fit.py +0 -0
- {sidereon-3.0.4 → sidereon-3.0.5}/tests/test_tle_roundtrip.py +0 -0
- {sidereon-3.0.4 → sidereon-3.0.5}/tests/test_tropo.py +0 -0
- {sidereon-3.0.4 → sidereon-3.0.5}/tests/test_unix_compress.py +0 -0
- {sidereon-3.0.4 → sidereon-3.0.5}/tests/test_visible_ground_track.py +0 -0
- {sidereon-3.0.4 → sidereon-3.0.5}/tests/test_weather_terrain_error_details.py +0 -0
- {sidereon-3.0.4 → sidereon-3.0.5}/third_party_licenses/ERFA-BSD-3-Clause.txt +0 -0
- {sidereon-3.0.4 → sidereon-3.0.5}/third_party_licenses/IERS-CONVENTIONS-SOFTWARE-LICENSE.txt +0 -0
- {sidereon-3.0.4 → sidereon-3.0.5}/third_party_licenses/SciPy-BSD-3-Clause.txt +0 -0
- {sidereon-3.0.4 → sidereon-3.0.5}/third_party_source/sidereon-core-3.0.4/tides/mod.rs +0 -0
- {sidereon-3.0.4 → sidereon-3.0.5}/third_party_source/sidereon-core-3.0.4/tides/ocean.rs +0 -0
- {sidereon-3.0.4 → sidereon-3.0.5}/third_party_source/sidereon-core-3.0.4/tides/pole.rs +0 -0
|
@@ -169,6 +169,8 @@ jobs:
|
|
|
169
169
|
run: uv run --locked --extra test --group dev mypy
|
|
170
170
|
- name: Build the extension (maturin develop)
|
|
171
171
|
run: uv run --locked --extra test --group dev maturin develop --locked --features exact-cache-test-failpoints
|
|
172
|
+
- name: Release consumer contract
|
|
173
|
+
run: uv run --locked --extra test --group dev python scripts/smoke-release.py
|
|
172
174
|
- name: stub accuracy
|
|
173
175
|
env:
|
|
174
176
|
SIDEREON_CORE_FIXTURES: ${{ github.workspace }}/.core-checkout/crates/sidereon-core/tests/fixtures
|
|
@@ -153,10 +153,10 @@ jobs:
|
|
|
153
153
|
done
|
|
154
154
|
for source in mod.rs ocean.rs pole.rs; do
|
|
155
155
|
unzip -p "$wheel" \
|
|
156
|
-
"third_party_source/sidereon-core-3.0.
|
|
156
|
+
"third_party_source/sidereon-core-3.0.5/tides/$source" \
|
|
157
157
|
>"$RUNNER_TEMP/$source"
|
|
158
158
|
cmp "$RUNNER_TEMP/$source" \
|
|
159
|
-
"third_party_source/sidereon-core-3.0.
|
|
159
|
+
"third_party_source/sidereon-core-3.0.5/tides/$source"
|
|
160
160
|
done
|
|
161
161
|
done
|
|
162
162
|
notice="$RUNNER_TEMP/sdist.notices"
|
|
@@ -173,10 +173,10 @@ jobs:
|
|
|
173
173
|
done
|
|
174
174
|
for source in mod.rs ocean.rs pole.rs; do
|
|
175
175
|
tar -xOf "${sdists[0]}" --wildcards \
|
|
176
|
-
"*/third_party_source/sidereon-core-3.0.
|
|
176
|
+
"*/third_party_source/sidereon-core-3.0.5/tides/$source" \
|
|
177
177
|
>"$RUNNER_TEMP/sdist-$source"
|
|
178
178
|
cmp "$RUNNER_TEMP/sdist-$source" \
|
|
179
|
-
"third_party_source/sidereon-core-3.0.
|
|
179
|
+
"third_party_source/sidereon-core-3.0.5/tides/$source"
|
|
180
180
|
done
|
|
181
181
|
- name: Smoke-test installed x86_64 Linux wheel
|
|
182
182
|
shell: bash
|
|
@@ -4,6 +4,20 @@ All notable changes to the Sidereon Python interface are documented here.
|
|
|
4
4
|
|
|
5
5
|
## [Unreleased]
|
|
6
6
|
|
|
7
|
+
## [3.0.5] - 2026-10-30
|
|
8
|
+
|
|
9
|
+
### Added
|
|
10
|
+
|
|
11
|
+
- Add opt-in SP3 column rounding writers that report maximum absolute SI changes; strict writers remain unchanged.
|
|
12
|
+
- Preserve strictly writable SP3 columns for grid-aligned merge and alignment products.
|
|
13
|
+
|
|
14
|
+
### Fixed
|
|
15
|
+
|
|
16
|
+
- Normalize extreme-scale quaternions robustly while preserving ordinary quaternion rounding.
|
|
17
|
+
- Reject zero probability values where probability inputs must be strictly between zero and one.
|
|
18
|
+
- Describe the seven raw LNAV broadcast angular fields as semicircles or
|
|
19
|
+
semicircles/second, matching their unchanged transmitted-integer scaling.
|
|
20
|
+
|
|
7
21
|
## [3.0.4] - 2026-10-18
|
|
8
22
|
|
|
9
23
|
### Fixed
|
|
@@ -611,9 +611,9 @@ checksum = "f8fadd59c855ef2080decdef8ff161eb6661b86933c9d82e5ba29dc602a55aba"
|
|
|
611
611
|
|
|
612
612
|
[[package]]
|
|
613
613
|
name = "sidereon"
|
|
614
|
-
version = "3.0.
|
|
614
|
+
version = "3.0.5"
|
|
615
615
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
616
|
-
checksum = "
|
|
616
|
+
checksum = "fa3b2d18f88640b1bc0a86ed17bbacd9298eeea5b202174ec8da5ce7ae9a46e2"
|
|
617
617
|
dependencies = [
|
|
618
618
|
"crc32fast",
|
|
619
619
|
"flate2",
|
|
@@ -622,9 +622,9 @@ dependencies = [
|
|
|
622
622
|
|
|
623
623
|
[[package]]
|
|
624
624
|
name = "sidereon-core"
|
|
625
|
-
version = "3.0.
|
|
625
|
+
version = "3.0.5"
|
|
626
626
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
627
|
-
checksum = "
|
|
627
|
+
checksum = "3ba2c37c8b12bc20827e8e90971d635895e8a45fc715ad81c38d45cc3a4d3591"
|
|
628
628
|
dependencies = [
|
|
629
629
|
"approx",
|
|
630
630
|
"cc",
|
|
@@ -646,7 +646,7 @@ dependencies = [
|
|
|
646
646
|
|
|
647
647
|
[[package]]
|
|
648
648
|
name = "sidereon-py"
|
|
649
|
-
version = "3.0.
|
|
649
|
+
version = "3.0.5"
|
|
650
650
|
dependencies = [
|
|
651
651
|
"nalgebra",
|
|
652
652
|
"numpy",
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[package]
|
|
2
2
|
name = "sidereon-py"
|
|
3
|
-
version = "3.0.
|
|
3
|
+
version = "3.0.5"
|
|
4
4
|
authors = []
|
|
5
5
|
edition = "2021"
|
|
6
6
|
description = "Python (PyO3) bindings over the sidereon ergonomic API: SP3 loading and SPP/RTK/PPP positioning solves"
|
|
@@ -25,8 +25,8 @@ exact-cache-test-failpoints = ["sidereon-core/exact-cache-test-failpoints"]
|
|
|
25
25
|
# The thin ergonomic engine surface this binding marshals to. No modeling logic
|
|
26
26
|
# lives here: every solve delegates to a `sidereon` entry point, which in turn
|
|
27
27
|
# delegates to `sidereon-core`.
|
|
28
|
-
sidereon = "=3.0.
|
|
29
|
-
sidereon-core = { version = "=3.0.
|
|
28
|
+
sidereon = { version = "=3.0.5" }
|
|
29
|
+
sidereon-core = { version = "=3.0.5", features = ["mmap"] }
|
|
30
30
|
# The standalone general-purpose trust-region least-squares solver: a data-driven
|
|
31
31
|
# `least_squares` whose residual and Jacobian are evaluated entirely in Rust, so
|
|
32
32
|
# no per-iteration Python callback is paid.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: sidereon
|
|
3
|
-
Version: 3.0.
|
|
3
|
+
Version: 3.0.5
|
|
4
4
|
Classifier: Programming Language :: Rust
|
|
5
5
|
Classifier: Programming Language :: Python :: 3
|
|
6
6
|
Classifier: Topic :: Scientific/Engineering
|
|
@@ -280,7 +280,10 @@ The Python package mirrors the full breadth of the engine.
|
|
|
280
280
|
defines, including exact validity seconds (see `docs/antex.md`).
|
|
281
281
|
- **Data acquisition:** the `sidereon.data` module downloads and caches GNSS
|
|
282
282
|
products (SP3 and IONEX from IGS/MGEX analysis centers, including merged
|
|
283
|
-
multi-center SP3) and DTED terrain tiles.
|
|
283
|
+
multi-center SP3) and DTED terrain tiles. Merges from column-grid inputs
|
|
284
|
+
retain SP3-writable records; higher-precision inputs can still need the
|
|
285
|
+
opt-in rounding writer. Agreement metrics use combined values before final
|
|
286
|
+
column quantization. Exact-product requests can select
|
|
284
287
|
direct archives, NASA CDDIS/Earthdata, local files, or caller-provided bytes
|
|
285
288
|
without changing product identity. `ExactSp3Request` validates the declared
|
|
286
289
|
cadence, regular epoch grid, exact half-open or inclusive coverage, producer,
|
|
@@ -261,7 +261,10 @@ The Python package mirrors the full breadth of the engine.
|
|
|
261
261
|
defines, including exact validity seconds (see `docs/antex.md`).
|
|
262
262
|
- **Data acquisition:** the `sidereon.data` module downloads and caches GNSS
|
|
263
263
|
products (SP3 and IONEX from IGS/MGEX analysis centers, including merged
|
|
264
|
-
multi-center SP3) and DTED terrain tiles.
|
|
264
|
+
multi-center SP3) and DTED terrain tiles. Merges from column-grid inputs
|
|
265
|
+
retain SP3-writable records; higher-precision inputs can still need the
|
|
266
|
+
opt-in rounding writer. Agreement metrics use combined values before final
|
|
267
|
+
column quantization. Exact-product requests can select
|
|
265
268
|
direct archives, NASA CDDIS/Earthdata, local files, or caller-provided bytes
|
|
266
269
|
without changing product identity. `ExactSp3Request` validates the declared
|
|
267
270
|
cadence, regular epoch grid, exact half-open or inclusive coverage, producer,
|
|
@@ -330,9 +330,9 @@ endorsed by the IERS Conventions Center. The Rust source describes the origin,
|
|
|
330
330
|
the renamed routines, and the differences from the Fortran implementation.
|
|
331
331
|
The complete non-test tide source distributed in the compiled extension is
|
|
332
332
|
included under
|
|
333
|
-
`third_party_source/sidereon-core-3.0.
|
|
334
|
-
distributions. These files match sidereon-core 3.0.
|
|
335
|
-
Source: [sidereon-core tides at the pinned commit](https://github.com/neilberkman/sidereon/tree/
|
|
333
|
+
`third_party_source/sidereon-core-3.0.5/tides/` in wheels and source
|
|
334
|
+
distributions. These files match sidereon-core 3.0.5 at commit da59d0eba8e273cc37821eac5535662e5d991126.
|
|
335
|
+
Source: [sidereon-core tides at the pinned commit](https://github.com/neilberkman/sidereon/tree/da59d0eba8e273cc37821eac5535662e5d991126/crates/sidereon-core/src/tides).
|
|
336
336
|
The authoritative original is available from:
|
|
337
337
|
|
|
338
338
|
<https://iers-conventions.obspm.fr/content/chapter7/software/dehanttideinel/DEHANTTIDEINEL.F>
|
|
@@ -278,11 +278,11 @@ except sidereon.Sp3WriteError as error:
|
|
|
278
278
|
assert data.verify_merge_report(json.loads(persisted_report_json))
|
|
279
279
|
```
|
|
280
280
|
|
|
281
|
-
The
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
281
|
+
The merge path preserves grid-in/grid-out for record values derived from
|
|
282
|
+
on-grid inputs, including means between column values. The file helpers write
|
|
283
|
+
those merged products directly. Other products can still hold higher-precision
|
|
284
|
+
values than the record columns; the strict writer names those with
|
|
285
|
+
`Sp3WriteError`, while the explicit rounding writer reports its SI changes.
|
|
286
286
|
|
|
287
287
|
`report.to_dict()` writes merged-SP3 report schema 3. A merge keeps a
|
|
288
288
|
satellite whose orbit is missing but whose clock reached a consensus as a
|
|
@@ -25,6 +25,7 @@ parsing, rounding or repair of its own.
|
|
|
25
25
|
| `clock_record(satellite, epoch_index)` | `Sp3ClockRecord`: a clock beside a missing orbit |
|
|
26
26
|
| `clock_records_at(epoch_index)` | dict from satellite token to `Sp3ClockRecord` at one epoch, ascending |
|
|
27
27
|
| `to_sp3_string()` | the SP3 text, or `Sp3WriteError` |
|
|
28
|
+
| `to_sp3_string_with_rounding()` | `(text, Sp3RoundingReport)`, or `Sp3WriteError` |
|
|
28
29
|
|
|
29
30
|
`state` and `clock_record` raise `IndexError` for an epoch index past the end
|
|
30
31
|
and `KeyError` when the satellite has no such record at that epoch.
|
|
@@ -86,11 +87,20 @@ back unchanged; it can still be refused on a header base finer than its field,
|
|
|
86
87
|
on header text wider than its columns, or on velocity records under a `P`
|
|
87
88
|
header.
|
|
88
89
|
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
`
|
|
90
|
+
`to_sp3_string_with_rounding()` is an explicit alternative for products whose
|
|
91
|
+
record values need the precision of their SP3 columns. It returns
|
|
92
|
+
`(text, Sp3RoundingReport)`. The immutable report gives maximum absolute changes
|
|
93
|
+
per field in SI units (`position_*_m`, `velocity_*_m_s`, `clock_s`, and
|
|
94
|
+
`clock_rate_s_s`). It applies no rounding to header fields or epochs; refusals
|
|
95
|
+
there still raise `Sp3WriteError`. `data.write_sp3_with_rounding()` writes the
|
|
96
|
+
text atomically and returns `(path, report)`.
|
|
97
|
+
|
|
98
|
+
The merge path preserves grid-in/grid-out for record values derived from
|
|
99
|
+
on-grid inputs, including means between column values. Agreement and dispersion
|
|
100
|
+
metrics are computed from combined values before the final column quantization;
|
|
101
|
+
their arithmetic is unchanged. Other products can still hold record values
|
|
102
|
+
finer than their columns; the strict writer refuses those, and the explicit
|
|
103
|
+
rounding writer can state them while reporting the maximum SI change.
|
|
94
104
|
|
|
95
105
|
### Sp3WriteError
|
|
96
106
|
|
|
@@ -4,7 +4,7 @@ build-backend = "maturin"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "sidereon"
|
|
7
|
-
version = "3.0.
|
|
7
|
+
version = "3.0.5"
|
|
8
8
|
description = "Python (PyO3) bindings over the sidereon engine: SP3 loading and SPP/RTK/PPP positioning solves"
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
license = { text = "MIT" }
|
|
@@ -82,7 +82,7 @@ include = [
|
|
|
82
82
|
"third_party_licenses/ERFA-BSD-3-Clause.txt",
|
|
83
83
|
"third_party_licenses/IERS-CONVENTIONS-SOFTWARE-LICENSE.txt",
|
|
84
84
|
"third_party_licenses/SciPy-BSD-3-Clause.txt",
|
|
85
|
-
"third_party_source/sidereon-core-3.0.
|
|
86
|
-
"third_party_source/sidereon-core-3.0.
|
|
87
|
-
"third_party_source/sidereon-core-3.0.
|
|
85
|
+
"third_party_source/sidereon-core-3.0.5/tides/mod.rs",
|
|
86
|
+
"third_party_source/sidereon-core-3.0.5/tides/ocean.rs",
|
|
87
|
+
"third_party_source/sidereon-core-3.0.5/tides/pole.rs",
|
|
88
88
|
]
|
|
@@ -509,6 +509,8 @@ class Sp3:
|
|
|
509
509
|
def to_sp3_string(self) -> str:
|
|
510
510
|
"""Serialize to SP3 text; raises `Sp3WriteError` rather than change a
|
|
511
511
|
value to fit its columns."""
|
|
512
|
+
def to_sp3_string_with_rounding(self) -> tuple[str, Sp3RoundingReport]:
|
|
513
|
+
"""Write rounded record values and return their maximum SI deltas."""
|
|
512
514
|
def precise_ephemeris_samples(self) -> list[PreciseEphemerisSample]: ...
|
|
513
515
|
def precise_ephemeris_accuracy_samples(
|
|
514
516
|
self,
|
|
@@ -518,6 +520,26 @@ class Sp3:
|
|
|
518
520
|
) -> bytes: ...
|
|
519
521
|
def __repr__(self) -> str: ...
|
|
520
522
|
|
|
523
|
+
class Sp3RoundingReport:
|
|
524
|
+
"""Immutable maximum absolute SI changes made by the SP3 rounding writer."""
|
|
525
|
+
@property
|
|
526
|
+
def position_x_m(self) -> float: ...
|
|
527
|
+
@property
|
|
528
|
+
def position_y_m(self) -> float: ...
|
|
529
|
+
@property
|
|
530
|
+
def position_z_m(self) -> float: ...
|
|
531
|
+
@property
|
|
532
|
+
def velocity_x_m_s(self) -> float: ...
|
|
533
|
+
@property
|
|
534
|
+
def velocity_y_m_s(self) -> float: ...
|
|
535
|
+
@property
|
|
536
|
+
def velocity_z_m_s(self) -> float: ...
|
|
537
|
+
@property
|
|
538
|
+
def clock_s(self) -> float: ...
|
|
539
|
+
@property
|
|
540
|
+
def clock_rate_s_s(self) -> float: ...
|
|
541
|
+
def __repr__(self) -> str: ...
|
|
542
|
+
|
|
521
543
|
class ExactSp3ValidationError(ValueError):
|
|
522
544
|
kind: str | None
|
|
523
545
|
detail: dict[str, object] | None
|
|
@@ -13177,9 +13199,13 @@ class LnavDecoded:
|
|
|
13177
13199
|
@property
|
|
13178
13200
|
def crs(self) -> float: ...
|
|
13179
13201
|
@property
|
|
13180
|
-
def delta_n(self) -> float:
|
|
13202
|
+
def delta_n(self) -> float:
|
|
13203
|
+
"""Mean motion difference, semicircles/second."""
|
|
13204
|
+
...
|
|
13181
13205
|
@property
|
|
13182
|
-
def m0(self) -> float:
|
|
13206
|
+
def m0(self) -> float:
|
|
13207
|
+
"""Mean anomaly at reference time, semicircles."""
|
|
13208
|
+
...
|
|
13183
13209
|
@property
|
|
13184
13210
|
def cuc(self) -> float: ...
|
|
13185
13211
|
@property
|
|
@@ -13197,19 +13223,29 @@ class LnavDecoded:
|
|
|
13197
13223
|
@property
|
|
13198
13224
|
def cic(self) -> float: ...
|
|
13199
13225
|
@property
|
|
13200
|
-
def omega0(self) -> float:
|
|
13226
|
+
def omega0(self) -> float:
|
|
13227
|
+
"""Longitude of ascending node at reference time, semicircles."""
|
|
13228
|
+
...
|
|
13201
13229
|
@property
|
|
13202
13230
|
def cis(self) -> float: ...
|
|
13203
13231
|
@property
|
|
13204
|
-
def i0(self) -> float:
|
|
13232
|
+
def i0(self) -> float:
|
|
13233
|
+
"""Inclination at reference time, semicircles."""
|
|
13234
|
+
...
|
|
13205
13235
|
@property
|
|
13206
13236
|
def crc(self) -> float: ...
|
|
13207
13237
|
@property
|
|
13208
|
-
def omega(self) -> float:
|
|
13238
|
+
def omega(self) -> float:
|
|
13239
|
+
"""Argument of perigee, semicircles."""
|
|
13240
|
+
...
|
|
13209
13241
|
@property
|
|
13210
|
-
def omega_dot(self) -> float:
|
|
13242
|
+
def omega_dot(self) -> float:
|
|
13243
|
+
"""Rate of right ascension, semicircles/second."""
|
|
13244
|
+
...
|
|
13211
13245
|
@property
|
|
13212
|
-
def idot(self) -> float:
|
|
13246
|
+
def idot(self) -> float:
|
|
13247
|
+
"""Rate of inclination, semicircles/second."""
|
|
13248
|
+
...
|
|
13213
13249
|
def __repr__(self) -> str: ...
|
|
13214
13250
|
|
|
13215
13251
|
def lnav_tow(bits: Sequence[int] | bytes) -> int | None: ...
|
|
@@ -284,6 +284,7 @@ __all__ = [
|
|
|
284
284
|
"sp3_merge_input_identity",
|
|
285
285
|
"verify_merge_report",
|
|
286
286
|
"write_sp3",
|
|
287
|
+
"write_sp3_with_rounding",
|
|
287
288
|
"DistributionSource",
|
|
288
289
|
"Distribution",
|
|
289
290
|
"ProductIdentity",
|
|
@@ -5872,9 +5873,10 @@ def write_sp3(sp3: "sidereon.Sp3", path: str, *, gzip: bool = False) -> str:
|
|
|
5872
5873
|
|
|
5873
5874
|
Pass ``gzip=True`` to gzip-compress the output (pair it with a ``.gz``
|
|
5874
5875
|
extension on ``path``). Returns the written path. Raises
|
|
5875
|
-
:class:`sidereon.Sp3WriteError` before anything is written when
|
|
5876
|
-
|
|
5877
|
-
|
|
5876
|
+
:class:`sidereon.Sp3WriteError` before anything is written when a product
|
|
5877
|
+
holds record values finer than SP3 columns; ``detail`` names the value.
|
|
5878
|
+
Merges from column-grid inputs keep records on that grid, including means.
|
|
5879
|
+
Higher-precision inputs can still require :func:`write_sp3_with_rounding`.
|
|
5878
5880
|
"""
|
|
5879
5881
|
data = sp3.to_sp3_string().encode("ascii")
|
|
5880
5882
|
if gzip:
|
|
@@ -5890,6 +5892,29 @@ def write_sp3(sp3: "sidereon.Sp3", path: str, *, gzip: bool = False) -> str:
|
|
|
5890
5892
|
return path
|
|
5891
5893
|
|
|
5892
5894
|
|
|
5895
|
+
def write_sp3_with_rounding(
|
|
5896
|
+
sp3: "sidereon.Sp3", path: str, *, gzip: bool = False
|
|
5897
|
+
) -> tuple[str, "sidereon.Sp3RoundingReport"]:
|
|
5898
|
+
"""Write rounded SP3 record values atomically and return ``(path, report)``.
|
|
5899
|
+
|
|
5900
|
+
Header fields and epochs retain the exact checks of the strict writer. The
|
|
5901
|
+
immutable report gives maximum absolute changes in SI units for each field.
|
|
5902
|
+
"""
|
|
5903
|
+
text, report = sp3.to_sp3_string_with_rounding()
|
|
5904
|
+
data = text.encode("ascii")
|
|
5905
|
+
if gzip:
|
|
5906
|
+
data = _gzip.compress(data)
|
|
5907
|
+
directory = _os.path.dirname(_os.path.abspath(path))
|
|
5908
|
+
_ensure_dir(directory)
|
|
5909
|
+
tmp = _write_temp(directory, data)
|
|
5910
|
+
try:
|
|
5911
|
+
_os.replace(tmp, path)
|
|
5912
|
+
except OSError as exc:
|
|
5913
|
+
_silent_remove(tmp)
|
|
5914
|
+
raise CacheNotWritable(f"cannot write {path}: {exc}") from exc
|
|
5915
|
+
return path, report
|
|
5916
|
+
|
|
5917
|
+
|
|
5893
5918
|
def fetch_merged_sp3_file(
|
|
5894
5919
|
target: Union[_dt.date, _dt.datetime],
|
|
5895
5920
|
centers: Sequence[str],
|
|
@@ -5911,10 +5936,11 @@ def fetch_merged_sp3_file(
|
|
|
5911
5936
|
path by default. Pass ``return_report=True`` to receive ``(path, report)``
|
|
5912
5937
|
and retain the exact contributor provenance and stable input identity.
|
|
5913
5938
|
Nothing is written if the fetch/merge step raises, or if the merged product
|
|
5914
|
-
cannot be written as SP3 text (:class:`sidereon.Sp3WriteError`).
|
|
5915
|
-
|
|
5916
|
-
|
|
5917
|
-
|
|
5939
|
+
cannot be written as SP3 text (:class:`sidereon.Sp3WriteError`). When
|
|
5940
|
+
contributors are on the SP3 column grid, merge results stay on that grid,
|
|
5941
|
+
including means, medians and clock-datum adjustments. Higher-precision
|
|
5942
|
+
contributor values can still require :func:`write_sp3_with_rounding`;
|
|
5943
|
+
``detail`` on a strict-writer exception names the value.
|
|
5918
5944
|
"""
|
|
5919
5945
|
merged, report = fetch_merged_sp3(
|
|
5920
5946
|
target,
|
|
@@ -494,3 +494,6 @@ def fetch_merged_sp3_file(
|
|
|
494
494
|
**fetch_opts: object,
|
|
495
495
|
) -> Union[str, tuple[str, MergeReport]]: ...
|
|
496
496
|
def write_sp3(sp3: sidereon.Sp3, path: str, *, gzip: bool = ...) -> str: ...
|
|
497
|
+
def write_sp3_with_rounding(
|
|
498
|
+
sp3: sidereon.Sp3, path: str, *, gzip: bool = ...
|
|
499
|
+
) -> tuple[str, sidereon.Sp3RoundingReport]: ...
|
|
@@ -13,7 +13,7 @@ import tomllib
|
|
|
13
13
|
ROOT = Path(__file__).resolve().parents[1]
|
|
14
14
|
CORE_GIT_URL = "https://github.com/neilberkman/sidereon"
|
|
15
15
|
FULL_GIT_REVISION = re.compile(r"^[0-9a-f]{40}$")
|
|
16
|
-
CORE_SOURCE_REVISION = "
|
|
16
|
+
CORE_SOURCE_REVISION = "da59d0eba8e273cc37821eac5535662e5d991126"
|
|
17
17
|
|
|
18
18
|
|
|
19
19
|
def registry_version(name, value, package_version):
|
|
@@ -307,7 +307,7 @@ def main() -> None:
|
|
|
307
307
|
"ocean.rs": "25946677944425671a92717860ac2d70f255de5403eeb1fbf98b361716821d5c",
|
|
308
308
|
"pole.rs": "b4cc4c16bdd8ce1d8f04073602ab47dfb85a002b946ab192e8d4d2d600f0a1f8",
|
|
309
309
|
}
|
|
310
|
-
tide_root = ROOT / "third_party_source" / "sidereon-core-3.0.
|
|
310
|
+
tide_root = ROOT / "third_party_source" / "sidereon-core-3.0.5" / "tides"
|
|
311
311
|
for filename, expected_digest in tide_sources.items():
|
|
312
312
|
source = tide_root / filename
|
|
313
313
|
if not source.is_file():
|
|
@@ -316,7 +316,7 @@ def main() -> None:
|
|
|
316
316
|
if digest != expected_digest:
|
|
317
317
|
raise SystemExit(
|
|
318
318
|
f"IERS-derived source disclosure {source} has digest {digest}, "
|
|
319
|
-
f"expected {expected_digest} from sidereon-core 3.0.
|
|
319
|
+
f"expected {expected_digest} from sidereon-core 3.0.5 at "
|
|
320
320
|
f"{CORE_SOURCE_REVISION}"
|
|
321
321
|
)
|
|
322
322
|
|
|
@@ -8,7 +8,7 @@ use std::path::{Path, PathBuf};
|
|
|
8
8
|
|
|
9
9
|
const REGISTRY_SOURCE: &str = "registry+https://github.com/rust-lang/crates.io-index";
|
|
10
10
|
const GIT_SOURCE_PREFIX: &str = "git+https://github.com/neilberkman/sidereon?rev=";
|
|
11
|
-
const RELEASE_VERSION: &str = "3.0.
|
|
11
|
+
const RELEASE_VERSION: &str = "3.0.5";
|
|
12
12
|
|
|
13
13
|
#[derive(Debug)]
|
|
14
14
|
struct LockedPackage {
|
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""Smoke-test public APIs from the installed release artifact."""
|
|
3
|
+
|
|
4
|
+
from __future__ import annotations
|
|
5
|
+
|
|
6
|
+
import math
|
|
7
|
+
import os
|
|
8
|
+
import struct
|
|
9
|
+
|
|
10
|
+
import sidereon
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
def _sp3(text: str):
|
|
14
|
+
return sidereon.load_sp3(text.encode("ascii"))
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
def _check_sp3_grid_merge() -> None:
|
|
18
|
+
first_text = """\
|
|
19
|
+
#cP2020 6 25 0 0 0.00000000 1 ORBIT IGS14 FIT TST
|
|
20
|
+
## 2111 432000.00000000 900.00000000 59025 0.0000000000000
|
|
21
|
+
+ 1 G01 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
|
|
22
|
+
++ 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
|
|
23
|
+
%c G cc GPS ccc cccc cccc cccc cccc ccccc ccccc ccccc ccccc
|
|
24
|
+
%c cc cc ccc ccc cccc cccc cccc cccc ccccc ccccc ccccc ccccc
|
|
25
|
+
%f 1.2500000 1.025000000 0.00000000000 0.000000000000000
|
|
26
|
+
%f 0.0000000 0.000000000 0.00000000000 0.000000000000000
|
|
27
|
+
%i 0 0 0 0 0 0 0 0 0
|
|
28
|
+
%i 0 0 0 0 0 0 0 0 0
|
|
29
|
+
/* RELEASE CONSUMER SP3-C FIXTURE
|
|
30
|
+
* 2020 6 25 0 0 0.00000000
|
|
31
|
+
PG01 15000.000000 -20000.000000 5000.000000 100.000000
|
|
32
|
+
EOF
|
|
33
|
+
"""
|
|
34
|
+
second_text = first_text.replace("15000.000000", "15000.000001")
|
|
35
|
+
merged, _report = sidereon.merge_sp3(
|
|
36
|
+
[_sp3(first_text), _sp3(second_text)],
|
|
37
|
+
sidereon.Sp3MergeOptions(min_agree=1, clock_min_common=1),
|
|
38
|
+
)
|
|
39
|
+
|
|
40
|
+
strict_text = merged.to_sp3_string()
|
|
41
|
+
reread = sidereon.load_sp3(strict_text.encode("ascii"))
|
|
42
|
+
first_x = _sp3(first_text).state("G01", 0).position_m[0]
|
|
43
|
+
second_x = _sp3(second_text).state("G01", 0).position_m[0]
|
|
44
|
+
x_m = reread.state("G01", 0).position_m[0]
|
|
45
|
+
if x_m != merged.state("G01", 0).position_m[0] or x_m not in (first_x, second_x):
|
|
46
|
+
raise SystemExit(
|
|
47
|
+
"strict SP3 merge round-trip did not preserve a parser-scaled grid value"
|
|
48
|
+
)
|
|
49
|
+
|
|
50
|
+
rounded_text, rounding = merged.to_sp3_string_with_rounding()
|
|
51
|
+
if rounded_text != strict_text or rounding.position_x_m != 0.0:
|
|
52
|
+
raise SystemExit(
|
|
53
|
+
"SP3 rounding report disagrees with the writable merged product"
|
|
54
|
+
)
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
def _clock_sp3(clocks_us: list[float]):
|
|
58
|
+
satellites = ["G01", "G02", "G03"]
|
|
59
|
+
satellite_header = "".join(satellites) + " 0" * 14
|
|
60
|
+
records = "\n".join(
|
|
61
|
+
f"P{sat}{15000.0:14.6f}{-20000.0:14.6f}{5000.0:14.6f}{clock:14.6f}"
|
|
62
|
+
for sat, clock in zip(satellites, clocks_us)
|
|
63
|
+
)
|
|
64
|
+
text = f"""\
|
|
65
|
+
#cP2020 6 25 0 0 0.00000000 1 ORBIT IGS14 FIT TST
|
|
66
|
+
## 2111 432000.00000000 900.00000000 59025 0.0000000000000
|
|
67
|
+
+ 3 {satellite_header}
|
|
68
|
+
++ 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
|
|
69
|
+
%c G cc GPS ccc cccc cccc cccc cccc ccccc ccccc ccccc ccccc
|
|
70
|
+
%c cc cc ccc ccc cccc cccc cccc cccc ccccc ccccc ccccc ccccc
|
|
71
|
+
%f 1.2500000 1.025000000 0.00000000000 0.000000000000000
|
|
72
|
+
%f 0.0000000 0.000000000 0.00000000000 0.000000000000000
|
|
73
|
+
%i 0 0 0 0 0 0 0 0 0
|
|
74
|
+
%i 0 0 0 0 0 0 0 0 0
|
|
75
|
+
/* RELEASE CONSUMER SP3 CLOCK FIXTURE
|
|
76
|
+
* 2020 6 25 0 0 0.00000000
|
|
77
|
+
{records}
|
|
78
|
+
EOF
|
|
79
|
+
"""
|
|
80
|
+
return _sp3(text)
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
def _check_sp3_half_grid_clock_merge() -> None:
|
|
84
|
+
first = _clock_sp3([-598.410235, 138.983111, 0.0])
|
|
85
|
+
second = _clock_sp3([-598.410234, 138.983110, 0.0])
|
|
86
|
+
first.to_sp3_string()
|
|
87
|
+
second.to_sp3_string()
|
|
88
|
+
merged, _report = sidereon.merge_sp3(
|
|
89
|
+
[first, second], sidereon.Sp3MergeOptions(min_agree=1, clock_min_common=3)
|
|
90
|
+
)
|
|
91
|
+
|
|
92
|
+
strict_text = merged.to_sp3_string()
|
|
93
|
+
reread = sidereon.load_sp3(strict_text.encode("ascii"))
|
|
94
|
+
for satellite in ("G01", "G02", "G03"):
|
|
95
|
+
left = first.state(satellite, 0).clock_s
|
|
96
|
+
right = second.state(satellite, 0).clock_s
|
|
97
|
+
clock = reread.state(satellite, 0).clock_s
|
|
98
|
+
if clock != merged.state(satellite, 0).clock_s or clock not in (left, right):
|
|
99
|
+
raise SystemExit(f"strict SP3 merge round-trip changed {satellite} clock")
|
|
100
|
+
|
|
101
|
+
rounded_text, report = merged.to_sp3_string_with_rounding()
|
|
102
|
+
if (
|
|
103
|
+
rounded_text != strict_text
|
|
104
|
+
or report.clock_s != 0.0
|
|
105
|
+
or report.clock_rate_s_s != 0.0
|
|
106
|
+
):
|
|
107
|
+
raise SystemExit(
|
|
108
|
+
"SP3 half-grid clock merge did not return a zero rounding report"
|
|
109
|
+
)
|
|
110
|
+
|
|
111
|
+
|
|
112
|
+
def main() -> None:
|
|
113
|
+
expected_version = os.environ.get("SIDEREON_EXPECTED_VERSION")
|
|
114
|
+
if expected_version is not None and sidereon.__version__ != expected_version:
|
|
115
|
+
raise SystemExit(
|
|
116
|
+
f"installed sidereon {sidereon.__version__}, expected {expected_version}"
|
|
117
|
+
)
|
|
118
|
+
|
|
119
|
+
header = struct.pack(">ddddii", -90.0, -180.0, 0.25, 0.25, 721, 1440)
|
|
120
|
+
data = header + struct.pack(">f", 2.5) * (721 * 1440)
|
|
121
|
+
grid = sidereon.GeoidGrid.from_proj_egm96_gtx(data)
|
|
122
|
+
|
|
123
|
+
for arithmetic in (
|
|
124
|
+
sidereon.ProjVgridshiftArithmetic.SEPARATE_MULTIPLY_ADD,
|
|
125
|
+
sidereon.ProjVgridshiftArithmetic.FUSED_MULTIPLY_ADD,
|
|
126
|
+
):
|
|
127
|
+
got = grid.undulation_proj_rad(
|
|
128
|
+
math.radians(40.0), math.radians(-105.0), arithmetic
|
|
129
|
+
)
|
|
130
|
+
if got != 2.5:
|
|
131
|
+
raise SystemExit(f"PROJ EGM96 GTX smoke returned {got}, expected 2.5")
|
|
132
|
+
|
|
133
|
+
try:
|
|
134
|
+
grid.undulation_proj_rad(
|
|
135
|
+
math.nan,
|
|
136
|
+
0.0,
|
|
137
|
+
sidereon.ProjVgridshiftArithmetic.FUSED_MULTIPLY_ADD,
|
|
138
|
+
)
|
|
139
|
+
except sidereon.ProjVgridshiftNonFiniteCoordinateError as error:
|
|
140
|
+
if not isinstance(error, (sidereon.ProjVgridshiftError, ValueError)):
|
|
141
|
+
raise SystemExit(
|
|
142
|
+
"typed PROJ coordinate exception hierarchy is broken"
|
|
143
|
+
) from None
|
|
144
|
+
else:
|
|
145
|
+
raise SystemExit("non-finite PROJ coordinate did not raise")
|
|
146
|
+
|
|
147
|
+
_check_sp3_grid_merge()
|
|
148
|
+
_check_sp3_half_grid_clock_merge()
|
|
149
|
+
|
|
150
|
+
print(f"sidereon {sidereon.__version__} release smoke passed")
|
|
151
|
+
|
|
152
|
+
|
|
153
|
+
if __name__ == "__main__":
|
|
154
|
+
main()
|