virtualship.expedition package#

Everything for simulating an expedition.

class virtualship.expedition.ADCPConfig(*, max_depth_meter: Annotated[float, Le(le=0)], num_bins: Annotated[int, Gt(gt=0)], period_minutes: Annotated[timedelta, Gt(gt=datetime.timedelta(0))])#

Bases: BaseModel

Configuration for ADCP instrument.

max_depth_meter: float#
model_config: ClassVar[ConfigDict] = {'populate_by_name': True}#

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

num_bins: int#
period: timedelta#
class virtualship.expedition.ArgoFloatConfig(*, min_depth_meter: Annotated[float, Le(le=0)], max_depth_meter: Annotated[float, Le(le=0)], drift_depth_meter: Annotated[float, Le(le=0)], vertical_speed_meter_per_second: Annotated[float, Lt(lt=0)], cycle_days: Annotated[float, Gt(gt=0)], drift_days: Annotated[float, Gt(gt=0)])#

Bases: BaseModel

Configuration for argos floats.

cycle_days: float#
drift_days: float#
drift_depth_meter: float#
max_depth_meter: float#
min_depth_meter: float#
model_config: ClassVar[ConfigDict] = {}#

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

vertical_speed_meter_per_second: float#
class virtualship.expedition.CTDConfig(*, stationkeeping_time_minutes: Annotated[timedelta, Gt(gt=datetime.timedelta(0))], min_depth_meter: Annotated[float, Le(le=0)], max_depth_meter: Annotated[float, Le(le=0)])#

Bases: BaseModel

Configuration for CTD instrument.

max_depth_meter: float#
min_depth_meter: float#
model_config: ClassVar[ConfigDict] = {'populate_by_name': True}#

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

stationkeeping_time: timedelta#
class virtualship.expedition.DrifterConfig(*, depth_meter: Annotated[float, Le(le=0)], lifetime_minutes: Annotated[timedelta, Gt(gt=datetime.timedelta(0))])#

Bases: BaseModel

Configuration for drifters.

depth_meter: float#
lifetime: timedelta#
model_config: ClassVar[ConfigDict] = {'populate_by_name': True}#

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

class virtualship.expedition.InstrumentType(*values)#

Bases: Enum

Types of instruments.

ARGO_FLOAT = 'ARGO_FLOAT'#
CTD = 'CTD'#
DRIFTER = 'DRIFTER'#
XBT = 'XBT'#
class virtualship.expedition.Schedule(*, waypoints: list[Waypoint], space_time_region: SpaceTimeRegion | None = None)#

Bases: BaseModel

Schedule of the virtual ship.

classmethod from_yaml(file_path: str | Path) Schedule#

Load schedule from yaml file.

Parameters:

file_path – Path to the file to load from.

Returns:

The schedule.

model_config: ClassVar[ConfigDict] = {'extra': 'forbid'}#

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

space_time_region: SpaceTimeRegion | None#
to_yaml(file_path: str | Path) None#

Write schedule to yaml file.

Parameters:

file_path – Path to the file to write to.

waypoints: list[Waypoint]#
class virtualship.expedition.ShipConfig(*, ship_speed_knots: Annotated[float, Gt(gt=0)], argo_float_config: ArgoFloatConfig | None = None, adcp_config: ADCPConfig | None = None, ctd_config: CTDConfig | None = None, ship_underwater_st_config: ShipUnderwaterSTConfig | None = None, drifter_config: DrifterConfig | None = None, xbt_config: XBTConfig | None = None)#

Bases: BaseModel

Configuration of the virtual ship.

adcp_config: ADCPConfig | None#

ADCP configuration.

If None, no ADCP measurements will be performed.

argo_float_config: ArgoFloatConfig | None#

Argo float configuration.

If None, no argo floats can be deployed.

ctd_config: CTDConfig | None#

CTD configuration.

If None, no CTDs can be cast.

drifter_config: DrifterConfig | None#

Drifter configuration.

If None, no drifters can be deployed.

classmethod from_yaml(file_path: str | Path) ShipConfig#

