Skip to content

Commit e9a0c54

Browse files
committed
CTD_BGC fieldset bug fix
1 parent 43afe97 commit e9a0c54

File tree

3 files changed

+38
-48
lines changed

3 files changed

+38
-48
lines changed

src/virtualship/cli/_plan.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1046,7 +1046,6 @@ def save_pressed(self) -> None:
10461046
# verify schedule
10471047
expedition_editor.expedition.schedule.verify(
10481048
ship_speed_value,
1049-
bathy_data_dir=None,
10501049
check_space_time_region=True,
10511050
ignore_missing_bathymetry=True,
10521051
)

src/virtualship/instruments/base.py

Lines changed: 38 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,11 @@
44
from typing import TYPE_CHECKING
55

66
import copernicusmarine
7-
import numpy as np
87
import xarray as xr
98
from yaspin import yaspin
109

1110
from parcels import FieldSet
1211
from virtualship.utils import (
13-
COPERNICUSMARINE_BGC_VARIABLES,
1412
COPERNICUSMARINE_PHYS_VARIABLES,
1513
_get_bathy_data,
1614
_select_product_id,
@@ -61,31 +59,16 @@ def __init__(
6159
def load_input_data(self) -> FieldSet:
6260
"""Load and return the input data as a FieldSet for the instrument."""
6361
try:
64-
datasets = []
65-
for var in self.variables.values():
66-
physical = True if var in COPERNICUSMARINE_PHYS_VARIABLES else False
67-
datasets.append(self._get_copernicus_ds(physical=physical, var=var))
68-
69-
# make sure time dims are matched if BGC variables are present (different monthly/daily resolutions can impact fieldset_endtime in simulate)
70-
all_keys = set().union(*(ds.keys() for ds in datasets))
71-
if all_keys & set(COPERNICUSMARINE_BGC_VARIABLES):
72-
datasets = self._align_temporal(datasets)
73-
74-
ds_concat = xr.merge(datasets) # TODO: deal with WARNINGS?
75-
76-
fieldset = FieldSet.from_xarray_dataset(
77-
ds_concat, self.variables, self.dimensions, mesh="spherical"
78-
)
79-
62+
fieldset = self._generate_fieldset()
8063
except Exception as e:
8164
raise FileNotFoundError(
82-
f"Failed to load input data directly from Copernicus Marine for instrument '{self.name}'. "
83-
f"Please check your credentials, network connection, and variable names. Original error: {e}"
65+
f"Failed to load input data directly from Copernicus Marine for instrument '{self.name}'.Original error: {e}"
8466
) from e
8567

8668
# interpolation methods
8769
for var in (v for v in self.variables if v not in ("U", "V")):
8870
getattr(fieldset, var).interp_method = "linear_invdist_land_tracer"
71+
8972
# depth negative
9073
for g in fieldset.gridset.grids:
9174
g.negate_depth()
@@ -109,18 +92,22 @@ def simulate(self, data_dir: Path, measurements: list, out_path: str | Path):
10992

11093
def execute(self, measurements: list, out_path: str | Path) -> None:
11194
"""Run instrument simulation."""
112-
if not self.verbose_progress:
113-
with yaspin(
114-
text=f"Simulating {self.name} measurements... ",
115-
side="right",
116-
spinner=ship_spinner,
117-
) as spinner:
95+
TMP = False
96+
if not TMP:
97+
if not self.verbose_progress:
98+
with yaspin(
99+
text=f"Simulating {self.name} measurements... ",
100+
side="right",
101+
spinner=ship_spinner,
102+
) as spinner:
103+
self.simulate(measurements, out_path)
104+
spinner.ok("✅\n")
105+
else:
106+
print(f"Simulating {self.name} measurements... ")
118107
self.simulate(measurements, out_path)
119-
spinner.ok("✅\n")
108+
print("\n")
120109
else:
121-
print(f"Simulating {self.name} measurements... ")
122110
self.simulate(measurements, out_path)
123-
print("\n")
124111

125112
def _get_copernicus_ds(
126113
self,
@@ -160,19 +147,25 @@ def _get_copernicus_ds(
160147
coordinates_selection_method="outside",
161148
)
162149

163-
def _align_temporal(self, datasets: list[xr.Dataset]) -> list[xr.Dataset]:
164-
"""Align monthly and daily time dims of multiple datasets (by repeating monthly values daily)."""
165-
reference_time = datasets[
166-
np.argmax(ds.time for ds in datasets)
167-
].time # daily timeseries
168-
169-
datasets_aligned = []
170-
for ds in datasets:
171-
if not np.array_equal(ds.time, reference_time):
172-
# TODO: NEED TO CHOOSE BEST METHOD HERE
173-
# ds = ds.resample(time="1D").ffill().reindex(time=reference_time)
174-
# ds = ds.resample(time="1D").ffill()
175-
ds = ds.reindex({"time": reference_time}, method="nearest")
176-
datasets_aligned.append(ds)
177-
178-
return datasets_aligned
150+
def _generate_fieldset(self) -> FieldSet:
151+
"""
152+
Fieldset per variable then combine.
153+
154+
Avoids issues when creating one FieldSet of ds's sourced from different Copernicus Marine product IDs, which is often the case for BGC variables.
155+
156+
"""
157+
fieldsets_list = []
158+
for key, var in self.variables.items():
159+
physical = True if var in COPERNICUSMARINE_PHYS_VARIABLES else False
160+
ds = self._get_copernicus_ds(physical=physical, var=var)
161+
fieldset = FieldSet.from_xarray_dataset(
162+
ds, {key: var}, self.dimensions, mesh="spherical"
163+
)
164+
fieldsets_list.append(fieldset)
165+
base_fieldset = fieldsets_list[0]
166+
if len(fieldsets_list) > 1:
167+
for fs, key in zip(
168+
fieldsets_list[1:], list(self.variables.keys())[1:], strict=True
169+
):
170+
base_fieldset.add_field(getattr(fs, key))
171+
return base_fieldset

src/virtualship/instruments/ctd_bgc.py

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -205,8 +205,6 @@ def simulate(self, measurements, out_path) -> None:
205205
# define output file for the simulation
206206
out_file = ctd_bgc_particleset.ParticleFile(name=out_path, outputdt=OUTPUT_DT)
207207

208-
breakpoint()
209-
210208
# execute simulation
211209
ctd_bgc_particleset.execute(
212210
[

0 commit comments

Comments
 (0)