diff --git a/.gitignore b/.gitignore index 2ba7edec79a71c3affe1802207f82be2801d113a..f8dcb218fce7c4136c9aedd300cde151fa259618 100644 --- a/.gitignore +++ b/.gitignore @@ -22,3 +22,4 @@ cache/ .venv .pixi results*/ +environment.yaml diff --git a/src/mednet/libs/classification/config/data/hivtb/datamodule.py b/src/mednet/libs/classification/config/data/hivtb/datamodule.py index 190832504db85bd9e07b1f561a31e0d4841e3dad..5d8170b77d50d658b22f3716ed2890a2eb395545 100644 --- a/src/mednet/libs/classification/config/data/hivtb/datamodule.py +++ b/src/mednet/libs/classification/config/data/hivtb/datamodule.py @@ -10,11 +10,15 @@ import os import pathlib import PIL.Image +from mednet.libs.classification.data.typing import ( + ClassificationRawDataLoader as _ClassificationRawDataLoader, +) from mednet.libs.common.data.datamodule import CachingDataModule from mednet.libs.common.data.image_utils import remove_black_borders + from mednet.libs.common.data.split import make_split from mednet.libs.common.data.typing import Sample -from mednet.libs.common.data.typing import RawDataLoader as _BaseRawDataLoader + from torchvision.transforms.functional import to_tensor from ....utils.rc import load_rc @@ -24,7 +28,7 @@ CONFIGURATION_KEY_DATADIR = "datadir." + (__name__.rsplit(".", 2)[-2]) database.""" -class RawDataLoader(_BaseRawDataLoader): +class ClassificationRawDataLoader(_ClassificationRawDataLoader): """A specialized raw-data-loader for the HIV-TB dataset.""" datadir: pathlib.Path @@ -123,7 +127,7 @@ class DataModule(CachingDataModule): assert __package__ is not None super().__init__( database_split=make_split(__package__, split_filename), - raw_data_loader=RawDataLoader(), - database_name=__package__.rsplit(".", 1)[1], + raw_data_loader=_ClassificationRawDataLoader(), + database_name=__package__.rsplit(".", 1)[1], split_name=pathlib.Path(split_filename).stem, ) diff --git a/src/mednet/libs/classification/config/data/indian/datamodule.py b/src/mednet/libs/classification/config/data/indian/datamodule.py index 6b4f9c77631e00f6a2cb1172b18147151112b0b9..63ff00c284201f797dc4eb51f5b1e7ef8c723f4f 100644 --- a/src/mednet/libs/classification/config/data/indian/datamodule.py +++ b/src/mednet/libs/classification/config/data/indian/datamodule.py @@ -11,8 +11,9 @@ import pathlib from mednet.libs.common.data.datamodule import CachingDataModule from mednet.libs.common.data.split import make_split -from ....config.data.shenzhen.datamodule import RawDataLoader - +from mednet.libs.classification.data.typing import ( + ClassificationRawDataLoader as _ClassificationRawDataLoader, +) CONFIGURATION_KEY_DATADIR = "datadir." + (__name__.rsplit(".", 2)[-2]) """Key to search for in the configuration file for the root directory of this database.""" @@ -60,10 +61,11 @@ class DataModule(CachingDataModule): """ def __init__(self, split_filename: str): - assert __package__ + assert __package__ is not None super().__init__( database_split=make_split(__package__, split_filename), - raw_data_loader=RawDataLoader(config_variable=CONFIGURATION_KEY_DATADIR), - database_name=__package__.rsplit(".", 1)[1], + raw_data_loader=_ClassificationRawDataLoader(), + database_name=__package__.rsplit(".", 1)[1], split_name=pathlib.Path(split_filename).stem, ) + diff --git a/src/mednet/libs/classification/config/data/montgomery/datamodule.py b/src/mednet/libs/classification/config/data/montgomery/datamodule.py index ecdd12a8bc351e6c1ca4299a48a44444aaac3ec4..83753205a142a5c06548527dc224a75849718768 100644 --- a/src/mednet/libs/classification/config/data/montgomery/datamodule.py +++ b/src/mednet/libs/classification/config/data/montgomery/datamodule.py @@ -10,11 +10,15 @@ import os import pathlib import PIL.Image +from mednet.libs.classification.data.typing import ( + ClassificationRawDataLoader as _ClassificationRawDataLoader, +) from mednet.libs.common.data.datamodule import CachingDataModule from mednet.libs.common.data.image_utils import remove_black_borders + from mednet.libs.common.data.split import make_split from mednet.libs.common.data.typing import Sample -from mednet.libs.common.data.typing import RawDataLoader as _BaseRawDataLoader + from torchvision.transforms.functional import to_tensor from ....utils.rc import load_rc @@ -136,7 +140,7 @@ class DataModule(CachingDataModule): assert __package__ is not None super().__init__( database_split=make_split(__package__, split_filename), - raw_data_loader=RawDataLoader(), - database_name=__package__.rsplit(".", 1)[1], + raw_data_loader=_ClassificationRawDataLoader(), + database_name=__package__.rsplit(".", 1)[1], split_name=pathlib.Path(split_filename).stem, ) diff --git a/src/mednet/libs/classification/config/data/montgomery_shenzhen/datamodule.py b/src/mednet/libs/classification/config/data/montgomery_shenzhen/datamodule.py index f3bf981423df05cf61b80fcd0382fa6fca05ad46..cce90f7a2a1fc48d7381653fcb09c04b8ec464ae 100644 --- a/src/mednet/libs/classification/config/data/montgomery_shenzhen/datamodule.py +++ b/src/mednet/libs/classification/config/data/montgomery_shenzhen/datamodule.py @@ -8,8 +8,10 @@ import pathlib from mednet.libs.common.data.datamodule import ConcatDataModule from mednet.libs.common.data.split import make_split -from ..montgomery.datamodule import RawDataLoader as MontgomeryLoader -from ..shenzhen.datamodule import RawDataLoader as ShenzhenLoader +from ..montgomery.datamodule import ( + ClassificationRawDataLoader as MontgomeryLoader, +) +from ..shenzhen.datamodule import ClassificationRawDataLoader as ShenzhenLoader class DataModule(ConcatDataModule): diff --git a/src/mednet/libs/classification/config/data/montgomery_shenzhen_indian/datamodule.py b/src/mednet/libs/classification/config/data/montgomery_shenzhen_indian/datamodule.py index 73b6d765be2a9e938f9d1675a2261fb263524ddc..b09fa338731907c6a5fcd0196eccff6d57013c2b 100644 --- a/src/mednet/libs/classification/config/data/montgomery_shenzhen_indian/datamodule.py +++ b/src/mednet/libs/classification/config/data/montgomery_shenzhen_indian/datamodule.py @@ -12,9 +12,11 @@ from mednet.libs.common.data.split import make_split from ..indian.datamodule import CONFIGURATION_KEY_DATADIR as INDIAN_KEY_DATADIR from ..indian.datamodule import DataModule as IndianDataModule -from ..indian.datamodule import RawDataLoader as IndianLoader -from ..montgomery.datamodule import RawDataLoader as MontgomeryLoader -from ..shenzhen.datamodule import RawDataLoader as ShenzhenLoader +from ..indian.datamodule import ClassificationRawDataLoader as IndianLoader +from ..montgomery.datamodule import ( + ClassificationRawDataLoader as MontgomeryLoader, +) +from ..shenzhen.datamodule import ClassificationRawDataLoader as ShenzhenLoader class DataModule(ConcatDataModule): diff --git a/src/mednet/libs/classification/config/data/montgomery_shenzhen_indian_padchest/datamodule.py b/src/mednet/libs/classification/config/data/montgomery_shenzhen_indian_padchest/datamodule.py index 942326b2cde9e920bb764a812d8b0eea03cb3398..5daef8128be0293db3e45270593eb851337580a5 100644 --- a/src/mednet/libs/classification/config/data/montgomery_shenzhen_indian_padchest/datamodule.py +++ b/src/mednet/libs/classification/config/data/montgomery_shenzhen_indian_padchest/datamodule.py @@ -11,11 +11,13 @@ from mednet.libs.common.data.datamodule import ConcatDataModule from mednet.libs.common.data.split import make_split from ..indian.datamodule import CONFIGURATION_KEY_DATADIR as INDIAN_KEY_DATADIR +from ..indian.datamodule import ClassificationRawDataLoader as IndianLoader from ..indian.datamodule import DataModule as IndianDataModule -from ..indian.datamodule import RawDataLoader as IndianLoader -from ..montgomery.datamodule import RawDataLoader as MontgomeryLoader -from ..padchest.datamodule import RawDataLoader as PadchestLoader -from ..shenzhen.datamodule import RawDataLoader as ShenzhenLoader +from ..montgomery.datamodule import ( + ClassificationRawDataLoader as MontgomeryLoader, +) +from ..padchest.datamodule import ClassificationRawDataLoader as PadchestLoader +from ..shenzhen.datamodule import ClassificationRawDataLoader as ShenzhenLoader class DataModule(ConcatDataModule): diff --git a/src/mednet/libs/classification/config/data/montgomery_shenzhen_indian_tbx11k/datamodule.py b/src/mednet/libs/classification/config/data/montgomery_shenzhen_indian_tbx11k/datamodule.py index daf575f7abe5376659559ad168f72d2d31389368..532945277debb3558fae1a97c0a26d434690cea4 100644 --- a/src/mednet/libs/classification/config/data/montgomery_shenzhen_indian_tbx11k/datamodule.py +++ b/src/mednet/libs/classification/config/data/montgomery_shenzhen_indian_tbx11k/datamodule.py @@ -12,10 +12,12 @@ from mednet.libs.common.data.split import make_split from ..indian.datamodule import CONFIGURATION_KEY_DATADIR as INDIAN_KEY_DATADIR from ..indian.datamodule import DataModule as IndianDataModule -from ..indian.datamodule import RawDataLoader as IndianLoader -from ..montgomery.datamodule import RawDataLoader as MontgomeryLoader -from ..shenzhen.datamodule import RawDataLoader as ShenzhenLoader -from ..tbx11k.datamodule import RawDataLoader as TBX11kLoader +from ..indian.datamodule import ClassificationRawDataLoader as IndianLoader +from ..montgomery.datamodule import ( + ClassificationRawDataLoader as MontgomeryLoader, +) +from ..shenzhen.datamodule import ClassificationRawDataLoader as ShenzhenLoader +from ..tbx11k.datamodule import ClassificationRawDataLoader as TBX11kLoader class DataModule(ConcatDataModule): diff --git a/src/mednet/libs/classification/config/data/nih_cxr14/datamodule.py b/src/mednet/libs/classification/config/data/nih_cxr14/datamodule.py index 10b02268f61c7105e7057e699f3580a4d80b89ff..900dcc9d0091a8571629bf283ee6c1829fa62286 100644 --- a/src/mednet/libs/classification/config/data/nih_cxr14/datamodule.py +++ b/src/mednet/libs/classification/config/data/nih_cxr14/datamodule.py @@ -10,10 +10,14 @@ import os import pathlib import PIL.Image +from mednet.libs.classification.data.typing import ( + ClassificationRawDataLoader as _ClassificationRawDataLoader, +) from mednet.libs.common.data.datamodule import CachingDataModule + from mednet.libs.common.data.split import make_split from mednet.libs.common.data.typing import Sample -from mednet.libs.common.data.typing import RawDataLoader as _BaseRawDataLoader + from torchvision.transforms.functional import to_tensor from ....utils.rc import load_rc @@ -35,7 +39,7 @@ different folder structure, that was adapted to Idiap's requirements """ -class RawDataLoader(_BaseRawDataLoader): +class ClassificationRawDataLoader(_ClassificationRawDataLoader): """A specialized raw-data-loader for the NIH CXR-14 dataset.""" datadir: pathlib.Path @@ -172,7 +176,7 @@ class DataModule(CachingDataModule): assert __package__ is not None super().__init__( database_split=make_split(__package__, split_filename), - raw_data_loader=RawDataLoader(), - database_name=__package__.rsplit(".", 1)[1], + raw_data_loader=_ClassificationRawDataLoader(), + database_name=__package__.rsplit(".", 1)[1], split_name=pathlib.Path(split_filename).stem, ) diff --git a/src/mednet/libs/classification/config/data/nih_cxr14_padchest/datamodule.py b/src/mednet/libs/classification/config/data/nih_cxr14_padchest/datamodule.py index beeb3d9655cd434122d59fe36ee18eb63e7c12b8..d5a44ce64e5060f69083f95824a5995f63246e05 100644 --- a/src/mednet/libs/classification/config/data/nih_cxr14_padchest/datamodule.py +++ b/src/mednet/libs/classification/config/data/nih_cxr14_padchest/datamodule.py @@ -8,9 +8,8 @@ import pathlib from mednet.libs.common.data.datamodule import ConcatDataModule from mednet.libs.common.data.split import make_split -from ..nih_cxr14.datamodule import RawDataLoader as CXR14Loader -from ..padchest.datamodule import RawDataLoader as PadchestLoader - +from ..nih_cxr14.datamodule import ClassificationRawDataLoader as CXR14Loader +from ..padchest.datamodule import ClassificationRawDataLoader as PadchestLoader class DataModule(ConcatDataModule): """Aggregated dataset composed of NIH CXR14 relabeld and PadChest diff --git a/src/mednet/libs/classification/config/data/padchest/datamodule.py b/src/mednet/libs/classification/config/data/padchest/datamodule.py index 8ea0eb7c0262c0dac7a713828d6c0ec749589131..0fed49ab85d409ed6ae4b248de849cb31851a3eb 100644 --- a/src/mednet/libs/classification/config/data/padchest/datamodule.py +++ b/src/mednet/libs/classification/config/data/padchest/datamodule.py @@ -11,11 +11,15 @@ import pathlib import numpy import PIL.Image +from mednet.libs.classification.data.typing import ( + ClassificationRawDataLoader as _ClassificationRawDataLoader, +) from mednet.libs.common.data.datamodule import CachingDataModule from mednet.libs.common.data.image_utils import remove_black_borders + from mednet.libs.common.data.split import make_split from mednet.libs.common.data.typing import Sample -from mednet.libs.common.data.typing import RawDataLoader as _BaseRawDataLoader + from torchvision.transforms.functional import to_tensor from ....utils.rc import load_rc @@ -25,7 +29,7 @@ CONFIGURATION_KEY_DATADIR = "datadir." + (__name__.rsplit(".", 2)[-2]) database.""" -class RawDataLoader(_BaseRawDataLoader): +class ClassificationRawDataLoader(_ClassificationRawDataLoader): """A specialized raw-data-loader for the PadChest dataset.""" datadir: pathlib.Path @@ -325,7 +329,7 @@ class DataModule(CachingDataModule): assert __package__ is not None super().__init__( database_split=make_split(__package__, split_filename), - raw_data_loader=RawDataLoader(), - database_name=__package__.rsplit(".", 1)[1], + raw_data_loader=_ClassificationRawDataLoader(), + database_name=__package__.rsplit(".", 1)[1], split_name=pathlib.Path(split_filename).stem, ) diff --git a/src/mednet/libs/classification/config/data/shenzhen/datamodule.py b/src/mednet/libs/classification/config/data/shenzhen/datamodule.py index f68851b6bb53ddc9fbff044c3eee87db24f23003..7ab4d171825e4894c4d25eb0dfe35c72ba7229a9 100644 --- a/src/mednet/libs/classification/config/data/shenzhen/datamodule.py +++ b/src/mednet/libs/classification/config/data/shenzhen/datamodule.py @@ -10,11 +10,15 @@ import os import pathlib import PIL.Image +from mednet.libs.classification.data.typing import ( + ClassificationRawDataLoader as _ClassificationRawDataLoader, +) from mednet.libs.common.data.datamodule import CachingDataModule from mednet.libs.common.data.image_utils import remove_black_borders + from mednet.libs.common.data.split import make_split from mednet.libs.common.data.typing import Sample -from mednet.libs.common.data.typing import RawDataLoader as _BaseRawDataLoader + from torchvision.transforms.functional import to_tensor from ....utils.rc import load_rc @@ -24,7 +28,7 @@ CONFIGURATION_KEY_DATADIR = "datadir." + (__name__.rsplit(".", 2)[-2]) database.""" -class RawDataLoader(_BaseRawDataLoader): +class ClassificationRawDataLoader(_ClassificationRawDataLoader): """A specialized raw-data-loader for the Shenzhen dataset. Parameters @@ -135,7 +139,7 @@ class DataModule(CachingDataModule): assert __package__ is not None super().__init__( database_split=make_split(__package__, split_filename), - raw_data_loader=RawDataLoader(), - database_name=__package__.rsplit(".", 1)[1], + raw_data_loader=_ClassificationRawDataLoader(), + database_name=__package__.rsplit(".", 1)[1], split_name=pathlib.Path(split_filename).stem, ) diff --git a/src/mednet/libs/classification/config/data/tbpoc/datamodule.py b/src/mednet/libs/classification/config/data/tbpoc/datamodule.py index 122f6686b4831cfb74e35320a7d23e5ee64192e6..2ba9f688a1abc5a3fc38a45ae92d4d6f7f2d38be 100644 --- a/src/mednet/libs/classification/config/data/tbpoc/datamodule.py +++ b/src/mednet/libs/classification/config/data/tbpoc/datamodule.py @@ -6,11 +6,15 @@ import os import pathlib import PIL.Image +from mednet.libs.classification.data.typing import ( + ClassificationRawDataLoader as _ClassificationRawDataLoader, +) from mednet.libs.common.data.datamodule import CachingDataModule from mednet.libs.common.data.image_utils import remove_black_borders + from mednet.libs.common.data.split import make_split from mednet.libs.common.data.typing import Sample -from mednet.libs.common.data.typing import RawDataLoader as _BaseRawDataLoader + from torchvision.transforms.functional import to_tensor from ....utils.rc import load_rc @@ -20,7 +24,7 @@ CONFIGURATION_KEY_DATADIR = "datadir." + (__name__.rsplit(".", 2)[-2]) database.""" -class RawDataLoader(_BaseRawDataLoader): +class ClassificationRawDataLoader(_ClassificationRawDataLoader): """A specialized raw-data-loader for the Shenzen dataset.""" datadir: pathlib.Path @@ -121,7 +125,7 @@ class DataModule(CachingDataModule): assert __package__ is not None super().__init__( database_split=make_split(__package__, split_filename), - raw_data_loader=RawDataLoader(), - database_name=__package__.rsplit(".", 1)[1], + raw_data_loader=_ClassificationRawDataLoader(), + database_name=__package__.rsplit(".", 1)[1], split_name=pathlib.Path(split_filename).stem, ) diff --git a/src/mednet/libs/classification/config/data/tbx11k/datamodule.py b/src/mednet/libs/classification/config/data/tbx11k/datamodule.py index b633d8e9e4d87fdf6c9113f16c2703e3bcf71b1b..fb86030754971e0dc6551009d161a4965f029bac 100644 --- a/src/mednet/libs/classification/config/data/tbx11k/datamodule.py +++ b/src/mednet/libs/classification/config/data/tbx11k/datamodule.py @@ -10,10 +10,12 @@ import typing import PIL.Image import typing_extensions +from mednet.libs.classification.data.typing import ( + ClassificationRawDataLoader as _ClassificationRawDataLoader, +) from mednet.libs.common.data.datamodule import CachingDataModule from mednet.libs.common.data.split import make_split from mednet.libs.common.data.typing import Sample -from mednet.libs.common.data.typing import RawDataLoader as _BaseRawDataLoader from torch.utils.data._utils.collate import default_collate_fn_map from torchvision.transforms.functional import to_tensor @@ -167,7 +169,7 @@ finding locations, as described above. """ -class RawDataLoader(_BaseRawDataLoader): +class ClassificationRawDataLoader(_ClassificationRawDataLoader): """A specialized raw-data-loader for the TBX11k dataset. Parameters @@ -377,7 +379,7 @@ class DataModule(CachingDataModule): assert __package__ is not None super().__init__( database_split=make_split(__package__, split_filename), - raw_data_loader=RawDataLoader(ignore_bboxes=ignore_bboxes), + raw_data_loader=ClassificationRawDataLoader(ignore_bboxes=ignore_bboxes), database_name=__package__.rsplit(".", 1)[1], split_name=pathlib.Path(split_filename).stem, ) diff --git a/src/mednet/libs/classification/data/__init__.py b/src/mednet/libs/classification/data/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/src/mednet/libs/classification/data/typing.py b/src/mednet/libs/classification/data/typing.py new file mode 100644 index 0000000000000000000000000000000000000000..8cd214053c02cc975bfc1d48c4f5418bd8c28bf5 --- /dev/null +++ b/src/mednet/libs/classification/data/typing.py @@ -0,0 +1,41 @@ +import typing + +from mednet.libs.common.data.typing import RawDataLoader, Sample + + +class ClassificationRawDataLoader(RawDataLoader): + """A loader object can load samples and labels from storage for classification tasks.""" + + def __init__(self): + super().__init__() + + def sample(self, _: typing.Any) -> Sample: + """Load whole samples from media. + + Parameters + ---------- + _ + Information about the sample to load. Implementation dependent. + """ + + raise NotImplementedError("You must implement the `sample()` method") + + def label(self, k: typing.Any) -> int | list[int]: + """Load only sample label from media. + + If you do not override this implementation, then, by default, + this method will call :py:meth:`sample` to load the whole sample + and extract the label. + + Parameters + ---------- + k + The sample to load. This is implementation-dependent. + + Returns + ------- + int | list[int] + The label corresponding to the specified sample. + """ + + return self.sample(k)[1]["label"] diff --git a/src/mednet/libs/common/data/typing.py b/src/mednet/libs/common/data/typing.py index 93bbfc970b50549ae03a125ef89b785e62a161d0..48cce9e780dd1be756d5f7b85947feda2b7dc0be 100644 --- a/src/mednet/libs/common/data/typing.py +++ b/src/mednet/libs/common/data/typing.py @@ -35,26 +35,6 @@ class RawDataLoader: raise NotImplementedError("You must implement the `sample()` method") - def label(self, k: typing.Any) -> int | list[int]: - """Load only sample label from media. - - If you do not override this implementation, then, by default, - this method will call :py:meth:`sample` to load the whole sample - and extract the label. - - Parameters - ---------- - k - The sample to load. This is implementation-dependent. - - Returns - ------- - int | list[int] - The label corresponding to the specified sample. - """ - - return self.sample(k)[1]["label"] - Transform: typing.TypeAlias = typing.Callable[[torch.Tensor], torch.Tensor] """A callable that transforms tensors into (other) tensors. diff --git a/src/mednet/libs/segmentation/config/data/drive/datamodule.py b/src/mednet/libs/segmentation/config/data/drive/datamodule.py index b61941a59797ed80baf01f580cd6f92e50da5829..2ef7d1cbd97dd0361ad7d00221b016c3e4d77ab1 100644 --- a/src/mednet/libs/segmentation/config/data/drive/datamodule.py +++ b/src/mednet/libs/segmentation/config/data/drive/datamodule.py @@ -11,7 +11,9 @@ import PIL.Image from mednet.libs.common.data.datamodule import CachingDataModule from mednet.libs.common.data.split import JSONDatabaseSplit from mednet.libs.common.data.typing import DatabaseSplit, Sample -from mednet.libs.common.data.typing import RawDataLoader as _BaseRawDataLoader +from mednet.libs.segmentation.data.typing import ( + SegmentationRawDataLoader as _SegmentationRawDataLoader, +) from torchvision import tv_tensors from torchvision.transforms.functional import to_tensor @@ -22,7 +24,7 @@ CONFIGURATION_KEY_DATADIR = "datadir." + (__name__.rsplit(".", 2)[-2]) database.""" -class RawDataLoader(_BaseRawDataLoader): +class SegmentationRawDataLoader(_SegmentationRawDataLoader): """A specialized raw-data-loader for the Montgomery dataset.""" datadir: str @@ -116,5 +118,5 @@ class DataModule(CachingDataModule): def __init__(self, split_filename: str): super().__init__( database_split=make_split(split_filename), - raw_data_loader=RawDataLoader(), + raw_data_loader=SegmentationRawDataLoader(), ) diff --git a/src/mednet/libs/segmentation/data/typing.py b/src/mednet/libs/segmentation/data/typing.py new file mode 100644 index 0000000000000000000000000000000000000000..e1d95cdbb276c58bd8e21467948c44a6343e00e2 --- /dev/null +++ b/src/mednet/libs/segmentation/data/typing.py @@ -0,0 +1,21 @@ +import typing + +from mednet.libs.common.data.typing import RawDataLoader, Sample + + +class SegmentationRawDataLoader(RawDataLoader): + """A loader object can load samples and labels from storage for classification tasks.""" + + def __init__(self): + super().__init__() + + def sample(self, _: typing.Any) -> Sample: + """Load whole samples from media. + + Parameters + ---------- + _ + Information about the sample to load. Implementation dependent. + """ + + raise NotImplementedError("You must implement the `sample()` method")