RINEX v2.11 parsing¶
Rnxv2Obs reads RINEX 2.11 observation files into the same (epoch × sid) Dataset that Rnxv3Obs produces. Every rule on this page cites that specification.
from pathlib import Path
from canvod.readers import Rnxv2Obs
ds = Rnxv2Obs(fpath=Path("p0481660.08o")).to_ds(keep_data_vars=["SNR", "Phase"])
One data structure: RINEX 3 signal IDs¶
canvodpy has one signal axis for every input format: SV|BAND|CODE, with bands and tracking codes in RINEX 3 nomenclature. A RINEX 3 observation code names the signal completely: L2W is the phase of the L2 P-code tracked by Z-tracking or a similar technique under antispoofing (RINEX 3.04 Table 4), L2L the phase of the L2C pilot channel. Two signals with different codes are different measurements, and canvodpy keeps them apart until an analysis explicitly aggregates them.
RINEX 2 cannot express that. Its observation codes are one letter for the observable and one digit for the frequency (L2, P2, C1, S1). RINEX 2.11 Table A1 defines only two pseudorange families:
| RINEX 2 code | Defined as (Table A1) |
|---|---|
C1 |
GPS C/A · GLONASS C/A · Galileo "All" |
C2 |
GPS C/A or L2C (Table A1 does not distinguish them) |
P1, P2 |
GPS / GLONASS P code |
Lx, Dx, Sx |
carrier phase, Doppler, signal strength on frequency x, no code |
and section 10.1.1 states that the two-character code cannot express the underlying code (P, Y, M in GPS) or the channel (for example I/Q in L5, the GPS L2C channels). Table A1 adds that observations collected under antispoofing are stored as "L2" or "P2," so the tracking technique is not recorded either. Phase, Doppler, and signal strength carry no code information at all.
Mapping RINEX 3 down to RINEX 2 would throw that information away for every modern file. canvodpy therefore lifts RINEX 2 up into the RINEX 3 structure, and fills in only what RINEX 2 itself defines.
Lowercase tracking-code markers¶
Where RINEX 2 leaves the code unresolved, the reader writes a lowercase marker in the code position:
| Marker | Meaning | Candidate RINEX 3 codes | From |
|---|---|---|---|
p |
P-code family, technique not recorded | P, W, Y; D on L2 only (RINEX 3.04 Table 4) |
GPS P1, P2 |
l |
civil code on L2 (C/A or L2C), not recorded which | C, S, L, X |
GPS C2 |
u |
carrier band only, no code information | any | phase, Doppler, signal strength; Galileo and L5 pseudoranges |
RINEX 3 and 4 attributes are uppercase only, so a marker can never collide with a real code. A plausible-looking uppercase guess would: X is a real signal (the combined L1C D+P or L2C M+L channel), and W asserts a tracking technique the file does not record.
Where RINEX 2 does identify the signal, the reader writes the real RINEX 3 code:
- GPS
C1is the C/A code \(\rightarrow\)C. - GLONASS
C1/C2are C/A \(\rightarrow\)C;P1/P2are the P code, for which RINEX 3.04 Table 5 defines a single attribute \(\rightarrow\)P. - A band with a single RINEX 3 signal resolves to that signal for every observable: SBAS L1 carries only C/A, so SBAS
C1,L1,S1all becomeL1|C.
| System | RINEX 2 code | Signal ID |
|---|---|---|
| GPS | C1 |
G05\|L1\|C |
| GPS | P1 |
G05\|L1\|p |
| GPS | P2 |
G05\|L2\|p |
| GPS | C2 |
G05\|L2\|l |
| GPS | L1, D1, S1 |
G05\|L1\|u |
| GPS | L2, D2, S2 |
G05\|L2\|u |
| GLONASS | C1 / P2 |
R07\|G1\|C / R07\|G2\|P |
| GLONASS | L1, S1 |
R07\|G1\|u |
| Galileo | C1, L1, S1 |
E11\|E1\|u |
| SBAS | C1, L1, S1 |
S20\|L1\|C |
| SBAS | C5, L5, S5 |
S20\|L5\|u |
Two consequences follow directly from the specification:
- Phase and signal strength of a RINEX 2 file share one SID per band (
L1|u), and the pseudoranges get their own (L1|C,L1|p). Table A1 describes signal strength as belonging "to the respective phase observations"; neither is tied to a code. - Selecting a RINEX 3 code picks up RINEX 2 data only where RINEX 2 defines that code (for example GPS
C1inL1|C).ds.sel(sid=ds.code == "W")returns nothing from a RINEX 2 file, because RINEX 2 never said the signal wasW. To use the remaining RINEX 2 data, select the markers explicitly and decide how to treat them.
Every RINEX 2 dataset documents the markers in its "Tracking Code Markers" attribute and records the source version in "RINEX Version".
Global SID padding
The markers are registered in the constellation BAND_CODES, so
pad_to_global_sid() keeps them. RINEX 2 and RINEX 3 data of the same
station can share one store: their SIDs are disjoint wherever RINEX 2
could not resolve the code, and identical where it could (G05|L1|C).
Default SID preset¶
The default SID preset is defined in RINEX 3 codes, which RINEX 2 signal strength never carries. Band-only SIDs are populated only from RINEX 2 files, so the preset does not include them; otherwise every RINEX 3 or SBF dataset would carry them as empty SIDs. To process RINEX 2 files, select them explicitly (sids: mode: custom). The commented-out block at the end of presets/default.yaml lists the band-only SIDs of the satellites of the preset that follow its exclusion rule (no codeless or semi-codeless tracking):
| Band | RINEX 3 candidates for u |
Listed |
|---|---|---|
| GLONASS G1 | C, P; RINEX 3.04 defines codeless/semi-codeless attributes for GPS only (Sect. 5.1) |
Rnn\|G1\|u |
| Galileo E1 | A, B, C, X, Z; likewise no codeless/semi-codeless attribute |
Enn\|E1\|u |
| GPS L1 | C/A, L1C, P(Y) codeless (N) or Z-tracking (W) |
Gnn\|L1\|u, assuming S1 does not come from codeless or Z-tracking of P(Y) |
| GPS L2 | L2C, C/A, or P(Y) | excluded: without L2C, L2 carries P(Y) or, by ground command, C/A (IS-GPS-200N Sect. 3.2.3); civil receivers track P(Y) only by codeless or semi-codeless processing (Betz & Cerruti 2020, doi:10.1002/navi.347), and RINEX 2 cannot tell these modes from L2C |
GLONASS G2 and Galileo E5a/E5b band-only SIDs are not listed.
Satellites¶
RINEX 2 satellite numbers snn follow the same convention as RINEX 3: for SBAS, \(nn = \text{PRN} - 100\) (PRN 120 \(\rightarrow\) S20). SBAS satellites S01–S99 are recognized.
Loss of lock and signal strength indicators¶
The LLI variable has the RINEX 3.04 meaning for every input format. The RINEX 2.11 bits (Table A2) differ, so the reader translates them:
| Bit | RINEX 2.11 (Table A2) | Written as (RINEX 3.04 Table A3) |
|---|---|---|
| 0 | lost lock, cycle slip possible | bit 0, unchanged |
| 1 | wavelength factor opposite to the one in force | bit 1 (half-cycle ambiguity) if the phase's resulting factor is 2 |
| 2 | observation under antispoofing | dropped: RINEX 3.04 sect. 7 declares the antispoofing flag obsolete |
The WAVELENGTH FACT L1/2 header record gives the factor for GPS L1 and L2 phase: 1 = full-cycle, 2 = half-cycle ambiguities (squaring receivers). The factor in force is the header default or a satellite-specific record, including records inserted with epoch flag 4 later in the file. Bit 1 switches it for the current epoch only. Every phase with factor 2 gets RINEX 3 bit 1, even without an LLI digit.
Phase, Doppler, and signal strength of one band land in one SID, and some converters write flags on every observable. Following RINEX 3.04 Table A3 notes 1–3:
- LLI is taken only from the phase observation. Flags on code, Doppler, or signal strength are ignored.
- SSI is taken from the phase; for a SID without phase, from the pseudorange. RINEX 2.11 does not assign the SSI to an observable.
Signal strength unit¶
RINEX 2.11 Table A1 defines S as "raw signal strengths or SNR values as given by the receiver" and declares no unit. SNR is labeled dB, and its description attribute states the assumption.
Header¶
obs_codes_per_system lists the observation codes in RINEX 3 notation per system, with the resolved code or marker in the attribute position, for a mixed GPS/GLONASS file with L1 L2 C1 P1 P2 S1 S2:
{
"G": ["L1u", "L2u", "C1C", "C1p", "C2p", "S1u", "S2u"],
"R": ["L1u", "L2u", "C1C", "C1P", "C2P", "S1u", "S2u"],
}