Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 16 additions & 0 deletions .github/lazy-imports/sitecustomize.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
"""Limit globally enabled lazy imports to imports involving QCoDeS."""

# ruff: noqa: INP001

import sys


def qcodes_import_filter(
importing: str | None, imported: str, fromlist: tuple[str, ...] | None
) -> bool:
return imported.startswith("qcodes") or (
importing is not None and importing.startswith("qcodes")
)


sys.set_lazy_imports_filter(qcodes_import_filter)
2 changes: 2 additions & 0 deletions .github/workflows/pytest.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,8 @@ jobs:
env:
OS: ${{ matrix.os }}
PYTHON: ${{ matrix.python-version }}
PYTHON_LAZY_IMPORTS: ${{ matrix.python-version == '3.15' && 'all' || '' }}
PYTHONPATH: ${{ matrix.python-version == '3.15' && format('{0}/.github/lazy-imports', github.workspace) || '' }}

steps:

Expand Down
16 changes: 16 additions & 0 deletions docs/changes/newsfragments/8600.breaking
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
To support Python 3.15 lazy imports, modules whose names collide with objects exported
from their parent package have been moved to private modules. This affects
``qcodes.dataset.dond`` and its submodules, ``qcodes.utils.full_class``, the Stanford Research
driver modules (e.g. ``qcodes.instrument_drivers.stanford_research.SR830``) and the Basel
driver modules (e.g. ``qcodes.instrument_drivers.basel.BaselSP983``). The old module paths
remain available as deprecated aliases that emit a ``QCoDeSDeprecationWarning`` and will be
removed in a future release. Import the objects from the parent package instead, e.g.
``from qcodes.instrument_drivers.stanford_research import SR830`` or
``from qcodes.dataset import dond``.

