From 8aadf3849e3069a7b0e87a204474bfbb6dd5a9d5 Mon Sep 17 00:00:00 2001 From: Thomas Lemon Date: Mon, 29 Sep 2025 16:23:00 -0700 Subject: [PATCH 01/12] Add blocking during temperature ramp --- .../QuantumDesign/DynaCoolPPMS/DynaCool.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/qcodes/instrument_drivers/QuantumDesign/DynaCoolPPMS/DynaCool.py b/src/qcodes/instrument_drivers/QuantumDesign/DynaCoolPPMS/DynaCool.py index 657f15af54bd..5770e045facb 100644 --- a/src/qcodes/instrument_drivers/QuantumDesign/DynaCoolPPMS/DynaCool.py +++ b/src/qcodes/instrument_drivers/QuantumDesign/DynaCoolPPMS/DynaCool.py @@ -410,6 +410,12 @@ def _temp_setter( values[self.temp_params.index(param)] = value self.write(f"TEMP {values[0]}, {values[1]}, {values[2]}") + self._block_on_temperature_ramp() + + def _block_on_temperature_ramp(self) -> None: + """Block all instrument interactions until temperature stabilizes.""" + while self.temperature_state() != "stable": + sleep(1) def write(self, cmd: str) -> None: """ From 3de59529fc05557b6a9fd4c9f13ca877cb6b522d Mon Sep 17 00:00:00 2001 From: Thomas Lemon Date: Mon, 29 Sep 2025 16:39:43 -0700 Subject: [PATCH 02/12] Update newsfragment for DynaCool PPMS driver improvement --- docs/changes/newsfragments/7534.improved_driver | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 docs/changes/newsfragments/7534.improved_driver diff --git a/docs/changes/newsfragments/7534.improved_driver b/docs/changes/newsfragments/7534.improved_driver new file mode 100644 index 000000000000..00505ea20703 --- /dev/null +++ b/docs/changes/newsfragments/7534.improved_driver @@ -0,0 +1,3 @@ +Added blocking function to DynaCool PPMS driver that waits for temperature +state to be stable before allowing other functions to be called when +setting the temperature. From 433c77fbc27f46b3abcd2df6c9f48146378b0bde Mon Sep 17 00:00:00 2001 From: Thomas Lemon Date: Mon, 27 Oct 2025 08:23:46 -0700 Subject: [PATCH 03/12] Add optional bool to _temp_setter to control blocking_t function to prevent breaking current implementations. --- .../QuantumDesign/DynaCoolPPMS/DynaCool.py | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/src/qcodes/instrument_drivers/QuantumDesign/DynaCoolPPMS/DynaCool.py b/src/qcodes/instrument_drivers/QuantumDesign/DynaCoolPPMS/DynaCool.py index 5770e045facb..2b2a29a97355 100644 --- a/src/qcodes/instrument_drivers/QuantumDesign/DynaCoolPPMS/DynaCool.py +++ b/src/qcodes/instrument_drivers/QuantumDesign/DynaCoolPPMS/DynaCool.py @@ -83,6 +83,15 @@ def __init__( ) """Parameter temperature_setpoint""" + self.blocking_t: Parameter = self.add_parameter( + "blocking_t", + label="Block instrument while ramping temp", + unit="K", + vals=vals.Numbers(1.6, 400), + set_cmd=partial(self._temp_setter, "temperature_setpoint", True), + ) + """Parameter blocking_t will block instrument interaction while temperature is ramping to setpoint.""" + self.temperature_rate: Parameter = self.add_parameter( "temperature_rate", label="Temperature settle rate", @@ -400,6 +409,7 @@ def _temp_setter( "temperature_setpoint", "temperature_rate", "temperature_settling" ], value: float, + block_while_ramping: bool = False, ) -> None: """ The setter function for the temperature parameters. All three are set @@ -410,12 +420,10 @@ def _temp_setter( values[self.temp_params.index(param)] = value self.write(f"TEMP {values[0]}, {values[1]}, {values[2]}") - self._block_on_temperature_ramp() - def _block_on_temperature_ramp(self) -> None: - """Block all instrument interactions until temperature stabilizes.""" - while self.temperature_state() != "stable": - sleep(1) + if block_while_ramping: + while self.temperature_state() != "stable": + sleep(self._ramp_time_resolution) def write(self, cmd: str) -> None: """ From ce37e3c6b99c3b63f94bc37413dcff1f56d4f1ff Mon Sep 17 00:00:00 2001 From: Thomas Lemon Date: Mon, 27 Oct 2025 13:28:59 -0700 Subject: [PATCH 04/12] Use new attribute for blocking_t sleep --- .../instrument_drivers/QuantumDesign/DynaCoolPPMS/DynaCool.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/qcodes/instrument_drivers/QuantumDesign/DynaCoolPPMS/DynaCool.py b/src/qcodes/instrument_drivers/QuantumDesign/DynaCoolPPMS/DynaCool.py index 2b2a29a97355..f0ca54b47a99 100644 --- a/src/qcodes/instrument_drivers/QuantumDesign/DynaCoolPPMS/DynaCool.py +++ b/src/qcodes/instrument_drivers/QuantumDesign/DynaCoolPPMS/DynaCool.py @@ -44,6 +44,7 @@ class DynaCool(VisaInstrument): # the ramp time resolution is in (s) and is used in the # _do_blocking_ramp method _ramp_time_resolution = 0.1 + _blocking_t_sleep = 0.5 temp_params = ("temperature_setpoint", "temperature_rate", "temperature_settling") field_params = ("field_target", "field_rate", "field_approach") @@ -423,7 +424,7 @@ def _temp_setter( if block_while_ramping: while self.temperature_state() != "stable": - sleep(self._ramp_time_resolution) + sleep(self._blocking_t_sleep) def write(self, cmd: str) -> None: """ From 6f650c8f6a7181bfb4100aa1831b9f4ebcbef70d Mon Sep 17 00:00:00 2001 From: Thomas Lemon Date: Fri, 2 Jan 2026 11:16:11 -0800 Subject: [PATCH 05/12] Fix bug that crashes PPMS server --- .../instrument_drivers/QuantumDesign/DynaCoolPPMS/DynaCool.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/qcodes/instrument_drivers/QuantumDesign/DynaCoolPPMS/DynaCool.py b/src/qcodes/instrument_drivers/QuantumDesign/DynaCoolPPMS/DynaCool.py index f0ca54b47a99..0c331e13c6ca 100644 --- a/src/qcodes/instrument_drivers/QuantumDesign/DynaCoolPPMS/DynaCool.py +++ b/src/qcodes/instrument_drivers/QuantumDesign/DynaCoolPPMS/DynaCool.py @@ -89,7 +89,9 @@ def __init__( label="Block instrument while ramping temp", unit="K", vals=vals.Numbers(1.6, 400), - set_cmd=partial(self._temp_setter, "temperature_setpoint", True), + set_cmd=partial( + self._temp_setter, "temperature_setpoint", block_while_ramping=True + ), ) """Parameter blocking_t will block instrument interaction while temperature is ramping to setpoint.""" From 07e45fd83cda14d5bbdacff2084c1fef085c60fc Mon Sep 17 00:00:00 2001 From: Thomas <56311859+trlemon@users.noreply.github.com> Date: Wed, 14 Jan 2026 11:50:19 -0800 Subject: [PATCH 06/12] Update setpoint and blocking_t caches after calling either's set Co-authored-by: Mikhail Astafev --- .../instrument_drivers/QuantumDesign/DynaCoolPPMS/DynaCool.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/qcodes/instrument_drivers/QuantumDesign/DynaCoolPPMS/DynaCool.py b/src/qcodes/instrument_drivers/QuantumDesign/DynaCoolPPMS/DynaCool.py index 0c331e13c6ca..4c0885c22e2a 100644 --- a/src/qcodes/instrument_drivers/QuantumDesign/DynaCoolPPMS/DynaCool.py +++ b/src/qcodes/instrument_drivers/QuantumDesign/DynaCoolPPMS/DynaCool.py @@ -427,7 +427,8 @@ def _temp_setter( if block_while_ramping: while self.temperature_state() != "stable": sleep(self._blocking_t_sleep) - + self.setpoint.cache._set_from_raw_value(values[0]) + self.blocking_t.cache._set_from_raw_value(values[0]) def write(self, cmd: str) -> None: """ Since the error code is always returned, we must read it back From a4e1f1ca68a7e46e3b7f48583332ab0f8ddeed74 Mon Sep 17 00:00:00 2001 From: Thomas <56311859+trlemon@users.noreply.github.com> Date: Wed, 14 Jan 2026 11:52:33 -0800 Subject: [PATCH 07/12] Make blocking_t parameter not gettable Co-authored-by: Mikhail Astafev --- .../instrument_drivers/QuantumDesign/DynaCoolPPMS/DynaCool.py | 1 + 1 file changed, 1 insertion(+) diff --git a/src/qcodes/instrument_drivers/QuantumDesign/DynaCoolPPMS/DynaCool.py b/src/qcodes/instrument_drivers/QuantumDesign/DynaCoolPPMS/DynaCool.py index 4c0885c22e2a..9f9aa7ac0adc 100644 --- a/src/qcodes/instrument_drivers/QuantumDesign/DynaCoolPPMS/DynaCool.py +++ b/src/qcodes/instrument_drivers/QuantumDesign/DynaCoolPPMS/DynaCool.py @@ -89,6 +89,7 @@ def __init__( label="Block instrument while ramping temp", unit="K", vals=vals.Numbers(1.6, 400), + get_cmd=False, set_cmd=partial( self._temp_setter, "temperature_setpoint", block_while_ramping=True ), From f759f5222991760cec5d5367ee5805d52323cce3 Mon Sep 17 00:00:00 2001 From: Thomas <56311859+trlemon@users.noreply.github.com> Date: Wed, 14 Jan 2026 12:11:18 -0800 Subject: [PATCH 08/12] Change "temp" to unabbreviated "temperature" for clarity Co-authored-by: Mikhail Astafev --- .../instrument_drivers/QuantumDesign/DynaCoolPPMS/DynaCool.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/qcodes/instrument_drivers/QuantumDesign/DynaCoolPPMS/DynaCool.py b/src/qcodes/instrument_drivers/QuantumDesign/DynaCoolPPMS/DynaCool.py index 9f9aa7ac0adc..e03abfbcddf1 100644 --- a/src/qcodes/instrument_drivers/QuantumDesign/DynaCoolPPMS/DynaCool.py +++ b/src/qcodes/instrument_drivers/QuantumDesign/DynaCoolPPMS/DynaCool.py @@ -86,7 +86,7 @@ def __init__( self.blocking_t: Parameter = self.add_parameter( "blocking_t", - label="Block instrument while ramping temp", + label="Block instrument while ramping temperature", unit="K", vals=vals.Numbers(1.6, 400), get_cmd=False, From 4a7b704235b954ab0e9b3f136617308ff2642eb7 Mon Sep 17 00:00:00 2001 From: Thomas Lemon Date: Wed, 14 Jan 2026 12:11:58 -0800 Subject: [PATCH 09/12] Format for readability. --- .../instrument_drivers/QuantumDesign/DynaCoolPPMS/DynaCool.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/qcodes/instrument_drivers/QuantumDesign/DynaCoolPPMS/DynaCool.py b/src/qcodes/instrument_drivers/QuantumDesign/DynaCoolPPMS/DynaCool.py index 9f9aa7ac0adc..e5e6689abafe 100644 --- a/src/qcodes/instrument_drivers/QuantumDesign/DynaCoolPPMS/DynaCool.py +++ b/src/qcodes/instrument_drivers/QuantumDesign/DynaCoolPPMS/DynaCool.py @@ -428,8 +428,10 @@ def _temp_setter( if block_while_ramping: while self.temperature_state() != "stable": sleep(self._blocking_t_sleep) + self.setpoint.cache._set_from_raw_value(values[0]) self.blocking_t.cache._set_from_raw_value(values[0]) + def write(self, cmd: str) -> None: """ Since the error code is always returned, we must read it back From 605a4f8ef30cf8eaed5f2508d9cf5d09ece33c50 Mon Sep 17 00:00:00 2001 From: Thomas Lemon Date: Wed, 14 Jan 2026 12:24:06 -0800 Subject: [PATCH 10/12] Add note on blocking_t to PPMS example notebook --- .../Qcodes example with DynaCool PPMS.ipynb | 788 +----------------- 1 file changed, 17 insertions(+), 771 deletions(-) diff --git a/docs/examples/driver_examples/Qcodes example with DynaCool PPMS.ipynb b/docs/examples/driver_examples/Qcodes example with DynaCool PPMS.ipynb index 106550749dd7..7d9c2eb639fa 100644 --- a/docs/examples/driver_examples/Qcodes example with DynaCool PPMS.ipynb +++ b/docs/examples/driver_examples/Qcodes example with DynaCool PPMS.ipynb @@ -157,777 +157,7 @@ "outputs": [ { "data": { - "application/javascript": [ - "/* Put everything inside the global mpl namespace */\n", - "window.mpl = {};\n", - "\n", - "\n", - "mpl.get_websocket_type = function() {\n", - " if (typeof(WebSocket) !== 'undefined') {\n", - " return WebSocket;\n", - " } else if (typeof(MozWebSocket) !== 'undefined') {\n", - " return MozWebSocket;\n", - " } else {\n", - " alert('Your browser does not have WebSocket support.' +\n", - " 'Please try Chrome, Safari or Firefox ≥ 6. ' +\n", - " 'Firefox 4 and 5 are also supported but you ' +\n", - " 'have to enable WebSockets in about:config.');\n", - " };\n", - "}\n", - "\n", - "mpl.figure = function(figure_id, websocket, ondownload, parent_element) {\n", - " this.id = figure_id;\n", - "\n", - " this.ws = websocket;\n", - "\n", - " this.supports_binary = (this.ws.binaryType != undefined);\n", - "\n", - " if (!this.supports_binary) {\n", - " var warnings = document.getElementById(\"mpl-warnings\");\n", - " if (warnings) {\n", - " warnings.style.display = 'block';\n", - " warnings.textContent = (\n", - " \"This browser does not support binary websocket messages. \" +\n", - " \"Performance may be slow.\");\n", - " }\n", - " }\n", - "\n", - " this.imageObj = new Image();\n", - "\n", - " this.context = undefined;\n", - " this.message = undefined;\n", - " this.canvas = undefined;\n", - " this.rubberband_canvas = undefined;\n", - " this.rubberband_context = undefined;\n", - " this.format_dropdown = undefined;\n", - "\n", - " this.image_mode = 'full';\n", - "\n", - " this.root = $('
');\n", - " this._root_extra_style(this.root)\n", - " this.root.attr('style', 'display: inline-block');\n", - "\n", - " $(parent_element).append(this.root);\n", - "\n", - " this._init_header(this);\n", - " this._init_canvas(this);\n", - " this._init_toolbar(this);\n", - "\n", - " var fig = this;\n", - "\n", - " this.waiting = false;\n", - "\n", - " this.ws.onopen = function () {\n", - " fig.send_message(\"supports_binary\", {value: fig.supports_binary});\n", - " fig.send_message(\"send_image_mode\", {});\n", - " if (mpl.ratio != 1) {\n", - " fig.send_message(\"set_dpi_ratio\", {'dpi_ratio': mpl.ratio});\n", - " }\n", - " fig.send_message(\"refresh\", {});\n", - " }\n", - "\n", - " this.imageObj.onload = function() {\n", - " if (fig.image_mode == 'full') {\n", - " // Full images could contain transparency (where diff images\n", - " // almost always do), so we need to clear the canvas so that\n", - " // there is no ghosting.\n", - " fig.context.clearRect(0, 0, fig.canvas.width, fig.canvas.height);\n", - " }\n", - " fig.context.drawImage(fig.imageObj, 0, 0);\n", - " };\n", - "\n", - " this.imageObj.onunload = function() {\n", - " fig.ws.close();\n", - " }\n", - "\n", - " this.ws.onmessage = this._make_on_message_function(this);\n", - "\n", - " this.ondownload = ondownload;\n", - "}\n", - "\n", - "mpl.figure.prototype._init_header = function() {\n", - " var titlebar = $(\n", - " '
');\n", - " var titletext = $(\n", - " '
');\n", - " titlebar.append(titletext)\n", - " this.root.append(titlebar);\n", - " this.header = titletext[0];\n", - "}\n", - "\n", - "\n", - "\n", - "mpl.figure.prototype._canvas_extra_style = function(canvas_div) {\n", - "\n", - "}\n", - "\n", - "\n", - "mpl.figure.prototype._root_extra_style = function(canvas_div) {\n", - "\n", - "}\n", - "\n", - "mpl.figure.prototype._init_canvas = function() {\n", - " var fig = this;\n", - "\n", - " var canvas_div = $('
');\n", - "\n", - " canvas_div.attr('style', 'position: relative; clear: both; outline: 0');\n", - "\n", - " function canvas_keyboard_event(event) {\n", - " return fig.key_event(event, event['data']);\n", - " }\n", - "\n", - " canvas_div.keydown('key_press', canvas_keyboard_event);\n", - " canvas_div.keyup('key_release', canvas_keyboard_event);\n", - " this.canvas_div = canvas_div\n", - " this._canvas_extra_style(canvas_div)\n", - " this.root.append(canvas_div);\n", - "\n", - " var canvas = $('');\n", - " canvas.addClass('mpl-canvas');\n", - " canvas.attr('style', \"left: 0; top: 0; z-index: 0; outline: 0\")\n", - "\n", - " this.canvas = canvas[0];\n", - " this.context = canvas[0].getContext(\"2d\");\n", - "\n", - " var backingStore = this.context.backingStorePixelRatio ||\n", - "\tthis.context.webkitBackingStorePixelRatio ||\n", - "\tthis.context.mozBackingStorePixelRatio ||\n", - "\tthis.context.msBackingStorePixelRatio ||\n", - "\tthis.context.oBackingStorePixelRatio ||\n", - "\tthis.context.backingStorePixelRatio || 1;\n", - "\n", - " mpl.ratio = (window.devicePixelRatio || 1) / backingStore;\n", - "\n", - " var rubberband = $('');\n", - " rubberband.attr('style', \"position: absolute; left: 0; top: 0; z-index: 1;\")\n", - "\n", - " var pass_mouse_events = true;\n", - "\n", - " canvas_div.resizable({\n", - " start: function(event, ui) {\n", - " pass_mouse_events = false;\n", - " },\n", - " resize: function(event, ui) {\n", - " fig.request_resize(ui.size.width, ui.size.height);\n", - " },\n", - " stop: function(event, ui) {\n", - " pass_mouse_events = true;\n", - " fig.request_resize(ui.size.width, ui.size.height);\n", - " },\n", - " });\n", - "\n", - " function mouse_event_fn(event) {\n", - " if (pass_mouse_events)\n", - " return fig.mouse_event(event, event['data']);\n", - " }\n", - "\n", - " rubberband.mousedown('button_press', mouse_event_fn);\n", - " rubberband.mouseup('button_release', mouse_event_fn);\n", - " // Throttle sequential mouse events to 1 every 20ms.\n", - " rubberband.mousemove('motion_notify', mouse_event_fn);\n", - "\n", - " rubberband.mouseenter('figure_enter', mouse_event_fn);\n", - " rubberband.mouseleave('figure_leave', mouse_event_fn);\n", - "\n", - " canvas_div.on(\"wheel\", function (event) {\n", - " event = event.originalEvent;\n", - " event['data'] = 'scroll'\n", - " if (event.deltaY < 0) {\n", - " event.step = 1;\n", - " } else {\n", - " event.step = -1;\n", - " }\n", - " mouse_event_fn(event);\n", - " });\n", - "\n", - " canvas_div.append(canvas);\n", - " canvas_div.append(rubberband);\n", - "\n", - " this.rubberband = rubberband;\n", - " this.rubberband_canvas = rubberband[0];\n", - " this.rubberband_context = rubberband[0].getContext(\"2d\");\n", - " this.rubberband_context.strokeStyle = \"#000000\";\n", - "\n", - " this._resize_canvas = function(width, height) {\n", - " // Keep the size of the canvas, canvas container, and rubber band\n", - " // canvas in synch.\n", - " canvas_div.css('width', width)\n", - " canvas_div.css('height', height)\n", - "\n", - " canvas.attr('width', width * mpl.ratio);\n", - " canvas.attr('height', height * mpl.ratio);\n", - " canvas.attr('style', 'width: ' + width + 'px; height: ' + height + 'px;');\n", - "\n", - " rubberband.attr('width', width);\n", - " rubberband.attr('height', height);\n", - " }\n", - "\n", - " // Set the figure to an initial 600x600px, this will subsequently be updated\n", - " // upon first draw.\n", - " this._resize_canvas(600, 600);\n", - "\n", - " // Disable right mouse context menu.\n", - " $(this.rubberband_canvas).bind(\"contextmenu\",function(e){\n", - " return false;\n", - " });\n", - "\n", - " function set_focus () {\n", - " canvas.focus();\n", - " canvas_div.focus();\n", - " }\n", - "\n", - " window.setTimeout(set_focus, 100);\n", - "}\n", - "\n", - "mpl.figure.prototype._init_toolbar = function() {\n", - " var fig = this;\n", - "\n", - " var nav_element = $('
')\n", - " nav_element.attr('style', 'width: 100%');\n", - " this.root.append(nav_element);\n", - "\n", - " // Define a callback function for later on.\n", - " function toolbar_event(event) {\n", - " return fig.toolbar_button_onclick(event['data']);\n", - " }\n", - " function toolbar_mouse_event(event) {\n", - " return fig.toolbar_button_onmouseover(event['data']);\n", - " }\n", - "\n", - " for(var toolbar_ind in mpl.toolbar_items) {\n", - " var name = mpl.toolbar_items[toolbar_ind][0];\n", - " var tooltip = mpl.toolbar_items[toolbar_ind][1];\n", - " var image = mpl.toolbar_items[toolbar_ind][2];\n", - " var method_name = mpl.toolbar_items[toolbar_ind][3];\n", - "\n", - " if (!name) {\n", - " // put a spacer in here.\n", - " continue;\n", - " }\n", - " var button = $('');\n button.click(method_name, toolbar_event);\n button.mouseover(tooltip, toolbar_mouse_event);\n nav_element.append(button);\n }\n\n // Add the status bar.\n var status_bar = $('');\n nav_element.append(status_bar);\n this.message = status_bar[0];\n\n // Add the close button to the window.\n var buttongrp = $('
');\n var button = $('');\n button.click(function (evt) { fig.handle_close(fig, {}); } );\n button.mouseover('Stop Interaction', toolbar_mouse_event);\n buttongrp.append(button);\n var titlebar = this.root.find($('.ui-dialog-titlebar'));\n titlebar.prepend(buttongrp);\n}\n\nmpl.figure.prototype._root_extra_style = function(el){\n var fig = this\n el.on(\"remove\", function(){\n\tfig.close_ws(fig, {});\n });\n}\n\nmpl.figure.prototype._canvas_extra_style = function(el){\n // this is important to make the div 'focusable\n el.attr('tabindex', 0)\n // reach out to IPython and tell the keyboard manager to turn it's self\n // off when our div gets focus\n\n // location in version 3\n if (IPython.notebook.keyboard_manager) {\n IPython.notebook.keyboard_manager.register_events(el);\n }\n else {\n // location in version 2\n IPython.keyboard_manager.register_events(el);\n }\n\n}\n\nmpl.figure.prototype._key_event_extra = function(event, name) {\n var manager = IPython.notebook.keyboard_manager;\n if (!manager)\n manager = IPython.keyboard_manager;\n\n // Check for shift+enter\n if (event.shiftKey && event.which == 13) {\n this.canvas_div.blur();\n event.shiftKey = false;\n // Send a \"J\" for go to next cell\n event.which = 74;\n event.keyCode = 74;\n manager.command_mode();\n manager.handle_keydown(event);\n }\n}\n\nmpl.figure.prototype.handle_save = function(fig, msg) {\n fig.ondownload(fig, null);\n}\n\n\nmpl.find_output_cell = function(html_output) {\n // Return the cell and output element which can be found *uniquely* in the notebook.\n // Note - this is a bit hacky, but it is done because the \"notebook_saving.Notebook\"\n // IPython event is triggered only after the cells have been serialised, which for\n // our purposes (turning an active figure into a static one), is too late.\n var cells = IPython.notebook.get_cells();\n var ncells = cells.length;\n for (var i=0; i= 3 moved mimebundle to data attribute of output\n data = data.data;\n }\n if (data['text/html'] == html_output) {\n return [cell, data, j];\n }\n }\n }\n }\n}\n\n// Register the function which deals with the matplotlib target/channel.\n// The kernel may be null if the page has been refreshed.\nif (IPython.notebook.kernel != null) {\n IPython.notebook.kernel.comm_manager.register_target('matplotlib', mpl.mpl_figure_comm);\n}\n", "text/plain": [ "" ] @@ -966,6 +196,22 @@ "plt.ylabel(\"Temperature (K)\")" ] }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Alternatively, you can use the `blocking_t` parameter to prevent users from taking any action until the setpoint is reached. This may be useful for measurements where you are sweeping temperature and want to ensure the temperature is stable before taking a measurement." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "dynacool.blocking_t(dynacool.temperature() + 1.3)" + ] + }, { "cell_type": "markdown", "metadata": {}, From 11c4a6880f04ef45e50ae24b8a73b18387962e3c Mon Sep 17 00:00:00 2001 From: Thomas Lemon Date: Wed, 14 Jan 2026 12:36:57 -0800 Subject: [PATCH 11/12] Convert private _blocking_t_sleep attribute to Parameter. --- .../QuantumDesign/DynaCoolPPMS/DynaCool.py | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/src/qcodes/instrument_drivers/QuantumDesign/DynaCoolPPMS/DynaCool.py b/src/qcodes/instrument_drivers/QuantumDesign/DynaCoolPPMS/DynaCool.py index df7ca0b17130..1e3451552608 100644 --- a/src/qcodes/instrument_drivers/QuantumDesign/DynaCoolPPMS/DynaCool.py +++ b/src/qcodes/instrument_drivers/QuantumDesign/DynaCoolPPMS/DynaCool.py @@ -44,7 +44,6 @@ class DynaCool(VisaInstrument): # the ramp time resolution is in (s) and is used in the # _do_blocking_ramp method _ramp_time_resolution = 0.1 - _blocking_t_sleep = 0.5 temp_params = ("temperature_setpoint", "temperature_rate", "temperature_settling") field_params = ("field_target", "field_rate", "field_approach") @@ -96,6 +95,17 @@ def __init__( ) """Parameter blocking_t will block instrument interaction while temperature is ramping to setpoint.""" + self.blocking_t_state_check_interval: Parameter = self.add_parameter( + name="blocking_t_state_check_interval", + instrument=self, + initial_value=0.5, + unit="s", + vals=vals.Numbers(0, 60), + set_cmd=None, + get_cmd=None, + ) + """Parameter blocking_t_state_check_interval sets how often blocking_t checks for temperature stability.""" + self.temperature_rate: Parameter = self.add_parameter( "temperature_rate", label="Temperature settle rate", @@ -427,7 +437,7 @@ def _temp_setter( if block_while_ramping: while self.temperature_state() != "stable": - sleep(self._blocking_t_sleep) + sleep(self.blocking_t_state_check_interval()) self.setpoint.cache._set_from_raw_value(values[0]) self.blocking_t.cache._set_from_raw_value(values[0]) From e59def47df1290b24b87b92fb78f0f79407e8742 Mon Sep 17 00:00:00 2001 From: Thomas Lemon Date: Wed, 14 Jan 2026 12:39:38 -0800 Subject: [PATCH 12/12] Update PPMS example notebook with blocking_t state check interval --- .../driver_examples/Qcodes example with DynaCool PPMS.ipynb | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/docs/examples/driver_examples/Qcodes example with DynaCool PPMS.ipynb b/docs/examples/driver_examples/Qcodes example with DynaCool PPMS.ipynb index 7d9c2eb639fa..f3a9188101dd 100644 --- a/docs/examples/driver_examples/Qcodes example with DynaCool PPMS.ipynb +++ b/docs/examples/driver_examples/Qcodes example with DynaCool PPMS.ipynb @@ -200,7 +200,9 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "Alternatively, you can use the `blocking_t` parameter to prevent users from taking any action until the setpoint is reached. This may be useful for measurements where you are sweeping temperature and want to ensure the temperature is stable before taking a measurement." + "Alternatively, you can use the `blocking_t` parameter to prevent users from taking any action until the setpoint is reached. This may be useful for measurements where you are sweeping temperature and want to ensure the temperature is stable before taking a measurement.\n", + "\n", + "The interval at which `blocking_t` checks for temperature stability can be modified through the parameter `blocking_t_state_check_interval`." ] }, { @@ -209,6 +211,7 @@ "metadata": {}, "outputs": [], "source": [ + "dynacool.blocking_t_state_check_interval(0.5)\n", "dynacool.blocking_t(dynacool.temperature() + 1.3)" ] },