Load config from yaml file.

Parameters:

file_path – Path to the file to load from.

Returns:

The config.

model_config: ClassVar[ConfigDict] = {'extra': 'forbid'}#

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

ship_speed_knots: float#

Velocity of the ship in knots.

ship_underwater_st_config: ShipUnderwaterSTConfig | None#

Ship underwater salinity temperature measurementconfiguration.

If None, no ST measurements will be performed.

to_yaml(file_path: str | Path) None#

Write config to yaml file.

Parameters:

file_path – Path to the file to write to.

xbt_config: XBTConfig | None#

XBT configuration.

If None, no XBTs can be cast.

class virtualship.expedition.ShipUnderwaterSTConfig(*, period_minutes: Annotated[timedelta, Gt(gt=datetime.timedelta(0))])#

Bases: BaseModel

Configuration for underwater ST.

model_config: ClassVar[ConfigDict] = {'populate_by_name': True}#

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

period: timedelta#
class virtualship.expedition.SpaceTimeRegion(*, spatial_range: SpatialRange, time_range: TimeRange)#

Bases: BaseModel

An space-time region with spatial and temporal boundaries.

model_config: ClassVar[ConfigDict] = {}#

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

spatial_range: SpatialRange#
time_range: TimeRange#
class virtualship.expedition.Waypoint(*, location: Location, time: datetime | None = None, instrument: InstrumentType | list[InstrumentType] | None = None)#

Bases: BaseModel

A Waypoint to sail to with an optional time and an optional instrument.

instrument: InstrumentType | list[InstrumentType] | None#
location: Location#
model_config: ClassVar[ConfigDict] = {}#

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

serialize_instrument(instrument)#

Ensure InstrumentType is serialized as a string (or list of strings).

time: datetime | None#
virtualship.expedition.do_expedition(expedition_dir: str | Path, input_data: Path | None = None) None#

Perform an expedition, providing terminal feedback and file output.

Parameters:
  • expedition_dir – The base directory for the expedition.

  • input_data – Input data folder folder (override used for testing).

Submodules#

virtualship.expedition.checkpoint module#

Checkpoint class.

class virtualship.expedition.checkpoint.Checkpoint(*, past_schedule: Schedule)#

Bases: BaseModel

A checkpoint of schedule simulation.

Copy of the schedule until where the simulation proceeded without troubles.

classmethod from_yaml(file_path: str | Path) Checkpoint#

Load checkpoint from yaml file.

Parameters:

file_path – Path to the file to load from.

Returns:

The checkpoint.

model_config: ClassVar[ConfigDict] = {}#

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

past_schedule: Schedule#
to_yaml(file_path: str | Path) None#

Write checkpoint to yaml file.

Parameters:

file_path – Path to the file to write to.

virtualship.expedition.do_expedition module#

do_expedition function.

virtualship.expedition.do_expedition.do_expedition(expedition_dir: str | Path, input_data: Path | None = None) None#

Perform an expedition, providing terminal feedback and file output.

Parameters:
  • expedition_dir – The base directory for the expedition.

  • input_data – Input data folder folder (override used for testing).

virtualship.expedition.expedition_cost module#

expedition_cost function.

virtualship.expedition.expedition_cost.expedition_cost(schedule_results: ScheduleOk, time_past: timedelta) float#

Calculate the cost of the expedition in US$.

Parameters:
  • schedule_results – Results from schedule simulation.

  • time_past – Time the expedition took.

Returns:

The calculated cost of the expedition in US$.

virtualship.expedition.input_data module#

InputData class.

class virtualship.expedition.input_data.InputData(adcp_fieldset: FieldSet | None, argo_float_fieldset: FieldSet | None, ctd_fieldset: FieldSet | None, drifter_fieldset: FieldSet | None, xbt_fieldset: FieldSet | None, ship_underwater_st_fieldset: FieldSet | None)#

Bases: object

A collection of fieldsets that function as input data for simulation.