Any other names that were importable from these modules but are not exported from the parent
package are now considered private. This includes the type aliases such as ``ParamMeasT`` and
``ActionsT``, as well as ``DondKWargs``, ``ParameterGroup``, ``ParameterSetEvent`` and
``catch_interrupts`` from ``qcodes.dataset.dond``. They remain importable from the deprecated
module aliases until those are removed. If you rely on one of these names, please open an issue
at https://github.com/microsoft/Qcodes/issues so that we can consider making it public.
7 changes: 7 additions & 0 deletions docs/changes/newsfragments/8600.breaking.1
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
``VoltageParameter`` from the SR560 driver has been renamed to ``SR560VoltageParameter`` and is now
exported from ``qcodes.instrument_drivers.stanford_research``. The parameter classes
``ChannelBuffer``, ``ChannelTrace`` and ``GeneratedSetPoints`` of the SR830 driver have been
renamed to ``SR830ChannelBuffer``, ``SR830ChannelTrace`` and ``SR830GeneratedSetPoints``. These
and ``SR86xBufferReadout`` of the SR86x drivers are only created by the drivers themselves and are
now private. The old names remain available from the deprecated ``SR560``, ``SR830`` and ``SR86x``
module aliases until those are removed.
4 changes: 4 additions & 0 deletions docs/changes/newsfragments/8600.improved
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
``do2d_retrace`` is now exported from ``qcodes.dataset``. It has also been fixed: previously it
failed because the setpoints of the outer sweep were not added to the datasets. Parameters
given as ``additional_setpoints`` are now registered in the datasets, and ``exit_actions`` are
called once at the end of the measurement rather than after every step of the outer sweep.
Original file line number Diff line number Diff line change
Expand Up @@ -851,7 +851,7 @@
"- example: `instrument_drivers.AlazarTech.ATS9870.AlazarTech_ATS9870`\n",
"\n",
"Although the class name can be just the model if it is globally unambiguous. For example:\n",
"- example: `instrument_drivers.stanford_research.SR560.SR560`\n",
"- example: `instrument_drivers.stanford_research.SR560`\n",
"\n",
"And note that due to mergers, some drivers may not be in the folder you expect:\n",
"- example: `instrument_drivers.tektronix.Keithley_2600.Keithley_2600_Channels`"
Expand Down
21 changes: 15 additions & 6 deletions src/qcodes/dataset/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,15 @@
and from disk
"""

from qcodes.utils.deprecate import _keep_attributes_shadowing_submodules

from ._dond.do2d_retrace import do2d_retrace
from ._dond.do_0d import do0d
from ._dond.do_1d import do1d
from ._dond.do_2d import do2d
from ._dond.do_nd import dond
from ._dond.do_nd_utils import BreakConditionInterrupt
from ._dond.sweeps import AbstractSweep, ArraySweep, LinSweep, LogSweep, TogetherSweep
from ._raw_data_storage import (
cleanup_datasets,
purge_orphaned_datasets,
Expand All @@ -26,12 +35,6 @@
from .descriptions.param_spec import ParamSpec
from .descriptions.rundescriber import RunDescriber
from .descriptions.versioning.serialization import rundescriber_from_json
from .dond.do_0d import do0d
from .dond.do_1d import do1d
from .dond.do_2d import do2d
from .dond.do_nd import dond
from .dond.do_nd_utils import BreakConditionInterrupt
from .dond.sweeps import AbstractSweep, ArraySweep, LinSweep, LogSweep, TogetherSweep
from .experiment_container import (
experiments,
load_experiment,
Expand Down Expand Up @@ -71,6 +74,11 @@
call_params_threaded,
)

# Keep the public objects when the deprecated module aliases that share
# their names are imported.
_keep_attributes_shadowing_submodules(__name__)


__all__ = [
"AbstractSweep",
"ArraySweep",
Expand Down Expand Up @@ -100,6 +108,7 @@
"do0d",
"do1d",
"do2d",
"do2d_retrace",
"dond",
"dond_into",
"experiments",
Expand Down
Empty file.
154 changes: 154 additions & 0 deletions src/qcodes/dataset/_dond/do2d_retrace.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,154 @@
from __future__ import annotations

import logging
from typing import TYPE_CHECKING

from opentelemetry import trace

from qcodes import config
from qcodes.dataset._dond.sweeps import LinSweep
from qcodes.dataset.measurement_extensions import (
DataSetDefinition,
LinSweeper,
datasaver_builder,
dond_into,
)

LOG = logging.getLogger(__name__)
TRACER = trace.get_tracer(__name__)

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wonder if this dod2_retrace is something that we want to deprecate instead. The code is not working on main . It was never documented etc.



if TYPE_CHECKING:
from collections.abc import Sequence

from qcodes.dataset._dond.do_nd_utils import ActionsT
from qcodes.dataset.data_set_protocol import DataSetProtocol
from qcodes.dataset.experiment_container import Experiment
from qcodes.parameters import ParameterBase


@TRACER.start_as_current_span("qcodes.dataset.do2d")
def do2d_retrace(
param_set1: ParameterBase,
start1: float,
stop1: float,
num_points1: int,
delay1: float,
param_set2: ParameterBase,
start2: float,
stop2: float,
num_points2: int,
delay2: float,
*param_meas: ParameterBase,
enter_actions: ActionsT = (),
exit_actions: ActionsT = (),
before_inner_actions: ActionsT = (),
after_inner_actions: ActionsT = (),
measurement_name: str = "",
exp: Experiment | None = None,
additional_setpoints: Sequence[ParameterBase] = (),
show_progress: bool | None = None,
) -> tuple[DataSetProtocol, DataSetProtocol]:
"""
Perform a 1D scan of ``param_set1`` from ``start1`` to ``stop1`` in
``num_points1`` and ``param_set2`` from ``start2`` to ``stop2`` in
``num_points2`` measuring param_meas at each step.

Args:
param_set1: The QCoDeS parameter to sweep over in the outer loop
start1: Starting point of sweep in outer loop
stop1: End point of sweep in the outer loop
num_points1: Number of points to measure in the outer loop
delay1: Delay after setting parameter in the outer loop
param_set2: The QCoDeS parameter to sweep over in the inner loop
start2: Starting point of sweep in inner loop
stop2: End point of sweep in the inner loop
num_points2: Number of points to measure in the inner loop
delay2: Delay after setting parameter before measurement is performed
param_meas: Parameter(s) to measure at each step or functions that
will be called at each step. The function should take no arguments.
The parameters and functions are called in the order they are
supplied.
enter_actions: A list of functions taking no arguments that will be
called before the measurements start
exit_actions: A list of functions taking no arguments that will be
called after the measurements ends
before_inner_actions: Actions executed before each run of the inner loop
after_inner_actions: Actions executed after each run of the inner loop
measurement_name: Name of the measurement. This will be passed down to
the dataset produced by the measurement. If not given, a default
value of 'results' is used for the dataset.
exp: The experiment to use for this measurement.
additional_setpoints: A list of setpoint parameters to be registered in
the measurement but not scanned.
show_progress: should a progress bar be displayed during the
measurement. If None the setting will be read from ``qcodesrc.json``

Returns:
The QCoDeS dataset.

