Source code for piel.base.experimental.measurements.data.experiment
from typing import Union
import pandas as pd
[docs]
def index_experiment_data(instance, index: Union[int, slice, pd.DataFrame]):
"""
Indexes the data attribute of an ExperimentData instance based on an integer, slice, or pandas DataFrame.
Returns a new ExperimentData instance with the indexed data, preserving all other attributes.
If a pandas DataFrame is provided, it extracts the corresponding indices and uses them to index the data.
Args:
instance: The ExperimentData instance to index.
index: An integer index, slice, or pandas DataFrame specifying the subset.
Returns:
A new ExperimentData instance with the indexed data.
"""
# Create a copy of the instance's attributes
attrs = vars(instance).copy()
if isinstance(index, pd.DataFrame):
# Assume the DataFrame's index corresponds to the indices of the data's collection
if not index.index.is_integer():
raise ValueError(
"DataFrame index must be integer-based to correspond with data.collection indices."
)
indices = index.index.tolist()
elif isinstance(index, (int, slice)):
# Handle integer and slice indexing
if isinstance(index, int):
indices = [index]
else:
indices = list(range(*index.indices(len(instance.data.collection))))
else:
raise TypeError("Index must be an integer, slice, or pandas DataFrame.")
# Validate indices
max_index = len(instance.data.collection) - 1
for idx in indices:
if idx < 0 or idx > max_index:
raise IndexError(
f"Index {idx} out of range for data.collection with length {len(instance.data.collection)}."
)
# Index the data's collection
new_data = instance.data[index]
new_experiment = instance.experiment[index]
# Update the 'data' attribute in the copied attributes
attrs["data"] = new_data
attrs["experiment"] = new_experiment
# Create and return a new ExperimentData instance with updated attributes
return instance.__class__(**attrs)