Skip to content

Commit 956000e

Browse files
authored
Merge pull request #194 from MBARIMike/main
Fixes for plotting realtime pyxis data
2 parents 5db9406 + 1366aab commit 956000e

2 files changed

Lines changed: 47 additions & 21 deletions

File tree

.vscode/launch.json

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -503,12 +503,15 @@
503503
// Test a month with fewer plots to make
504504
//"args": ["--auv_name", "daphne", "--start", "20260101", "--end", "20260131", "-v", "2", "--clobber"]
505505
// Test pyxis and cbit_amphoursused plot
506-
"args": ["--auv_name", "pyxis", "--start", "20260526", "--end", "20260531", "-v", "1", "--clobber"]
506+
//"args": ["--auv_name", "pyxis", "--start", "20260526", "--end", "20260531", "-v", "1", "--clobber"]
507507
// Test --current_month
508508
//"args": ["--current_month", "-v", "1"]
509509
// Test reading downwelling_photosynthetic
510510
// _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
511511
//"args": ["--auv_name", "daphne", "--start", "20260501", "--end", "20260531", "-v", "1", "--clobber"]
512+
// Test stoqs url creation with valid start and end times - problem was that data hadn't loaded into stoqs yet.
513+
//"args": ["--auv_name", "makai", "--start", "20260601", "--end", "20260604", "-v", "1", "--clobber"]
514+
"args": ["--auv_name", "pyxis", "--current_month", "-v", "1"]
512515
},
513516
{
514517
"name": "lrauv_deployment_plots",

src/data/create_products.py

Lines changed: 43 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1070,32 +1070,41 @@ def _grid_dims(self, plot_vars: list[str] | None = None) -> tuple:
10701070
attrs=distnav.attrs,
10711071
)
10721072

1073-
# Horizontal gridded to 3x the number of profiles
1073+
# Horizontal gridded to 3x the number of profiles (or len of distnav if unavailable)
1074+
num_profiles = (
1075+
int(np.nanmax(self.ds["profile_number"].to_numpy()))
1076+
if "profile_number" in self.ds
1077+
else len(distnav)
1078+
)
10741079
idist = np.linspace(
10751080
distnav.to_numpy()[0],
10761081
distnav.to_numpy()[-1],
1077-
int(3 * np.nanmax(self.ds["profile_number"].to_numpy())),
1082+
3 * num_profiles,
10781083
)
10791084
# Vertical gridded to .5 m, rounded down to nearest 10m (minimum 10m)
10801085
# Use only depths where at least one sensor variable has valid data to
10811086
# exclude bogus depth values recorded when no valid sensor data was logged
10821087
# (e.g. from memory corruption events)
1083-
depth_values = self.ds.cf["depth"].to_numpy()
1084-
time_dim = self.ds.cf["depth"].dims[0]
1085-
nav_vars = {"depth", "latitude", "longitude", "profile_number"}
1086-
has_valid_sensor_data = np.zeros(len(depth_values), dtype=bool)
1087-
vars_to_check = [
1088-
v for v in (plot_vars or self.ds.data_vars) if v in self.ds and "pitch" not in v
1089-
]
1090-
for var in vars_to_check:
1091-
if var not in nav_vars and time_dim in self.ds[var].dims and self.ds[var].ndim == 1:
1092-
has_valid_sensor_data |= ~np.isnan(self.ds[var].to_numpy())
1093-
depths_with_data = depth_values[has_valid_sensor_data]
1094-
if len(depths_with_data) > 0 and not np.all(np.isnan(depths_with_data)):
1095-
max_depth = max(np.floor(np.nanmax(depths_with_data) / 10) * 10, 10)
1088+
if "depth" not in self.ds.cf:
1089+
self.logger.debug("No depth variable in dataset, using minimal iz")
1090+
iz = np.arange(0, 10.5, 0.5)
10961091
else:
1097-
max_depth = max(np.floor(np.nanmax(depth_values) / 10) * 10, 10)
1098-
iz = np.arange(0, max_depth + 0.5, 0.5) # include max_depth so axis reaches it
1092+
depth_values = self.ds.cf["depth"].to_numpy()
1093+
time_dim = self.ds.cf["depth"].dims[0]
1094+
nav_vars = {"depth", "latitude", "longitude", "profile_number"}
1095+
has_valid_sensor_data = np.zeros(len(depth_values), dtype=bool)
1096+
vars_to_check = [
1097+
v for v in (plot_vars or self.ds.data_vars) if v in self.ds and "pitch" not in v
1098+
]
1099+
for var in vars_to_check:
1100+
if var not in nav_vars and time_dim in self.ds[var].dims and self.ds[var].ndim == 1:
1101+
has_valid_sensor_data |= ~np.isnan(self.ds[var].to_numpy())
1102+
depths_with_data = depth_values[has_valid_sensor_data]
1103+
if len(depths_with_data) > 0 and not np.all(np.isnan(depths_with_data)):
1104+
max_depth = max(np.floor(np.nanmax(depths_with_data) / 10) * 10, 10)
1105+
else:
1106+
max_depth = max(np.floor(np.nanmax(depth_values) / 10) * 10, 10)
1107+
iz = np.arange(0, max_depth + 0.5, 0.5) # include max_depth so axis reaches it
10991108

