Analyze RINEX observation files to compute signal quality scores, detect threats (jamming, spoofing, interference), generate per-constellation statistics, and produce skyplot data. Used in production at Romanian national geodetic network (ROMPOS), precision agriculture, and GNSS security research.
Features
|
🛡️ Threat Detection Jamming · Spoofing · Interference Three independent detectors Visibility-based spoofing (new in 0.3.8) |
📊 Quality Scoring Composite 0–100 score 5 weighted components A–F letter grade |
🌍 6 Constellations GPS · GLONASS · Galileo BeiDou · QZSS · NavIC Per-constellation stats |
|
⚡ Rust Performance < 0.3 s per 24h file Zero Python dependencies ThreadPool-parallel batches |
📡 RINEX Support v2.x / v3.x / v4.x Hatanaka compression SP3 precise orbits |
🔬 Full API JSON export · Timeseries Skyplot data · Anomaly list Desktop GUI script included |
Installation
pip install geoveil-cn0
No Rust toolchain required — pre-built wheels for Linux (x86_64 + ARM/piwheels), Windows, and macOS. Python 3.9–3.12.
Quick Start
from geoveil_cn0 import CN0Analyzer, AnalyzerConfig
config = AnalyzerConfig(
time_bin_seconds=300, # 5-minute bins
anomaly_sensitivity=0.5, # 0.0 = permissive, 1.0 = strict
interference_threshold_db=6.0,
)
analyzer = CN0Analyzer(config)
result = analyzer.analyze("COST00ROU_R_20260408_0100_30S_MO.rnx")
print(f"Quality score : {result.quality_score:.1f} / 100 ({result.quality_grade})")
print(f"Jamming : {'⚠️ DETECTED' if result.jamming_detected else '✅ Clean'}")
print(f"Spoofing : {'⚠️ DETECTED' if result.spoofing_detected else '✅ Clean'}")
print(f"Interference : {'⚠️ DETECTED' if result.interference_detected else '✅ Clean'}")
print(f"Satellites : {result.total_satellites_tracked} tracked")
print(f"Constellations: {', '.join(result.active_constellations)}")
Spoofing: visibility-based detection (new in 0.3.8)
# Requires navigation file for ephemeris comparison
result = analyzer.analyze_with_nav(
"COST00ROU_R_20260408_0100_30S_MO.rnx",
"BRDC00IGS_R_20260408_01D_MN.rnx",
)
if result.has_visibility_prediction:
print(f"Confirmation rate: {result.visibility_confirmation_rate:.0%}")
print(f"Unexpected sats : {result.visibility_mean_unexpected:.1f}")
print(f"Missing sats : {result.visibility_mean_missing:.1f}")
Architecture
flowchart LR
A["RINEX obs\n.rnx/.crx/.gz"] --> C
B["BRDC nav\n.nav/.rnx"] --> C
C["CN0Analyzer\nRust core"] --> D["Quality Score\n0–100"]
C --> E["Threat Flags\nJam/Spoof/Interf"]
C --> F["Visibility\nPrediction"]
C --> G["Timeseries\nCN0 per bin"]
C --> H["Skyplot\nAz/El tracks"]
D & E & F & G & H --> I["AnalysisResult\nJSON / Python API"]
Performance
| File size | Epochs | Satellites | Time |
|---|---|---|---|
| 2.1 MB | 2 880 | 18–24 | 0.18 s |
| 8.4 MB | 11 520 | 22–28 | 0.26 s |
| 31 MB | 43 200 | 24–32 | 0.29 s |
| 100 MB | 86 400 | 28–36 | 0.31 s |
Benchmarked on a single core (Intel i7-1185G7). ThreadPool batch processing scales linearly with core count.
Quality Score Components
The composite quality score (0–100) is computed from five weighted components:
| Component | Weight | Description |
|---|---|---|
| CN0 Quality | 35% | Mean signal strength relative to expected |
| Availability | 25% | Fraction of epochs with sufficient satellites |
| Continuity | 20% | Absence of tracking gaps and cycle slips |
| Stability | 12% | Low variance in per-satellite CN0 |
| Diversity | 8% | Multi-constellation coverage |
Letter grades: A ≥ 90 · B ≥ 80 · C ≥ 70 · D ≥ 60 · F < 60
Threat Detection
| Threat | Algorithm | Default Threshold |
|---|---|---|
| Jamming | Rapid CN0 drop rate | >6 dB in <3 s |
| Spoofing | Unexpected satellite ratio (BRDC ephemeris comparison) | >40% ratio + >8 count + corroboration |
| Interference | Sustained CN0 degradation | >6 dB from baseline |
Spoofing detection requires a navigation file (
analyze_with_nav). The 0.3.8 algorithm compares observed satellites against ephemeris predictions — a high ratio of unexplained observations indicates signal replay attacks.
API Reference
AnalyzerConfig
| Parameter | Type | Default | Description |
|---|---|---|---|
time_bin_seconds |
int |
300 |
Seconds per analysis bin |
min_elevation_deg |
float |
10.0 |
Mask angle in degrees |
anomaly_sensitivity |
float |
0.5 |
Detection sensitivity 0–1 |
interference_threshold_db |
float |
6.0 |
Interference trigger (dB) |
spoofing_unexpected_threshold |
float |
0.4 |
Fraction of unexpected sats |
spoofing_min_unexpected_count |
int |
8 |
Minimum count to flag |
enable_timeseries |
bool |
True |
Output per-bin CN0 data |
enable_skyplot |
bool |
False |
Compute Az/El tracks |
AnalysisResult — key properties
| Property | Type | Description |
|---|---|---|
quality_score |
float |
Composite 0–100 |
quality_grade |
str |
Letter A–F |
jamming_detected |
bool |
Jamming flag |
spoofing_detected |
bool |
Spoofing flag |
interference_detected |
bool |
Interference flag |
has_visibility_prediction |
bool |
Nav file was provided |
visibility_confirmation_rate |
float |
Fraction of predicted sats seen |
visibility_mean_unexpected |
float |
Mean unexpected sats per epoch |
visibility_mean_missing |
float |
Mean missing sats per epoch |
constellation_stats |
dict |
Per-GNSS stats |
timeseries |
list |
Per-bin CN0 data |
anomalies |
list |
Detected anomaly events |
Supported Formats
| Format | Extensions | Notes |
|---|---|---|
| RINEX 2.x | .obs, .??o |
All standard types |
| RINEX 3.x | .rnx, .obs |
Mixed observation files |
| RINEX 4.x | .rnx |
Latest format |
| Hatanaka | .crx, .??d |
Compressed observation |
| Gzip | .gz |
Any RINEX inside |
| ZIP | .zip |
Single-file archives |
Live Demo
batch.geoveil-rinex.eu — the GeoVeil batch dashboard runs this library in production: CN0 quality scoring, threat detection, skyplots and heatmaps for every processed RINEX file, plus advanced multipath sessions (per-code MP RMS, cycle slips, SNR-residual wavelet spectra, Fresnel zones) and long-term trend monitoring on daily 30 s station data.
Batch Processing
For large-scale processing this library is wrapped by the GeoVeil batch system (FastAPI + Celery + MongoDB + MinIO + React dashboard): parallel workers, automatic BRDC ephemeris download, per-session analysis settings, WebSocket progress, and result persistence. See the live demo above. For local scripting, CN0Analyzer is stateless — instantiate one per thread and process files with a ThreadPoolExecutor.
License
PolyForm Noncommercial 1.0.0 with an attribution term — see LICENSE.
Free for research, education, personal and other non-commercial use, provided you credit the author and cite the library (see Citation below). Commercial use requires a separate license — contact miluta.flueras@cartografie.ro.
Citation
@software{geoveil_cn0_2026,
title = {geoveil-cn0: High-performance GNSS signal quality analysis},
author = {Dulea-Flueras, Miluta},
year = {2026},
version = {0.4.0},
url = {https://github.com/miluta7/geoveil-cn0},
}
Metadata
Release files for geoveil-cn0 0.4.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| geoveil_cn0-0.4.0.tar.gz | 153.7 kB | Details |
Built distributions (wheels)
Total release size: 5.7 MB
Release files / geoveil_cn0-0.4.0.tar.gz
| Download URL | geoveil_cn0-0.4.0.tar.gz |
|---|---|
| Size | 153.7 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
a770b8e1000541a82d94c45e2cb55c07e213dfe805a046a7b3987ee22e1dcb11
|
|
BLAKE2b-256 checksum How to use checksums |
10bff3c68f3eb7b5938bb997180bc21fe79d5352fb1adcbd76176048265307bb
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.11.16
|
Release files / geoveil_cn0-0.4.0-cp312-cp312-win_amd64.whl
| Download URL | geoveil_cn0-0.4.0-cp312-cp312-win_amd64.whl |
|---|---|
| Size | 445.4 kB |
| Tags | CPython 3.12 Windows x86-64 |
|
SHA-256 checksum How to use checksums |
8507962890ba21137f715d55184141b004afdb0c87995f29f5cd7f04f6e666c5
|
|
BLAKE2b-256 checksum How to use checksums |
11f1990c96d5d028a2e6e4de90cba2f421847f1b47d710fad4acef00468251fa
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.11.16
|
Release files / geoveil_cn0-0.4.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
| Download URL | geoveil_cn0-0.4.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl |
|---|---|
| Size | 494.9 kB |
| Tags | CPython 3.12 Linux glibc 2.17+ x86-64 |
|
SHA-256 checksum How to use checksums |
f3066519fd0eceb9d7b9b963d99e81518f398ee29cb52c25a82c565c23f74ec3
|
|
BLAKE2b-256 checksum How to use checksums |
db4641dd4a5ba2a0b6cefb59f08ddd5edfe7386966596e851641bf535d1cdb2f
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.11.16
|
Release files / geoveil_cn0-0.4.0-cp312-cp312-macosx_11_0_arm64.whl
| Download URL | geoveil_cn0-0.4.0-cp312-cp312-macosx_11_0_arm64.whl |
|---|---|
| Size | 450.2 kB |
| Tags | CPython 3.12 macOS 11.0+ ARM64 |
|
SHA-256 checksum How to use checksums |
1047e614f46701622790110e30fd04e41a0f371617fde3a02f0c45af4aa86785
|
|
BLAKE2b-256 checksum How to use checksums |
8368ce0c8ba29c2ddc6426455370028349d90e9cb3c55f490649ecb723bdfda5
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.11.16
|
Release files / geoveil_cn0-0.4.0-cp311-cp311-win_amd64.whl
| Download URL | geoveil_cn0-0.4.0-cp311-cp311-win_amd64.whl |
|---|---|
| Size | 444.3 kB |
| Tags | CPython 3.11 Windows x86-64 |
|
SHA-256 checksum How to use checksums |
f3b072c8140f49d0dd9e809c90c24e634a9243fc4ad9876e6346c06dc4fb30d4
|
|
BLAKE2b-256 checksum How to use checksums |
e9bc808f2bc01f08fee8cd51ba2649236342e5e5ef6b7b613d20f9021b6f3b16
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.11.16
|
Release files / geoveil_cn0-0.4.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
| Download URL | geoveil_cn0-0.4.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl |
|---|---|
| Size | 494.3 kB |
| Tags | CPython 3.11 Linux glibc 2.17+ x86-64 |
|
SHA-256 checksum How to use checksums |
a0c2d20ce9166f290fe88d72e53cef224f612af5b287ff88ef3558118972685b
|
|
BLAKE2b-256 checksum How to use checksums |
9c59c512f44ceb7d555a37e16b28636f9af4afea673bff0c48a498c7bb9bb4d6
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.11.16
|
Release files / geoveil_cn0-0.4.0-cp311-cp311-macosx_11_0_arm64.whl
| Download URL | geoveil_cn0-0.4.0-cp311-cp311-macosx_11_0_arm64.whl |
|---|---|
| Size | 451.4 kB |
| Tags | CPython 3.11 macOS 11.0+ ARM64 |
|
SHA-256 checksum How to use checksums |
7f3d8c6272f59fd9ffaa2089b1c57c3b199a6b5351a14da27a36b7a635b475d0
|
|
BLAKE2b-256 checksum How to use checksums |
c0c7159a7bcfebb398730b0f486808c959a4856d006b23d68f558494656eee9f
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.11.16
|
Release files / geoveil_cn0-0.4.0-cp310-cp310-win_amd64.whl
| Download URL | geoveil_cn0-0.4.0-cp310-cp310-win_amd64.whl |
|---|---|
| Size | 444.3 kB |
| Tags | CPython 3.10 Windows x86-64 |
|
SHA-256 checksum How to use checksums |
9ce5d91490269efb26ba5c03e62c1df1fad1765107b91b8fc40c053fd701178f
|
|
BLAKE2b-256 checksum How to use checksums |
a7ce791e44e3b0f78dd279bbd5d8c854e2409340cd8dd000ecd7f173c6ac60c8
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.11.16
|
Release files / geoveil_cn0-0.4.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
| Download URL | geoveil_cn0-0.4.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl |
|---|---|
| Size | 493.9 kB |
| Tags | CPython 3.10 Linux glibc 2.17+ x86-64 |
|
SHA-256 checksum How to use checksums |
b3008816f1d932898729106ff65c4d0b6a691fbcb9c1e414cde64ae4ab6d50b4
|
|
BLAKE2b-256 checksum How to use checksums |
a4e6e77d8d7ee7002f8ef1c730f380a5df16780e0a867f78f91b1dedf4ad9f41
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.11.16
|
Release files / geoveil_cn0-0.4.0-cp310-cp310-macosx_11_0_arm64.whl
| Download URL | geoveil_cn0-0.4.0-cp310-cp310-macosx_11_0_arm64.whl |
|---|---|
| Size | 451.3 kB |
| Tags | CPython 3.10 macOS 11.0+ ARM64 |
|
SHA-256 checksum How to use checksums |
f899baadd7e83824057f3f62b5110e84d137a7df540d6e151fece79087bbb77e
|
|
BLAKE2b-256 checksum How to use checksums |
736aa74054a45e77956718d38aca8400e5d1d1e82745d81849acb2865513e6dc
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.11.16
|
Release files / geoveil_cn0-0.4.0-cp39-cp39-win_amd64.whl
| Download URL | geoveil_cn0-0.4.0-cp39-cp39-win_amd64.whl |
|---|---|
| Size | 444.9 kB |
| Tags | CPython 3.9 Windows x86-64 |
|
SHA-256 checksum How to use checksums |
1dd03b996d8d42534719a59f225e5df36d5289f350eefb221eae349e1792ce6b
|
|
BLAKE2b-256 checksum How to use checksums |
f46d57188dfa3b31ab768edf5c6b6f5987bdeb299968c6bc2c8fdf579d7d4ed9
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.11.16
|
Release files / geoveil_cn0-0.4.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
| Download URL | geoveil_cn0-0.4.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl |
|---|---|
| Size | 494.3 kB |
| Tags | CPython 3.9 Linux glibc 2.17+ x86-64 |
|
SHA-256 checksum How to use checksums |
038439397384995c66218eb8fbf98f299a66452811cf43e2fbda48ebee602a47
|
|
BLAKE2b-256 checksum How to use checksums |
c01c7e85d0be6088a989c9bd29896493512eafb963c23a202e2fa3139669d9dd
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.11.16
|
Release files / geoveil_cn0-0.4.0-cp39-cp39-macosx_11_0_arm64.whl
| Download URL | geoveil_cn0-0.4.0-cp39-cp39-macosx_11_0_arm64.whl |
|---|---|
| Size | 451.6 kB |
| Tags | CPython 3.9 macOS 11.0+ ARM64 |
|
SHA-256 checksum How to use checksums |
c0d9df24c4e2f864db549db347a31a3684b1a35d8b8c4da961cb1912e34bb0a3
|
|
BLAKE2b-256 checksum How to use checksums |
8b49ff141e91d0840aeceb840da6003288b51192f46bad8a6a66b8cc8ce5cc12
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.11.16
|