Skip to content
78 changes: 76 additions & 2 deletions src/qcodes/dataset/data_set.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
import numpy
import numpy.typing as npt
from tqdm.auto import trange
from typing_extensions import deprecated

import qcodes
from qcodes.dataset.data_set_protocol import (
Expand Down Expand Up @@ -84,6 +85,7 @@
from qcodes.utils import (
NumpyJSONEncoder,
)
from qcodes.utils.deprecate import QCoDeSDeprecationWarning

from .data_set_cache import DataSetCacheWithDBBackend
from .data_set_in_memory import DataSetInMem, load_from_file
Expand All @@ -95,8 +97,9 @@
load_to_dataframe_dict,
)
from .exporters.export_to_xarray import (
load_to_xarray_dataarray_dict,
load_to_xarray_dataarray_dict, # pyright: ignore[reportDeprecated]
load_to_xarray_dataset,
load_to_xarray_dataset_dict,
xarray_to_h5netcdf_with_complex_numbers,
)
from .subscriber import _Subscriber
Expand Down Expand Up @@ -964,6 +967,10 @@ def to_pandas_dataframe(
datadict = self.get_parameter_data(*params, start=start, end=end)
return load_to_concatenated_dataframe(datadict, self.description.interdeps)

@deprecated(
"to_xarray_dataarray_dict is deprecated, use to_xarray_dataset_dict instead",
category=QCoDeSDeprecationWarning,
)
def to_xarray_dataarray_dict(
self,
*params: str | ParamSpec | ParameterBase,
Expand Down Expand Up @@ -1025,7 +1032,74 @@ def to_xarray_dataarray_dict(

"""
data = self.get_parameter_data(*params, start=start, end=end)
datadict = load_to_xarray_dataarray_dict(
datadict = load_to_xarray_dataarray_dict( # pyright: ignore[reportDeprecated]
self, data, use_multi_index=use_multi_index
)

return datadict

def to_xarray_dataset_dict(
self,
*params: str | ParamSpec | ParameterBase,
start: int | None = None,
end: int | None = None,
use_multi_index: Literal["auto", "always", "never"] = "auto",
) -> dict[str, xr.Dataset]:
"""
Returns the values stored in the :class:`.DataSet` for the specified parameters
and their dependencies as a dict of :py:class:`xr.DataSet` s
Each element in the dict is indexed by the names of the requested
parameters.

If no parameters are supplied data will be be
returned for all parameters in the :class:`.DataSet` that are not them self
dependencies of other parameters.

If provided, the start and end arguments select a range of results
by result count (index). If the range is empty - that is, if the end is
less than or equal to the start, or if start is after the current end
of the :class:`.DataSet` - then a dict of empty :py:class:`xr.Dataset` s is
returned.

The dependent parameters of the Dataset are normally used as coordinates of the
XArray dataframe. However if non unique values are found for the dependent parameter
values we will fall back to using an index as coordinates.

Args:
*params: string parameter names, QCoDeS Parameter objects, and
ParamSpec objects. If no parameters are supplied data for
all parameters that are not a dependency of another
parameter will be returned.
start: start value of selection range (by result count); ignored
if None
end: end value of selection range (by results count); ignored if
None
use_multi_index: Should the data be exported using a multi index
rather than regular cartesian indexes. With regular cartesian
coordinates, the xarray dimensions are calculated from the sets or all
values along the setpoint axis of the QCoDeS dataset. Any position
in this grid not corresponding to a measured value will be filled
with a placeholder (typically NaN) potentially creating a sparse
dataset with significant storage overhead.
Multi index avoids this and is therefor better
suited for data that is known to not be on a grid.
If set to "auto" multi index will be used if projecting the data onto
a grid requires filling non measured values with NaN and the shapes
of the data has not been set in the run description.

Returns:
Dictionary from requested parameter names to :py:class:`xr.Dataset` s
with the requested parameter(s) as a column(s) and coordinates
formed by the dependencies.

Example:
Return a dict of xr.Dataset with

dataset_dict = ds.to_xarray_dataset_dict()

"""
data = self.get_parameter_data(*params, start=start, end=end)
datadict = load_to_xarray_dataset_dict(
self, data, use_multi_index=use_multi_index
)

Expand Down
40 changes: 34 additions & 6 deletions src/qcodes/dataset/data_set_cache.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,17 +6,20 @@

import numpy as np
import numpy.typing as npt
from typing_extensions import deprecated

from qcodes.dataset.exporters.export_info import ExportInfo
from qcodes.dataset.sqlite.queries import completed, load_new_data_for_rundescriber
from qcodes.utils import QCoDeSDeprecationWarning

from .exporters.export_to_pandas import (
load_to_concatenated_dataframe,
load_to_dataframe_dict,
)
from .exporters.export_to_xarray import (
load_to_xarray_dataarray_dict,
load_to_xarray_dataarray_dict, # pyright: ignore[reportDeprecated]
load_to_xarray_dataset,
load_to_xarray_dataset_dict,
)

if TYPE_CHECKING:
Expand Down Expand Up @@ -79,7 +82,7 @@ def data(self) -> ParameterData:
Loads data from the database on disk if needed and returns
the cached data. The cached data is in almost the same format as
:py:class:`.DataSet.get_parameter_data`. However if a shape is provided
as part of the dataset metadata and fewer datapoints than expected are
as part of the dataset metadata and fewer data points than expected are
returned the missing values will be replaced by `NaN` or zeroes
depending on the datatype.

Expand Down Expand Up @@ -118,7 +121,7 @@ def _empty_data_dict(

def prepare(self) -> None:
"""
Set up the internal datastructure of the cache.
Set up the internal data structure of the cache.
Must be called after the dataset has been setup with
interdependencies but before data is added to the dataset.
"""
Expand Down Expand Up @@ -185,6 +188,10 @@ def to_pandas_dataframe(self) -> pd.DataFrame:
data = self.data()
return load_to_concatenated_dataframe(data, self.rundescriber.interdeps)

@deprecated(
"to_xarray_dataarray_dict is deprecated, use to_xarray_dataset_dict instead",
category=QCoDeSDeprecationWarning,
)
def to_xarray_dataarray_dict(
self, *, use_multi_index: Literal["auto", "always", "never"] = "auto"
) -> dict[str, xr.DataArray]:
Expand All @@ -200,9 +207,30 @@ def to_xarray_dataarray_dict(

"""
data = self.data()
return load_to_xarray_dataarray_dict(
data_dict = load_to_xarray_dataarray_dict( # pyright: ignore[reportDeprecated]
self._dataset, data, use_multi_index=use_multi_index
)
return data_dict

def to_xarray_dataset_dict(
self, *, use_multi_index: Literal["auto", "always", "never"] = "auto"
) -> dict[str, xr.Dataset]:
"""
Returns the values stored in the :class:`.dataset.data_set.DataSet` as a dict of
:py:class:`xr.DataArray` s
Each element in the dict is indexed by the names of the dependent parameters.

Returns:
Dictionary from requested parameter names to :py:class:`xr.DataArray` s
with the requested parameter(s) as a column(s) and coordinates
formed by the dependencies.

"""
data = self.data()
data_dict = load_to_xarray_dataset_dict(
self._dataset, data, use_multi_index=use_multi_index
)
return data_dict

def to_xarray_dataset(
self, *, use_multi_index: Literal["auto", "always", "never"] = "auto"
Expand Down Expand Up @@ -503,11 +531,11 @@ def load_data_from_db(self) -> None:
)

def _load_xr_dataset(self) -> xr.Dataset:
import cf_xarray as cfxr
import cf_xarray as cf_xr
import xarray as xr

loaded_data = xr.load_dataset(self._xr_dataset_path, engine="h5netcdf")
loaded_data = cfxr.coding.decode_compress_to_multi_index(loaded_data)
loaded_data = cf_xr.coding.decode_compress_to_multi_index(loaded_data)
export_info = ExportInfo.from_str(loaded_data.attrs.get("export_info", ""))
export_info.export_paths["nc"] = str(self._xr_dataset_path)
loaded_data.attrs["export_info"] = export_info.to_str()
Expand Down
19 changes: 17 additions & 2 deletions src/qcodes/dataset/data_set_in_memory.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@

import numpy as np
import numpy.typing as npt
from typing_extensions import deprecated

from qcodes.dataset.data_set_protocol import (
SPECS,
Expand Down Expand Up @@ -40,7 +41,7 @@
update_parent_datasets,
update_run_description,
)
from qcodes.utils import NumpyJSONEncoder
from qcodes.utils import NumpyJSONEncoder, QCoDeSDeprecationWarning

from .data_set_cache import DataSetCacheDeferred, DataSetCacheInMem
from .dataset_helpers import _add_run_to_runs_table
Expand Down Expand Up @@ -848,6 +849,10 @@ def _parameters(self) -> str | None:
else:
return None

@deprecated(
"to_xarray_dataarray_dict is deprecated, use to_xarray_dataset_dict instead",
category=QCoDeSDeprecationWarning,
)
def to_xarray_dataarray_dict(
self,
*params: str | ParamSpec | ParameterBase,
Expand All @@ -856,7 +861,17 @@ def to_xarray_dataarray_dict(
use_multi_index: Literal["auto", "always", "never"] = "auto",
) -> dict[str, xr.DataArray]:
self._warn_if_set(*params, start=start, end=end)
return self.cache.to_xarray_dataarray_dict()
return self.cache.to_xarray_dataarray_dict() # pyright: ignore[reportDeprecated]

def to_xarray_dataset_dict(
self,
*params: str | ParamSpec | ParameterBase,
start: int | None = None,
end: int | None = None,
use_multi_index: Literal["auto", "always", "never"] = "auto",
) -> dict[str, xr.Dataset]:
self._warn_if_set(*params, start=start, end=end)
return self.cache.to_xarray_dataset_dict(use_multi_index=use_multi_index)

def to_xarray_dataset(
self,
Expand Down
8 changes: 8 additions & 0 deletions src/qcodes/dataset/data_set_protocol.py
Original file line number Diff line number Diff line change
Expand Up @@ -233,6 +233,14 @@ def to_xarray_dataarray_dict(
use_multi_index: Literal["auto", "always", "never"] = "auto",
) -> dict[str, xr.DataArray]: ...

def to_xarray_dataset_dict(
self,
*params: str | ParamSpec | ParameterBase,
start: int | None = None,
end: int | None = None,
use_multi_index: Literal["auto", "always", "never"] = "auto",
) -> dict[str, xr.Dataset]: ...

def to_xarray_dataset(
self,
*params: str | ParamSpec | ParameterBase,
Expand Down
Loading
Loading