Source code for piel.experimental.measurements.data.extract
import logging
from piel.types import PathTypes
from piel.types.experimental import (
Experiment,
ExperimentData,
)
from piel.file_system import return_path
from piel.models import load_from_json
from piel.experimental.measurements.experiment import (
compose_measurement_collection_from_experiment,
)
from piel.types.experimental import (
MeasurementCollectionTypes,
MeasurementDataCollectionTypes,
)
from piel.experimental.measurements.map import (
measurement_to_data_map,
measurement_to_data_method_map,
measurement_data_to_measurement_collection_data_map,
)
logger = logging.getLogger(__name__)
[docs]
def extract_data_from_measurement_collection(
measurement_collection: MeasurementCollectionTypes,
measurement_to_data_map: dict = measurement_to_data_map,
measurement_to_data_method_map: dict = measurement_to_data_method_map,
skip_missing: bool = False,
**kwargs,
) -> MeasurementDataCollectionTypes:
"""
The goal of this function is to compose the data from a collection of measurement references.
Based on each type of measurement, it will apply an extraction function based on the data mapping accordingly.
It will return a collection of data measurement which is inherent to the type of the measurement collection provided.
"""
measurement_data_collection: MeasurementDataCollectionTypes = list()
logger.debug(
f"extract_data_from_measurement_collection: Starting to extracting data from measurement collection: {measurement_collection}"
)
i = 0
for measurement_i in measurement_collection.collection:
logger.debug(
f"extract_data_from_measurement_collection: Extracting data from measurement: {measurement_i.name}"
)
# Identify correct data mapping
measurement_data_type = measurement_to_data_map[measurement_i.type]
logger.debug(f"measurement_i.type: {measurement_i.type}")
logger.debug(
f"measurement_to_data_method_map: {measurement_to_data_method_map}"
)
extract_data_method = measurement_to_data_method_map[measurement_i.type]
try:
measurement_data_i = extract_data_method(measurement_i)
except Exception as e:
missing_data_error = f"Missing data for measurement: {measurement_i.name} in collection: {measurement_collection.name} with index: {i}"
if skip_missing:
logger.debug(missing_data_error)
measurement_data_i = measurement_data_type()
else:
raise e
try:
logger.debug(
f"Constructed {measurement_data_i} is not of the target measurement data type {measurement_data_type}"
)
assert isinstance(measurement_data_i, measurement_data_type)
except AssertionError as e:
raise e
measurement_data_collection.append(measurement_data_i)
i += 1
# Now we need to extract the corresponding MeasurementCollection type from measurement_data_collection
# Use the last element
measurement_data_collection_type = (
measurement_data_to_measurement_collection_data_map[measurement_data_i.type]
)
# Create the validated instance
measurement_data_collection = measurement_data_collection_type(
collection=measurement_data_collection
)
return measurement_data_collection
[docs]
def extract_data_from_experiment(
experiment: Experiment,
experiment_directory: PathTypes,
composition_kwargs: dict = None,
extraction_kwargs: dict = None,
**kwargs,
) -> ExperimentData:
"""
This function must be run after data has already been written within the ``Experiment`` directories
and the metadata has been created accordingly. This will extract all the corresponding measurements collection,
and also extract the corresponding data from each setup accordingly. It will create a `ExperimentData` that collects
both the metadata and measurement data.
Parameters
----------
experiment : Experiment
The experiment object that contains the metadata of the experiment.
experiment_directory : PathTypes
The directory where the experiment is located.
**kwargs
Extra keyword arguments passed to the class instantiation.
Returns
-------
ExperimentData
The data extracted from the experiment.
"""
if composition_kwargs is None:
composition_kwargs = dict()
if extraction_kwargs is None:
extraction_kwargs = {"skip_missing": True}
logger.debug(f"Extracting data with the following kwargs: {extraction_kwargs}")
logger.debug(f"Composing data with the following kwargs: {composition_kwargs}")
measurement_collection = compose_measurement_collection_from_experiment(
experiment=experiment,
experiment_directory=experiment_directory,
**composition_kwargs,
)
measurement_data_collection = extract_data_from_measurement_collection(
measurement_collection=measurement_collection, **extraction_kwargs
)
return ExperimentData(
experiment=experiment, data=measurement_data_collection, **kwargs
)
[docs]
def load_experiment_data_from_directory(
experiment_directory: PathTypes, **kwargs
) -> ExperimentData:
"""
This function will load an `Experiment` from the metadata stored in the `experiment.json` directory.
"""
logger.debug(
"Loading experiment data from the experiment directory {}".format(
experiment_directory
)
)
experiment_directory = return_path(experiment_directory)
experiment_metadata_json = experiment_directory / "experiment.json"
assert experiment_metadata_json.exists()
logger.debug("Loading experiment from the experiment json.")
experiment = load_from_json(experiment_metadata_json, Experiment)
logger.debug("Loaded experiment from experiment json.")
logger.debug("Loading measurement data from the experiment data.")
experiment_data = extract_data_from_experiment(
experiment, experiment_directory=experiment_directory, **kwargs
)
return experiment_data