"""

if show_progress is None:
show_progress = config.dataset.dond_show_progress

independent = [param_set1, param_set2, *additional_setpoints]
# the outer parameter is set by the LinSweeper below rather than swept by
# dond_into so it is recorded as an additional setpoint of the inner sweeps
inner_additional_setpoints = (param_set1, *additional_setpoints)

dataset_definition = [
DataSetDefinition(
name=measurement_name,
independent=independent,
dependent=param_meas,
experiment=exp,
),
DataSetDefinition(
name=f"retrace {measurement_name}",
independent=independent,
dependent=param_meas,
experiment=exp,
),
]

with datasaver_builder(dataset_definition) as datasavers:
for action in enter_actions:
action()
for _ in LinSweeper(param_set1, start1, stop1, num_points1, delay1):
sweep_up = LinSweep(
param_set2,
start2,
stop2,
num_points2,
delay2,
post_actions=after_inner_actions,
)
sweep_down = LinSweep(
param_set2,
stop2,
start2,
num_points2,
delay2,
post_actions=after_inner_actions,
)
for action in before_inner_actions:
action()
dond_into(
datasavers[0],
sweep_up,
*param_meas,
additional_setpoints=inner_additional_setpoints,
)
for action in before_inner_actions:
action()
dond_into(
datasavers[1],
sweep_down,
*param_meas,
additional_setpoints=inner_additional_setpoints,
)
for action in exit_actions:
action()
datasets = (datasavers[0].dataset, datasavers[1].dataset)
return datasets
50 changes: 50 additions & 0 deletions src/qcodes/dataset/_dond/do_0d.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
from __future__ import annotations

import logging
from typing import TYPE_CHECKING, cast

from opentelemetry import trace

from .do_nd import DondKWargs, dond

if TYPE_CHECKING:
from typing import Unpack

from .do_nd_utils import (
AxesTupleListWithDataSet,
ParamMeasT,
)

LOG = logging.getLogger(__name__)
TRACER = trace.get_tracer(__name__)


@TRACER.start_as_current_span("qcodes.dataset.do0d")
def do0d(
*param_meas: ParamMeasT, **kwargs: Unpack[DondKWargs]
) -> AxesTupleListWithDataSet:
"""
Perform a measurement of a single parameter. This is probably most
useful for a ParameterWithSetpoints that already returns an array of data points.

Args:
*param_meas: Parameter(s) to measure at each step or functions that
will be called at each step. The function should take no arguments.
The parameters and functions are called in the order they are
supplied.
**kwargs: kwargs are the same as for :func:`dond` and forwarded directly to :func:`dond`.

Returns:
The QCoDeS dataset.

"""

kwargs.setdefault("log_info", "Using 'qcodes.dataset.do0d'")

# since we only support entering parameters
# as a simple list or args we are sure to always
# get back a AxesTupleListWithDataSet and cast is safe
return cast(
"AxesTupleListWithDataSet",
dond(*param_meas, **kwargs, squeeze=True),
)
71 changes: 71 additions & 0 deletions src/qcodes/dataset/_dond/do_1d.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
from __future__ import annotations

import logging
from typing import TYPE_CHECKING, cast

from opentelemetry import trace

from .do_nd import DondKWargs, dond
from .sweeps import LinSweep

if TYPE_CHECKING:
from typing import Unpack

from qcodes.dataset._dond.do_nd_utils import (
AxesTupleListWithDataSet,
ParamMeasT,
)
from qcodes.parameters import ParameterBase

LOG = logging.getLogger(__name__)
TRACER = trace.get_tracer(__name__)


@TRACER.start_as_current_span("qcodes.dataset.do1d")
def do1d(
param_set: ParameterBase,
start: float,
stop: float,
num_points: int,
delay: float,
*param_meas: ParamMeasT,
**kwargs: Unpack[DondKWargs],
) -> AxesTupleListWithDataSet:
"""
Perform a 1D scan of ``param_set`` from ``start`` to ``stop`` in
``num_points`` measuring param_meas at each step. In case param_meas is
an ArrayParameter this is effectively a 2d scan.

Args:
param_set: The QCoDeS parameter to sweep over
start: Starting point of sweep
stop: End point of sweep
num_points: Number of points in sweep
delay: Delay after setting parameter before measurement is performed
*param_meas: Parameter(s) to measure at each step or functions that
will be called at each step. The function should take no arguments.
The parameters and functions are called in the order they are
supplied.
**kwargs: kwargs are the same as for :func:`dond` and forwarded directly to :func:`dond`.

Returns:
The QCoDeS dataset.

"""
kwargs.setdefault("log_info", "Using 'qcodes.dataset.do1d'")

return cast(
"AxesTupleListWithDataSet",
dond(
LinSweep(
param=param_set,
start=start,
stop=stop,
delay=delay,
num_points=num_points,
),
*param_meas,
**kwargs,
squeeze=True,
),
)
Loading
Loading