From 686541f492b198509cb192166933680c0c559bbb Mon Sep 17 00:00:00 2001 From: Mike McCann Date: Wed, 20 May 2026 11:35:51 -0700 Subject: [PATCH] Write sentinal file to help with freshness check. Add minutes of duration in STOQS link text. --- .vscode/launch.json | 7 ++++--- src/data/lrauv_deployment_plots.py | 10 +++++++++- src/data/process_lrauv_sbd.py | 20 ++++++++++++++------ 3 files changed, 27 insertions(+), 10 deletions(-) diff --git a/.vscode/launch.json b/.vscode/launch.json index 1027292..3c2316c 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -502,10 +502,11 @@ // Test a month with fewer plots to make //"args": ["--auv_name", "daphne", "--start", "20260101", "--end", "20260131", "-v", "2", "--clobber"] // Test pyxis and cbit_amphoursused plot - "args": ["--auv_name", "pyxis", "--start", "20260501", "--end", "20260531", "-v", "1", "--clobber"] + //"args": ["--auv_name", "pyxis", "--start", "20260501", "--end", "20260531", "-v", "1", "--clobber"] // Test --current_month - //"args": ["--current_month", "-v", "1"] - // Test reading downwelling_photosynthetic_photon_flux_in_sea_water from the root group of the netCDF file instead of the instrument group, which was the case for some early daphne log files + "args": ["--current_month", "-v", "1"] + // Test reading downwelling_photosynthetic + // _photon_flux_in_sea_water from the root group of the netCDF file instead of the instrument group, which was the case for some early daphne log files //"args": ["--auv_name", "daphne", "--start", "20260501", "--end", "20260531", "-v", "1", "--clobber"] }, { diff --git a/src/data/lrauv_deployment_plots.py b/src/data/lrauv_deployment_plots.py index b8c0d9c..6eb0b4d 100755 --- a/src/data/lrauv_deployment_plots.py +++ b/src/data/lrauv_deployment_plots.py @@ -837,6 +837,13 @@ def _duration_min_from_nc_url(self, nc_url: str) -> int | None: except ValueError: return None + def _resolve_dur_min(self, nc_url: str, nc_durations: dict[str, int] | None) -> int | None: + """Return duration in minutes for nc_url, trying filename parse then nc_durations.""" + d = self._duration_min_from_nc_url(nc_url) + if d is None and nc_durations: + d = nc_durations.get(nc_url) + return d + def _per_log_png_links(self, nc_urls: list[str]) -> list[tuple[str, str]]: """Return (url, label) pairs for each existing per-log PNG.""" parts: list[tuple[str, str]] = [] @@ -858,6 +865,7 @@ def _write_per_png_html( # noqa: C901, PLR0913 auv_name: str = "", png_file_path: Path | None = None, other_png_paths: list[str] | None = None, + nc_durations: dict[str, int] | None = None, ) -> None: """Write a plain HTML page for one deployment PNG. @@ -895,7 +903,7 @@ def _write_per_png_html( # noqa: C901, PLR0913 ( d for nc_url in nc_urls - if (d := self._duration_min_from_nc_url(nc_url)) is not None + if (d := self._resolve_dur_min(nc_url, nc_durations)) is not None ), None, ) diff --git a/src/data/process_lrauv_sbd.py b/src/data/process_lrauv_sbd.py index dbe2b42..ac4daf0 100755 --- a/src/data/process_lrauv_sbd.py +++ b/src/data/process_lrauv_sbd.py @@ -201,12 +201,10 @@ def _make_per_log_plots( ) -> None: """Create per-log plots for each shore_1S.nc in month_files.""" for p in month_files: - out_png = p.parent / f"shore_{FREQ}_2column_cmocean.png" - if out_png.exists() and not args.clobber: - if p.stat().st_mtime <= out_png.stat().st_mtime: - logger.info( - "Per-log plot up to date, skipping: %s", _rel(out_png, args.vehicle_dir) - ) + sentinel = p.parent / f"shore_{FREQ}.plotted" + if sentinel.exists() and not args.clobber: + if p.stat().st_mtime <= sentinel.stat().st_mtime: + logger.info("Per-log plots up to date, skipping: %s", _rel(p, args.vehicle_dir)) continue logger.info("shore_1S.nc is newer — replotting: %s", _rel(p, args.vehicle_dir)) else: @@ -231,6 +229,7 @@ def _make_per_log_plots( cp.plot_cbit_2column() except Exception as e: # noqa: BLE001 logger.warning("Per-log plot failed for %s: %s", p.name, e) + sentinel.touch() def _make_products( @@ -302,6 +301,14 @@ def _make_products( html_title = f"Interpolated realtime SBD data for {args.auv_name} in {month_year}" nc_file_strs = [_to_opendap_url(p, args.vehicle_dir) for p in month_files] + nc_durations: dict[str, int] = {} + for p, url in zip(month_files, nc_file_strs, strict=True): + with xr.open_dataset(p) as d: + times = d.cf["time"].to_numpy() + if len(times) > 1: + nc_durations[url] = int( + (times[-1] - times[0]).astype("timedelta64[m]").astype(int) + ) html_paths = [] for png_path in png_paths: html_path = png_path.with_suffix(".html") @@ -316,6 +323,7 @@ def _make_products( auv_name=args.auv_name, png_file_path=png_path, other_png_paths=other_pngs, + nc_durations=nc_durations, ) html_paths.append(html_path)