Source code for quantify_core.data.experiment
# Repository: https://gitlab.com/quantify-os/quantify-core
# Licensed according to the LICENCE file on the main branch
"""Utilities for managing experiment data."""
import os
from pathlib import Path
from typing import Dict, Any, Optional
import xarray as xr
from quantify_core.data.handling import (
locate_experiment_container,
load_dataset,
DATASET_NAME,
write_dataset,
create_exp_folder,
)
from quantify_core.data.handling import snapshot as create_snapshot
from quantify_core.data.types import TUID
from quantify_core.utilities.general import save_json, load_json
SNAPSHOT_FILENAME = "snapshot.json"
METADATA_FILENAME = "metadata.json"
[docs]
class QuantifyExperiment:
"""
Class which represents all data related to an experiment. This allows the user to
run experiments and store data without the
`quantify_core.measurement.control.MeasurementControl`. The class serves as an
initial interface for other data storage backends.
"""
[docs]
def __init__(self, tuid: Optional[str], dataset=None):
"""
Creates an instance of the QuantifyExperiment.
Parameters
----------
tuid
TUID to use
dataset
If the TUID is None, use the TUID from this dataset
"""
if tuid is None:
self.tuid = dataset.tuid
self.dataset = dataset
else:
self.tuid = tuid
self.dataset = None
self.tuid = TUID(self.tuid)
def __repr__(self) -> str:
classname = ".".join([self.__module__, self.__class__.__qualname__])
idx = f"{id(self)}x"
return f"<{classname} at %x{idx}>: TUID {self.tuid}"
@property
def experiment_directory(self) -> Path:
"""
Returns a path to the experiment directory containing the TUID set within
the class.
Returns
-------
:
"""
experiment_directory = locate_experiment_container(tuid=self.tuid)
return Path(experiment_directory)
@property
def experiment_name(self) -> str:
"""The name of the experiment."""
location = locate_experiment_container(tuid=self.tuid)
name = location[location.find(self.tuid) + len(self.tuid) + 1 :]
return name
[docs]
def _get_or_create_experiment_directory(self, name: str = "") -> Path:
"""
Create the experiment directory containing the TUID set within the class,
if it does not exist already.
To be used by methods that write/save. The experiment directory will be
created on the first write/save, not before. Methods that load should not
create an experiment directory.
name:
Readable name given to the datafile
Returns
-------
:
The path to the experiment directory.
"""
try:
experiment_directory = self.experiment_directory
except FileNotFoundError:
experiment_directory = create_exp_folder(tuid=self.tuid, name=name)
return Path(experiment_directory)
[docs]
def load_dataset(self) -> xr.Dataset:
"""
Loads the quantify dataset associated with the TUID set within
the class.
Returns
-------
:
Raises
------
FileNotFoundError
If no file with a dataset can be found
"""
self.dataset = load_dataset(self.tuid)
return self.dataset
[docs]
def write_dataset(self, dataset: xr.Dataset):
"""
Writes the quantify dataset to the directory specified by
`~.experiment_directory`.
Parameters
----------
dataset
The dataset to be written to the directory
"""
name = dataset.attrs.get("name", "")
path = self._get_or_create_experiment_directory(name=name) / DATASET_NAME
write_dataset(path, dataset)
[docs]
def load_snapshot(self) -> Dict[str, Any]:
"""
Loads the snapshot from the directory specified by
`~.experiment_directory`.
Returns
-------
:
The loaded snapshot from disk
Raises
------
FileNotFoundError
If no file with a snapshot can be found
"""
return load_json(full_path=self.experiment_directory / SNAPSHOT_FILENAME)
[docs]
def save_snapshot(self, snapshot: Optional[Dict[str, Any]] = None):
"""
Writes the snapshot to disk as specified by
`~.experiment_directory`.
Parameters
----------
snapshot
The snapshot to be written to the directory
"""
if snapshot is None:
snapshot = create_snapshot()
save_json(
directory=self._get_or_create_experiment_directory(),
filename=SNAPSHOT_FILENAME,
data=snapshot,
)
[docs]
def load_text(self, rel_path: str) -> str:
"""
Loads a string from a text file from the path specified by
`~.experiment_directory` / rel_path.
Parameters
----------
rel_path
path relative to the base directory of the experiment,
e.g. "data.json" or "my_folder/data.txt"
Returns
-------
:
The loaded text from disk
Raises
------
FileNotFoundError
If no file can be found at `rel_path`
"""
file_path = self.experiment_directory / rel_path
text = file_path.read_text(encoding="utf-8")
return text
[docs]
def save_text(self, text: str, rel_path: str) -> None:
"""
Saves a string to a text file in the path specified by
`~.experiment_directory` / rel_path.
Parameters
----------
text
text to be saved
rel_path
path relative to the base directory of the experiment,
e.g. "data.json" or "my_folder/data.txt"
"""
directory = (self._get_or_create_experiment_directory() / rel_path).parent
os.makedirs(directory, exist_ok=True)
file_path = self.experiment_directory / rel_path
file_path.write_text(text, encoding="utf-8")