Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 16 additions & 0 deletions src/virtualship/instruments/adcp.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
"""ADCP instrument."""

import logging
from pathlib import Path

import numpy as np
from parcels import FieldSet, ParticleSet, ScipyParticle, Variable

from ..log_filter import DuplicateFilter
from ..spacetime import Spacetime

# we specifically use ScipyParticle because we have many small calls to execute
Expand All @@ -30,6 +32,7 @@ def simulate_adcp(
min_depth: float,
num_bins: int,
sample_points: list[Spacetime],
log_filter: bool = True,
) -> None:
"""
Use Parcels to simulate an ADCP in a fieldset.
Expand All @@ -40,6 +43,7 @@ def simulate_adcp(
:param min_depth: Minimum depth the ADCP can measure.
:param num_bins: How many samples to take in the complete range between max_depth and min_depth.
:param sample_points: The places and times to sample at.
:param log_filter: Whether to filter duplicate log messages (defaults to True). This is a bit of a hack, but it works and could be removed if changed in Parcels.
"""
sample_points.sort(key=lambda p: p.time)

Expand All @@ -60,6 +64,12 @@ def simulate_adcp(
# outputdt set to infinite as we just want to write at the end of every call to 'execute'
out_file = particleset.ParticleFile(name=out_path, outputdt=np.inf)

# whether to filter parcels duplicate log messages
if log_filter:
external_logger = logging.getLogger("parcels.tools.loggers")
for handler in external_logger.handlers:
handler.addFilter(DuplicateFilter())

for point in sample_points:
particleset.lon_nextloop[:] = point.location.lon
particleset.lat_nextloop[:] = point.location.lat
Expand All @@ -76,3 +86,9 @@ def simulate_adcp(
verbose_progress=False,
output_file=out_file,
)

# turn off log filter after .execute(), to prevent being applied universally to all loggers
# separate if statement from above to prevent error if log_filter is False
if log_filter:
for handler in external_logger.handlers:
handler.removeFilter(handler.filters[0])
16 changes: 16 additions & 0 deletions src/virtualship/instruments/ship_underwater_st.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
"""Ship salinity and temperature."""

import logging
from pathlib import Path

import numpy as np
from parcels import FieldSet, ParticleSet, ScipyParticle, Variable

from ..log_filter import DuplicateFilter
from ..spacetime import Spacetime

# we specifically use ScipyParticle because we have many small calls to execute
Expand Down Expand Up @@ -32,6 +34,7 @@ def simulate_ship_underwater_st(
out_path: str | Path,
depth: float,
sample_points: list[Spacetime],
log_filter: bool = True,
) -> None:
"""
Use Parcels to simulate underway data, measuring salinity and temperature at the given depth along the ship track in a fieldset.
Expand All @@ -40,6 +43,7 @@ def simulate_ship_underwater_st(
:param out_path: The path to write the results to.
:param depth: The depth at which to measure. 0 is water surface, negative is into the water.
:param sample_points: The places and times to sample at.
:param log_filter: Whether to filter duplicate log messages (defaults to True). This is a bit of a hack, but it works and could be removed if changed in Parcels.
"""
sample_points.sort(key=lambda p: p.time)

Expand All @@ -56,6 +60,12 @@ def simulate_ship_underwater_st(
# outputdt set to infinie as we want to just want to write at the end of every call to 'execute'
out_file = particleset.ParticleFile(name=out_path, outputdt=np.inf)

# whether to filter parcels duplicate log messages
if log_filter:
external_logger = logging.getLogger("parcels.tools.loggers")
for handler in external_logger.handlers:
handler.addFilter(DuplicateFilter())

# iterate over each point, manually set lat lon time, then
# execute the particle set for one step, performing one set of measurement
for point in sample_points:
Expand All @@ -74,3 +84,9 @@ def simulate_ship_underwater_st(
verbose_progress=False,
output_file=out_file,
)

# turn off log filter after .execute(), to prevent being applied universally to all loggers
# separate if statement from above to prevent error if log_filter is False
if log_filter:
for handler in external_logger.handlers:
handler.removeFilter(handler.filters[0])
17 changes: 17 additions & 0 deletions src/virtualship/log_filter.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
"""Class for suppressing duplicate log messages in Python logging."""

import logging


class DuplicateFilter(logging.Filter):
"""Logging filter for suppressing duplicate log messages."""

def __init__(self):
self.last_log = None

def filter(self, record):
current_log = record.getMessage()
if current_log != self.last_log:
self.last_log = current_log
return True
return False