From 7aea9a9d3f5673a751f5e60b35694cdf7f960862 Mon Sep 17 00:00:00 2001
From: Peter Somhorst
Date: Mon, 16 Dec 2024 15:07:24 +0100
Subject: [PATCH 01/10] Add parametrization for the frame size and medibus
fields
---
eitprocessing/datahandling/loading/draeger.py | 147 ++++++++++--------
1 file changed, 80 insertions(+), 67 deletions(-)
diff --git a/eitprocessing/datahandling/loading/draeger.py b/eitprocessing/datahandling/loading/draeger.py
index 0f8affa1a..508bd0d84 100644
--- a/eitprocessing/datahandling/loading/draeger.py
+++ b/eitprocessing/datahandling/loading/draeger.py
@@ -22,7 +22,6 @@
from numpy.typing import NDArray
-_FRAME_SIZE_BYTES = 4358
load_draeger_data = partial(load_eit_data, vendor=Vendor.DRAEGER)
@@ -34,15 +33,21 @@ def load_from_single_path(
) -> dict[str, DataCollection]:
"""Load Dräger EIT data from path."""
file_size = path.stat().st_size
- if file_size % _FRAME_SIZE_BYTES:
+
+ for _file_format_data in _bin_file_formats.values():
+ frame_size: int = _file_format_data["frame_size"]
+ if file_size % frame_size == 0:
+ medibus_fields = _file_format_data["medibus_fields"]
+ break
+ else:
msg = (
- f"File size {file_size} of file {path!s} not divisible by {_FRAME_SIZE_BYTES}.\n"
+ f"File size {file_size} of file {path!s} does not match the supported *.bin file formats.\n"
"Currently this package does not support loading files containing "
"esophageal pressure or other non-standard data. "
"Make sure this is a valid and uncorrupted Dräger data file."
)
raise OSError(msg)
- total_frames = file_size // _FRAME_SIZE_BYTES
+ total_frames = file_size // frame_size
if (f0 := first_frame) > (fn := total_frames):
msg = f"Invalid input: `first_frame` ({f0}) is larger than the total number of frames in the file ({fn})."
@@ -68,10 +73,10 @@ def load_from_single_path(
time = np.zeros((n_frames,))
events: list[tuple[float, Event]] = []
phases: list[tuple[float, int]] = []
- medibus_data = np.zeros((52, n_frames))
+ medibus_data = np.zeros((len(medibus_fields), n_frames))
with path.open("br") as fo, mmap.mmap(fo.fileno(), length=0, access=mmap.ACCESS_READ) as fh:
- fh.seek(first_frame_to_load * _FRAME_SIZE_BYTES)
+ fh.seek(first_frame_to_load * frame_size)
reader = BinReader(fh)
previous_marker = None
@@ -83,6 +88,7 @@ def load_from_single_path(
time,
pixel_impedance,
medibus_data,
+ len(medibus_fields),
events,
phases,
previous_marker,
@@ -117,7 +123,7 @@ def load_from_single_path(
(
continuousdata_collection,
sparsedata_collection,
- ) = _convert_medibus_data(medibus_data, time, sample_frequency)
+ ) = _convert_medibus_data(medibus_data, medibus_fields, time, sample_frequency)
intervaldata_collection = DataCollection(IntervalData)
# TODO: move some medibus data to sparse / interval
# TODO: move phases and events to sparse / interval
@@ -182,13 +188,14 @@ def load_from_single_path(
def _convert_medibus_data(
medibus_data: NDArray,
+ medibus_fields: list,
time: NDArray,
sample_frequency: float,
) -> tuple[DataCollection, DataCollection]:
continuousdata_collection = DataCollection(ContinuousData)
sparsedata_collection = DataCollection(SparseData)
- for field_info, data in zip(_medibus_fields, medibus_data, strict=True):
+ for field_info, data in zip(medibus_fields, medibus_data, strict=True):
if field_info.continuous:
continuous_data = ContinuousData(
label=field_info.signal_name,
@@ -216,6 +223,7 @@ def _read_frame(
time: NDArray,
pixel_impedance: NDArray,
medibus_data: NDArray,
+ n_medibus_fields: int,
events: list,
phases: list,
previous_marker: int | None,
@@ -236,7 +244,7 @@ def _read_frame(
event_text = reader.string(length=30)
timing_error = reader.int32()
- frame_medibus_data = reader.npfloat32(length=52)
+ frame_medibus_data = reader.npfloat32(length=n_medibus_fields)
if index < 0:
# do not keep any loaded data, just return the event marker
@@ -266,61 +274,66 @@ class _MedibusField(NamedTuple):
continuous: bool
-_medibus_fields = [
- _MedibusField("airway pressure", "mbar", True),
- _MedibusField("flow", "L/min", True),
- _MedibusField("volume", "mL", True),
- _MedibusField("CO2 (%)", "%", True),
- _MedibusField("CO2 (kPa)", "kPa", True),
- _MedibusField("CO2 (mmHg)", "mmHg", True),
- _MedibusField("dynamic compliance", "mL/mbar", False),
- _MedibusField("resistance", "mbar/L/s", False),
- _MedibusField("r^2", "", False),
- _MedibusField("spontaneous inspiratory time", "s", False),
- _MedibusField("minimal pressure", "mbar", False),
- _MedibusField("P0.1", "mbar", False),
- _MedibusField("mean pressure", "mbar", False),
- _MedibusField("plateau pressure", "mbar", False),
- _MedibusField("PEEP", "mbar", False),
- _MedibusField("intrinsic PEEP", "mbar", False),
- _MedibusField("mandatory respiratory rate", "/min", False),
- _MedibusField("mandatory minute volume", "L/min", False),
- _MedibusField("peak inspiratory pressure", "mbar", False),
- _MedibusField("mandatory tidal volume", "L", False),
- _MedibusField("spontaneous tidal volume", "L", False),
- _MedibusField("trapped volume", "mL", False),
- _MedibusField("mandatory expiratory tidal volume", "mL", False),
- _MedibusField("spontaneous expiratory tidal volume", "mL", False),
- _MedibusField("mandatory inspiratory tidal volume", "mL", False),
- _MedibusField("tidal volume", "mL", False),
- _MedibusField("spontaneous inspiratory tidal volume", "mL", False),
- _MedibusField("negative inspiratory force", "mbar", False),
- _MedibusField("leak minute volume", "L/min", False),
- _MedibusField("leak percentage", "%", False),
- _MedibusField("spontaneous respiratory rate", "/min", False),
- _MedibusField("percentage of spontaneous minute volume", "%", False),
- _MedibusField("spontaneous minute volume", "L/min", False),
- _MedibusField("minute volume", "L/min", False),
- _MedibusField("airway temperature", "degrees C", False),
- _MedibusField("rapid shallow breating index", "1/min/L", False),
- _MedibusField("respiratory rate", "/min", False),
- _MedibusField("inspiratory:expiratory ratio", "", False),
- _MedibusField("CO2 flow", "mL/min", False),
- _MedibusField("dead space volume", "mL", False),
- _MedibusField("percentage dead space of expiratory tidal volume", "%", False),
- _MedibusField("end-tidal CO2", "%", False),
- _MedibusField("end-tidal CO2", "kPa", False),
- _MedibusField("end-tidal CO2", "mmHg", False),
- _MedibusField("fraction inspired O2", "%", False),
- _MedibusField("spontaneous inspiratory:expiratory ratio", "", False),
- _MedibusField("elastance", "mbar/L", False),
- _MedibusField("time constant", "s", False),
- _MedibusField(
- "ratio between upper 20% pressure range and total dynamic compliance",
- "",
- False,
- ),
- _MedibusField("end-inspiratory pressure", "mbar", False),
- _MedibusField("expiratory tidal volume", "mL", False),
- _MedibusField("time at low pressure", "s", False),
-]
+_bin_file_formats = {
+ "original": {
+ "frame_size": 4358,
+ "medibus_fields": [
+ _MedibusField("airway pressure", "mbar", True),
+ _MedibusField("flow", "L/min", True),
+ _MedibusField("volume", "mL", True),
+ _MedibusField("CO2 (%)", "%", True),
+ _MedibusField("CO2 (kPa)", "kPa", True),
+ _MedibusField("CO2 (mmHg)", "mmHg", True),
+ _MedibusField("dynamic compliance", "mL/mbar", False),
+ _MedibusField("resistance", "mbar/L/s", False),
+ _MedibusField("r^2", "", False),
+ _MedibusField("spontaneous inspiratory time", "s", False),
+ _MedibusField("minimal pressure", "mbar", False),
+ _MedibusField("P0.1", "mbar", False),
+ _MedibusField("mean pressure", "mbar", False),
+ _MedibusField("plateau pressure", "mbar", False),
+ _MedibusField("PEEP", "mbar", False),
+ _MedibusField("intrinsic PEEP", "mbar", False),
+ _MedibusField("mandatory respiratory rate", "/min", False),
+ _MedibusField("mandatory minute volume", "L/min", False),
+ _MedibusField("peak inspiratory pressure", "mbar", False),
+ _MedibusField("mandatory tidal volume", "L", False),
+ _MedibusField("spontaneous tidal volume", "L", False),
+ _MedibusField("trapped volume", "mL", False),
+ _MedibusField("mandatory expiratory tidal volume", "mL", False),
+ _MedibusField("spontaneous expiratory tidal volume", "mL", False),
+ _MedibusField("mandatory inspiratory tidal volume", "mL", False),
+ _MedibusField("tidal volume", "mL", False),
+ _MedibusField("spontaneous inspiratory tidal volume", "mL", False),
+ _MedibusField("negative inspiratory force", "mbar", False),
+ _MedibusField("leak minute volume", "L/min", False),
+ _MedibusField("leak percentage", "%", False),
+ _MedibusField("spontaneous respiratory rate", "/min", False),
+ _MedibusField("percentage of spontaneous minute volume", "%", False),
+ _MedibusField("spontaneous minute volume", "L/min", False),
+ _MedibusField("minute volume", "L/min", False),
+ _MedibusField("airway temperature", "degrees C", False),
+ _MedibusField("rapid shallow breating index", "1/min/L", False),
+ _MedibusField("respiratory rate", "/min", False),
+ _MedibusField("inspiratory:expiratory ratio", "", False),
+ _MedibusField("CO2 flow", "mL/min", False),
+ _MedibusField("dead space volume", "mL", False),
+ _MedibusField("percentage dead space of expiratory tidal volume", "%", False),
+ _MedibusField("end-tidal CO2", "%", False),
+ _MedibusField("end-tidal CO2", "kPa", False),
+ _MedibusField("end-tidal CO2", "mmHg", False),
+ _MedibusField("fraction inspired O2", "%", False),
+ _MedibusField("spontaneous inspiratory:expiratory ratio", "", False),
+ _MedibusField("elastance", "mbar/L", False),
+ _MedibusField("time constant", "s", False),
+ _MedibusField(
+ "ratio between upper 20% pressure range and total dynamic compliance",
+ "",
+ False,
+ ),
+ _MedibusField("end-inspiratory pressure", "mbar", False),
+ _MedibusField("expiratory tidal volume", "mL", False),
+ _MedibusField("time at low pressure", "s", False),
+ ],
+ }
+}
From ac233838eba13644fcdc54ffde66eaa6d305a6e4 Mon Sep 17 00:00:00 2001
From: Peter Somhorst
Date: Mon, 16 Dec 2024 15:26:52 +0100
Subject: [PATCH 02/10] Medibus data will contain NaN instead of smallest
possible float
---
eitprocessing/datahandling/loading/draeger.py | 1 +
1 file changed, 1 insertion(+)
diff --git a/eitprocessing/datahandling/loading/draeger.py b/eitprocessing/datahandling/loading/draeger.py
index 508bd0d84..a8a48b887 100644
--- a/eitprocessing/datahandling/loading/draeger.py
+++ b/eitprocessing/datahandling/loading/draeger.py
@@ -196,6 +196,7 @@ def _convert_medibus_data(
sparsedata_collection = DataCollection(SparseData)
for field_info, data in zip(medibus_fields, medibus_data, strict=True):
+ data[data < -1e30] = np.nan
if field_info.continuous:
continuous_data = ContinuousData(
label=field_info.signal_name,
From 5337b470ed4858cfcb96f6f2accbe0d7e8113cf7 Mon Sep 17 00:00:00 2001
From: Peter Somhorst
Date: Mon, 16 Dec 2024 15:27:01 +0100
Subject: [PATCH 03/10] Add pressure pod bin file format
---
eitprocessing/datahandling/loading/draeger.py | 69 ++++++++++++++++++-
1 file changed, 68 insertions(+), 1 deletion(-)
diff --git a/eitprocessing/datahandling/loading/draeger.py b/eitprocessing/datahandling/loading/draeger.py
index a8a48b887..3ce638176 100644
--- a/eitprocessing/datahandling/loading/draeger.py
+++ b/eitprocessing/datahandling/loading/draeger.py
@@ -336,5 +336,72 @@ class _MedibusField(NamedTuple):
_MedibusField("expiratory tidal volume", "mL", False),
_MedibusField("time at low pressure", "s", False),
],
- }
+ },
+ "pressure_pod": {
+ "frame_size": 4382,
+ "medibus_fields": [
+ _MedibusField("airway pressure", "mbar", True),
+ _MedibusField("flow", "L/min", True),
+ _MedibusField("volume", "mL", True),
+ _MedibusField("CO2 (%)", "%", True),
+ _MedibusField("CO2 (kPa)", "kPa", True),
+ _MedibusField("CO2 (mmHg)", "mmHg", True),
+ _MedibusField("dynamic compliance", "mL/mbar", False),
+ _MedibusField("resistance", "mbar/L/s", False),
+ _MedibusField("r^2", "", False),
+ _MedibusField("spontaneous inspiratory time", "s", False),
+ _MedibusField("minimal pressure", "mbar", False),
+ _MedibusField("P0.1", "mbar", False),
+ _MedibusField("mean pressure", "mbar", False),
+ _MedibusField("plateau pressure", "mbar", False),
+ _MedibusField("PEEP", "mbar", False),
+ _MedibusField("intrinsic PEEP", "mbar", False),
+ _MedibusField("mandatory respiratory rate", "/min", False),
+ _MedibusField("mandatory minute volume", "L/min", False),
+ _MedibusField("peak inspiratory pressure", "mbar", False),
+ _MedibusField("mandatory tidal volume", "L", False),
+ _MedibusField("spontaneous tidal volume", "L", False),
+ _MedibusField("trapped volume", "mL", False),
+ _MedibusField("mandatory expiratory tidal volume", "mL", False),
+ _MedibusField("spontaneous expiratory tidal volume", "mL", False),
+ _MedibusField("mandatory inspiratory tidal volume", "mL", False),
+ _MedibusField("tidal volume", "mL", False),
+ _MedibusField("spontaneous inspiratory tidal volume", "mL", False),
+ _MedibusField("negative inspiratory force", "mbar", False),
+ _MedibusField("leak minute volume", "L/min", False),
+ _MedibusField("leak percentage", "%", False),
+ _MedibusField("spontaneous respiratory rate", "/min", False),
+ _MedibusField("percentage of spontaneous minute volume", "%", False),
+ _MedibusField("spontaneous minute volume", "L/min", False),
+ _MedibusField("minute volume", "L/min", False),
+ _MedibusField("airway temperature", "degrees C", False),
+ _MedibusField("rapid shallow breating index", "1/min/L", False),
+ _MedibusField("respiratory rate", "/min", False),
+ _MedibusField("inspiratory:expiratory ratio", "", False),
+ _MedibusField("CO2 flow", "mL/min", False),
+ _MedibusField("dead space volume", "mL", False),
+ _MedibusField("percentage dead space of expiratory tidal volume", "%", False),
+ _MedibusField("end-tidal CO2", "%", False),
+ _MedibusField("end-tidal CO2", "kPa", False),
+ _MedibusField("end-tidal CO2", "mmHg", False),
+ _MedibusField("fraction inspired O2", "%", False),
+ _MedibusField("spontaneous inspiratory:expiratory ratio", "", False),
+ _MedibusField("elastance", "mbar/L", False),
+ _MedibusField("time constant", "s", False),
+ _MedibusField(
+ "ratio between upper 20% pressure range and total dynamic compliance",
+ "",
+ False,
+ ),
+ _MedibusField("end-inspiratory pressure", "mbar", False),
+ _MedibusField("expiratory tidal volume", "mL", False),
+ _MedibusField("high pressure", "mbar", False),
+ _MedibusField("low pressure", "mbar", False),
+ _MedibusField("time at low pressure", "s", False),
+ _MedibusField("airway pressure (pod)", "mbar", True),
+ _MedibusField("esophageal pressure (pod)", "mbar", True),
+ _MedibusField("transpulmonary pressure (pod)", "mbar", True),
+ _MedibusField("gastric pressure/auxiliary pressure (pod)", "mbar", True),
+ ],
+ },
}
From 829159b67bcad1337f1b37d346680e491d975f82 Mon Sep 17 00:00:00 2001
From: Peter Somhorst
Date: Mon, 16 Dec 2024 15:46:54 +0100
Subject: [PATCH 04/10] Replace fixed value with constant
---
eitprocessing/datahandling/loading/draeger.py | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/eitprocessing/datahandling/loading/draeger.py b/eitprocessing/datahandling/loading/draeger.py
index 3ce638176..4c580bfd0 100644
--- a/eitprocessing/datahandling/loading/draeger.py
+++ b/eitprocessing/datahandling/loading/draeger.py
@@ -23,6 +23,7 @@
from numpy.typing import NDArray
load_draeger_data = partial(load_eit_data, vendor=Vendor.DRAEGER)
+NAN_VALUE_INDICATOR = -1e30
def load_from_single_path(
@@ -196,7 +197,7 @@ def _convert_medibus_data(
sparsedata_collection = DataCollection(SparseData)
for field_info, data in zip(medibus_fields, medibus_data, strict=True):
- data[data < -1e30] = np.nan
+ data[data < NAN_VALUE_INDICATOR] = np.nan
if field_info.continuous:
continuous_data = ContinuousData(
label=field_info.signal_name,
From db0d104764a843dc5c33ed9e25ca5c640d1d44a1 Mon Sep 17 00:00:00 2001
From: Peter Somhorst
Date: Mon, 16 Dec 2024 20:48:05 +0100
Subject: [PATCH 05/10] Add test for loading draeger data including pressure
pod data
---
tests/conftest.py | 6 ++++++
tests/test_loading.py | 5 +++++
2 files changed, 11 insertions(+)
diff --git a/tests/conftest.py b/tests/conftest.py
index 748099f67..9ec0e72b1 100644
--- a/tests/conftest.py
+++ b/tests/conftest.py
@@ -16,6 +16,7 @@
draeger_file2 = data_directory / "Draeger_Test.bin"
draeger_file3 = data_directory / "Draeger_Test_event_on_first_frame.bin"
draeger_wrapped_time_axis_file = data_directory / "Draeger_wrapped_time_axis.bin"
+draeger_file_pp = data_directory / "Draeger_PP_data.bin"
timpel_file = data_directory / "Timpel_test.txt"
dummy_file = data_directory / "not_a_file.dummy"
@@ -35,6 +36,11 @@ def draeger_both():
return load_eit_data([draeger_file2, draeger_file1], vendor="draeger", sample_frequency=20, label="draeger_both")
+@pytest.fixture(scope="session")
+def draeger_pp():
+ return load_eit_data(draeger_file_pp, vendor="draeger", sample_frequency=20, label="draeger2")
+
+
@pytest.fixture(scope="session")
def timpel1():
return load_eit_data(timpel_file, vendor="timpel", label="timpel")
diff --git a/tests/test_loading.py b/tests/test_loading.py
index 46c748d26..27cf65326 100644
--- a/tests/test_loading.py
+++ b/tests/test_loading.py
@@ -19,6 +19,7 @@ def test_loading_draeger(
draeger1: Sequence,
draeger2: Sequence,
draeger_both: Sequence,
+ draeger_pp: Sequence,
):
assert isinstance(draeger1, Sequence)
assert isinstance(draeger1.eit_data["raw"], EITData)
@@ -35,6 +36,10 @@ def test_loading_draeger(
draeger2.eit_data["raw"],
)
+ # draeger data with pressure pod data has 10 continuous medibus fields, 'normal' only 6
+ assert len(draeger_pp.continuous_data) == 10 + 1
+ assert len(draeger1.continuous_data) == 6 + 1
+
# test below not possible due to requirement of axis 1 ending before axis b starts
# draeger_inverted = load_eit_data([draeger_file1, draeger_file2], vendor="draeger", label="inverted")
# assert len(draeger_both) == len(draeger_inverted)
From ffbf411da2a125bbaafe4ffa5c0ef156c1bb67b2 Mon Sep 17 00:00:00 2001
From: Peter Somhorst
Date: Mon, 16 Dec 2024 20:49:01 +0100
Subject: [PATCH 06/10] Remove mention of draeger data limitation
---
eitprocessing/datahandling/loading/__init__.py | 4 ----
1 file changed, 4 deletions(-)
diff --git a/eitprocessing/datahandling/loading/__init__.py b/eitprocessing/datahandling/loading/__init__.py
index ca3c37d9f..e037e4085 100644
--- a/eitprocessing/datahandling/loading/__init__.py
+++ b/eitprocessing/datahandling/loading/__init__.py
@@ -18,10 +18,6 @@ def load_eit_data(
) -> Sequence:
"""Load EIT data from path(s).
- Current limitations:
- - Dräger data is assumed to have a limited set of (Medibus) data. Newer additions that add data like pleural
- pressure are not yet supported.
-
Args:
path: relative or absolute path(s) to data file.
vendor: vendor indicating the device used.
From a864c163050f1a679114a570ef727075a950327a Mon Sep 17 00:00:00 2001
From: Peter Somhorst
Date: Mon, 16 Dec 2024 21:02:01 +0100
Subject: [PATCH 07/10] Fix sample frequency of pressure pod data
---
tests/conftest.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/tests/conftest.py b/tests/conftest.py
index 9ec0e72b1..b1fd7d619 100644
--- a/tests/conftest.py
+++ b/tests/conftest.py
@@ -38,7 +38,7 @@ def draeger_both():
@pytest.fixture(scope="session")
def draeger_pp():
- return load_eit_data(draeger_file_pp, vendor="draeger", sample_frequency=20, label="draeger2")
+ return load_eit_data(draeger_file_pp, vendor="draeger", sample_frequency=50, label="draeger2")
@pytest.fixture(scope="session")
From 917eca8981aaaf9ae7f5a3aaf85072685e66f665 Mon Sep 17 00:00:00 2001
From: Peter Somhorst
Date: Mon, 20 Jan 2025 14:21:59 +0100
Subject: [PATCH 08/10] Clarify determination of file format
---
eitprocessing/datahandling/loading/draeger.py | 7 ++++++-
1 file changed, 6 insertions(+), 1 deletion(-)
diff --git a/eitprocessing/datahandling/loading/draeger.py b/eitprocessing/datahandling/loading/draeger.py
index 4c580bfd0..a8d3816af 100644
--- a/eitprocessing/datahandling/loading/draeger.py
+++ b/eitprocessing/datahandling/loading/draeger.py
@@ -35,9 +35,14 @@ def load_from_single_path(
"""Load Dräger EIT data from path."""
file_size = path.stat().st_size
+ frame_size: int
+ medibus_fields: list
+
+ # iterate over the supported file formats to find the frame size that matches the file size
for _file_format_data in _bin_file_formats.values():
- frame_size: int = _file_format_data["frame_size"]
+ frame_size = _file_format_data["frame_size"]
if file_size % frame_size == 0:
+ # if the file size is an integer multiple of the frame size, assume this is the correct format
medibus_fields = _file_format_data["medibus_fields"]
break
else:
From 094dd9454553b2c49d0765d10625784e8dc788d6 Mon Sep 17 00:00:00 2001
From: Peter Somhorst
Date: Mon, 20 Jan 2025 14:22:19 +0100
Subject: [PATCH 09/10] Fix type of medibus data to 32 bit float
---
eitprocessing/datahandling/loading/draeger.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/eitprocessing/datahandling/loading/draeger.py b/eitprocessing/datahandling/loading/draeger.py
index a8d3816af..d7184125f 100644
--- a/eitprocessing/datahandling/loading/draeger.py
+++ b/eitprocessing/datahandling/loading/draeger.py
@@ -79,7 +79,7 @@ def load_from_single_path(
time = np.zeros((n_frames,))
events: list[tuple[float, Event]] = []
phases: list[tuple[float, int]] = []
- medibus_data = np.zeros((len(medibus_fields), n_frames))
+ medibus_data = np.zeros((len(medibus_fields), n_frames), dtype=np.float32)
with path.open("br") as fo, mmap.mmap(fo.fileno(), length=0, access=mmap.ACCESS_READ) as fh:
fh.seek(first_frame_to_load * frame_size)
From 098dc69f60fd3c85ab213148513ee015ed7e59b2 Mon Sep 17 00:00:00 2001
From: Peter Somhorst
Date: Mon, 20 Jan 2025 14:22:30 +0100
Subject: [PATCH 10/10] Move estimation of sample frequency to separate
function
---
eitprocessing/datahandling/loading/draeger.py | 31 ++++++++++++-------
1 file changed, 19 insertions(+), 12 deletions(-)
diff --git a/eitprocessing/datahandling/loading/draeger.py b/eitprocessing/datahandling/loading/draeger.py
index d7184125f..c23fc665a 100644
--- a/eitprocessing/datahandling/loading/draeger.py
+++ b/eitprocessing/datahandling/loading/draeger.py
@@ -100,21 +100,11 @@ def load_from_single_path(
previous_marker,
)
- estimated_sample_frequency = round((len(time) - 1) / (time[-1] - time[0]), 4)
-
- if not sample_frequency:
- sample_frequency = estimated_sample_frequency
-
- elif sample_frequency != estimated_sample_frequency:
- msg = (
- f"Provided sample frequency ({sample_frequency}) does not match "
- f"the estimated sample frequency ({estimated_sample_frequency})."
- )
- warnings.warn(msg, RuntimeWarning)
-
# time wraps around the number of seconds in a day
time = np.unwrap(time, period=24 * 60 * 60)
+ sample_frequency = _estimate_sample_frequency(time, sample_frequency)
+
eit_data = EITData(
vendor=Vendor.DRAEGER,
path=path,
@@ -192,6 +182,23 @@ def load_from_single_path(
}
+def _estimate_sample_frequency(time: np.ndarray, sample_frequency: float | None) -> float:
+ """Estimate the sample frequency from the time axis, and check with provided sample frequency."""
+ estimated_sample_frequency = round((len(time) - 1) / (time[-1] - time[0]), 4)
+
+ if sample_frequency is None:
+ return estimated_sample_frequency
+
+ if sample_frequency != estimated_sample_frequency:
+ msg = (
+ f"Provided sample frequency ({sample_frequency}) does not match "
+ f"the estimated sample frequency ({estimated_sample_frequency})."
+ )
+ warnings.warn(msg, RuntimeWarning)
+
+ return sample_frequency
+
+
def _convert_medibus_data(
medibus_data: NDArray,
medibus_fields: list,