Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

NPI-3688 Improved SP3 content writer tests, test data, header formatting correctness, and comment handling / passthrough options #73

Open
wants to merge 20 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
de7f6a6
SP3 comment preservation and output
treefern Jan 14, 2025
80c1c47
sp3 unit tests for content generation functions
treefern Jan 14, 2025
642f62d
NPI-3688 improve sp3 generation function unit test to check output li…
treefern Jan 15, 2025
2918387
NPI-3688 improve sp3 comment output functionality to auto-pad, ensuri…
treefern Jan 16, 2025
a5ca5fd
NPI-3688 update sp3 header generator to set format version to d if no…
treefern Jan 16, 2025
ef29722
NPI-3688 add constants for SP3 comment start sequence and max length
treefern Jan 16, 2025
98e2759
NPI-3688 add checks for SP3 format version, and start of an optional …
treefern Jan 16, 2025
bf36200
NPI-3688 update SP3 comment handling to store and work with comment l…
treefern Jan 16, 2025
8c3ba83
NPI-3688 initial attempt at fixing SP3 header line 1 alignments, need…
treefern Jan 16, 2025
1a00f62
NPI-3688 Fix field size and padding in gen_sp3_header() to make the f…
treefern Jan 17, 2025
a5e49f5
NPI-3688 deprecated j20002rnxdt and refactored into three functions t…
treefern Jan 17, 2025
c3a90a1
NPI-3688 fix realignment issue in date formatting (year had been padd…
treefern Jan 17, 2025
d93fb07
NPI-3688 sp3 comment handling utilities
treefern Jan 21, 2025
4417c4f
Complex conflict resolution - Merge branch 'main' into NPI-3688-store…
treefern Jan 30, 2025
b0e10db
NPI-3688 todo for better tests for comment handling functions. Lintin…
treefern Jan 30, 2025
eb46238
NPI-3688 add todo for attribute merge test
treefern Jan 30, 2025
55b0375
NPI-3688 remove actioned todos and no longer relevant comments
treefern Jan 30, 2025
caac791
NPI-3688 fix SP3 comment update function to not expect optional args
treefern Jan 30, 2025
6fa2f97
NPI-3688 remove todo after checking functionality
treefern Jan 30, 2025
d5f5441
NPI-3688 cleanup docstring and parameter name relating to stricter SP…
treefern Jan 30, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
67 changes: 66 additions & 1 deletion gnssanalysis/gn_datetime.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
"""Base time conversion functions"""

import logging

from datetime import datetime as _datetime
from datetime import timedelta as _timedelta
from io import StringIO as _StringIO
Expand All @@ -11,6 +13,9 @@
from . import gn_const as _gn_const


logger = logging.getLogger(__name__)


def gpsweekD(yr, doy, wkday_suff=False):
"""
Convert year, day-of-year to GPS week format: WWWWD or WWWW
Expand Down Expand Up @@ -270,11 +275,71 @@ def mjd2j2000(mjd: _np.ndarray, seconds_frac: _np.ndarray, pea_partials=False) -
return datetime2j2000(datetime)


def j2000_to_igs_dt(j2000_secs: _np.ndarray) -> _np.ndarray:
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should probably have unittests for this and the other functions as well? (including j2000_to_igs_epoch_row_header_dt and j2000_to_sp3_head_dt)

"""
Converts array of j2000 times to format string representation used by many IGS formats including Rinex and SP3.
E.g. 674913600 -> '2021-05-22T00:00:00' -> '2021 5 22 0 0 0.00000000'
:param _np.ndarray j2000_secs: Numpy NDArray of (typically epoch) times in J2000 seconds.
:return _np.ndarray: Numpy NDArray with those same times as strings.
"""
datetime = j20002datetime(j2000_secs)
year = datetime.astype("datetime64[Y]")
month = datetime.astype("datetime64[M]")
day = datetime.astype("datetime64[D]")
hour = datetime.astype("datetime64[h]")
minute = datetime.astype("datetime64[m]")

date_y = _pd.Series(year.astype(str)).str.rjust(4).values
date_m = _pd.Series(((month - year).astype("int64") + 1).astype(str)).str.rjust(3).values
date_d = _pd.Series(((day - month).astype("int64") + 1).astype(str)).str.rjust(3).values

time_h = _pd.Series((hour - day).astype("int64").astype(str)).str.rjust(3).values
time_m = _pd.Series((minute - hour).astype("int64").astype(str)).str.rjust(3).values
# Width 12 due to one extra leading space (for easier concatenation next), then _0.00000000 format per SP3d spec:
time_s = (_pd.Series((datetime - minute)).view("int64") / 1e9).apply("{:.8f}".format).str.rjust(12).values
return date_y + date_m + date_d + time_h + time_m + time_s


def j2000_to_igs_epoch_row_header_dt(j2000_secs: _np.ndarray) -> _np.ndarray:
"""
Utility wrapper function to format J2000 time values (typically epoch values) to be written as epoch header lines
within the body of SP3, Rinex, etc. files.
E.g. 674913600 -> '2021-05-22T00:00:00' -> '* 2021 5 22 0 0 0.00000000\n'
:param _np.ndarray j2000_secs: Numpy NDArray of (typically epoch) times in J2000 seconds.
:return _np.ndarray: Numpy NDArray with those same times as strings, including epoch line lead-in and newline.
"""
# Add leading "* "s and trailing newlines around all values
return "* " + j2000_to_igs_dt(j2000_secs) + "\n"


def j2000_to_sp3_head_dt(j2000secs: _np.ndarray) -> _np.ndarray:
"""
Utility wrapper function to format a J2000 time value for the SP3 header. Takes NDArray, but only expects one value
in it.
:param _np.ndarray j2000_secs: Numpy NDArray of (typically epoch) time(s) in J2000 seconds.
:return _np.ndarray: Numpy NDArray with those same times as strings.
"""
formatted_times = j2000_to_igs_dt(j2000secs)

# If making a header there should be one value. If not it's a mistake, or at best inefficient.
if len(formatted_times) != 1:
logger.warning(
"More than one time value passed through. This function is meant to be used to format a single value "
"in the SP3 header. Check for mistakes."
)
return formatted_times[0]


# TODO DEPRECATED.
def j20002rnxdt(j2000secs: _np.ndarray) -> _np.ndarray:
"""
Converts j2000 array to rinex format string representation
DEPRECATED since about version 0.0.58
TODO remove in version 0.0.59
Converts array of j2000 times to rinex format string representation
674913600 -> '2021-05-22T00:00:00' -> '* 2021 5 22 0 0 0.00000000\n'
"""
logger.warning("j20002rnxdt() is deprecated. Please use j2000_to_igs_epoch_row_header_dt() instead.")

datetime = j20002datetime(j2000secs)
year = datetime.astype("datetime64[Y]")
month = datetime.astype("datetime64[M]")
Expand Down
Loading