Classes that simplify imports from fedbiomed.common.dataset
Attributes¶
DATASET_CLASSES_PER_TYPE module-attribute ¶
DATASET_CLASSES_PER_TYPE = {
DatasetTypes.CUSTOM: CustomDataset,
DatasetTypes.IMAGES: ImageFolderDataset,
DatasetTypes.MEDICAL_FOLDER: MedicalFolderDataset,
DatasetTypes.MEDNIST: MedNistDataset,
DatasetTypes.DEFAULT: MnistDataset,
DatasetTypes.TABULAR: TabularDataset,
}
REGISTRY_CONTROLLERS module-attribute ¶
REGISTRY_CONTROLLERS = {
DatasetTypes.TABULAR: (
TabularController,
DATASET_CLASSES_PER_TYPE[DatasetTypes.TABULAR],
),
DatasetTypes.MEDICAL_FOLDER: (
MedicalFolderController,
DATASET_CLASSES_PER_TYPE[
DatasetTypes.MEDICAL_FOLDER
],
),
DatasetTypes.IMAGES: (
ImageFolderController,
DATASET_CLASSES_PER_TYPE[DatasetTypes.IMAGES],
),
DatasetTypes.DEFAULT: (
MnistController,
DATASET_CLASSES_PER_TYPE[DatasetTypes.DEFAULT],
),
DatasetTypes.MEDNIST: (
MedNistController,
DATASET_CLASSES_PER_TYPE[DatasetTypes.MEDNIST],
),
DatasetTypes.CUSTOM: (
CustomController,
DATASET_CLASSES_PER_TYPE[DatasetTypes.CUSTOM],
),
}
Classes¶
CustomDataset ¶
Bases: Dataset
A class representing a custom dataset.
This class allows users to create and manage their own datasets for use in federated learning scenarios.
Attributes¶
Methods:¶
get_item abstractmethod ¶
get_item(index)
Return the sample for the given index.
May return either data alone, or a (data, target) tuple. When only data is returned, the target is treated as None.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
index | int | Index of the sample to retrieve. | required |
Source code in fedbiomed/common/dataset/_custom_dataset.py
@abstractmethod
def get_item(self, index):
"""Return the sample for the given index.
May return either ``data`` alone, or a ``(data, target)`` tuple. When
only ``data`` is returned, the target is treated as ``None``.
Args:
index (int): Index of the sample to retrieve.
"""
pass
load ¶
load(root, to_format)
Finalize initialization of object to be able to recover items.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
root | Union[str, Path] | path to the dataset (must not be | required |
to_format | DataReturnFormat | expected format of data returned by | required |
Source code in fedbiomed/common/dataset/_custom_dataset.py
def load(
self,
root: Union[str, Path],
to_format: DataReturnFormat,
) -> None:
"""Finalize initialization of object to be able to recover items.
Args:
root: path to the dataset (must not be ``None``).
to_format: expected format of data returned by ``__getitem__``.
"""
if root is None:
raise FedbiomedError(
f"{ErrorNumbers.FB632.value}: Custom Dataset ERROR: 'root' must be provided to specify dataset location."
)
self.__path = root
self._to_format = to_format
# Call user defined read function to read the dataset
try:
self.read()
except Exception as e:
raise FedbiomedError(
f"{ErrorNumbers.FB632.value}: Failed to read "
f"from dataset using read method. Please see error: {e}"
) from e
if len(self) == 0:
raise FedbiomedError(
f"{ErrorNumbers.FB632.value}: Custom Dataset ERROR: dataset is empty (len == 0)."
)
try:
sample = self.get_item(0)
except Exception as e:
raise FedbiomedError(
f"{ErrorNumbers.FB632.value}: Failed to retrieve item "
f"from dataset using get_item method. Please see error: {e}"
) from e
data, target = self._split_sample(sample)
target = self._normalize_target(target)
self._composed: dict[str, Union[bool, None]] = {
"data": None,
"target": None,
}
self._check_type(data, "data")
if target is not None:
self._check_type(target, "target")
read abstractmethod ¶
read()
Reads the dataset from the specified path.
This method should be implemented by subclasses to load the dataset from the given path and prepare it for use.
Source code in fedbiomed/common/dataset/_custom_dataset.py
@abstractmethod
def read(self) -> None:
"""Reads the dataset from the specified path.
This method should be implemented by subclasses to load the dataset
from the given path and prepare it for use.
"""
pass
Dataset ¶
Bases: ABC
Attributes¶
Methods:¶
apply_transforms ¶
apply_transforms(sample)
Apply transforms to sample in place
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
sample | Dict[str, Any] | sample returned by | required |
Raises:
| Type | Description |
|---|---|
FedbiomedError | if there is a problem applying |
Source code in fedbiomed/common/dataset/_dataset.py
def apply_transforms(self, sample: Dict[str, Any]) -> Dict[str, Any]:
"""Apply transforms to sample in place
Args:
sample: sample returned by `self._controller.get_sample`
Raises:
FedbiomedError: if there is a problem applying `transform` or `target_transform`
"""
try:
sample["data"] = self._transform(
self._get_default_types_callable()(
self._get_format_conversion_callable()(sample["data"])
)
)
except Exception as e:
raise FedbiomedError(
f"{ErrorNumbers.FB632.value}: Failed to apply `transform` to `data` "
f"in sample in {self._to_format.value} format."
) from e
try:
sample["data"] = self._get_default_types_callable()(sample["data"])
except Exception as e:
raise FedbiomedError(
f"{ErrorNumbers.FB632.value}: Failed to apply default training plan types to `data` "
f"in sample in {self._to_format.value} format."
) from e
if sample.get("target") is not None:
try:
sample["target"] = self._target_transform(
self._get_default_types_callable()(
self._get_format_conversion_callable()(sample["target"])
)
)
except Exception as e:
raise FedbiomedError(
f"{ErrorNumbers.FB632.value}: Failed to apply `target_transform` to "
f"`target` in sample in {self._to_format.value} format."
) from e
try:
sample["target"] = self._get_default_types_callable()(sample["target"])
except Exception as e:
raise FedbiomedError(
f"{ErrorNumbers.FB632.value}: Failed to apply default training plan types to `target` "
f"in sample in {self._to_format.value} format."
) from e
return sample
complete_initialization ¶
complete_initialization(controller_kwargs, to_format)
Deprecated alias for load.
Preserves the legacy signature where root was passed inside the controller_kwargs dict; it is unpacked so it binds to the root parameter of load.
.. deprecated:: Use load instead. This method will be removed in a future Fed-BioMed release.
Source code in fedbiomed/common/dataset/_dataset.py
def complete_initialization(
self, controller_kwargs: Dict[str, Any], to_format: DataReturnFormat
) -> None:
"""Deprecated alias for `load`.
Preserves the legacy signature where ``root`` was passed inside the
``controller_kwargs`` dict; it is unpacked so it binds to the ``root``
parameter of `load`.
.. deprecated::
Use `load` instead. This method will be removed in a future Fed-BioMed release.
"""
logger.warning(
"`complete_initialization` is deprecated and will be removed in future "
"Fed-BioMed releases; use `load` instead."
)
return self.load(to_format=to_format, **controller_kwargs)
compute_stats ¶
compute_stats(
dataset_schema=None, stats=None, stats_args=None
)
Computes statistics over the dataset using the AnalyticsOrchestrator.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
schema_args | Selection arguments to filter the schema (e.g. subset of columns/keys). | required | |
stats | Optional[List[str]] | List of statistics names to compute (e.g. ['mean', 'std']). If None or empty, default statistics are chosen based on data type. | None |
stats_args | Optional[Dict[str, Any]] | Specific arguments for statistics, structured matching the schema. | None |
Returns:
| Type | Description |
|---|---|
Any | Computed statistics structure. |
Raises:
| Type | Description |
|---|---|
FedbiomedError | If the dataset does not support analytics (missing get_schema_for_analytics). |
Source code in fedbiomed/common/dataset/_dataset.py
def compute_stats(
self,
dataset_schema: Optional[Union[str, List[str], Dict[str, Any]]] = None,
stats: Optional[List[str]] = None,
stats_args: Optional[Dict[str, Any]] = None,
) -> Any:
"""Computes statistics over the dataset using the AnalyticsOrchestrator.
Args:
schema_args: Selection arguments to filter the schema (e.g. subset of columns/keys).
stats: List of statistics names to compute (e.g. ['mean', 'std']).
If None or empty, default statistics are chosen based on data type.
stats_args: Specific arguments for statistics, structured matching the schema.
Returns:
Computed statistics structure.
Raises:
FedbiomedError: If the dataset does not support analytics (missing get_schema_for_analytics).
"""
orchestrator = AnalyticsOrchestrator()
return orchestrator.compute_stats(
self,
dataset_schema=dataset_schema,
stats=stats,
stats_args=stats_args,
)
load abstractmethod ¶
load(root, to_format, **kwargs)
Finalize initialization of object to be able to recover items
Source code in fedbiomed/common/dataset/_dataset.py
@abstractmethod
def load(
self,
root: Union[str, Path],
to_format: DataReturnFormat,
**kwargs: Any,
) -> None:
"""Finalize initialization of object to be able to recover items"""
# Recover sample and validate consistency of transforms
pass
ImageFolderDataset ¶
ImageFolderDataset(transform=None, target_transform=None)
Bases: _ImageLabelDataset
Source code in fedbiomed/common/dataset/_image_label_dataset.py
def __init__(
self,
transform: Optional[Callable] = None,
target_transform: Optional[Callable] = None,
):
if type(self) is _ImageLabelDataset:
raise FedbiomedValueError(
f"{ErrorNumbers.FB632.value}: "
"`_ImageLabelDataset` cannot be instantiated directly"
)
self._transform = self._validate_transform(transform)
self._target_transform = self._validate_transform(target_transform)
MedNistDataset ¶
MedNistDataset(transform=None, target_transform=None)
Bases: _ImageLabelDataset
Source code in fedbiomed/common/dataset/_image_label_dataset.py
def __init__(
self,
transform: Optional[Callable] = None,
target_transform: Optional[Callable] = None,
):
if type(self) is _ImageLabelDataset:
raise FedbiomedValueError(
f"{ErrorNumbers.FB632.value}: "
"`_ImageLabelDataset` cannot be instantiated directly"
)
self._transform = self._validate_transform(transform)
self._target_transform = self._validate_transform(target_transform)
MedicalFolderDataset ¶
MedicalFolderDataset(
data_modalities,
target_modalities=None,
transform=None,
target_transform=None,
)
Bases: Dataset
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
data_modalities | Union[str, Iterable[str]] | The data modalities to use. | required |
target_modalities | Optional[Union[str, Iterable[str]]] | The target modalities to use. | None |
transform | Transform | The transform to apply to the data. Defaults to None. | None |
target_transform | Transform | The transform to apply to the target data. Defaults to None. | None |
Raises:
| Type | Description |
|---|---|
FedbiomedValueError | |
Source code in fedbiomed/common/dataset/_medical_folder_dataset.py
def __init__(
self,
data_modalities: Union[str, Iterable[str]],
target_modalities: Optional[Union[str, Iterable[str]]] = None,
transform: Transform = None,
target_transform: Transform = None,
):
"""Initializes the MedicalFolderDataset.
Args:
data_modalities (Union[str, Iterable[str]]): The data modalities to use.
target_modalities (Optional[Union[str, Iterable[str]]]): The target modalities to use.
transform (Transform, optional): The transform to apply to the data. Defaults to None.
target_transform (Transform, optional): The transform to apply to the target data. Defaults to None.
Raises:
FedbiomedValueError:
- If the input modalities are not valid.
- If `data_modalities` is empty.
- If `target_transform` is given but `target_modalities` is None\
"""
if not data_modalities:
raise FedbiomedValueError(
f"{ErrorNumbers.FB632.value}: `data_modalities` cannot be empty"
)
self._data_modalities = self._normalize_modalities(data_modalities)
self._target_modalities = (
None
if target_modalities is None
else self._normalize_modalities(target_modalities)
)
self._transform = self._validate_transform(
transform=transform,
modalities=self._data_modalities,
)
if self._target_modalities is None:
if target_transform is not None:
raise FedbiomedValueError(
f"{ErrorNumbers.FB632.value}: `target_transform` provided but "
"`target_modalities` is None"
)
else:
self._target_transform = None
else:
self._target_transform = self._validate_transform(
transform=target_transform,
modalities=self._target_modalities,
)
Attributes¶
demographics_columns property ¶
demographics_columns
Returns the columns of the dataset if 'demographics' modality is present, else None.
target_modalities property ¶
target_modalities
Returns the target modalities of the dataset, or None if not defined.
Methods:¶
analytics_schema ¶
analytics_schema()
Return schema associated with federated analytics.
Source code in fedbiomed/common/dataset/_medical_folder_dataset.py
def analytics_schema(self):
"""Return schema associated with federated analytics."""
if self._controller is None:
raise FedbiomedError(
f"{ErrorNumbers.FB632.value}: Dataset object has not completed "
"initialization. It is not ready to use yet."
)
schema = {}
# Add demographics schema if available
if self.demographics_columns is not None:
schema["demographics"] = RowSpec(columns=self.demographics_columns)
# Add image schema for all other modalities
schema.update(
{
modality: ImageSpec()
for modality in self._data_modalities
if modality != "demographics"
}
)
return schema, None
load ¶
load(
root,
to_format,
tabular_file=None,
index_col=None,
dlp=None,
)
Finalize initialization of object to be able to recover items
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
root | Union[str, Path] | path to the dataset root | required |
to_format | DataReturnFormat | format associated to expected return format | required |
tabular_file | Optional[str] | path to the CSV file holding the demographic information | None |
index_col | Optional[str] | column in the tabular file holding the subject names | None |
dlp | Optional[DataLoadingPlan] | data loading plan to apply | None |
Source code in fedbiomed/common/dataset/_medical_folder_dataset.py
def load(
self,
root: Union[str, Path],
to_format: DataReturnFormat,
tabular_file: Optional[str] = None,
index_col: Optional[str] = None,
dlp: Optional[DataLoadingPlan] = None,
) -> None:
"""Finalize initialization of object to be able to recover items
Args:
root: path to the dataset root
to_format: format associated to expected return format
tabular_file: path to the CSV file holding the demographic information
index_col: column in the tabular file holding the subject names
dlp: data loading plan to apply
"""
self.to_format = to_format
self._init_controller(
root=root,
tabular_file=tabular_file,
index_col=index_col,
dlp=dlp,
)
# Recover sample and validate consistency of transforms
sample = self._controller.get_sample(0)
self._validate_format_and_transformations(
{modality: sample[modality] for modality in self._data_modalities},
transform=self._transform,
)
if self._target_modalities is not None:
self._validate_format_and_transformations(
{modality: sample[modality] for modality in self._target_modalities},
transform=self._target_transform,
is_target=True,
)
MnistDataset ¶
MnistDataset(transform=None, target_transform=None)
Bases: _ImageLabelDataset
Source code in fedbiomed/common/dataset/_image_label_dataset.py
def __init__(
self,
transform: Optional[Callable] = None,
target_transform: Optional[Callable] = None,
):
if type(self) is _ImageLabelDataset:
raise FedbiomedValueError(
f"{ErrorNumbers.FB632.value}: "
"`_ImageLabelDataset` cannot be instantiated directly"
)
self._transform = self._validate_transform(transform)
self._target_transform = self._validate_transform(target_transform)
Methods:¶
load ¶
load(root, to_format, train=True, download=True)
Finalize initialization of object to be able to recover items
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
root | Union[str, Path] | path to the dataset root | required |
to_format | DataReturnFormat | format associated to expected return format | required |
train | bool | if true then train files are used | True |
download | bool | if true then downloads and extracts the files if they do not exist | True |
Source code in fedbiomed/common/dataset/_image_label_dataset.py
def load(
self,
root: Union[str, Path],
to_format: DataReturnFormat,
train: bool = True,
download: bool = True,
) -> None:
"""Finalize initialization of object to be able to recover items
Args:
root: path to the dataset root
to_format: format associated to expected return format
train: if true then train files are used
download: if true then downloads and extracts the files if they do not exist
"""
self.to_format = to_format
self._init_controller(root=root, train=train, download=download)
self._validate_initial_sample()
TabularDataset ¶
TabularDataset(
input_columns,
target_columns=None,
transform=None,
target_transform=None,
)
Bases: Dataset
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
input_columns | Iterable | int | str | Columns to be used as input features | required |
target_columns | Optional[Iterable | int | str] | Columns to be used as target | None |
transform | Optional[Callable] | Transformation to be applied to input features | None |
target_transform | Optional[Callable] | Transformation to be applied to target | None |
Source code in fedbiomed/common/dataset/_tabular_dataset.py
def __init__(
self,
input_columns: Iterable | int | str,
target_columns: Optional[Iterable | int | str] = None,
transform: Optional[Callable] = None,
target_transform: Optional[Callable] = None,
) -> None:
"""Constructor of the class
Args:
input_columns: Columns to be used as input features
target_columns: Columns to be used as target
transform: Transformation to be applied to input features
target_transform: Transformation to be applied to target
Raises:
FedbiomedValueError: if `input_columns` or `target_columns` are not valid
FedbiomedValueError: if `transform` or `target_transform` are not valid callables
"""
# Transformation checks
self._transform = self._validate_transform(transform=transform)
self._target_transform = self._validate_transform(transform=target_transform)
# Validation of columns is deferred to load
# as self._controller._reader implements the logic to validate columns
self._input_columns = input_columns
self._target_columns = target_columns
Methods:¶
analytics_schema ¶
analytics_schema()
Return schema for federated analytics
Source code in fedbiomed/common/dataset/_tabular_dataset.py
def analytics_schema(self):
"""Return schema for federated analytics"""
return RowSpec(columns=self._input_columns), None
load ¶
load(root, to_format)
Finalize initialization of object to be able to recover items
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
root | Union[str, Path] | path to the dataset root | required |
to_format | DataReturnFormat | format associated to expected return format | required |
Source code in fedbiomed/common/dataset/_tabular_dataset.py
def load(
self,
root: Union[str, Path],
to_format: DataReturnFormat,
) -> None:
"""Finalize initialization of object to be able to recover items
Args:
root: path to the dataset root
to_format: format associated to expected return format
"""
self.to_format = to_format
self._init_controller(root=root)
# Normalize columns using controller (implies validation)
self._input_columns = self._controller.normalize_columns(self._input_columns)
if self._target_columns is not None:
self._target_columns = self._controller.normalize_columns(
self._target_columns
)
# Check for overlap between input_columns and target_columns
_intersection_cols = list(
set(self._input_columns) & set(self._target_columns)
)
if _intersection_cols:
logger.warning(
f"Columns {_intersection_cols} are present in both input_columns and target_columns."
)
sample = self._controller.get_sample(0) # type: ignore
n_rows, _ = sample.shape
if n_rows > 1:
raise FedbiomedError(
f"{ErrorNumbers.FB632.value}: TabularDataset currently only supports "
"row-wise samples. Sample obtained from controller has multiple rows."
)
self._validate_format_and_transformations(
self._get_item_from_sample(sample, self._input_columns),
transform=self._transform,
)
if self._target_columns is not None:
self._validate_format_and_transformations(
self._get_item_from_sample(sample, self._target_columns),
transform=self._target_transform,
)
Functions:¶
get_controller ¶
get_controller(data_type, controller_parameters)
Get controller instance based on data_type and controller_parameters.
Only the keyword arguments accepted by the controller's constructor are forwarded; unknown keys and None values are dropped.
Source code in fedbiomed/common/dataset/_mappings.py
def get_controller(
data_type: str,
controller_parameters: dict,
) -> Controller:
"""Get controller instance based on data_type and controller_parameters.
Only the keyword arguments accepted by the controller's constructor are
forwarded; unknown keys and `None` values are dropped.
"""
# Validate that data_type is implemented.
data_type_: Optional[DatasetTypes] = DatasetTypes.get_type_by_value(data_type)
if not data_type_ or data_type_ not in REGISTRY_CONTROLLERS:
raise FedbiomedError(
f"{ErrorNumbers.FB632.value}: "
f"Unknown 'data_type', implemented are: {list(REGISTRY_CONTROLLERS.keys())}"
)
controller_class, _ = REGISTRY_CONTROLLERS[data_type_]
accepted = inspect.signature(controller_class.__init__).parameters
parameters = {
k: v
for k, v in controller_parameters.items()
if k in accepted and v is not None
}
try:
return controller_class(**parameters)
except FedbiomedError:
raise
except Exception as e:
raise FedbiomedError(
f"{ErrorNumbers.FB632.value}: Unhandled exception occurred: {str(e)}"
) from e