Coordinate Converter
Convert Earth-centered (ECEF) X/Y/Z coordinates and CCSDS OEM orbit files to WGS84 latitude, longitude, and altitude. Includes a desktop app and a command-line tool, and handles files with millions of points.
Features
- Accurate at any altitude: within a micrometer from the surface out past GEO.
- CSV input: any CSV with X, Y, Z columns in meters. Your other columns are kept exactly as they were.
- CCSDS OEM input: text (KVN) orbit files in Earth-fixed or space-fixed frames. Space-fixed positions are rotated to Earth-fixed at each epoch.
- Epoch output as written in the file, as Gregorian calendar dates, or as Modified Julian Dates.
- Comma or space separated output.
- NAIRAS trajectory export: OEM files can be saved in the exact trajectory format used by NASA's NAIRAS radiation model on CCMC Runs-on-Request.
- Large files: processed in chunks, so memory stays flat. Tested on a 1 GB, 20 million row CSV.
- Safe writes: a failed or stopped run never leaves a half-written output file.
- Signed updates: the app installs only published releases, and checks every file against SHA-256 checksums signed with the maintainer's offline key.
Standalone apps for Windows, macOS, and Linux are planned. See the roadmap for what's coming next.
Install
Option 1: pip (recommended)
Requires Python 3.11 or newer.
pip install orbit-converter
This installs the dependencies and two commands:
coordinate-converteropens the desktop appxyz-to-llaruns the command-line tool
To update:
pip install --upgrade orbit-converter
Installed with pip before version 1.4.0? That copy was registered under an older name, so switch over once:
pip uninstall coordinate-converter orbit-converter
pip install orbit-converter
Option 2: download the zip
- Click Code > Download ZIP and unzip it.
- Install the dependencies:
pip install -r requirements.txt - Run the app:
python converter_gui.py
To update, click Check for updates in the app. It installs the latest release and checks each file against its checksum before replacing anything.
Desktop app
- Choose an input file (
.csv,.oem, or.txt). - Pick the options:
- OEM files: epoch format, and fast mode for space-fixed frames
- CSV files: the names of your X, Y, and Z columns
- Output: comma separated, space separated, or NAIRAS trajectory, and whether to include column names
- Choose where to save and click Convert.
Command line
# CSV
xyz-to-lla input.csv output.csv
xyz-to-lla input.csv output.csv --x X --y Y --z Z
# OEM
xyz-to-lla orbit.oem output.csv
xyz-to-lla orbit.oem output.csv --time-format mjd
xyz-to-lla orbit.oem output.csv --fast
xyz-to-lla orbit.txt output.csv --format oem
# Space separated, no header line
xyz-to-lla orbit.oem output.txt --separator space --no-header
# NAIRAS trajectory, one point per minute
xyz-to-lla orbit.oem trajectory_1.txt --nairas --step 60
If you downloaded the zip, use python xyz_to_lla.py in place of xyz-to-lla.
| Option | What it does |
|---|---|
--format auto|csv|oem |
Input type. auto treats .oem files as OEM and everything else as CSV. |
--x, --y, --z |
CSV column names (default x, y, z). |
--time-format original|gregorian|mjd |
How OEM epochs are written. |
--fast |
Faster rotation for space-fixed OEM frames, within 0.05 mm of exact. |
--separator comma|space |
Output column separator. |
--no-header |
Leave out the column names line (or the # comment lines with --nairas). |
--nairas |
OEM only: write a NAIRAS trajectory file. |
--step SECONDS |
With --nairas: keep one point per this many seconds (default 0 keeps all). |
--chunksize N |
Rows processed at a time. |
--version |
Show the version. |
Output
CSV input: your original columns, plus lat, lon, alt.
OEM input: object, epoch, time_system, x_ecef_m, y_ecef_m, z_ecef_m, lat, lon, alt
Latitude and longitude are in degrees. Altitude is meters above the WGS84 ellipsoid. In space separated output, empty values are written as NaN and text containing spaces is put in quotes.
Supported OEM files
| Field | Supported |
|---|---|
| Format | Text (KVN). XML is not supported. |
CENTER_NAME |
EARTH |
REF_FRAME |
Earth-fixed: ITRF*, EFG, ECEF. Space-fixed: EME2000/J2000, GCRF, ICRF, TEME. |
TIME_SYSTEM |
UTC, TAI, TT, TDB, TCG, TCB, UT1, GPS |
| Epochs | 2026-10-19T12:00:00.000 or day-of-year 2026-292T12:00:00.000 |
Covariance blocks are skipped. Space-fixed frames use astropy and IERS Earth orientation data, which it downloads when online.
NAIRAS trajectories (CCMC Runs-on-Request)
Choose NAIRAS trajectory in the app, or use --nairas. The output matches the trajectory input files NASA published with the RaD-X flight data, checked byte for byte against their balloon flight file:
# year(yyyy),month(mm),day(dd),hour(hh),min(mm),sec(fractional second),alt(km),lat(deg),lon(deg)
2015 9 25 17 6 6.000 1.394765 34.490002 255.783325
- Space separated, with
#comment lines at the top - Date and time in UTC (TAI, TT, GPS and other OEM time systems are converted)
- Altitude in km, before latitude
- Longitude from 0 to 360 degrees east
- One vehicle per file, with times in order
Notes:
- NASA's sample files use one point per minute. Long, high-rate OEM files can produce very large trajectories, so
--step 60(or the "Keep one point every" box) is a good starting point. - Altitude is height above the WGS84 ellipsoid. NASA's aircraft and balloon files use barometric altitude, which can differ by tens of meters. For spacecraft this makes no practical difference.
- The CCMC uploader checks file names: use only letters, numbers, and underscores (like
trajectory_1.txt) and keep the file in a folder with no spaces in its path. The app suggests a safe name for you.
Use in your own code
from xyz_to_lla import xyz_to_lla
lat, lon, alt = xyz_to_lla(x_array, y_array, z_array)
Running the tests
pip install ".[test]"
pytest
The tests cover the conversion math, CSV and OEM input, every output option, the NAIRAS format (checked byte for byte against an excerpt of NASA's RaD-X trajectory file in tests/data), safe writes, and the updater. The desktop app tests need a screen, so they only run when RUN_GUI_TESTS=1 is set.
GitHub Actions runs everything on Linux, macOS, and Windows on every push. The badge at the top shows the latest result.
Publishing an update (maintainer notes)
- Create a branch for the change, for example
v1.4.0. - Make the changes on that branch, raise
__version__inxyz_to_lla.py, and add a section toCHANGELOG.md. - Open a pull request into
mainand wait for the tests to pass. - Merge the pull request.
- Go to Releases > Draft a new release, create a tag named after the version (like
v1.4.0) onmain, paste the changelog section, and publish. - The release workflow checks the tag, signs the files with Sigstore, attaches
SHA256SUMSand the packages, and publishes to PyPI. Wait for a green check on the Actions tab. - On your own computer, sign the release with your offline key:
It checks thatscripts/sign_release.sh v1.4.0SHA256SUMSmatches the files at the tag before signing. Attach theSHA256SUMS.minisigit makes to the release (Edit release, drag the file in, Update release).
The app's update button won't install a release until both SHA256SUMS and SHA256SUMS.minisig are attached. Code merged into main without a release is never sent to users.
Metadata
Release files for orbit-converter 1.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 | Provenance | Actions |
|---|---|---|---|---|
| orbit_converter-1.4.0.tar.gz | 48.8 kB | With provenance | Details for orbit_converter-1.4.0.tar.gz |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Actions Reset |
|---|---|---|---|---|
| orbit_converter-1.4.0-py3-none-any.whl | Python 3 | none | any | Details for orbit_converter-1.4.0-py3-none-any.whl |
Total release size: 80.1 kB
Release files / orbit_converter-1.4.0.tar.gz
| Download URL | orbit_converter-1.4.0.tar.gz |
|---|---|
| Size | 48.8 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
e4b4914cad373a84aa39408939bd00c6ac8744c78db22f38270b9c7729060b97
|
|
BLAKE2b-256 checksum How to use checksums |
f4007b06600b8679fb959bae81faae7c0ea53426f16d063bb5866b3f9702a093
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.16
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Nov 5, 2026.
Transparency logRelease files / orbit_converter-1.4.0-py3-none-any.whl
| Download URL | orbit_converter-1.4.0-py3-none-any.whl |
|---|---|
| Size | 31.3 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
5298bb11ab6a11c3b0348990c82a4509523305b774f5a475fc527844e9c29dce
|
|
BLAKE2b-256 checksum How to use checksums |
d0636e3a50a87b6ad9bb7253c92e566bdf07807feff9d6543364814ad9f674ad
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.16
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Nov 5, 2026.
Transparency logSecurity for orbit-converter 1.4.0
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
Full provenance
Both files in this release have been uploaded with provenance metadata.
Attestation for orbit_converter-1.4.0.tar.gz
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Nov 5, 2026.
Transparency logA note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.