Skip to content

Commit 5cd2f07

Browse files
Clearer error message when the column Instrument is missing (#134)
* Clearer error message when the column Instrument is missing * Fixing mfp unit test * Also adding error when instrument name is not valid * Quickfix for issue where instruments from mfp is a list * Fixing for unit tests * Adding ship-download when ADCP or underwater in config
1 parent 68855d7 commit 5cd2f07

4 files changed

Lines changed: 43 additions & 9 deletions

File tree

src/virtualship/cli/commands.py

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,11 @@
1515
get_space_time_region_hash,
1616
hash_to_filename,
1717
)
18-
from virtualship.expedition.do_expedition import _get_schedule, do_expedition
18+
from virtualship.expedition.do_expedition import (
19+
_get_schedule,
20+
_get_ship_config,
21+
do_expedition,
22+
)
1923
from virtualship.utils import SCHEDULE, SHIP_CONFIG, mfp_to_yaml
2024

2125

@@ -107,6 +111,7 @@ def fetch(path: str | Path, username: str | None, password: str | None) -> None:
107111
data_folder.mkdir(exist_ok=True)
108112

109113
schedule = _get_schedule(path)
114+
ship_config = _get_ship_config(path)
110115

111116
if schedule.space_time_region is None:
112117
raise ValueError(
@@ -131,7 +136,10 @@ def fetch(path: str | Path, username: str | None, password: str | None) -> None:
131136
start_datetime = time_range.start_time
132137
end_datetime = time_range.end_time
133138
instruments_in_schedule = [
134-
waypoint.instrument.name for waypoint in schedule.waypoints
139+
waypoint.instrument[0].name
140+
if isinstance(waypoint.instrument, list)
141+
else waypoint.instrument.name
142+
for waypoint in schedule.waypoints # TODO check why instrument is a list here
135143
]
136144

137145
# Create download folder and set download metadata
@@ -142,7 +150,11 @@ def fetch(path: str | Path, username: str | None, password: str | None) -> None:
142150
)
143151
shutil.copyfile(path / SCHEDULE, download_folder / SCHEDULE)
144152

145-
if set(["XBT", "CTD", "SHIP_UNDERWATER_ST"]) & set(instruments_in_schedule):
153+
if (
154+
(set(["XBT", "CTD", "SHIP_UNDERWATER_ST"]) & set(instruments_in_schedule))
155+
or hasattr(ship_config, "ship_underwater_st_config")
156+
or hasattr(ship_config, "adcp_config")
157+
):
146158
print("Ship data will be downloaded")
147159

148160
# Define all ship datasets to download, including bathymetry

src/virtualship/expedition/do_expedition.py

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -42,8 +42,6 @@ def do_expedition(expedition_dir: str | Path, input_data: Path | None = None) ->
4242
"DRIFTER",
4343
"XBT",
4444
"CTD",
45-
"ADCP",
46-
"SHIP_UNDERWATER_ST",
4745
]: # TODO make instrument names consistent capitals or lowercase throughout codebase
4846
if (
4947
hasattr(ship_config, instrument.lower() + "_config")
@@ -182,6 +180,15 @@ def _get_schedule(expedition_dir: Path) -> Schedule:
182180
raise FileNotFoundError(f'Schedule not found. Save it to "{file_path}".') from e
183181

184182

183+
def _get_ship_config(expedition_dir: Path) -> Schedule:
184+
"""Load Schedule object from yaml config file in `expedition_dir`."""
185+
file_path = expedition_dir.joinpath(SHIP_CONFIG)
186+
try:
187+
return ShipConfig.from_yaml(file_path)
188+
except FileNotFoundError as e:
189+
raise FileNotFoundError(f'Config not found. Save it to "{file_path}".') from e
190+
191+
185192
def _load_checkpoint(expedition_dir: Path) -> Checkpoint | None:
186193
file_path = expedition_dir.joinpath(CHECKPOINT)
187194
try:

src/virtualship/utils.py

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,11 @@ def mfp_to_yaml(excel_file_path: str, yaml_output_path: str): # noqa: D417
7575
# Check if the headers match the expected ones
7676
actual_columns = set(coordinates_data.columns)
7777

78+
if "Instrument" not in actual_columns:
79+
raise ValueError(
80+
"Error: Missing column 'Instrument'. Have you added this column after exporting from MFP?"
81+
)
82+
7883
missing_columns = expected_columns - actual_columns
7984
if missing_columns:
8085
raise ValueError(
@@ -134,9 +139,18 @@ def mfp_to_yaml(excel_file_path: str, yaml_output_path: str): # noqa: D417
134139
# Generate waypoints
135140
waypoints = []
136141
for _, row in coordinates_data.iterrows():
137-
instruments = [
138-
InstrumentType(instrument) for instrument in row["Instrument"].split(", ")
139-
]
142+
try:
143+
instruments = [
144+
InstrumentType(instrument)
145+
for instrument in row["Instrument"].split(", ")
146+
]
147+
except ValueError as err:
148+
raise ValueError(
149+
f"Error: Invalid instrument type in row {row.name}. "
150+
"Please ensure that the instrument type is one of: "
151+
f"{[instrument.name for instrument in InstrumentType]}. "
152+
"Also be aware that these are case-sensitive."
153+
) from err
140154
waypoints.append(
141155
Waypoint(
142156
instrument=instruments,

tests/test_mfp_to_yaml.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,8 @@ def test_mfp_to_yaml_missing_headers(mock_read_excel, tmp_path):
5858
yaml_output_path = tmp_path / "schedule.yaml"
5959

6060
with pytest.raises(
61-
ValueError, match="Error: Found columns .* but expected columns .*"
61+
ValueError,
62+
match="Error: Missing column 'Instrument'. Have you added this column after exporting from MFP?",
6263
):
6364
mfp_to_yaml("mock_file.xlsx", yaml_output_path)
6465

0 commit comments

Comments
 (0)