This tool compares TinyGS receptions from a newly deployed CubeSat against a list of candidate NORAD objects. It was built for HUCSat, but the mission details and input files live in configuration, so the same workflow can be reused for another satellite without changing the Python code.
The included HUCSat example is self-contained and runs offline. It compares NORAD IDs 69794–69799 using 221 receptions from 96 TinyGS stations.
Python 3.11 or newer is required.
python -m venv .venv
.venv\Scripts\python.exe -m pip install -e ".[dev]"
.venv\Scripts\cubesat-correlate.exe run --config examples/hucsat/config.yamlResults are written to examples/hucsat/output/.
Each candidate receives a correlation_support_percent. This is the percentage of
contact-arc bootstrap runs won by that candidate. The values always add up to 100% across
the configured candidate list.
This number is best read as relative support, not as an absolute probability that a NORAD object is the satellite. A strong claim also needs to hold up under the separate visibility, Doppler, leave-one-contact-arc, paired-loss, and sensitivity checks. The final status is therefore either:
CLAIM_SUPPORTED: every configured check passed.INCONCLUSIVE: the current evidence is not strong enough to make a claim.
The workflow:
- Validates the TinyGS observations and removes configured CRC failures.
- Checks TLE integrity and confirms that every candidate has orbit data.
- Propagates each candidate with SGP4 at every reception time.
- Recomputes station-relative elevation and Doppler instead of using TinyGS-derived satellite geometry.
- Scores visibility and station-centered carrier-shift agreement.
- Tests the result with contact-arc bootstrapping, leave-one-arc-out runs, and several model sensitivities.
Only positive receptions are used. A missing packet is not treated as evidence because receiver availability and the satellite transmit schedule are not known well enough.
The HUCSat example contains:
examples/hucsat/config.yaml— mission settings, candidate IDs, thresholds, and paths.examples/hucsat/data/tinygs_observations.csv— the reception fields used by the analysis.examples/hucsat/data/candidate_orbits.json— candidate TLEs and source metadata.
The orbit records come from Space-Track, and the reception data comes from TinyGS. The bundled TLEs postdate some receptions, so this should be understood as a retrospective correlation.
Each run creates:
correlation_summary.json— the decision, candidate support percentages, checks, and evidence counts.candidate_scores.csv— the full candidate ranking and component scores.sensitivity_results.csv— results under alternate assumptions.provenance.json— input hashes, source information, and dependency versions.SHA256SUMS.txt— hashes for the generated package.candidate_evidence.png— support, visibility, and Doppler comparison.doppler_fit.png— winner versus runner-up Doppler agreement.robustness.png— bootstrap, leave-one-arc, and sensitivity results.
Large intermediate geometry and resampling tables are not written to disk. They can be reproduced from the committed inputs if needed.
The example does not need network access, but its Space-Track records can be refreshed:
$env:SPACETRACK_IDENTITY = "account-email"
$env:SPACETRACK_PASSWORD = "account-password"
.venv\Scripts\cubesat-correlate.exe refresh-orbits --config examples/hucsat/config.yamlCredentials are read from the environment and are never written to the repository or generated output.
Copy examples/hucsat/ to a new folder under examples/, replace the two files in its
data/ directory, and update the copied config.yaml. All configured paths must stay
relative to that example directory.
The TinyGS CSV should use the same header as the HUCSat file. Each orbit record needs a NORAD ID, object name, UTC epoch, and two TLE lines.
.venv\Scripts\python.exe -m pytest
.venv\Scripts\python.exe -m ruff check .The tests use the bundled HUCSat data and do not require Space-Track credentials.
- TLEs are mean orbital elements, not precision ephemerides.
- TinyGS receiver clocks and frequency calibration vary between stations.
- Receiver altitude is assumed to be zero because it is not in the compact input.
- The result only compares the candidates listed in the configuration.
- This analysis supports a correlation request; Space-Track makes the official catalog determination.
When sharing a claim, include the configuration, input data, generated output, deployment details, radio information, and any independent observations.