diff --git a/src/georinex/nav2.py b/src/georinex/nav2.py index de985d8..231e8ed 100644 --- a/src/georinex/nav2.py +++ b/src/georinex/nav2.py @@ -195,6 +195,8 @@ def rinexnav2(fn: T.TextIO | Path, tlim: tuple[datetime, datetime] | None = None nav[name] *= 1e3 # %% other attributes + if "LEAP SECONDS" in header: + nav.attrs["leap_seconds"] = int(header["LEAP SECONDS"]) nav.attrs["version"] = header["version"] nav.attrs["svtype"] = [svtype] # Use list for consistency with NAV3. nav.attrs["rinextype"] = "nav" @@ -208,6 +210,13 @@ def rinexnav2(fn: T.TextIO | Path, tlim: tuple[datetime, datetime] | None = None beta = [rinex_string_to_float(beta[2 + i * 12 : 2 + (i + 1) * 12]) for i in range(4)] nav.attrs["ionospheric_corr_GPS"] = np.hstack((alpha, beta)) + if "DELTA-UTC: A0,A1,T,W" in header: + delta_utc = header["DELTA-UTC: A0,A1,T,W"] + nav.attrs["A0"] = rinex_string_to_float(delta_utc[2 : 22]) + nav.attrs["A1"] = rinex_string_to_float(delta_utc[22 : 42]) + nav.attrs["Tot"] = rinex_string_to_float(delta_utc[42 : 52]) + nav.attrs["Wnt"] = rinex_string_to_float(delta_utc[52 : 59]) + return nav diff --git a/src/georinex/nav3.py b/src/georinex/nav3.py index aa936f8..ed8706f 100644 --- a/src/georinex/nav3.py +++ b/src/georinex/nav3.py @@ -78,7 +78,6 @@ def rinexnav3( raw += ln[STARTCOL3:80] # one line per SV raws.append(raw.replace("D", "E").replace("\n", "")) - # %% parse collected data per SV # NOTE: must be 'ns' or .to_netcdf will fail! t = np.array([np.datetime64(t, "ns") for t in times]) @@ -153,7 +152,8 @@ def rinexnav3( nav.attrs["ionospheric_corr_BDS"] = np.hstack((corr["BDSA"], corr["BDSB"])) if "IRNA" in corr and "IRNB" in corr: nav.attrs["ionospheric_corr_IRN"] = np.hstack((corr["IRNA"], corr["IRNB"])) - + if "LEAP SECONDS" in header: + nav.attrs["leap_seconds"] = int(header["LEAP SECONDS"].split()[0]) nav.attrs["version"] = header["version"] nav.attrs["svtype"] = svtypes nav.attrs["rinextype"] = "nav" @@ -230,9 +230,10 @@ def _sparefields(cf: list[str], sys: str, N: int) -> list[str]: elif N == 27: # no middle or trailing spare fields cf = cf[:22] + cf[23:-3] elif sys == "I": - if N == 28: + if N == 26: + cf = cf[:22] + cf[23:26] + [cf[27]] + elif N == 28: cf = cf[:28] - if N != len(cf): raise ValueError(f"System {sys} NAV data is not the same length as the number of fields.") diff --git a/src/georinex/obs2.py b/src/georinex/obs2.py index 292db34..f4c1c8e 100644 --- a/src/georinex/obs2.py +++ b/src/georinex/obs2.py @@ -305,10 +305,11 @@ def rinexsystem2( obs.attrs["rxmodel"] = hdr["rxmodel"] if "position" in hdr.keys(): obs.attrs["position"] = hdr["position"] - if "position_geodetic" in hdr.keys(): obs.attrs["position_geodetic"] = hdr["position_geodetic"] - + if "LEAP SECONDS" in hdr.keys(): + obs.attrs["leap_seconds"] = int(hdr["LEAP SECONDS"]) + return obs @@ -450,11 +451,14 @@ def obsheader2( except (KeyError, ValueError): pass - try: # This key is OPTIONAL + try: hdr["interval"] = float(hdr["INTERVAL"][:10]) except (KeyError, ValueError): pass - + try: + hdr["version"] = float(hdr["RINEX VERSION / TYPE"].split()[0]) + except (KeyError, ValueError): + pass try: s = " " hdr["rxmodel"] = s.join(hdr["REC # / TYPE / VERS"].split()[1:-1]) diff --git a/src/georinex/obs3.py b/src/georinex/obs3.py index a68dc21..89ce87a 100644 --- a/src/georinex/obs3.py +++ b/src/georinex/obs3.py @@ -160,7 +160,8 @@ def rinexobs3( data.attrs["receiver_clock_offset_applied"] = int(hdr["RCV CLOCK OFFS APPL"]) except ValueError: pass - + if "LEAP SECONDS" in hdr.keys(): + data.attrs["leap_seconds"] = int(hdr["LEAP SECONDS"]) return data diff --git a/src/georinex/tests/test_nav2.py b/src/georinex/tests/test_nav2.py index 127b8a2..d71d623 100755 --- a/src/georinex/tests/test_nav2.py +++ b/src/georinex/tests/test_nav2.py @@ -207,3 +207,15 @@ def test_ionospheric_correction(): -0.5243e06, ] ) + + +def test_delta_utc(): + nav = gr.load(R / "14601736.18n") + assert [nav.A0, nav.A1, nav.Tot, nav.Wnt] == approx( + [ + -0.186264514923e-08, + -0.888178419700e-15, + 61440.0, + 2006.0 + ] + )