adcp_fieldset: FieldSet | None#
argo_float_fieldset: FieldSet | None#
ctd_fieldset: FieldSet | None#
drifter_fieldset: FieldSet | None#
classmethod load(directory: str | Path, load_adcp: bool, load_argo_float: bool, load_ctd: bool, load_drifter: bool, load_xbt: bool, load_ship_underwater_st: bool) InputData#

Create an instance of this class from netCDF files.

For now this function makes a lot of assumption about file location and contents.

Parameters:
  • directory – Input data directory.

  • load_adcp – Whether to load the ADCP fieldset.

  • load_argo_float – Whether to load the argo float fieldset.

  • load_ctd – Whether to load the CTD fieldset.

  • load_drifter – Whether to load the drifter fieldset.

  • load_ship_underwater_st – Whether to load the ship underwater ST fieldset.

Returns:

An instance of this class with loaded fieldsets.

ship_underwater_st_fieldset: FieldSet | None#
xbt_fieldset: FieldSet | None#

virtualship.expedition.instrument_type module#

InstrumentType Enum.

class virtualship.expedition.instrument_type.InstrumentType(*values)#

Bases: Enum

Types of instruments.

ARGO_FLOAT = 'ARGO_FLOAT'#
CTD = 'CTD'#
DRIFTER = 'DRIFTER'#
XBT = 'XBT'#

virtualship.expedition.schedule module#

Schedule class.

class virtualship.expedition.schedule.Schedule(*, waypoints: list[Waypoint], space_time_region: SpaceTimeRegion | None = None)#

Bases: BaseModel

Schedule of the virtual ship.

classmethod from_yaml(file_path: str | Path) Schedule#

Load schedule from yaml file.

Parameters:

file_path – Path to the file to load from.

Returns:

The schedule.

model_config: ClassVar[ConfigDict] = {'extra': 'forbid'}#

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

space_time_region: SpaceTimeRegion | None#
to_yaml(file_path: str | Path) None#

Write schedule to yaml file.

Parameters:

file_path – Path to the file to write to.

waypoints: list[Waypoint]#

virtualship.expedition.ship_config module#

ShipConfig and supporting classes.

class virtualship.expedition.ship_config.ADCPConfig(*, max_depth_meter: Annotated[float, Le(le=0)], num_bins: Annotated[int, Gt(gt=0)], period_minutes: Annotated[timedelta, Gt(gt=datetime.timedelta(0))])#

Bases: BaseModel

Configuration for ADCP instrument.

max_depth_meter: float#
model_config: ClassVar[ConfigDict] = {'populate_by_name': True}#

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

num_bins: int#
period: timedelta#
class virtualship.expedition.ship_config.ArgoFloatConfig(*, min_depth_meter: Annotated[float, Le(le=0)], max_depth_meter: Annotated[float, Le(le=0)], drift_depth_meter: Annotated[float, Le(le=0)], vertical_speed_meter_per_second: Annotated[float, Lt(lt=0)], cycle_days: Annotated[float, Gt(gt=0)], drift_days: Annotated[float, Gt(gt=0)])#

Bases: BaseModel

Configuration for argos floats.

cycle_days: float#
drift_days: float#
drift_depth_meter: float#
max_depth_meter: float#
min_depth_meter: float#
model_config: ClassVar[ConfigDict] = {}#

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

vertical_speed_meter_per_second: float#
class virtualship.expedition.ship_config.CTDConfig(*, stationkeeping_time_minutes: Annotated[timedelta, Gt(gt=datetime.timedelta(0))], min_depth_meter: Annotated[float, Le(le=0)], max_depth_meter: Annotated[float, Le(le=0)])#

Bases: BaseModel

Configuration for CTD instrument.

max_depth_meter: float#
min_depth_meter: float#
model_config: ClassVar[ConfigDict] = {'populate_by_name': True}#

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

stationkeeping_time: timedelta#
class virtualship.expedition.ship_config.DrifterConfig(*, depth_meter: Annotated[float, Le(le=0)], lifetime_minutes: Annotated[timedelta, Gt(gt=datetime.timedelta(0))])#

