Parsing IGS Sitelog files (supports version 2+3)
Project description
SitelogParser
A Python library and command-line tool for parsing, validating, and exporting IGS (International GNSS Service) sitelog files. SitelogParser converts sitelog text files into structured Python dataclasses, enables programmatic manipulation of sitelog data, and exports them back to the IGS sitelog v2.0 format.
Features
- Parse IGS sitelog files into type-safe Python dataclasses
- Export sitelog data back to IGS sitelog v2.0 format with automatic metadata updates
- Generate Bernese files (.sta) from sitelog data with equipment history and time ranges
- Generate SINEX files (.snx) in SINEX 2.02 format with coordinates and eccentricity data
- Generate coordinate files (.crd) with ECEF coordinates in multiple reference frames
- Merge multiple sitelogs into single station information, SINEX, or coordinate files
- Command-line interface for validation, listing, preparing, and generating files
- Type hints throughout for better IDE support and type checking
- Automatic form metadata computation (latest modification dates and changed sections)
- Timestamp handling with UTC timezone support
- Glob pattern support for batch file processing
Installation
pip install sitelogparser
For development:
git clone <repository-url>
cd SitelogParser
pip install -e .
Command-Line Usage
The slp command provides several operations:
Validate a sitelog file
slp validate tests/AMST_20190705.txt
Output:
✓ Valid sitelog: tests/AMST_20190705.txt
📊 Statistics:
Site: Amsterdam, Netherlands (AMST)
DOMES: 13502M001
Location: Amsterdam, Netherlands
Receivers: 20
Antennas: 6
Last Modified: 2018-11-28
Modified Sections: 3.19, 3.20
List receivers, antennas, or metadata
# List all receivers
slp list tests/AMST_20190705.txt --type receivers
# List all antennas
slp list tests/AMST_20190705.txt --type antennas
# Show site metadata
slp list tests/AMST_20190705.txt --type metadata
# Show everything (default)
slp list tests/AMST_20190705.txt
Example output (receivers):
📡 GNSS Receivers:
# Type Serial Installed Removed
-------------------------------------------------------------------------------------
1 TRIMBLE NETRS 4439239154 2005-04-13T12:00Z 2005-12-15T10:00Z
2 TRIMBLE NETRS 4439239154 2005-12-15T10:00Z 2010-03-15T08:30Z
3 LEICA GRX1200+GNSS 495553 2010-03-15T08:30Z 2010-09-06T08:35Z
4 LEICA GRX1200+GNSS 495553 2010-09-06T08:35Z 2010-10-28T11:40Z
5 LEICA GRX1200+GNSS 495553 2010-10-28T11:50Z 2010-11-15T10:30Z
6 LEICA GRX1200+GNSS 495553 2010-11-15T10:30Z 2011-01-20T07:40Z
7 LEICA GRX1200+GNSS 495553 2011-01-20T07:50Z 2011-06-01T07:50Z
8 LEICA GRX1200+GNSS 495553 2011-06-01T07:50Z 2011-08-31T05:30Z
9 TRIMBLE NETR9 5106K73572 2011-08-31T05:30Z 2011-09-13T11:00Z
10 LEICA GRX1200+GNSS 495553 2011-09-13T11:00Z 2011-11-18T14:00Z
11 TPS GB-1000 8RXJKJ48V7K 2011-11-18T14:00Z 2012-08-22T07:30Z
12 TPS NET-G3A 618-00899 2012-08-22T07:30Z 2012-09-19T15:25Z
13 TPS NET-G3A 618-00899 2012-09-19T15:25Z 2013-10-31T15:23Z
14 TPS NET-G3A 618-00899 2013-10-31T15:34Z 2014-05-23T12:08Z
15 TPS NET-G3A 618-00899 2014-05-23T12:25Z 2017-03-17T13:12Z
16 LEICA GR30 1705298 2017-03-17T13:13Z 2017-10-10T05:17Z
17 TPS NET-G3A 618-00899 2017-10-10T06:07Z 2017-11-17T13:11Z
18 LEICA GR30 1705298 2017-11-17T14:24Z 2018-06-21T06:02Z
19 LEICA GR30 1705298 2018-06-21T06:04Z 2018-11-28T07:23Z
20 LEICA GR30 1705298 2018-11-28T07:25Z (CCYY-MM-DDThh:mmZ)
Example output (antennas):
📶 GNSS Antennas:
# Type Serial Installed Removed
-------------------------------------------------------------------------------------
1 TRM41249.00 TZGD 12696814 2005-04-13T12:00Z 2010-03-15T08:30Z
2 LEIAR25.R3 LEIT 09480032 2010-03-15T08:30Z 2011-08-31T05:30Z
3 TRM57971.00 TZGD 1441101374 2011-08-31T05:30Z 2011-09-13T11:00Z
4 LEIAR25.R3 LEIT 09470019 2011-09-13T11:00Z 2012-08-22T07:30Z
5 TPSCR.G3 TPSH 383-2172 2012-08-22T07:30Z 2017-10-10T06:07Z
6 LEIAR25.R4 LEIT 726448 2017-10-10T06:07Z (CCYY-MM-DDThh:mmZ)
Example output (metadata):
📋 Site Metadata:
Site Name: Amsterdam, Netherlands
Four Character ID: AMST
DOMES Number: 13502M001
Location: Amsterdam, Netherlands
Coordinates:
Latitude: +52.3712800855
Longitude: +4.8563185513
Elevation: 1.0 m
On-Site Agency: Technische Universiteit Delft
Responsible Agency: Technische Universiteit Delft
Prepare/export a sitelog file
# Read and export with auto-generated filename
slp prepare tests/AMST_20190705.txt
# Specify output file
slp prepare tests/AMST_20190705.txt -o output/AMST_prepared.log
Output:
✓ Parsed sitelog: tests/AMST_20190705.txt
✓ Exported to: output/AMST_prepared.log
The prepared file will be in IGS sitelog v2.0 format with:
- Automatically updated form metadata (date prepared, modified sections)
- Normalized formatting and field alignment
- UTC timestamps in
CCYY-MM-DDThh:mmZformat
Generate Bernese station information file (.sta)
Generate a Bernese GNSS Software 5.2 compatible station information file from one or more sitelogs:
# Generate from single file
slp generate_sta tests/AMST_20190705.txt
# Generate from multiple files (glob pattern)
slp generate_sta tests/testlogs/*.log -o stations.sta
# Generate from directory (finds all .txt and .log files)
slp generate_sta tests/testlogs/
# Custom output file
slp generate_sta tests/AMST_20190705.txt -o output/AMST.sta
Features:
- Combines multiple sitelogs into a single station file
- TYPE 001: Station renaming entries
- TYPE 002: Combined receiver and antenna entries (overlapping time periods)
- TYPE 003: Receiver equipment history
- TYPE 004: Antenna equipment history
- Automatic serial number replacement with "999999"
- Time range overlap resolution (prevents overlapping periods)
Output example:
✓ Loaded: AMST_20190705.log (AMST)
✓ Generated Bernese station information file (.sta)
Output: amst.sta
Stations: 1
Lines: 85
Size: 5234 bytes
📋 Included stations:
- AMST (11048M001): 20 RX, 6 ANT
Generate SINEX file (.snx)
Generate a SINEX 2.02 (Solution Independent Exchange) format file from one or more sitelogs:
# Generate from single file
slp generate_snx tests/AMST_20190705.txt
# Generate from multiple files (glob pattern)
slp generate_snx tests/testlogs/*.log -o stations.snx
# Generate from directory (finds all .txt and .log files)
slp generate_snx tests/testlogs/
# Custom output file
slp generate_snx tests/AMST_20190705.txt -o output/AMST.snx
Features:
- Combines multiple sitelogs into a single SINEX file
- +FILE/REFERENCE: File metadata and contact information
- +SITE/ID: Station identification with coordinates
- +SITE/RECEIVER: Receiver equipment history with time periods
- +SITE/ANTENNA: Antenna equipment history with time periods
- +SITE/ECCENTRICITY: Antenna offset information (Up, North, East)
- +SOLUTION/ESTIMATE: ECEF coordinates (X, Y, Z) for each station
- Automatic serial number replacement with "99999"
- Time range overlap resolution (prevents overlapping periods)
Output example:
✓ Loaded: AMST_20190705.log (AMST)
✓ Generated SINEX file (.snx)
Output: amst.snx
Stations: 1
Lines: 68
Size: 4334 bytes
📋 Included stations:
- AMST (11048M001): 20 RX, 6 ANT
Generate Bernese coordinate file (.crd)
Generate a Bernese GNSS Software coordinate list file from one or more sitelogs:
# Generate from single file with default ETRS89 frame
slp generate_crd tests/AMST_20190705.txt
# Generate with specific coordinate frame
slp generate_crd tests/AMST_20190705.txt --frame IGS20
# Generate from multiple files (glob pattern)
slp generate_crd tests/testlogs/*.log -o stations.crd
# Generate from directory (finds all .txt and .log files)
slp generate_crd tests/testlogs/
# Custom output file with coordinate frame
slp generate_crd tests/AMST_20190705.txt -o output/AMST.crd --frame ITRF2020
Features:
- Combines multiple sitelogs into a single coordinate file
- ECEF coordinates (X, Y, Z) in meters with 5 decimal precision
- Supports multiple coordinate frames: ETRS89 (default), IGS20, IGS14, ITRF2020, etc.
- Auto-determines datum name from coordinate frame
- Stations sorted alphabetically by four-character ID
- Skips stations with zero coordinates
- Includes station names and DOMES numbers
Output example:
✓ Loaded: AMST_20190705.log (AMST)
✓ Generated Bernese coordinate file (.crd)
Output: amst.crd
Frame: ETRS89
Stations: 1
Lines: 8
Size: 392 bytes
📋 Included stations:
- AMST (13502M001)
Generated file format:
ETRS89: coordinate list 23-JAN-26 07:50
--------------------------------------------------------------------------------
LOCAL GEODETIC DATUM: ETRS89 EPOCH: 2005-04-13 12:00:00
NUM STATION NAME X (M) Y (M) Z (M) FLAG SYSTEM
1 AMST 13502M001 3799725.65441 901944.13241 5028762.14325 ETRS89
Show version
slp --version
slp --version
API Usage
Basic Parsing
from sitelogparser.common.sitelog import SiteLogParser
# Parse a sitelog file
parser = SiteLogParser(sitelog_file="path/to/sitelog.txt")
sitelog = parser.sitelog
# Access site information
print(f"Site: {sitelog.site_identification.site_name}")
print(f"Four-char ID: {sitelog.site_identification.four_character_id}")
print(f"DOMES: {sitelog.site_identification.iers_domes_number}")
# Access location data
location = sitelog.site_location
print(f"Location: {location.city}, {location.country}")
print(f"Coordinates: {location.latitude}, {location.longitude}")
# Iterate over receivers
for receiver in sitelog.gnss_receivers:
print(f"Receiver {receiver.number}: {receiver.receiver_type}")
print(f" Serial: {receiver.serial_number}")
print(f" Firmware: {receiver.firmware_version}")
# Iterate over antennas
for antenna in sitelog.gnss_antennas:
print(f"Antenna {antenna.number}: {antenna.antenna_type}")
print(f" Serial: {antenna.serial_number}")
print(f" Radome: {antenna.antenna_radome_type}")
# Access agency information
print(f"On-site agency: {sitelog.on_site_agency.name}")
print(f"Primary contact: {sitelog.on_site_agency.primary_contact.name}")
print(f"Email: {sitelog.on_site_agency.primary_contact.email}")
Exporting Sitelog Data
from sitelogparser.common.sitelog import SiteLogParser
# Parse existing sitelog
parser = SiteLogParser(sitelog_file="input.txt")
# Modify data programmatically
parser.sitelog.site_identification.site_name = "Updated Site Name"
# Export to new file (automatically updates form metadata)
output_text = parser.export_sitelog()
with open("output.txt", "w") as f:
f.write(output_text)
Creating a New Sitelog
from sitelogparser.common.models import (
Sitelog, FormInformation, SiteIdentification, SiteLocation,
GNSSReceiver, GNSSAntenna, Agency, Contact
)
from sitelogparser.common.sitelog import SiteLogParser
from datetime import datetime, timezone
# Create sitelog structure
sitelog = Sitelog()
# Fill form information
sitelog.form_information = FormInformation(
prepared_by="John Doe",
report_type="NEW"
)
# Fill site identification
sitelog.site_identification = SiteIdentification(
site_name="Example Site",
four_character_id="EXMP",
iers_domes_number="12345M001",
date_installed=datetime(2025, 1, 1, tzinfo=timezone.utc).timestamp()
)
# Fill location
sitelog.site_location = SiteLocation(
city="Example City",
country="Example Country",
latitude="+12.3456789012",
longitude="+123.4567890123",
elevation="100.0"
)
# Add receivers
receiver = GNSSReceiver(
number=1,
receiver_type="EXAMPLE RECEIVER",
satellite_system="GPS",
serial_number="12345",
firmware_version="1.0.0",
elevation_cutoff_setting="0",
date_installed=datetime(2025, 1, 1, tzinfo=timezone.utc).timestamp(),
date_removed=0.0, # 0.0 means not removed yet
temperature_stabilization="none"
)
sitelog.gnss_receivers.append(receiver)
# Add antennas
antenna = GNSSAntenna(
number=1,
antenna_type="EXAMPLE ANTENNA",
serial_number="ANT123",
antenna_reference_point="BPA",
marker_arp_up_ecc="0.0000",
marker_arp_north_ecc="0.0000",
marker_arp_east_ecc="0.0000",
alignment_of_true_n="0",
antenna_radome_type="NONE",
radome_serial_number="",
antenna_cable_type="",
antenna_cable_length="",
date_installed=datetime(2025, 1, 1, tzinfo=timezone.utc).timestamp(),
date_removed=0.0
)
sitelog.gnss_antennas.append(antenna)
# Add agency information
sitelog.on_site_agency = Agency(
section="11",
name="Example Organization",
abbreviation="EXORG",
mail_address="123 Example St, Example City, Country",
primary_contact=Contact(
name="Jane Doe",
phone1="+1-555-0100",
email="jane.doe@example.org"
)
)
# Export to sitelog format
parser = SiteLogParser(sitelog_text="")
parser.sitelog = sitelog
output_text = parser.export_sitelog()
with open("new_sitelog.txt", "w") as f:
f.write(output_text)
Working with Timestamps
Dates in the dataclasses are stored as float timestamps (seconds since Unix epoch):
from datetime import datetime, timezone
# Convert datetime to timestamp (for setting dates)
dt = datetime(2025, 1, 15, 12, 30, tzinfo=timezone.utc)
timestamp = dt.timestamp()
receiver.date_installed = timestamp
# Convert timestamp to datetime (for reading dates)
from sitelogparser.common.sitelog import SiteLogParser
parser = SiteLogParser(sitelog_file="sitelog.txt")
receiver = parser.sitelog.gnss_receivers[0]
if receiver.date_installed > 0:
dt = datetime.fromtimestamp(receiver.date_installed, tz=timezone.utc)
print(f"Installed: {dt.strftime('%Y-%m-%d %H:%M:%S %Z')}")
# Dates are exported in IGS format: CCYY-MM-DDThh:mmZ
# Empty dates (0.0) are shown as: (CCYY-MM-DDThh:mmZ)
Data Models
The library uses Python dataclasses for type-safe data representation:
Sitelog: Top-level container for all sitelog dataFormInformation: Section 0 - Form metadataSiteIdentification: Section 1 - Site identificationSiteLocation: Section 2 - Site location informationGNSSReceiver: Section 3.x - Individual receiver configurationGNSSAntenna: Section 4.x - Individual antenna configurationAgency: Sections 11-12 - Agency information with contactsContact: Contact person information
All dataclasses have full type hints and can be converted to dictionaries using the to_dict() method.
Requirements
- Python >= 3.8
- No external dependencies (uses only Python standard library)
Development
Run tests:
python -m unittest discover tests/ -v
Run specific test:
python -m unittest tests.test_parser
python -m unittest tests.test_generate
License
See LICENSE.txt for details.
Contributing
Contributions are welcome! Please ensure all tests pass before submitting pull requests.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file sitelogparser-1.2.0.tar.gz.
File metadata
- Download URL: sitelogparser-1.2.0.tar.gz
- Upload date:
- Size: 93.2 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.13.9
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
48ab61efa9bdcc74ca7f79aef9f22280539ed9ae1e2318f4a8d4f5df920de8fd
|
|
| MD5 |
0e3dbb18f5ddd6a26ca421d0f85a6126
|
|
| BLAKE2b-256 |
cb17ee5f6810c49d6a55ceddb236051cf4ddd8f138a8481bb1e68bd043a89266
|
File details
Details for the file sitelogparser-1.2.0-py2.py3-none-any.whl.
File metadata
- Download URL: sitelogparser-1.2.0-py2.py3-none-any.whl
- Upload date:
- Size: 68.3 kB
- Tags: Python 2, Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.13.9
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
1a29b93c0d2ca130fc7efbfb8219163a3ac02e6dbdc388471d730c273652ec0f
|
|
| MD5 |
7629c123aa8ec2799f14f2e2479a54f0
|
|
| BLAKE2b-256 |
29bfa567040a9b5530f0d7850883c8477dc2b8940906a834986806b0b2882442
|