11001109
return idist, iz, distnav
11011110

@@ -1166,6 +1175,9 @@ def _profile_bottoms(
11661175
"""Return array of distance and depth points defining the bottom of the profiles
11671176
where there is no data"""
11681177

1178+
if "depth" not in self.ds.cf:
1179+
self.logger.debug("No depth variable in dataset, skipping profile bottoms")
1180+
return None
11691181
# Create a DataArray of depths indexed by distance
11701182
depth_dist = xr.DataArray(
11711183
self.ds.cf["depth"].to_numpy(),
@@ -1464,7 +1476,13 @@ def _section_overlays(self, distnav: xr.DataArray) -> tuple:
14641476
return profile_bottoms, bottom_depths
14651477

14661478
def _cumulative_profile_numbers(self) -> np.ndarray:
1467-
"""Return profile_number array that increments monotonically across log files."""
1479+
"""Return profile_number array that increments monotonically across log files.
1480+
1481+
Falls back to a simple index array when profile_number is absent.
1482+
"""
1483+
if "profile_number" not in self.ds:
1484+
self.logger.debug("profile_number not in dataset, using index array for track color")
1485+
return np.arange(len(self.ds["time"]), dtype=float)
14681486
profile_numbers = self.ds["profile_number"].to_numpy()
14691487
result = profile_numbers.copy().astype(float)
14701488
offset = 0
@@ -2066,14 +2084,19 @@ def _plot_var_scatter( # noqa: C901, PLR0912, PLR0913, PLR0915
20662084
# filtered in _grid_dims (e.g. sparse GPS in realtime SBD data).
20672085
# Align depth and var arrays to distnav's time subset.
20682086
n_ds = len(self.ds.cf["time"])
2087+
has_depth = "depth" in self.ds.cf
20692088
if len(distnav) != n_ds:
20702089
ds_time = self.ds.cf["time"].to_numpy()
20712090
nav_idx = np.searchsorted(ds_time, distnav.coords["time"].to_numpy())
20722091
nav_idx = nav_idx[nav_idx < n_ds]
2073-
depth_for_scatter = self.ds.cf["depth"].to_numpy()[nav_idx]
2092+
depth_for_scatter = (
2093+
self.ds.cf["depth"].to_numpy()[nav_idx] if has_depth else np.zeros(len(nav_idx))
2094+
)
20742095
var_for_scatter = var_to_plot[nav_idx]
20752096
else:
2076-
depth_for_scatter = self.ds.cf["depth"].to_numpy()
2097+
depth_for_scatter = (
2098+
self.ds.cf["depth"].to_numpy() if has_depth else np.zeros(len(var_to_plot))
2099+
)
20772100
var_for_scatter = var_to_plot
20782101

20792102
# Create scatter plot with actual data points

0 commit comments

Comments
 (0)