Bases: BaseModel

Configuration for drifters.

depth_meter: float#
lifetime: timedelta#
model_config: ClassVar[ConfigDict] = {'populate_by_name': True}#

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

class virtualship.expedition.ship_config.ShipConfig(*, ship_speed_knots: Annotated[float, Gt(gt=0)], argo_float_config: ArgoFloatConfig | None = None, adcp_config: ADCPConfig | None = None, ctd_config: CTDConfig | None = None, ship_underwater_st_config: ShipUnderwaterSTConfig | None = None, drifter_config: DrifterConfig | None = None, xbt_config: XBTConfig | None = None)#

Bases: BaseModel

Configuration of the virtual ship.

adcp_config: ADCPConfig | None#

ADCP configuration.

If None, no ADCP measurements will be performed.

argo_float_config: ArgoFloatConfig | None#

Argo float configuration.

If None, no argo floats can be deployed.

ctd_config: CTDConfig | None#

CTD configuration.

If None, no CTDs can be cast.

drifter_config: DrifterConfig | None#

Drifter configuration.

If None, no drifters can be deployed.

classmethod from_yaml(file_path: str | Path) ShipConfig#

Load config from yaml file.

Parameters:

file_path – Path to the file to load from.

Returns:

The config.

model_config: ClassVar[ConfigDict] = {'extra': 'forbid'}#

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

ship_speed_knots: float#

Velocity of the ship in knots.

ship_underwater_st_config: ShipUnderwaterSTConfig | None#

Ship underwater salinity temperature measurementconfiguration.

If None, no ST measurements will be performed.

to_yaml(file_path: str | Path) None#

Write config to yaml file.

Parameters:

file_path – Path to the file to write to.

xbt_config: XBTConfig | None#

XBT configuration.

If None, no XBTs can be cast.

class virtualship.expedition.ship_config.ShipUnderwaterSTConfig(*, period_minutes: Annotated[timedelta, Gt(gt=datetime.timedelta(0))])#

Bases: BaseModel

Configuration for underwater ST.

model_config: ClassVar[ConfigDict] = {'populate_by_name': True}#

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

period: timedelta#
class virtualship.expedition.ship_config.XBTConfig(*, min_depth_meter: Annotated[float, Le(le=0)], max_depth_meter: Annotated[float, Le(le=0)], fall_speed_meter_per_second: Annotated[float, Gt(gt=0)], deceleration_coefficient: Annotated[float, Gt(gt=0)])#

Bases: BaseModel

Configuration for xbt instrument.

deceleration_coefficient: float#
fall_speed_meter_per_second: float#
max_depth_meter: float#
min_depth_meter: float#
model_config: ClassVar[ConfigDict] = {}#

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

virtualship.expedition.simulate_measurements module#

simulate_measurements function.

virtualship.expedition.simulate_measurements.simulate_measurements(expedition_dir: str | Path, ship_config: ShipConfig, input_data: InputData, measurements: MeasurementsToSimulate) None#

Simulate measurements using Parcels.

Saves everything in expedition_dir/results.

Parameters:
  • expedition_dir – Base directory of the expedition.

  • ship_config – Ship configuration.

  • input_data – Input data for simulation.

  • measurements – The measurements to simulate.

Raises:

RuntimeError – In case fieldsets of configuration is not provided. Make sure to check this before calling this function.

virtualship.expedition.simulate_schedule module#

simulate_schedule function and supporting classes.

class virtualship.expedition.simulate_schedule.MeasurementsToSimulate#

Bases: object

The measurements to simulate, as concluded from schedule simulation.

adcps: list[Spacetime]#
argo_floats: list[ArgoFloat]#
ctds: list[CTD]#
drifters: list[Drifter]#
ship_underwater_sts: list[Spacetime]#
xbts: list[XBT]#
class virtualship.expedition.simulate_schedule.ScheduleOk(time: datetime, measurements_to_simulate: MeasurementsToSimulate)#

Bases: object

Result of schedule that could be completed.

