From 2a1dc2103708404168964ebddd4d81b1b2afec64 Mon Sep 17 00:00:00 2001 From: Samantha Ho Date: Fri, 4 Oct 2024 12:13:31 -0700 Subject: [PATCH 01/14] Implement snapshot of registered parameters --- src/qcodes/dataset/measurements.py | 31 +++++++++++++++++++++++++++--- 1 file changed, 28 insertions(+), 3 deletions(-) diff --git a/src/qcodes/dataset/measurements.py b/src/qcodes/dataset/measurements.py index 110b959e91c..1a062c09fe1 100644 --- a/src/qcodes/dataset/measurements.py +++ b/src/qcodes/dataset/measurements.py @@ -8,6 +8,7 @@ import collections import io +import json import logging import traceback as tb_module import warnings @@ -50,7 +51,7 @@ expand_setpoints_helper, ) from qcodes.station import Station -from qcodes.utils import DelayedKeyboardInterrupt +from qcodes.utils import DelayedKeyboardInterrupt, NumpyJSONEncoder if TYPE_CHECKING: from types import TracebackType @@ -549,6 +550,7 @@ def __init__( in_memory_cache: bool | None = None, dataset_class: DataSetType = DataSetType.DataSet, parent_span: trace.Span | None = None, + registered_parameters: Sequence[ParameterBase] | None = None, ) -> None: if in_memory_cache is None: in_memory_cache = qc.config.dataset.in_memory_cache @@ -577,6 +579,7 @@ def __init__( self._in_memory_cache = in_memory_cache self._parent_span = parent_span self.ds: DataSetProtocol + self._registered_parameters = registered_parameters @staticmethod def _calculate_write_period( @@ -672,7 +675,14 @@ def __enter__(self) -> DataSaver: shapes=self._shapes, parent_datasets=self._parent_datasets, ) - + if self._registered_parameters is not None: + parameter_snapshot = { + param.short_name: param.snapshot + for param in self._registered_parameters + } + self.ds.add_snapshot( + json.dumps({"parameters": parameter_snapshot}, cls=NumpyJSONEncoder) + ) # register all subscribers if isinstance(self.ds, DataSet): for callble, state in self.subscribers: @@ -803,6 +813,7 @@ def __init__( self._shapes: Shapes | None = None self._parent_datasets: list[dict[str, str]] = [] self._extra_log_info: str = "" + self._registered_parameters: list[ParameterBase] = [] @property def parameters(self) -> dict[str, ParamSpecBase]: @@ -926,7 +937,7 @@ def register_parameter( f"Can not register object of type {type(parameter)}. Can only " "register a QCoDeS Parameter." ) - + self._registered_parameters.append(parameter) paramtype = self._infer_paramtype(parameter, paramtype) # default to numeric if paramtype is None: @@ -1034,6 +1045,7 @@ def _register_parameter( setpoints: setpoints_type | None, basis: setpoints_type | None, paramtype: str, + metadata: dict[str, Any] | None = None, ) -> T: """ Update the interdependencies object with a new group @@ -1279,8 +1291,20 @@ def unregister_parameter(self, parameter: setpoints_type) -> None: """ if isinstance(parameter, ParameterBase): param = str_or_register_name(parameter) + try: + self._registered_parameters.remove(parameter) + except ValueError: + return elif isinstance(parameter, str): param = parameter + parameter_to_remove = [ + param_obj + for param_obj in self._registered_parameters + if parameter in (param_obj.name, param_obj.register_name) + ] + if len(parameter_to_remove) == 1: + self._registered_parameters.remove(parameter_to_remove[0]) + else: raise ValueError( "Wrong input type. Must be a QCoDeS parameter or" @@ -1412,6 +1436,7 @@ def run( in_memory_cache=in_memory_cache, dataset_class=dataset_class, parent_span=parent_span, + registered_parameters=self._registered_parameters, ) From 8e689822d2181016fd07e9a00540d396158cf583 Mon Sep 17 00:00:00 2001 From: Samantha Ho Date: Fri, 4 Oct 2024 12:29:32 -0700 Subject: [PATCH 02/14] Remove assumption that snapshot in prepare only contains the station snapshot Add parameters to snapshot passed to prepare --- src/qcodes/dataset/data_set.py | 2 +- src/qcodes/dataset/data_set_in_memory.py | 2 +- src/qcodes/dataset/measurements.py | 17 ++++++++--------- 3 files changed, 10 insertions(+), 11 deletions(-) diff --git a/src/qcodes/dataset/data_set.py b/src/qcodes/dataset/data_set.py index 231eee60fc8..a2230f450aa 100644 --- a/src/qcodes/dataset/data_set.py +++ b/src/qcodes/dataset/data_set.py @@ -329,7 +329,7 @@ def prepare( parent_datasets: Sequence[Mapping[Any, Any]] = (), write_in_background: bool = False, ) -> None: - self.add_snapshot(json.dumps({"station": snapshot}, cls=NumpyJSONEncoder)) + self.add_snapshot(json.dumps(snapshot, cls=NumpyJSONEncoder)) if interdeps == InterDependencies_(): raise RuntimeError("No parameters supplied") diff --git a/src/qcodes/dataset/data_set_in_memory.py b/src/qcodes/dataset/data_set_in_memory.py index 14ff4002373..3685256da21 100644 --- a/src/qcodes/dataset/data_set_in_memory.py +++ b/src/qcodes/dataset/data_set_in_memory.py @@ -421,7 +421,7 @@ def prepare( if not self.pristine: raise RuntimeError("Cannot prepare a dataset that is not pristine.") - self.add_snapshot(json.dumps({"station": snapshot}, cls=NumpyJSONEncoder)) + self.add_snapshot(json.dumps(snapshot, cls=NumpyJSONEncoder)) if interdeps == InterDependencies_(): raise RuntimeError("No parameters supplied") diff --git a/src/qcodes/dataset/measurements.py b/src/qcodes/dataset/measurements.py index 1a062c09fe1..4758f5c0569 100644 --- a/src/qcodes/dataset/measurements.py +++ b/src/qcodes/dataset/measurements.py @@ -664,9 +664,15 @@ def __enter__(self) -> DataSaver: station = self.station if station is not None: - snapshot = station.snapshot() + snapshot = {"station": station.snapshot()} else: snapshot = {} + if self._registered_parameters is not None: + parameter_snapshot = { + param.short_name: param.snapshot() + for param in self._registered_parameters + } + snapshot["parameters"] = parameter_snapshot self.ds.prepare( snapshot=snapshot, @@ -675,14 +681,7 @@ def __enter__(self) -> DataSaver: shapes=self._shapes, parent_datasets=self._parent_datasets, ) - if self._registered_parameters is not None: - parameter_snapshot = { - param.short_name: param.snapshot - for param in self._registered_parameters - } - self.ds.add_snapshot( - json.dumps({"parameters": parameter_snapshot}, cls=NumpyJSONEncoder) - ) + # register all subscribers if isinstance(self.ds, DataSet): for callble, state in self.subscribers: From 5dad67b33251a408b931563187500ca38a86ffde Mon Sep 17 00:00:00 2001 From: Samantha Ho Date: Fri, 4 Oct 2024 13:04:23 -0700 Subject: [PATCH 03/14] Remove unused imports --- src/qcodes/dataset/measurements.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/qcodes/dataset/measurements.py b/src/qcodes/dataset/measurements.py index 4758f5c0569..56db1f2d988 100644 --- a/src/qcodes/dataset/measurements.py +++ b/src/qcodes/dataset/measurements.py @@ -8,7 +8,6 @@ import collections import io -import json import logging import traceback as tb_module import warnings @@ -51,7 +50,7 @@ expand_setpoints_helper, ) from qcodes.station import Station -from qcodes.utils import DelayedKeyboardInterrupt, NumpyJSONEncoder +from qcodes.utils import DelayedKeyboardInterrupt if TYPE_CHECKING: from types import TracebackType From ee2b0c592bdd82e24f24fa291ca229f0adaf0fe3 Mon Sep 17 00:00:00 2001 From: Samantha Ho Date: Mon, 7 Oct 2024 10:50:38 -0700 Subject: [PATCH 04/14] Fixing broken tests --- src/qcodes/dataset/measurements.py | 34 ++++++++++++++++++------------ tests/dataset/test_snapshot.py | 9 ++++++-- 2 files changed, 28 insertions(+), 15 deletions(-) diff --git a/src/qcodes/dataset/measurements.py b/src/qcodes/dataset/measurements.py index 56db1f2d988..184787b57a6 100644 --- a/src/qcodes/dataset/measurements.py +++ b/src/qcodes/dataset/measurements.py @@ -1288,21 +1288,24 @@ def unregister_parameter(self, parameter: setpoints_type) -> None: running this measurement """ if isinstance(parameter, ParameterBase): - param = str_or_register_name(parameter) - try: - self._registered_parameters.remove(parameter) - except ValueError: - return + param_name = str_or_register_name(parameter) + parameter_to_remove = parameter elif isinstance(parameter, str): - param = parameter - parameter_to_remove = [ + param_name = parameter + parameters_to_remove: list[ParameterBase] = [ param_obj for param_obj in self._registered_parameters - if parameter in (param_obj.name, param_obj.register_name) + if param_name in (param_obj.name, param_obj.register_name) ] - if len(parameter_to_remove) == 1: - self._registered_parameters.remove(parameter_to_remove[0]) - + if len(parameters_to_remove) == 0: + raise ValueError( + f"No parameter matching {param_name} found in the list of registered parameters" + ) + elif len(parameters_to_remove) > 1: + raise ValueError( + f"Multiple parameters matching {param_name} found in the list of registered parameters" + ) + parameter_to_remove = parameters_to_remove[0] else: raise ValueError( "Wrong input type. Must be a QCoDeS parameter or" @@ -1310,13 +1313,18 @@ def unregister_parameter(self, parameter: setpoints_type) -> None: ) try: - paramspec: ParamSpecBase = self._interdeps[param] + paramspec: ParamSpecBase = self._interdeps[param_name] except KeyError: return self._interdeps = self._interdeps.remove(paramspec) - log.info(f"Removed {param} from Measurement.") + # Must follow interdeps removal, because interdeps removal may error + try: + self._registered_parameters.remove(parameter_to_remove) + except ValueError: + return + log.info(f"Removed {param_name} from Measurement.") def add_before_run(self: T, func: Callable[..., Any], args: Sequence[Any]) -> T: """ diff --git a/tests/dataset/test_snapshot.py b/tests/dataset/test_snapshot.py index b706b849356..10b53b928e4 100644 --- a/tests/dataset/test_snapshot.py +++ b/tests/dataset/test_snapshot.py @@ -43,7 +43,9 @@ def test_station_snapshot_during_measurement( measurement.register_parameter(dac.ch1) measurement.register_parameter(dmm.v1, setpoints=[dac.ch1]) - + snapshot_of_parameters = { + parameter.short_name: parameter.snapshot for parameter in (dac.ch1, dmm.v1) + } with measurement.run() as data_saver: data_saver.add_result((dac.ch1, 7), (dmm.v1, 5)) @@ -53,7 +55,10 @@ def test_station_snapshot_during_measurement( json_snapshot_from_dataset = data_saver.dataset.get_metadata("snapshot") # type: ignore[attr-defined] snapshot_from_dataset = json.loads(json_snapshot_from_dataset) - expected_snapshot = {"station": snapshot_of_station} + expected_snapshot = { + "station": snapshot_of_station, + "parameters": snapshot_of_parameters, + } assert expected_snapshot == snapshot_from_dataset # 2. Test `snapshot_raw` property From aa0e8492187252936d6ac77c62d0d6b5731a8861 Mon Sep 17 00:00:00 2001 From: Samantha Ho Date: Mon, 7 Oct 2024 11:01:54 -0700 Subject: [PATCH 05/14] Fix weird mypy error --- src/qcodes/dataset/measurements.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/qcodes/dataset/measurements.py b/src/qcodes/dataset/measurements.py index 184787b57a6..57b535c427f 100644 --- a/src/qcodes/dataset/measurements.py +++ b/src/qcodes/dataset/measurements.py @@ -1289,7 +1289,7 @@ def unregister_parameter(self, parameter: setpoints_type) -> None: """ if isinstance(parameter, ParameterBase): param_name = str_or_register_name(parameter) - parameter_to_remove = parameter + parameter_to_remove: ParameterBase = parameter elif isinstance(parameter, str): param_name = parameter parameters_to_remove: list[ParameterBase] = [ From 232a90e20a6ff65ca71f5b2189485ca8616eba04 Mon Sep 17 00:00:00 2001 From: Samantha Ho Date: Mon, 7 Oct 2024 11:16:51 -0700 Subject: [PATCH 06/14] Fixing example notebook --- docs/examples/DataSet/Working with snapshots.ipynb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/examples/DataSet/Working with snapshots.ipynb b/docs/examples/DataSet/Working with snapshots.ipynb index e918d3696dd..6ac653d0600 100644 --- a/docs/examples/DataSet/Working with snapshots.ipynb +++ b/docs/examples/DataSet/Working with snapshots.ipynb @@ -678,7 +678,7 @@ "metadata": {}, "outputs": [], "source": [ - "assert {\"station\": snapshot_of_station} == snapshot_of_run" + "assert {\"station\": snapshot_of_station} == snapshot_of_run[\"station\"]" ] }, { From c261efb2c8c29ec5d48ff23c1212b19de47ca1a8 Mon Sep 17 00:00:00 2001 From: Samantha Ho Date: Mon, 7 Oct 2024 11:18:37 -0700 Subject: [PATCH 07/14] Really fixing example notebook --- .../DataSet/Working with snapshots.ipynb | 417 ++---------------- 1 file changed, 38 insertions(+), 379 deletions(-) diff --git a/docs/examples/DataSet/Working with snapshots.ipynb b/docs/examples/DataSet/Working with snapshots.ipynb index 6ac653d0600..ac5f67c7de9 100644 --- a/docs/examples/DataSet/Working with snapshots.ipynb +++ b/docs/examples/DataSet/Working with snapshots.ipynb @@ -79,26 +79,9 @@ }, { "cell_type": "code", - "execution_count": 2, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "{'__class__': 'qcodes.instrument.parameter.Parameter',\n", - " 'full_name': 'p',\n", - " 'inter_delay': 0,\n", - " 'label': 'Parameter P',\n", - " 'name': 'p',\n", - " 'post_delay': 0,\n", - " 'raw_value': 123,\n", - " 'ts': '2019-06-21 13:10:37',\n", - " 'unit': 'kg',\n", - " 'value': 123}\n" - ] - } - ], + "execution_count": null, + "metadata": {}, + "outputs": [], "source": [ "p = Parameter(\"p\", label=\"Parameter P\", unit=\"kg\", set_cmd=None, get_cmd=None)\n", "p.set(123)\n", @@ -117,17 +100,9 @@ }, { "cell_type": "code", - "execution_count": 3, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Value of Parameter P was 123 (when it was snapshotted).\n" - ] - } - ], + "execution_count": null, + "metadata": {}, + "outputs": [], "source": [ "print(\n", " f\"Value of {snapshot_of_p['label']} was {snapshot_of_p['value']} (when it was snapshotted).\"\n", @@ -150,24 +125,9 @@ }, { "cell_type": "code", - "execution_count": 4, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "{'__class__': 'qcodes.instrument.parameter.Parameter',\n", - " 'full_name': 'q',\n", - " 'inter_delay': 0,\n", - " 'label': 'Parameter Q',\n", - " 'name': 'q',\n", - " 'post_delay': 0,\n", - " 'ts': None,\n", - " 'unit': 'A'}\n" - ] - } - ], + "execution_count": null, + "metadata": {}, + "outputs": [], "source": [ "q = Parameter(\n", " \"q\", label=\"Parameter Q\", unit=\"A\", snapshot_value=False, set_cmd=None, get_cmd=None\n", @@ -201,72 +161,9 @@ }, { "cell_type": "code", - "execution_count": 6, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "{ '__class__': 'qcodes.instrument_drivers.mock_instruments.DummyInstrument',\n", - " 'functions': {},\n", - " 'name': 'instr',\n", - " 'parameters': { 'IDN': { '__class__': 'qcodes.instrument.parameter.Parameter',\n", - " 'full_name': 'instr_IDN',\n", - " 'instrument': 'qcodes.instrument_drivers.mock_instruments.DummyInstrument',\n", - " 'instrument_name': 'instr',\n", - " 'inter_delay': 0,\n", - " 'label': 'IDN',\n", - " 'name': 'IDN',\n", - " 'post_delay': 0,\n", - " 'raw_value': None,\n", - " 'ts': None,\n", - " 'unit': '',\n", - " 'vals': '',\n", - " 'value': None},\n", - " 'gain': { '__class__': 'qcodes.instrument.parameter.Parameter',\n", - " 'full_name': 'instr_gain',\n", - " 'instrument': 'qcodes.instrument_drivers.mock_instruments.DummyInstrument',\n", - " 'instrument_name': 'instr',\n", - " 'inter_delay': 0,\n", - " 'label': 'Gate gain',\n", - " 'name': 'gain',\n", - " 'post_delay': 0,\n", - " 'raw_value': 11,\n", - " 'ts': '2019-06-21 13:10:37',\n", - " 'unit': 'V',\n", - " 'vals': '',\n", - " 'value': 11},\n", - " 'input': { '__class__': 'qcodes.instrument.parameter.Parameter',\n", - " 'full_name': 'instr_input',\n", - " 'instrument': 'qcodes.instrument_drivers.mock_instruments.DummyInstrument',\n", - " 'instrument_name': 'instr',\n", - " 'inter_delay': 0,\n", - " 'label': 'Gate input',\n", - " 'name': 'input',\n", - " 'post_delay': 0,\n", - " 'raw_value': 0,\n", - " 'ts': '2019-06-21 13:10:37',\n", - " 'unit': 'V',\n", - " 'vals': '',\n", - " 'value': 0},\n", - " 'output': { '__class__': 'qcodes.instrument.parameter.Parameter',\n", - " 'full_name': 'instr_output',\n", - " 'instrument': 'qcodes.instrument_drivers.mock_instruments.DummyInstrument',\n", - " 'instrument_name': 'instr',\n", - " 'inter_delay': 0,\n", - " 'label': 'Gate output',\n", - " 'name': 'output',\n", - " 'post_delay': 0,\n", - " 'raw_value': 0,\n", - " 'ts': '2019-06-21 13:10:37',\n", - " 'unit': 'V',\n", - " 'vals': '',\n", - " 'value': 0}},\n", - " 'submodules': {}}\n" - ] - } - ], + "execution_count": null, + "metadata": {}, + "outputs": [], "source": [ "snapshot_of_instr = instr.snapshot()\n", "\n", @@ -295,20 +192,9 @@ }, { "cell_type": "code", - "execution_count": 7, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "'instr'" - ] - }, - "execution_count": 7, - "metadata": {}, - "output_type": "execute_result" - } - ], + "execution_count": null, + "metadata": {}, + "outputs": [], "source": [ "station = Station()\n", "\n", @@ -321,94 +207,9 @@ }, { "cell_type": "code", - "execution_count": 8, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "{'components': {},\n", - " 'default_measurement': [],\n", - " 'instruments': {'instr': {'__class__': 'qcodes.instrument_drivers.mock_instruments.DummyInstrument',\n", - " 'functions': {},\n", - " 'name': 'instr',\n", - " 'parameters': {'IDN': {'__class__': 'qcodes.instrument.parameter.Parameter',\n", - " 'full_name': 'instr_IDN',\n", - " 'instrument': 'qcodes.instrument_drivers.mock_instruments.DummyInstrument',\n", - " 'instrument_name': 'instr',\n", - " 'inter_delay': 0,\n", - " 'label': 'IDN',\n", - " 'name': 'IDN',\n", - " 'post_delay': 0,\n", - " 'raw_value': {'firmware': None,\n", - " 'model': 'instr',\n", - " 'serial': None,\n", - " 'vendor': None},\n", - " 'ts': '2019-06-21 13:10:37',\n", - " 'unit': '',\n", - " 'vals': '',\n", - " 'value': {'firmware': None,\n", - " 'model': 'instr',\n", - " 'serial': None,\n", - " 'vendor': None}},\n", - " 'gain': {'__class__': 'qcodes.instrument.parameter.Parameter',\n", - " 'full_name': 'instr_gain',\n", - " 'instrument': 'qcodes.instrument_drivers.mock_instruments.DummyInstrument',\n", - " 'instrument_name': 'instr',\n", - " 'inter_delay': 0,\n", - " 'label': 'Gate gain',\n", - " 'name': 'gain',\n", - " 'post_delay': 0,\n", - " 'raw_value': 11,\n", - " 'ts': '2019-06-21 13:10:37',\n", - " 'unit': 'V',\n", - " 'vals': '',\n", - " 'value': 11},\n", - " 'input': {'__class__': 'qcodes.instrument.parameter.Parameter',\n", - " 'full_name': 'instr_input',\n", - " 'instrument': 'qcodes.instrument_drivers.mock_instruments.DummyInstrument',\n", - " 'instrument_name': 'instr',\n", - " 'inter_delay': 0,\n", - " 'label': 'Gate input',\n", - " 'name': 'input',\n", - " 'post_delay': 0,\n", - " 'raw_value': 0,\n", - " 'ts': '2019-06-21 13:10:37',\n", - " 'unit': 'V',\n", - " 'vals': '',\n", - " 'value': 0},\n", - " 'output': {'__class__': 'qcodes.instrument.parameter.Parameter',\n", - " 'full_name': 'instr_output',\n", - " 'instrument': 'qcodes.instrument_drivers.mock_instruments.DummyInstrument',\n", - " 'instrument_name': 'instr',\n", - " 'inter_delay': 0,\n", - " 'label': 'Gate output',\n", - " 'name': 'output',\n", - " 'post_delay': 0,\n", - " 'raw_value': 0,\n", - " 'ts': '2019-06-21 '\n", - " '13:10:37',\n", - " 'unit': 'V',\n", - " 'vals': '',\n", - " 'value': 0}},\n", - " 'submodules': {}}},\n", - " 'parameters': {'p': {'__class__': 'qcodes.instrument.parameter.Parameter',\n", - " 'full_name': 'p',\n", - " 'inter_delay': 0,\n", - " 'label': 'Parameter P',\n", - " 'name': 'p',\n", - " 'post_delay': 0,\n", - " 'raw_value': 456,\n", - " 'ts': '2019-06-21 13:10:37',\n", - " 'unit': 'kg',\n", - " 'value': 456}}}\n" - ] - } - ], + "execution_count": null, + "metadata": {}, + "outputs": [], "source": [ "snapshot_of_station = station.snapshot()\n", "\n", @@ -450,20 +251,9 @@ }, { "cell_type": "code", - "execution_count": 10, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "" - ] - }, - "execution_count": 10, - "metadata": {}, - "output_type": "execute_result" - } - ], + "execution_count": null, + "metadata": {}, + "outputs": [], "source": [ "measurement = Measurement(experiment, station)\n", "\n", @@ -473,17 +263,9 @@ }, { "cell_type": "code", - "execution_count": 11, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Starting experimental run with id: 5\n" - ] - } - ], + "execution_count": null, + "metadata": {}, + "outputs": [], "source": [ "with measurement.run() as data_saver:\n", " input_value = 111\n", @@ -567,100 +349,9 @@ }, { "cell_type": "code", - "execution_count": 16, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "{'station': {'components': {},\n", - " 'default_measurement': [],\n", - " 'instruments': {'instr': {'__class__': 'qcodes.instrument_drivers.mock_instruments.DummyInstrument',\n", - " 'functions': {},\n", - " 'name': 'instr',\n", - " 'parameters': {'IDN': {'__class__': 'qcodes.instrument.parameter.Parameter',\n", - " 'full_name': 'instr_IDN',\n", - " 'instrument': 'qcodes.instrument_drivers.mock_instruments.DummyInstrument',\n", - " 'instrument_name': 'instr',\n", - " 'inter_delay': 0,\n", - " 'label': 'IDN',\n", - " 'name': 'IDN',\n", - " 'post_delay': 0,\n", - " 'raw_value': {'firmware': None,\n", - " 'model': 'instr',\n", - " 'serial': None,\n", - " 'vendor': None},\n", - " 'ts': '2019-06-21 '\n", - " '13:10:37',\n", - " 'unit': '',\n", - " 'vals': '',\n", - " 'value': {'firmware': None,\n", - " 'model': 'instr',\n", - " 'serial': None,\n", - " 'vendor': None}},\n", - " 'gain': {'__class__': 'qcodes.instrument.parameter.Parameter',\n", - " 'full_name': 'instr_gain',\n", - " 'instrument': 'qcodes.instrument_drivers.mock_instruments.DummyInstrument',\n", - " 'instrument_name': 'instr',\n", - " 'inter_delay': 0,\n", - " 'label': 'Gate '\n", - " 'gain',\n", - " 'name': 'gain',\n", - " 'post_delay': 0,\n", - " 'raw_value': 11,\n", - " 'ts': '2019-06-21 '\n", - " '13:10:37',\n", - " 'unit': 'V',\n", - " 'vals': '',\n", - " 'value': 11},\n", - " 'input': {'__class__': 'qcodes.instrument.parameter.Parameter',\n", - " 'full_name': 'instr_input',\n", - " 'instrument': 'qcodes.instrument_drivers.mock_instruments.DummyInstrument',\n", - " 'instrument_name': 'instr',\n", - " 'inter_delay': 0,\n", - " 'label': 'Gate '\n", - " 'input',\n", - " 'name': 'input',\n", - " 'post_delay': 0,\n", - " 'raw_value': 0,\n", - " 'ts': '2019-06-21 '\n", - " '13:10:37',\n", - " 'unit': 'V',\n", - " 'vals': '',\n", - " 'value': 0},\n", - " 'output': {'__class__': 'qcodes.instrument.parameter.Parameter',\n", - " 'full_name': 'instr_output',\n", - " 'instrument': 'qcodes.instrument_drivers.mock_instruments.DummyInstrument',\n", - " 'instrument_name': 'instr',\n", - " 'inter_delay': 0,\n", - " 'label': 'Gate '\n", - " 'output',\n", - " 'name': 'output',\n", - " 'post_delay': 0,\n", - " 'raw_value': 0,\n", - " 'ts': '2019-06-21 '\n", - " '13:10:37',\n", - " 'unit': 'V',\n", - " 'vals': '',\n", - " 'value': 0}},\n", - " 'submodules': {}}},\n", - " 'parameters': {'p': {'__class__': 'qcodes.instrument.parameter.Parameter',\n", - " 'full_name': 'p',\n", - " 'inter_delay': 0,\n", - " 'label': 'Parameter P',\n", - " 'name': 'p',\n", - " 'post_delay': 0,\n", - " 'raw_value': 456,\n", - " 'ts': '2019-06-21 13:10:37',\n", - " 'unit': 'kg',\n", - " 'value': 456}}}}\n" - ] - } - ], + "execution_count": null, + "metadata": {}, + "outputs": [], "source": [ "pprint(snapshot_of_run)" ] @@ -678,7 +369,7 @@ "metadata": {}, "outputs": [], "source": [ - "assert {\"station\": snapshot_of_station} == snapshot_of_run[\"station\"]" + "assert snapshot_of_station == snapshot_of_run[\"station\"]" ] }, { @@ -698,20 +389,9 @@ }, { "cell_type": "code", - "execution_count": 18, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "" - ] - }, - "execution_count": 18, - "metadata": {}, - "output_type": "execute_result" - } - ], + "execution_count": null, + "metadata": {}, + "outputs": [], "source": [ "measurement = Measurement(experiment, station)\n", "\n", @@ -721,17 +401,9 @@ }, { "cell_type": "code", - "execution_count": 19, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Starting experimental run with id: 6\n" - ] - } - ], + "execution_count": null, + "metadata": {}, + "outputs": [], "source": [ "instr.gain(400) # Oops!\n", "with measurement.run() as data_saver:\n", @@ -766,22 +438,9 @@ }, { "cell_type": "code", - "execution_count": 21, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "{('instr', 'output'): (0, 222),\n", - " ('instr', 'gain'): (11, 400),\n", - " ('instr', 'input'): (0, 111)}" - ] - }, - "execution_count": 21, - "metadata": {}, - "output_type": "execute_result" - } - ], + "execution_count": null, + "metadata": {}, + "outputs": [], "source": [ "diff_param_values(dataset.snapshot, bad_dataset.snapshot).changed" ] @@ -810,7 +469,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.7.4" + "version": "3.11.8" }, "toc": { "base_numbering": 1, From bd362e73360aa4432909de2854a0ea7c2ae86da5 Mon Sep 17 00:00:00 2001 From: Samantha Ho Date: Mon, 7 Oct 2024 12:03:56 -0700 Subject: [PATCH 08/14] Fail unregister silently if parameter_by_str doesn't exist --- src/qcodes/dataset/measurements.py | 22 +++++++++------------- 1 file changed, 9 insertions(+), 13 deletions(-) diff --git a/src/qcodes/dataset/measurements.py b/src/qcodes/dataset/measurements.py index 57b535c427f..f29c51ebb45 100644 --- a/src/qcodes/dataset/measurements.py +++ b/src/qcodes/dataset/measurements.py @@ -1289,7 +1289,7 @@ def unregister_parameter(self, parameter: setpoints_type) -> None: """ if isinstance(parameter, ParameterBase): param_name = str_or_register_name(parameter) - parameter_to_remove: ParameterBase = parameter + parameter_to_remove: ParameterBase | None = parameter elif isinstance(parameter, str): param_name = parameter parameters_to_remove: list[ParameterBase] = [ @@ -1298,14 +1298,9 @@ def unregister_parameter(self, parameter: setpoints_type) -> None: if param_name in (param_obj.name, param_obj.register_name) ] if len(parameters_to_remove) == 0: - raise ValueError( - f"No parameter matching {param_name} found in the list of registered parameters" - ) - elif len(parameters_to_remove) > 1: - raise ValueError( - f"Multiple parameters matching {param_name} found in the list of registered parameters" - ) - parameter_to_remove = parameters_to_remove[0] + parameter_to_remove = None + else: + parameter_to_remove = parameters_to_remove[0] else: raise ValueError( "Wrong input type. Must be a QCoDeS parameter or" @@ -1320,10 +1315,11 @@ def unregister_parameter(self, parameter: setpoints_type) -> None: self._interdeps = self._interdeps.remove(paramspec) # Must follow interdeps removal, because interdeps removal may error - try: - self._registered_parameters.remove(parameter_to_remove) - except ValueError: - return + if parameter_to_remove is not None: + try: + self._registered_parameters.remove(parameter_to_remove) + except ValueError: + return log.info(f"Removed {param_name} from Measurement.") def add_before_run(self: T, func: Callable[..., Any], args: Sequence[Any]) -> T: From 433fdb2d538fbdec3e1797969a9099b9f7ad09d1 Mon Sep 17 00:00:00 2001 From: Samantha Ho Date: Mon, 7 Oct 2024 12:24:53 -0700 Subject: [PATCH 09/14] Refactored unregister code for greater clarity --- src/qcodes/dataset/measurements.py | 22 ++++++++++------------ 1 file changed, 10 insertions(+), 12 deletions(-) diff --git a/src/qcodes/dataset/measurements.py b/src/qcodes/dataset/measurements.py index f29c51ebb45..37877cd55e4 100644 --- a/src/qcodes/dataset/measurements.py +++ b/src/qcodes/dataset/measurements.py @@ -1289,18 +1289,8 @@ def unregister_parameter(self, parameter: setpoints_type) -> None: """ if isinstance(parameter, ParameterBase): param_name = str_or_register_name(parameter) - parameter_to_remove: ParameterBase | None = parameter elif isinstance(parameter, str): param_name = parameter - parameters_to_remove: list[ParameterBase] = [ - param_obj - for param_obj in self._registered_parameters - if param_name in (param_obj.name, param_obj.register_name) - ] - if len(parameters_to_remove) == 0: - parameter_to_remove = None - else: - parameter_to_remove = parameters_to_remove[0] else: raise ValueError( "Wrong input type. Must be a QCoDeS parameter or" @@ -1315,11 +1305,19 @@ def unregister_parameter(self, parameter: setpoints_type) -> None: self._interdeps = self._interdeps.remove(paramspec) # Must follow interdeps removal, because interdeps removal may error - if parameter_to_remove is not None: + if isinstance(parameter, ParameterBase): try: - self._registered_parameters.remove(parameter_to_remove) + self._registered_parameters.remove(parameter) except ValueError: return + elif isinstance(parameter, str): + with_parameters_removed = [ + param + for param in self._registered_parameters + if parameter not in (param.name, param.register_name) + ] + self._registered_parameters = with_parameters_removed + log.info(f"Removed {param_name} from Measurement.") def add_before_run(self: T, func: Callable[..., Any], args: Sequence[Any]) -> T: From 6cb6f042831ef5fac0404b34943bbf10c7a6c1c0 Mon Sep 17 00:00:00 2001 From: Samantha Ho Date: Mon, 7 Oct 2024 12:25:01 -0700 Subject: [PATCH 10/14] Fix snapshot test again --- tests/dataset/test_snapshot.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/dataset/test_snapshot.py b/tests/dataset/test_snapshot.py index 10b53b928e4..607f992b493 100644 --- a/tests/dataset/test_snapshot.py +++ b/tests/dataset/test_snapshot.py @@ -44,7 +44,7 @@ def test_station_snapshot_during_measurement( measurement.register_parameter(dac.ch1) measurement.register_parameter(dmm.v1, setpoints=[dac.ch1]) snapshot_of_parameters = { - parameter.short_name: parameter.snapshot for parameter in (dac.ch1, dmm.v1) + parameter.short_name: parameter.snapshot() for parameter in (dac.ch1, dmm.v1) } with measurement.run() as data_saver: data_saver.add_result((dac.ch1, 7), (dmm.v1, 5)) From 224d4550bda4242fb688ddf0b433c30f38e30de0 Mon Sep 17 00:00:00 2001 From: Samantha Ho Date: Mon, 7 Oct 2024 13:43:54 -0700 Subject: [PATCH 11/14] Add changelog --- docs/changes/newsfragments/6487.improved | 1 + 1 file changed, 1 insertion(+) create mode 100644 docs/changes/newsfragments/6487.improved diff --git a/docs/changes/newsfragments/6487.improved b/docs/changes/newsfragments/6487.improved new file mode 100644 index 00000000000..215a5e5a5cc --- /dev/null +++ b/docs/changes/newsfragments/6487.improved @@ -0,0 +1 @@ +Parameters registered in a qcodes Measurement are now snapshotted and stored in the resulting dataset under `dataset.snapshot["parameters"]` \ No newline at end of file From 50f3976c94462652bdfbf88fb19ffb4ffbd6a5a0 Mon Sep 17 00:00:00 2001 From: Samantha Ho Date: Tue, 8 Oct 2024 14:22:02 -0700 Subject: [PATCH 12/14] Lightly modify snapshot example notebook --- .../DataSet/Working with snapshots.ipynb | 472 ++++++++++++++++-- 1 file changed, 434 insertions(+), 38 deletions(-) diff --git a/docs/examples/DataSet/Working with snapshots.ipynb b/docs/examples/DataSet/Working with snapshots.ipynb index ac5f67c7de9..8ea736c4990 100644 --- a/docs/examples/DataSet/Working with snapshots.ipynb +++ b/docs/examples/DataSet/Working with snapshots.ipynb @@ -79,9 +79,27 @@ }, { "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], + "execution_count": 2, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "{'__class__': 'qcodes.parameters.parameter.Parameter',\n", + " 'full_name': 'p',\n", + " 'inter_delay': 0,\n", + " 'label': 'Parameter P',\n", + " 'name': 'p',\n", + " 'post_delay': 0,\n", + " 'raw_value': 123,\n", + " 'ts': '2024-10-08 14:04:12',\n", + " 'unit': 'kg',\n", + " 'validators': [],\n", + " 'value': 123}\n" + ] + } + ], "source": [ "p = Parameter(\"p\", label=\"Parameter P\", unit=\"kg\", set_cmd=None, get_cmd=None)\n", "p.set(123)\n", @@ -100,9 +118,17 @@ }, { "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], + "execution_count": 3, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Value of Parameter P was 123 (when it was snapshotted).\n" + ] + } + ], "source": [ "print(\n", " f\"Value of {snapshot_of_p['label']} was {snapshot_of_p['value']} (when it was snapshotted).\"\n", @@ -125,9 +151,25 @@ }, { "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], + "execution_count": 4, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "{'__class__': 'qcodes.parameters.parameter.Parameter',\n", + " 'full_name': 'q',\n", + " 'inter_delay': 0,\n", + " 'label': 'Parameter Q',\n", + " 'name': 'q',\n", + " 'post_delay': 0,\n", + " 'ts': None,\n", + " 'unit': 'A',\n", + " 'validators': []}\n" + ] + } + ], "source": [ "q = Parameter(\n", " \"q\", label=\"Parameter Q\", unit=\"A\", snapshot_value=False, set_cmd=None, get_cmd=None\n", @@ -161,9 +203,90 @@ }, { "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], + "execution_count": 6, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "{ '__class__': 'qcodes.instrument_drivers.mock_instruments.DummyInstrument',\n", + " 'functions': {},\n", + " 'label': 'instr',\n", + " 'name': 'instr',\n", + " 'parameters': { 'IDN': { '__class__': 'qcodes.parameters.parameter.Parameter',\n", + " 'full_name': 'instr_IDN',\n", + " 'instrument': 'qcodes.instrument_drivers.mock_instruments.DummyInstrument',\n", + " 'instrument_name': 'instr',\n", + " 'inter_delay': 0,\n", + " 'label': 'IDN',\n", + " 'name': 'IDN',\n", + " 'post_delay': 0,\n", + " 'raw_value': None,\n", + " 'ts': None,\n", + " 'unit': '',\n", + " 'validators': [''],\n", + " 'vals': '',\n", + " 'value': None},\n", + " 'fixed_parameter': { '__class__': 'qcodes.parameters.parameter.Parameter',\n", + " 'full_name': 'instr_fixed_parameter',\n", + " 'instrument': 'qcodes.instrument_drivers.mock_instruments.DummyInstrument',\n", + " 'instrument_name': 'instr',\n", + " 'inter_delay': 0,\n", + " 'label': 'fixed_parameter',\n", + " 'name': 'fixed_parameter',\n", + " 'post_delay': 0,\n", + " 'raw_value': 5,\n", + " 'ts': '2024-10-08 14:04:12',\n", + " 'unit': '',\n", + " 'validators': [],\n", + " 'value': 5},\n", + " 'gain': { '__class__': 'qcodes.parameters.parameter.Parameter',\n", + " 'full_name': 'instr_gain',\n", + " 'instrument': 'qcodes.instrument_drivers.mock_instruments.DummyInstrument',\n", + " 'instrument_name': 'instr',\n", + " 'inter_delay': 0,\n", + " 'label': 'Gate gain',\n", + " 'name': 'gain',\n", + " 'post_delay': 0,\n", + " 'raw_value': 11,\n", + " 'ts': '2024-10-08 14:04:12',\n", + " 'unit': 'V',\n", + " 'validators': [''],\n", + " 'vals': '',\n", + " 'value': 11},\n", + " 'input': { '__class__': 'qcodes.parameters.parameter.Parameter',\n", + " 'full_name': 'instr_input',\n", + " 'instrument': 'qcodes.instrument_drivers.mock_instruments.DummyInstrument',\n", + " 'instrument_name': 'instr',\n", + " 'inter_delay': 0,\n", + " 'label': 'Gate input',\n", + " 'name': 'input',\n", + " 'post_delay': 0,\n", + " 'raw_value': 0,\n", + " 'ts': '2024-10-08 14:04:12',\n", + " 'unit': 'V',\n", + " 'validators': [''],\n", + " 'vals': '',\n", + " 'value': 0},\n", + " 'output': { '__class__': 'qcodes.parameters.parameter.Parameter',\n", + " 'full_name': 'instr_output',\n", + " 'instrument': 'qcodes.instrument_drivers.mock_instruments.DummyInstrument',\n", + " 'instrument_name': 'instr',\n", + " 'inter_delay': 0,\n", + " 'label': 'Gate output',\n", + " 'name': 'output',\n", + " 'post_delay': 0,\n", + " 'raw_value': 0,\n", + " 'ts': '2024-10-08 14:04:12',\n", + " 'unit': 'V',\n", + " 'validators': [''],\n", + " 'vals': '',\n", + " 'value': 0}},\n", + " 'submodules': {}}\n" + ] + } + ], "source": [ "snapshot_of_instr = instr.snapshot()\n", "\n", @@ -192,9 +315,20 @@ }, { "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], + "execution_count": 7, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "'instr'" + ] + }, + "execution_count": 7, + "metadata": {}, + "output_type": "execute_result" + } + ], "source": [ "station = Station()\n", "\n", @@ -207,9 +341,119 @@ }, { "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], + "execution_count": 8, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "{'components': {},\n", + " 'config': None,\n", + " 'instruments': {'instr': {'__class__': 'qcodes.instrument_drivers.mock_instruments.DummyInstrument',\n", + " 'functions': {},\n", + " 'label': 'instr',\n", + " 'name': 'instr',\n", + " 'parameters': {'IDN': {'__class__': 'qcodes.parameters.parameter.Parameter',\n", + " 'full_name': 'instr_IDN',\n", + " 'instrument': 'qcodes.instrument_drivers.mock_instruments.DummyInstrument',\n", + " 'instrument_name': 'instr',\n", + " 'inter_delay': 0,\n", + " 'label': 'IDN',\n", + " 'name': 'IDN',\n", + " 'post_delay': 0,\n", + " 'raw_value': {'firmware': 'NA',\n", + " 'model': '\",\n", + " 'serial': 'NA',\n", + " 'vendor': 'QCoDeS'},\n", + " 'ts': '2024-10-08 14:04:12',\n", + " 'unit': '',\n", + " 'validators': [''],\n", + " 'vals': '',\n", + " 'value': {'firmware': 'NA',\n", + " 'model': '\",\n", + " 'serial': 'NA',\n", + " 'vendor': 'QCoDeS'}},\n", + " 'fixed_parameter': {'__class__': 'qcodes.parameters.parameter.Parameter',\n", + " 'full_name': 'instr_fixed_parameter',\n", + " 'instrument': 'qcodes.instrument_drivers.mock_instruments.DummyInstrument',\n", + " 'instrument_name': 'instr',\n", + " 'inter_delay': 0,\n", + " 'label': 'fixed_parameter',\n", + " 'name': 'fixed_parameter',\n", + " 'post_delay': 0,\n", + " 'raw_value': 5,\n", + " 'ts': '2024-10-08 '\n", + " '14:04:12',\n", + " 'unit': '',\n", + " 'validators': [],\n", + " 'value': 5},\n", + " 'gain': {'__class__': 'qcodes.parameters.parameter.Parameter',\n", + " 'full_name': 'instr_gain',\n", + " 'instrument': 'qcodes.instrument_drivers.mock_instruments.DummyInstrument',\n", + " 'instrument_name': 'instr',\n", + " 'inter_delay': 0,\n", + " 'label': 'Gate gain',\n", + " 'name': 'gain',\n", + " 'post_delay': 0,\n", + " 'raw_value': 11,\n", + " 'ts': '2024-10-08 14:04:12',\n", + " 'unit': 'V',\n", + " 'validators': [''],\n", + " 'vals': '',\n", + " 'value': 11},\n", + " 'input': {'__class__': 'qcodes.parameters.parameter.Parameter',\n", + " 'full_name': 'instr_input',\n", + " 'instrument': 'qcodes.instrument_drivers.mock_instruments.DummyInstrument',\n", + " 'instrument_name': 'instr',\n", + " 'inter_delay': 0,\n", + " 'label': 'Gate input',\n", + " 'name': 'input',\n", + " 'post_delay': 0,\n", + " 'raw_value': 0,\n", + " 'ts': '2024-10-08 14:04:12',\n", + " 'unit': 'V',\n", + " 'validators': [''],\n", + " 'vals': '',\n", + " 'value': 0},\n", + " 'output': {'__class__': 'qcodes.parameters.parameter.Parameter',\n", + " 'full_name': 'instr_output',\n", + " 'instrument': 'qcodes.instrument_drivers.mock_instruments.DummyInstrument',\n", + " 'instrument_name': 'instr',\n", + " 'inter_delay': 0,\n", + " 'label': 'Gate output',\n", + " 'name': 'output',\n", + " 'post_delay': 0,\n", + " 'raw_value': 0,\n", + " 'ts': '2024-10-08 '\n", + " '14:04:12',\n", + " 'unit': 'V',\n", + " 'validators': [''],\n", + " 'vals': '',\n", + " 'value': 0}},\n", + " 'submodules': {}}},\n", + " 'parameters': {'p': {'__class__': 'qcodes.parameters.parameter.Parameter',\n", + " 'full_name': 'p',\n", + " 'inter_delay': 0,\n", + " 'label': 'Parameter P',\n", + " 'name': 'p',\n", + " 'post_delay': 0,\n", + " 'raw_value': 456,\n", + " 'ts': '2024-10-08 14:04:12',\n", + " 'unit': 'kg',\n", + " 'validators': [],\n", + " 'value': 456}}}\n" + ] + } + ], "source": [ "snapshot_of_station = station.snapshot()\n", "\n", @@ -220,13 +464,15 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "## Saving snapshot next to the measurement data\n", + "## Saving snapshots next to the measurement data\n", "\n", "With the power of the station object, it is now possible to conveniently associate the snapshot information with the measured data.\n", "\n", "In order to do so, a station needs to be created, and then that station needs to be provided to the `Measurement` object. If no station is explicitly provided, the `Measurement` object will use the default station, `Station.default` (refer to `Measurement` and `Station` objects docstrings for more information). At the moment the new measurement run is started, a snapshot of the whole station will be taken, and added next to the measured data.\n", "\n", - "Note that the snapshot gets stored in a JSON format (an automatic convertion from python dictionary to JSON takes place). This is done in order to ensure that the snapshot can be read in environments other than python. JSON is an extemely popular data format, and all platforms/environments/languages/frameworks have means to read JSON-formatted data." + "The measured dataset also automatically snapshots the parameters involved in the measurement and stores it alongside the station snapshot.\n", + "\n", + "Note that these snapshots get stored in a JSON format (an automatic convertion from python dictionary to JSON takes place). This is done in order to ensure that the snapshot can be read in environments other than python. JSON is an extemely popular data format, and all platforms/environments/languages/frameworks have means to read JSON-formatted data." ] }, { @@ -251,9 +497,20 @@ }, { "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], + "execution_count": 10, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "" + ] + }, + "execution_count": 10, + "metadata": {}, + "output_type": "execute_result" + } + ], "source": [ "measurement = Measurement(experiment, station)\n", "\n", @@ -292,7 +549,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "Now we have a dataset that contains data from the measurement run. It also contains the snapshot.\n", + "Now we have a dataset that contains data from the measurement run. It also contains the station and parameters snapshots.\n", "\n", "In order to access the snapshot, use the `DataSet`'s properties called `snapshot` and `snapshot_raw`. As their docstrings declare, the former returns the snapshot of the run as a python dictionary, while the latter returns it as JSON string (in other words, in exactly the same format as it is stored in the experiments database)." ] @@ -344,14 +601,160 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "Finally, let's pretty-print the snapshot. Notice that the values of the `input` and `output` parameters of the `instr` instrument have `0`s as values, and not `111` and `222` that were set during the measurement run." + "Finally, let's pretty-print the snapshot. Notice that the values of the `input` and `output` parameters of the `instr` instrument have `0`s as values, and not `111` and `222` that were set during the measurement run.\n", + "\n", + "Also note that the `station` top-level-key contains the station snapshot, while the `parameters` top-level-key contains a snapshot of all the measurement parameters." ] }, { "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], + "execution_count": 16, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "{'parameters': {'input': {'__class__': 'qcodes.parameters.parameter.Parameter',\n", + " 'full_name': 'instr_input',\n", + " 'instrument': 'qcodes.instrument_drivers.mock_instruments.DummyInstrument',\n", + " 'instrument_name': 'instr',\n", + " 'inter_delay': 0,\n", + " 'label': 'Gate input',\n", + " 'name': 'input',\n", + " 'post_delay': 0,\n", + " 'raw_value': 0,\n", + " 'ts': '2024-10-08 14:04:12',\n", + " 'unit': 'V',\n", + " 'validators': [''],\n", + " 'vals': '',\n", + " 'value': 0},\n", + " 'output': {'__class__': 'qcodes.parameters.parameter.Parameter',\n", + " 'full_name': 'instr_output',\n", + " 'instrument': 'qcodes.instrument_drivers.mock_instruments.DummyInstrument',\n", + " 'instrument_name': 'instr',\n", + " 'inter_delay': 0,\n", + " 'label': 'Gate output',\n", + " 'name': 'output',\n", + " 'post_delay': 0,\n", + " 'raw_value': 0,\n", + " 'ts': '2024-10-08 14:04:12',\n", + " 'unit': 'V',\n", + " 'validators': [''],\n", + " 'vals': '',\n", + " 'value': 0}},\n", + " 'station': {'components': {},\n", + " 'config': None,\n", + " 'instruments': {'instr': {'__class__': 'qcodes.instrument_drivers.mock_instruments.DummyInstrument',\n", + " 'functions': {},\n", + " 'label': 'instr',\n", + " 'name': 'instr',\n", + " 'parameters': {'IDN': {'__class__': 'qcodes.parameters.parameter.Parameter',\n", + " 'full_name': 'instr_IDN',\n", + " 'instrument': 'qcodes.instrument_drivers.mock_instruments.DummyInstrument',\n", + " 'instrument_name': 'instr',\n", + " 'inter_delay': 0,\n", + " 'label': 'IDN',\n", + " 'name': 'IDN',\n", + " 'post_delay': 0,\n", + " 'raw_value': {'firmware': 'NA',\n", + " 'model': '\",\n", + " 'serial': 'NA',\n", + " 'vendor': 'QCoDeS'},\n", + " 'ts': '2024-10-08 '\n", + " '14:04:12',\n", + " 'unit': '',\n", + " 'validators': [''],\n", + " 'vals': '',\n", + " 'value': {'firmware': 'NA',\n", + " 'model': '\",\n", + " 'serial': 'NA',\n", + " 'vendor': 'QCoDeS'}},\n", + " 'fixed_parameter': {'__class__': 'qcodes.parameters.parameter.Parameter',\n", + " 'full_name': 'instr_fixed_parameter',\n", + " 'instrument': 'qcodes.instrument_drivers.mock_instruments.DummyInstrument',\n", + " 'instrument_name': 'instr',\n", + " 'inter_delay': 0,\n", + " 'label': 'fixed_parameter',\n", + " 'name': 'fixed_parameter',\n", + " 'post_delay': 0,\n", + " 'raw_value': 5,\n", + " 'ts': '2024-10-08 '\n", + " '14:04:12',\n", + " 'unit': '',\n", + " 'validators': [],\n", + " 'value': 5},\n", + " 'gain': {'__class__': 'qcodes.parameters.parameter.Parameter',\n", + " 'full_name': 'instr_gain',\n", + " 'instrument': 'qcodes.instrument_drivers.mock_instruments.DummyInstrument',\n", + " 'instrument_name': 'instr',\n", + " 'inter_delay': 0,\n", + " 'label': 'Gate '\n", + " 'gain',\n", + " 'name': 'gain',\n", + " 'post_delay': 0,\n", + " 'raw_value': 11,\n", + " 'ts': '2024-10-08 '\n", + " '14:04:12',\n", + " 'unit': 'V',\n", + " 'validators': [''],\n", + " 'vals': '',\n", + " 'value': 11},\n", + " 'input': {'__class__': 'qcodes.parameters.parameter.Parameter',\n", + " 'full_name': 'instr_input',\n", + " 'instrument': 'qcodes.instrument_drivers.mock_instruments.DummyInstrument',\n", + " 'instrument_name': 'instr',\n", + " 'inter_delay': 0,\n", + " 'label': 'Gate '\n", + " 'input',\n", + " 'name': 'input',\n", + " 'post_delay': 0,\n", + " 'raw_value': 0,\n", + " 'ts': '2024-10-08 '\n", + " '14:04:12',\n", + " 'unit': 'V',\n", + " 'validators': [''],\n", + " 'vals': '',\n", + " 'value': 0},\n", + " 'output': {'__class__': 'qcodes.parameters.parameter.Parameter',\n", + " 'full_name': 'instr_output',\n", + " 'instrument': 'qcodes.instrument_drivers.mock_instruments.DummyInstrument',\n", + " 'instrument_name': 'instr',\n", + " 'inter_delay': 0,\n", + " 'label': 'Gate '\n", + " 'output',\n", + " 'name': 'output',\n", + " 'post_delay': 0,\n", + " 'raw_value': 0,\n", + " 'ts': '2024-10-08 '\n", + " '14:04:12',\n", + " 'unit': 'V',\n", + " 'validators': [''],\n", + " 'vals': '',\n", + " 'value': 0}},\n", + " 'submodules': {}}},\n", + " 'parameters': {'p': {'__class__': 'qcodes.parameters.parameter.Parameter',\n", + " 'full_name': 'p',\n", + " 'inter_delay': 0,\n", + " 'label': 'Parameter P',\n", + " 'name': 'p',\n", + " 'post_delay': 0,\n", + " 'raw_value': 456,\n", + " 'ts': '2024-10-08 14:04:12',\n", + " 'unit': 'kg',\n", + " 'validators': [],\n", + " 'value': 456}}}}\n" + ] + } + ], "source": [ "pprint(snapshot_of_run)" ] @@ -360,7 +763,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "Note that the snapshot that we have just loaded from the dataset is almost the same as the snapshot that we directly obtained from the station above. The only difference is that the snapshot loaded from the dataset has a top-level `station` field. If you do not trust me, have a look at the following `assert` statement for the proof." + "Note that the snapshot that we have just loaded from the dataset is almost the same as the snapshot that we directly obtained from the station above. One difference is that the snapshot loaded from the dataset has a top-level `station` field. It also has a top-level `parameters` field. If you do not trust me, have a look at the following `assert` statement for the proof." ] }, { @@ -372,13 +775,6 @@ "assert snapshot_of_station == snapshot_of_run[\"station\"]" ] }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Comparing how two DataSets were taken" - ] - }, { "cell_type": "markdown", "metadata": {}, @@ -424,7 +820,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "The `diff_param_values` function tells us about the parameters that changed betw" + "The `diff_param_values` function tells us about the parameters that changed between the two snapshots" ] }, { @@ -433,7 +829,7 @@ "metadata": {}, "outputs": [], "source": [ - "from qcodes.utils.metadata import diff_param_values" + "from qcodes.utils import diff_param_values" ] }, { From 9ed504f28b126bf1c3de45b16e18afd3d4d5b7cc Mon Sep 17 00:00:00 2001 From: Samantha Ho Date: Tue, 8 Oct 2024 14:40:33 -0700 Subject: [PATCH 13/14] Fix pre-commit errors --- docs/changes/newsfragments/6487.improved | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/changes/newsfragments/6487.improved b/docs/changes/newsfragments/6487.improved index 215a5e5a5cc..e516aeefac6 100644 --- a/docs/changes/newsfragments/6487.improved +++ b/docs/changes/newsfragments/6487.improved @@ -1 +1 @@ -Parameters registered in a qcodes Measurement are now snapshotted and stored in the resulting dataset under `dataset.snapshot["parameters"]` \ No newline at end of file +Parameters registered in a qcodes Measurement are now snapshotted and stored in the resulting dataset under `dataset.snapshot["parameters"]` From 1a18a457eaae1aab5266ba142039c0db1ed6cc9b Mon Sep 17 00:00:00 2001 From: Samantha Ho Date: Wed, 9 Oct 2024 07:31:29 -0700 Subject: [PATCH 14/14] Move append of _registered_parameters list to end of method, so any errors have already happened --- src/qcodes/dataset/measurements.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/qcodes/dataset/measurements.py b/src/qcodes/dataset/measurements.py index 37877cd55e4..97e8d50286b 100644 --- a/src/qcodes/dataset/measurements.py +++ b/src/qcodes/dataset/measurements.py @@ -935,7 +935,6 @@ def register_parameter( f"Can not register object of type {type(parameter)}. Can only " "register a QCoDeS Parameter." ) - self._registered_parameters.append(parameter) paramtype = self._infer_paramtype(parameter, paramtype) # default to numeric if paramtype is None: @@ -990,6 +989,7 @@ def register_parameter( raise RuntimeError( f"Does not know how to register a parameter of type {type(parameter)}" ) + self._registered_parameters.append(parameter) return self