zea 0.0.7__py3-none-any.whl → 0.0.8__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- zea/__init__.py +1 -1
- zea/backend/tensorflow/dataloader.py +0 -4
- zea/beamform/pixelgrid.py +1 -1
- zea/data/__init__.py +0 -9
- zea/data/augmentations.py +221 -28
- zea/data/convert/__init__.py +1 -6
- zea/data/convert/__main__.py +123 -0
- zea/data/convert/camus.py +99 -39
- zea/data/convert/echonet.py +183 -82
- zea/data/convert/echonetlvh/README.md +2 -3
- zea/data/convert/echonetlvh/{convert_raw_to_usbmd.py → __init__.py} +173 -102
- zea/data/convert/echonetlvh/manual_rejections.txt +73 -0
- zea/data/convert/echonetlvh/precompute_crop.py +43 -64
- zea/data/convert/picmus.py +37 -40
- zea/data/convert/utils.py +86 -0
- zea/data/convert/{matlab.py → verasonics.py} +33 -61
- zea/data/data_format.py +124 -4
- zea/data/dataloader.py +12 -7
- zea/data/datasets.py +109 -70
- zea/data/file.py +91 -82
- zea/data/file_operations.py +496 -0
- zea/data/preset_utils.py +1 -1
- zea/display.py +7 -8
- zea/internal/checks.py +6 -12
- zea/internal/operators.py +4 -0
- zea/io_lib.py +108 -160
- zea/models/__init__.py +1 -1
- zea/models/diffusion.py +62 -11
- zea/models/lv_segmentation.py +2 -0
- zea/ops.py +398 -158
- zea/scan.py +18 -8
- zea/tensor_ops.py +82 -62
- zea/tools/fit_scan_cone.py +90 -160
- zea/tracking/__init__.py +16 -0
- zea/tracking/base.py +94 -0
- zea/tracking/lucas_kanade.py +474 -0
- zea/tracking/segmentation.py +110 -0
- zea/utils.py +11 -2
- {zea-0.0.7.dist-info → zea-0.0.8.dist-info}/METADATA +3 -1
- {zea-0.0.7.dist-info → zea-0.0.8.dist-info}/RECORD +43 -35
- {zea-0.0.7.dist-info → zea-0.0.8.dist-info}/WHEEL +0 -0
- {zea-0.0.7.dist-info → zea-0.0.8.dist-info}/entry_points.txt +0 -0
- {zea-0.0.7.dist-info → zea-0.0.8.dist-info}/licenses/LICENSE +0 -0
zea/data/file.py
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
import enum
|
|
4
4
|
from pathlib import Path
|
|
5
|
-
from typing import List
|
|
5
|
+
from typing import List, Tuple, Union
|
|
6
6
|
|
|
7
7
|
import h5py
|
|
8
8
|
import numpy as np
|
|
@@ -16,6 +16,7 @@ from zea.internal.checks import (
|
|
|
16
16
|
_REQUIRED_SCAN_KEYS,
|
|
17
17
|
get_check,
|
|
18
18
|
)
|
|
19
|
+
from zea.internal.core import DataTypes
|
|
19
20
|
from zea.internal.utils import reduce_to_signature
|
|
20
21
|
from zea.probes import Probe
|
|
21
22
|
from zea.scan import Scan
|
|
@@ -111,64 +112,10 @@ class File(h5py.File):
|
|
|
111
112
|
else:
|
|
112
113
|
raise NotImplementedError
|
|
113
114
|
|
|
114
|
-
@staticmethod
|
|
115
|
-
def _prepare_indices(indices):
|
|
116
|
-
"""Prepare the indices for loading data from hdf5 files.
|
|
117
|
-
Options:
|
|
118
|
-
- str("all")
|
|
119
|
-
- int -> single frame
|
|
120
|
-
- list of ints -> indexes first axis (frames)
|
|
121
|
-
- list of list, ranges or slices -> indexes multiple axes
|
|
122
|
-
|
|
123
|
-
Returns:
|
|
124
|
-
indices (tuple): A tuple of indices / slices to use for indexing.
|
|
125
|
-
"""
|
|
126
|
-
_value_error_msg = (
|
|
127
|
-
f"Invalid value for indices: {indices}. "
|
|
128
|
-
"Indices can be a 'all', int or a List[int, tuple, list, slice, range]."
|
|
129
|
-
)
|
|
130
|
-
|
|
131
|
-
# Check all options that only index the first axis
|
|
132
|
-
if isinstance(indices, str):
|
|
133
|
-
if indices == "all":
|
|
134
|
-
return slice(None)
|
|
135
|
-
else:
|
|
136
|
-
raise ValueError(_value_error_msg)
|
|
137
|
-
|
|
138
|
-
if isinstance(indices, range):
|
|
139
|
-
return list(indices)
|
|
140
|
-
|
|
141
|
-
if isinstance(indices, (int, slice, np.integer)):
|
|
142
|
-
return indices
|
|
143
|
-
|
|
144
|
-
# At this point, indices should be a list or tuple
|
|
145
|
-
assert isinstance(indices, (list, tuple, np.ndarray)), _value_error_msg
|
|
146
|
-
|
|
147
|
-
assert all(
|
|
148
|
-
isinstance(idx, (list, tuple, int, slice, range, np.ndarray, np.integer))
|
|
149
|
-
for idx in indices
|
|
150
|
-
), _value_error_msg
|
|
151
|
-
|
|
152
|
-
# Convert ranges to lists
|
|
153
|
-
processed_indices = [list(idx) if isinstance(idx, range) else idx for idx in indices]
|
|
154
|
-
|
|
155
|
-
# Check if items are list-like and cast to tuple (needed for hdf5)
|
|
156
|
-
if any(isinstance(idx, (list, tuple, slice)) for idx in processed_indices):
|
|
157
|
-
processed_indices = tuple(processed_indices)
|
|
158
|
-
|
|
159
|
-
return processed_indices
|
|
160
|
-
|
|
161
115
|
def load_scan(self, event=None):
|
|
162
116
|
"""Alias for get_scan_parameters."""
|
|
163
117
|
return self.get_scan_parameters(event)
|
|
164
118
|
|
|
165
|
-
@staticmethod
|
|
166
|
-
def check_data(data, key):
|
|
167
|
-
"""Check the data for a given key. For example, will check if the shape matches
|
|
168
|
-
the data type (such as raw_data, ...)"""
|
|
169
|
-
if key in _DATA_TYPES:
|
|
170
|
-
get_check(key)(data, with_batch_dim=None)
|
|
171
|
-
|
|
172
119
|
def format_key(self, key):
|
|
173
120
|
"""Format the key to match the data type."""
|
|
174
121
|
# TODO: support events
|
|
@@ -206,7 +153,7 @@ class File(h5py.File):
|
|
|
206
153
|
def load_transmits(self, key, selected_transmits):
|
|
207
154
|
"""Load raw_data or aligned_data for a given list of transmits.
|
|
208
155
|
Args:
|
|
209
|
-
|
|
156
|
+
key (str): The type of data to load. Options are 'raw_data' and 'aligned_data'.
|
|
210
157
|
selected_transmits (list, np.ndarray): The transmits to load.
|
|
211
158
|
"""
|
|
212
159
|
key = self.format_key(key)
|
|
@@ -214,23 +161,18 @@ class File(h5py.File):
|
|
|
214
161
|
assert data_type in ["raw_data", "aligned_data"], (
|
|
215
162
|
f"Cannot load transmits for {data_type}. Only raw_data and aligned_data are supported."
|
|
216
163
|
)
|
|
217
|
-
|
|
164
|
+
# First axis: all frames, second axis: selected transmits
|
|
165
|
+
indices = (slice(None), np.array(selected_transmits))
|
|
218
166
|
return self.load_data(key, indices)
|
|
219
167
|
|
|
220
|
-
def load_data(
|
|
168
|
+
def load_data(
|
|
169
|
+
self,
|
|
170
|
+
data_type,
|
|
171
|
+
indices: Tuple[Union[list, slice, int], ...] | List[int] | int | None = None,
|
|
172
|
+
):
|
|
221
173
|
"""Load data from the file.
|
|
222
174
|
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
- 'all' to load all data
|
|
226
|
-
|
|
227
|
-
- an int to load a single frame
|
|
228
|
-
|
|
229
|
-
- a list of ints to load specific frames
|
|
230
|
-
|
|
231
|
-
- a tuple of lists, ranges or slices to index frames and transmits. Note that
|
|
232
|
-
indexing with lists of indices for both axes is not supported. In that case,
|
|
233
|
-
try to define one of the axes with a slice.
|
|
175
|
+
.. include:: ../common/file_indexing.rst
|
|
234
176
|
|
|
235
177
|
.. doctest::
|
|
236
178
|
|
|
@@ -258,13 +200,12 @@ class File(h5py.File):
|
|
|
258
200
|
Args:
|
|
259
201
|
data_type (str): The type of data to load. Options are 'raw_data', 'aligned_data',
|
|
260
202
|
'beamformed_data', 'envelope_data', 'image' and 'image_sc'.
|
|
261
|
-
indices (
|
|
262
|
-
which case all
|
|
263
|
-
as a single index. If a list is provided, it will be used as a list of
|
|
264
|
-
indices.
|
|
203
|
+
indices (optional): The indices to load. Defaults to `None` in
|
|
204
|
+
which case all data is loaded.
|
|
265
205
|
"""
|
|
266
206
|
key = self.format_key(data_type)
|
|
267
|
-
indices
|
|
207
|
+
if indices is None or (isinstance(indices, str) and indices == "all"):
|
|
208
|
+
indices = slice(None)
|
|
268
209
|
|
|
269
210
|
if self._simple_index(key):
|
|
270
211
|
data = self[key]
|
|
@@ -274,7 +215,6 @@ class File(h5py.File):
|
|
|
274
215
|
raise ValueError(
|
|
275
216
|
f"Invalid indices {indices} for key {key}. {key} has shape {data.shape}."
|
|
276
217
|
) from exc
|
|
277
|
-
self.check_data(data, key)
|
|
278
218
|
elif self.events_have_same_shape(key):
|
|
279
219
|
raise NotImplementedError
|
|
280
220
|
else:
|
|
@@ -425,6 +365,21 @@ class File(h5py.File):
|
|
|
425
365
|
ans[key] = self.recursively_load_dict_contents_from_group(path + "/" + key + "/")
|
|
426
366
|
return ans
|
|
427
367
|
|
|
368
|
+
def has_key(self, key: str) -> bool:
|
|
369
|
+
"""Check if the file has a specific key.
|
|
370
|
+
|
|
371
|
+
Args:
|
|
372
|
+
key (str): The key to check.
|
|
373
|
+
|
|
374
|
+
Returns:
|
|
375
|
+
bool: True if the key exists, False otherwise.
|
|
376
|
+
"""
|
|
377
|
+
try:
|
|
378
|
+
key = self.format_key(key)
|
|
379
|
+
except AssertionError:
|
|
380
|
+
return False
|
|
381
|
+
return True
|
|
382
|
+
|
|
428
383
|
@classmethod
|
|
429
384
|
def get_shape(cls, path: str, key: str) -> tuple:
|
|
430
385
|
"""Get the shape of a key in a file.
|
|
@@ -490,10 +445,67 @@ class File(h5py.File):
|
|
|
490
445
|
_print_hdf5_attrs(self)
|
|
491
446
|
|
|
492
447
|
|
|
448
|
+
def load_file_all_data_types(
|
|
449
|
+
path,
|
|
450
|
+
indices: Tuple[Union[list, slice, int], ...] | List[int] | int | None = None,
|
|
451
|
+
scan_kwargs: dict = None,
|
|
452
|
+
):
|
|
453
|
+
"""Loads a zea data files (h5py file).
|
|
454
|
+
|
|
455
|
+
Returns all data types together with a scan object containing the parameters
|
|
456
|
+
of the acquisition and a probe object containing the parameters of the probe.
|
|
457
|
+
|
|
458
|
+
Additionally, it can load a specific subset of frames / transmits.
|
|
459
|
+
|
|
460
|
+
.. include:: ../common/file_indexing.rst
|
|
461
|
+
|
|
462
|
+
Args:
|
|
463
|
+
path (str, pathlike): The path to the hdf5 file.
|
|
464
|
+
indices (optional): The indices to load. Defaults to None in
|
|
465
|
+
which case all frames are loaded.
|
|
466
|
+
scan_kwargs (Config, dict, optional): Additional keyword arguments
|
|
467
|
+
to pass to the Scan object. These will override the parameters from the file
|
|
468
|
+
if they are present in the file. Defaults to None.
|
|
469
|
+
|
|
470
|
+
Returns:
|
|
471
|
+
(dict): A dictionary with all data types as keys and the corresponding data as values.
|
|
472
|
+
(Scan): A scan object containing the parameters of the acquisition.
|
|
473
|
+
(Probe): A probe object containing the parameters of the probe.
|
|
474
|
+
"""
|
|
475
|
+
# Define the additional keyword parameters from the scan object
|
|
476
|
+
if scan_kwargs is None:
|
|
477
|
+
scan_kwargs = {}
|
|
478
|
+
|
|
479
|
+
data_dict = {}
|
|
480
|
+
|
|
481
|
+
with File(path, mode="r") as file:
|
|
482
|
+
# Load the probe object from the file
|
|
483
|
+
probe = file.probe()
|
|
484
|
+
|
|
485
|
+
for data_type in DataTypes:
|
|
486
|
+
if not file.has_key(data_type.value):
|
|
487
|
+
data_dict[data_type.value] = None
|
|
488
|
+
continue
|
|
489
|
+
|
|
490
|
+
# Load the desired frames from the file
|
|
491
|
+
data_dict[data_type.value] = file.load_data(data_type.value, indices=indices)
|
|
492
|
+
|
|
493
|
+
# extract transmits from indices
|
|
494
|
+
# we only have to do this when the data has a n_tx dimension
|
|
495
|
+
# in that case we also have update scan parameters to match
|
|
496
|
+
# the number of selected transmits
|
|
497
|
+
if isinstance(indices, tuple) and len(indices) > 1:
|
|
498
|
+
scan_kwargs["selected_transmits"] = indices[1]
|
|
499
|
+
|
|
500
|
+
scan = file.scan(**scan_kwargs)
|
|
501
|
+
|
|
502
|
+
return data_dict, scan, probe
|
|
503
|
+
|
|
504
|
+
|
|
493
505
|
def load_file(
|
|
494
506
|
path,
|
|
495
507
|
data_type="raw_data",
|
|
496
|
-
indices:
|
|
508
|
+
indices: Tuple[Union[list, slice, int], ...] | List[int] | int | None = None,
|
|
497
509
|
scan_kwargs: dict = None,
|
|
498
510
|
):
|
|
499
511
|
"""Loads a zea data files (h5py file).
|
|
@@ -503,17 +515,15 @@ def load_file(
|
|
|
503
515
|
|
|
504
516
|
Additionally, it can load a specific subset of frames / transmits.
|
|
505
517
|
|
|
506
|
-
|
|
518
|
+
.. include:: ../common/file_indexing.rst
|
|
507
519
|
|
|
508
520
|
Args:
|
|
509
521
|
path (str, pathlike): The path to the hdf5 file.
|
|
510
522
|
data_type (str, optional): The type of data to load. Defaults to
|
|
511
523
|
'raw_data'. Other options are 'aligned_data', 'beamformed_data',
|
|
512
524
|
'envelope_data', 'image' and 'image_sc'.
|
|
513
|
-
indices (
|
|
514
|
-
which case all frames are loaded.
|
|
515
|
-
as a single index. If a list is provided, it will be used as a list of
|
|
516
|
-
indices.
|
|
525
|
+
indices (optional): The indices to load. Defaults to None in
|
|
526
|
+
which case all frames are loaded.
|
|
517
527
|
scan_kwargs (Config, dict, optional): Additional keyword arguments
|
|
518
528
|
to pass to the Scan object. These will override the parameters from the file
|
|
519
529
|
if they are present in the file. Defaults to None.
|
|
@@ -539,7 +549,6 @@ def load_file(
|
|
|
539
549
|
# in that case we also have update scan parameters to match
|
|
540
550
|
# the number of selected transmits
|
|
541
551
|
if data_type in ["raw_data", "aligned_data"]:
|
|
542
|
-
indices = File._prepare_indices(indices)
|
|
543
552
|
if isinstance(indices, tuple) and len(indices) > 1:
|
|
544
553
|
scan_kwargs["selected_transmits"] = indices[1]
|
|
545
554
|
|