measurements_to_simulate: MeasurementsToSimulate#
time: datetime#
class virtualship.expedition.simulate_schedule.ScheduleProblem(time: datetime, failed_waypoint_i: int)#

Bases: object

Result of schedule that could not be fully completed.

failed_waypoint_i: int#
time: datetime#
virtualship.expedition.simulate_schedule.simulate_schedule(projection: Geod, ship_config: ShipConfig, schedule: Schedule) ScheduleOk | ScheduleProblem#

Simulate a schedule.

Parameters:
  • projection – The projection to use for sailing.

  • ship_config – Ship configuration.

  • schedule – The schedule to simulate.

Returns:

Either the results of a successfully simulated schedule, or information on where the schedule became infeasible.

virtualship.expedition.space_time_region module#

SpaceTimeRegion class.

class virtualship.expedition.space_time_region.SpaceTimeRegion(*, spatial_range: SpatialRange, time_range: TimeRange)#

Bases: BaseModel

An space-time region with spatial and temporal boundaries.

model_config: ClassVar[ConfigDict] = {}#

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

spatial_range: SpatialRange#
time_range: TimeRange#
class virtualship.expedition.space_time_region.SpatialRange(*, minimum_longitude: Annotated[float, Ge(ge=-180), Le(le=180)], maximum_longitude: Annotated[float, Ge(ge=-180), Le(le=180)], minimum_latitude: Annotated[float, Ge(ge=-90), Le(le=90)], maximum_latitude: Annotated[float, Ge(ge=-90), Le(le=90)], minimum_depth: float | None = None, maximum_depth: float | None = None)#

Bases: BaseModel

Defines geographic boundaries.

maximum_depth: float | None#
maximum_latitude: Annotated[float, FieldInfo(annotation=NoneType, required=True, metadata=[Ge(ge=-90), Le(le=90)])]#
maximum_longitude: Annotated[float, FieldInfo(annotation=NoneType, required=True, metadata=[Ge(ge=-180), Le(le=180)])]#
minimum_depth: float | None#
minimum_latitude: Annotated[float, FieldInfo(annotation=NoneType, required=True, metadata=[Ge(ge=-90), Le(le=90)])]#
minimum_longitude: Annotated[float, FieldInfo(annotation=NoneType, required=True, metadata=[Ge(ge=-180), Le(le=180)])]#
model_config: ClassVar[ConfigDict] = {}#

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

class virtualship.expedition.space_time_region.TimeRange(*, start_time: datetime | None = None, end_time: datetime | None = None)#

Bases: BaseModel

Defines the temporal boundaries for a space-time region.

end_time: datetime | None#
model_config: ClassVar[ConfigDict] = {}#

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

start_time: datetime | None#

virtualship.expedition.verify_schedule module#

verify_schedule function and supporting classes.

exception virtualship.expedition.verify_schedule.PlanningError#

Bases: RuntimeError

An error in the schedule.

virtualship.expedition.verify_schedule.verify_schedule(projection: Geod, ship_config: ShipConfig, schedule: Schedule, input_data: InputData) None#

Verify waypoints are ordered by time, first waypoint has a start time, and that schedule is feasible in terms of time if no unexpected events happen.

Parameters:
  • projection – projection used to sail between waypoints.

  • ship_config – The cruise ship_configuration.

  • schedule – The schedule to verify.

  • input_data – Fieldsets that can be used to check for zero UV condition (is waypoint on land).

Raises:

virtualship.expedition.waypoint module#

Waypoint class.

class virtualship.expedition.waypoint.Waypoint(*, location: Location, time: datetime | None = None, instrument: InstrumentType | list[InstrumentType] | None = None)#

Bases: BaseModel

A Waypoint to sail to with an optional time and an optional instrument.

instrument: InstrumentType | list[InstrumentType] | None#
location: Location#
model_config: ClassVar[ConfigDict] = {}#

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

serialize_instrument(instrument)#

Ensure InstrumentType is serialized as a string (or list of strings).

time: datetime | None#