Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feat/Video Mode #233

Open
wants to merge 116 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 66 commits
Commits
Show all changes
116 commits
Select commit Hold shift + click to select a range
3888e18
Created first part of video mode
nulinspiratie Sep 20, 2024
0479d50
created basic working video mode, still need opx integration
nulinspiratie Sep 21, 2024
e261bce
working on opx data acquirer
nulinspiratie Sep 21, 2024
9a1eeb6
move to control_panel
nulinspiratie Sep 24, 2024
0a97b43
rename imports
nulinspiratie Sep 24, 2024
5eae7b2
added update button
nulinspiratie Sep 25, 2024
25769c7
remove print statement
nulinspiratie Sep 25, 2024
7f81002
(untested) working opx scan
nulinspiratie Sep 26, 2024
9666d4f
add save functionality
nulinspiratie Sep 26, 2024
ba715cc
add data saving
nulinspiratie Sep 26, 2024
736801e
add delay after setting voltages
nulinspiratie Sep 26, 2024
e3bb6da
working with OPX, though data isn't refreshing
nulinspiratie Sep 27, 2024
cc8044a
semi-working state
nulinspiratie Sep 27, 2024
5221511
getting ~5 fps
nulinspiratie Sep 27, 2024
f78a29e
use dash_extensions and get rid of is_acquiring
nulinspiratie Sep 27, 2024
7a9bfa3
rename stream vars
nulinspiratie Sep 27, 2024
b87d69c
zip results for (minor) performance gain
nulinspiratie Sep 27, 2024
d173a9b
working state updates
nulinspiratie Sep 27, 2024
d1e1e7b
use context manager for scans
nulinspiratie Sep 29, 2024
4eed737
make delays optional
nulinspiratie Sep 30, 2024
408930a
add attenuation to x and y axes
nulinspiratie Sep 30, 2024
6fdbd71
use parameter label if provided
nulinspiratie Sep 30, 2024
0319e12
Introduce spiral scan
nulinspiratie Sep 30, 2024
f57b019
fixed some bugs through simulation
nulinspiratie Sep 30, 2024
826ceb4
moved integration_time and pre_measurement_delay to inner_callabel
nulinspiratie Sep 30, 2024
5ca0dd2
spiral scan working on lone OPX
nulinspiratie Oct 1, 2024
2afc1a0
make integration_time a float always
nulinspiratie Oct 1, 2024
b61b7d6
simplify inner loop action
nulinspiratie Oct 1, 2024
f4667ec
fix pulse
nulinspiratie Oct 1, 2024
0a742b5
fixes
nulinspiratie Oct 1, 2024
a727c1f
revert order idxs
nulinspiratie Oct 1, 2024
67d9c44
reverse attenuation sign
nulinspiratie Oct 1, 2024
7c52262
gui fix + get_latest()
nulinspiratie Oct 2, 2024
0961e19
Clarify measurement vars
nulinspiratie Oct 1, 2024
c20bee8
spiral scan fixes
nulinspiratie Oct 1, 2024
9436279
add initial measurement
nulinspiratie Oct 1, 2024
cc23127
small fixes
nulinspiratie Oct 1, 2024
1f89fb6
add switch raster scan
nulinspiratie Oct 1, 2024
1fbdd4d
for each
nulinspiratie Oct 1, 2024
03200e5
fix switch raster scan mode
nulinspiratie Oct 1, 2024
aac74d4
final_delay -> initial_delay
nulinspiratie Oct 1, 2024
f9fc9c7
remove n_stream
nulinspiratie Oct 1, 2024
afe02f1
remove n
nulinspiratie Oct 1, 2024
6bd239a
change how offsets are added
nulinspiratie Oct 1, 2024
37983de
change 2d -> 1d
nulinspiratie Oct 1, 2024
f427ff5
separate offset
nulinspiratie Oct 1, 2024
abe284b
mistake in switchraster
nulinspiratie Oct 1, 2024
af95bbe
update init
nulinspiratie Oct 2, 2024
120a259
simplify data saving
nulinspiratie Oct 7, 2024
8bf8bec
clean up dash components
nulinspiratie Oct 7, 2024
f915a21
added sweep axes
nulinspiratie Oct 7, 2024
e2f1437
add sweep_axis docstring
nulinspiratie Oct 7, 2024
9af3017
clean up imports
nulinspiratie Oct 7, 2024
af2df90
Add scan dosctrings
nulinspiratie Oct 7, 2024
b94d5e1
ignore some qua errors
nulinspiratie Oct 7, 2024
e225da8
cleaning up init
nulinspiratie Oct 7, 2024
c31dcdc
fix plotting
nulinspiratie Oct 7, 2024
c402658
add docstrings
nulinspiratie Oct 7, 2024
e44b4dc
Create QUA and QUAM version of data acquirer
nulinspiratie Oct 7, 2024
136efdc
removing units
nulinspiratie Oct 7, 2024
9491850
added readme
nulinspiratie Oct 7, 2024
a6e5194
mroe readme
nulinspiratie Oct 7, 2024
a528d55
small iw change
nulinspiratie Oct 7, 2024
02b458c
remove tests
nulinspiratie Oct 7, 2024
5c2fb71
Merge remote-tracking branch 'origin/main' into feat/live-plot
nulinspiratie Oct 7, 2024
5af205e
update lock file
nulinspiratie Oct 7, 2024
e14c35a
docstring updates
nulinspiratie Oct 17, 2024
57ad90e
docstring for inner loop action
nulinspiratie Oct 17, 2024
927489a
pass qmm + config/quam to data acquirer
nulinspiratie Oct 17, 2024
3494768
Only instantiate qm at the start
nulinspiratie Oct 17, 2024
b8eddd5
add default 1 us pre delay
nulinspiratie Oct 17, 2024
6bcc31f
Remove references to voltages
nulinspiratie Oct 17, 2024
1b04522
Create InnerLoopAction base class
nulinspiratie Oct 17, 2024
d8a62f9
trying to get ramping to work
nulinspiratie Oct 17, 2024
7957070
working on ramps
nulinspiratie Oct 18, 2024
320b713
showing ramps but not the right type
nulinspiratie Oct 18, 2024
53c4679
Updated to a working version with ramps, could be improved a bit
TheoLaudatQM Oct 18, 2024
a49b36d
add acquire_time to RandomDataAcquirer
nulinspiratie Oct 22, 2024
9664ce5
Use dash bootstrap components
nulinspiratie Oct 22, 2024
d715792
adding custom components
nulinspiratie Oct 22, 2024
f1011bd
cleanup of code
nulinspiratie Oct 22, 2024
1765016
trying to get modular callbacks
nulinspiratie Oct 22, 2024
28d80bd
Separate callback logic
nulinspiratie Oct 23, 2024
d56523a
Struggling with pattern matching
nulinspiratie Oct 23, 2024
75ad3df
Pretty much working!
nulinspiratie Oct 23, 2024
cb6f908
update packages and minor save fix
nulinspiratie Oct 30, 2024
002d916
clean up dash
nulinspiratie Oct 30, 2024
a763eb5
added update_parameters
nulinspiratie Oct 30, 2024
6da9d9f
minor touch ups
nulinspiratie Oct 30, 2024
0283168
add dash_bootstrap_components
nulinspiratie Nov 1, 2024
f15b37a
split up data_acquirers.py
nulinspiratie Nov 1, 2024
6ef93b2
Reworking the structure
nulinspiratie Nov 1, 2024
b457e4e
add unit
nulinspiratie Nov 7, 2024
2ab07e4
Merge branch 'feat/live-plot-custom-components' into feat/live-plot
nulinspiratie Nov 7, 2024
b8e25c8
reduce h5netcdf requirement
nulinspiratie Nov 7, 2024
88e6fd1
fix netcdf4
nulinspiratie Nov 7, 2024
b22342c
Merge branch 'feat/live-plot-ramp' into feat/live-plot
nulinspiratie Nov 8, 2024
46dc1b6
add run program
nulinspiratie Nov 8, 2024
cc1978d
fix get_dash_components
nulinspiratie Nov 8, 2024
8e0581f
swap xy
nulinspiratie Nov 8, 2024
8ce9541
fix result-type
nulinspiratie Nov 8, 2024
dea03bc
abs -> amplitude
nulinspiratie Nov 8, 2024
b782f90
add parameters_modified
nulinspiratie Nov 8, 2024
540d852
update span
nulinspiratie Nov 8, 2024
6bebe88
fix bit operation
nulinspiratie Nov 8, 2024
100d4d7
transpose
nulinspiratie Nov 8, 2024
9380b08
add readout_frequency and readout_duration
nulinspiratie Dec 3, 2024
8e5fd37
update config when readout frequency is changed
nulinspiratie Dec 3, 2024
dc0feb1
Remove "step" pulse play
nulinspiratie Dec 3, 2024
70c6cb3
added additional align
nulinspiratie Dec 4, 2024
303e46b
visual fixes
nulinspiratie Dec 4, 2024
492a85d
added readout amplitude
nulinspiratie Dec 4, 2024
00cf815
modify inputs
nulinspiratie Dec 6, 2024
efb9b60
add SwitchRasterScan.start_from_middle
nulinspiratie Dec 16, 2024
1cc556f
Square aspect ratio
nulinspiratie Dec 18, 2024
63af1bd
add use_dBm
nulinspiratie Dec 18, 2024
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
113 changes: 109 additions & 4 deletions poetry.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

15 changes: 14 additions & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ dash-html-components = { version = "^2.0.0", optional = true }
dash-core-components = { version = "^2.0.0", optional = true }
dash-bootstrap-components = { version = "^1.0.0", optional = true }
dash-cytoscape = { version = "^0.3.0", optional = true }
dash-extensions = { version = "^1.0.0", optional = true }
dash-table = { version = "^5.0.0", optional = true }
dash-dangerously-set-inner-html = { version = "^0.0.2", optional = true }
docutils = { version = ">=0.14.0", optional = true }
Expand All @@ -47,8 +48,20 @@ setuptools = "^69.0.2"

[tool.poetry.extras]
interplot = ["dill", "pypiwin32", "ipython"]
configbuilder = ["pandas", "dash", "dash-html-components", "dash-core-components", "dash-bootstrap-components", "dash-cytoscape", "dash-table", "dash-dangerously-set-inner-html", "docutils", "waitress"]
configbuilder = [
"pandas",
"dash",
"dash-html-components",
"dash-core-components",
"dash-bootstrap-components",
"dash-cytoscape",
"dash-table",
"dash-dangerously-set-inner-html",
"docutils",
"waitress",
]
datahandler = ["xarray", "netcdf4"]
videomode = ["dash", "dash-extensions", "xarray"]

[tool.black]
line-length = 120
Expand Down
146 changes: 146 additions & 0 deletions qualang_tools/control_panel/video_mode/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,146 @@
# Video Mode

This module performs a continuous rapid 2D scan of two sweep axes, and measures a signal at each point. The results are shown through an interactive web frontend with a live plot and controls for the sweep parameters.

The video mode has been designed as a modular tool that is composed of four parts:

1. The `OPXDataAcquirer` class, which is responsible for the data acquisition.
2. The `ScanMode` class, which is responsible for how the 2D grid is traversed.
3. The `InnerLoopAction` class, which is responsible for what QUA code is performed during each step of the scan.
4. The `VideoMode` class, which handles interaction with the frontend.

The `ScanMode` and `InnerLoopAction` classes are highly flexible and can be selected/modified to suit the specific needs of the user. For example, three different scan modes (`RasterScan`, `SpiralScan`, and `SwitchRasterScan`) are provided, which can be used to acquire data in different ways. Similarly, the `InnerLoopAction` class can be modified to perform additional actions, such as adding specific pulses prior to each measurement.

## Installation

First, it is necessary to install the `qualang_tools` package with the `videomode` extra packages:

```bash
pip install qualang-tools[videomode]
```

## Basic Usage
To use the video mode, it is necessary to initialize the relevant classes and pass them to the `VideoMode` class.
We will go through a simple example to demonstrate the video mode. Most of the classes and functions described here have additional options which can be found in the docstrings and in the source code.

If you don't have access to an OPX but still want to try the video mode, see the `Simulated Video Mode`section in `Advanced Usage`

First, we assume that the machine is already connected.
```python
qmm, qm = connect_qua_machine()
nulinspiratie marked this conversation as resolved.
Show resolved Hide resolved
TheoLaudatQM marked this conversation as resolved.
Show resolved Hide resolved
```

Next we define the scan mode, which in this case is a raster scan.
```python
from qualang_tools.control_panel.video_mode import scan_modes
scan_mode = scan_modes.RasterScan()
```
TheoLaudatQM marked this conversation as resolved.
Show resolved Hide resolved

Next we define the inner loop action, which in this case is a QUA program that performs a measure of the readout pulse.
```python
# Define the inner loop action
# In this case
from qualang_tools.control_panel.video_mode.inner_loop_actions import InnerLoopAction
inner_loop_action = InnerLoopAction(
nulinspiratie marked this conversation as resolved.
Show resolved Hide resolved
x_element="output_ch1", # Must be a valid QUA element
y_element="output_ch2", # Must be a valid QUA element
integration_time=10e-6, # Integration time in seconds
nulinspiratie marked this conversation as resolved.
Show resolved Hide resolved
readout_element="measure_ch", # Must be a valid QUA element
readout_pulse="readout", # Name of the readout pulse registered in the readout_element
)
```
Note that this `InnerLoopAction` assumes that the `readout_pulse` has two integration weights called `cos` and `sin`

Next we define the sweep axes, which define the values that the 2D scan will take as coordinates.

```python
from qualang_tools.control_panel.video_mode.sweep_axis import SweepAxis
x_axis = SweepAxis(
name="voltage_gate1", # Sweep axis name, used among others for plotting
span=0.03, # Span of the sweep in volts
points=51, # Number of points to sweep
)
y_axis = SweepAxis(name="voltage_gate2", span=0.03, points=51)
```
The `SweepAxis` contains additional attributes, such as attenuation and a voltage offset, the latter of which is described in `Advanced Usage`.

Next we define the data acquirer, which is the object that will handle the data acquisition.
```python
from qualang_tools.control_panel.video_mode.data_acquirer import OPXDataAcquirer
data_acquirer = OPXDataAcquirer(
qm=qm,
qua_inner_loop_action=inner_loop_action,
scan_mode=scan_mode,
x_axis=x_axis,
y_axis=y_axis,
)
```

You can now test the data acquirer before using it in video mode.
```python
data_acquirer.run_program()
results = data_acquirer.acquire_data()
```

Finally, we can start the video mode.
```python
from qualang_tools.control_panel.video_mode.video_mode import VideoMode
video_mode = VideoMode(data_acquirer=data_acquirer)
video_mode.run()
```

Note that if you want to run this code in an interactive environment such as a Jupyter notebook, you should use `video_mode.run(use_reloader=False)`.

You can now access video mode from your browser at `http://localhost:8050/` (the port may be different, see the output logs for details).


## Advanced Usage
### Voltage offsets

The `SweepAxis` class has an `offset_parameter` attribute, which is an optional parameter that defines the sweep offset. This can be a QCoDeS DC voltage source parameter or a `VoltageParameter` object.

As an example, let us assume that we have a QCoDeS parameter `x_gate` for the DC voltage of a gate:

```python
x_offset() # Returns the DC voltage, e.g. 0.62
```

In this case, we can pass this parameter to the `SweepAxis` class to define the sweep offset.
```python
x_axis = SweepAxis(name="gate", span=0.03, points=51, offset_parameter=x_offset)
```
The video mode plot should now correctly show the sweep axes with the correct offset.

Note that if the offset voltage is changed, it will need to be changed in the same kernel where the video mode is running. One solution for this is using the `VoltageControl` module in py-qua-tools.
Copy link
Contributor

Choose a reason for hiding this comment

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

This is from another PR right?
Is it also ready for review?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Not really, it works but lacks documentation and tutorials

Copy link
Contributor

Choose a reason for hiding this comment

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

I still don't understand how this works.
When VideoMode is running the kernel is being used so that you can't run anything there...
One solution could be to use what we did here: https://github.com/qua-platform/py-qua-tools/tree/main/qualang_tools/video_mode

Copy link
Contributor Author

Choose a reason for hiding this comment

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

This doesn't work, it needs external instrument calls. The way it works is as follows:

Two threads are created:
Video Mode dash app that runs an OPX program and repeatedly shows results
Voltage Control GUI that allows setting QDAC voltages



### Simulated Video Mode
Below is an example of how to run the video mode without an actual OPX.
In this case, we will use the `RandomDataAcquirer` class, which simply displays uniformly-sampled random data.
```python
from qualang_tools.control_panel.video_mode import *

x_axis = SweepAxis(name="X", span=0.1, points=101)
y_axis = SweepAxis(name="Y", span=0.1, points=101)

data_acquirer = RandomDataAcquirer(
x_axis=x_axis,
y_axis=y_axis,
num_averages=5,
)

live_plotter = VideoMode(data_acquirer=data_acquirer)
live_plotter.run()
```

# Debugging

To see the logs which include useful debug information, you can update the logging configuration.

```python
import logging

logging.basicConfig(level=logging.DEBUG)
logging.getLogger("hpack.hpack").setLevel(logging.WARNING)
logging.getLogger("matplotlib").setLevel(logging.WARNING)
```
21 changes: 21 additions & 0 deletions qualang_tools/control_panel/video_mode/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
from qualang_tools.control_panel.video_mode.dash_tools import *
from qualang_tools.control_panel.video_mode.sweep_axis import SweepAxis
from qualang_tools.control_panel.video_mode.voltage_parameters import *
from qualang_tools.control_panel.video_mode.inner_loop_actions import *
from qualang_tools.control_panel.video_mode.scan_modes import *
from qualang_tools.control_panel.video_mode.data_acquirers import *
from qualang_tools.control_panel.video_mode.video_mode import *


if __name__ == "__main__":
x_axis = SweepAxis(name="X", span=0.1, points=101)
y_axis = SweepAxis(name="Y", span=0.1, points=101)

data_acquirer = RandomDataAcquirer(
x_axis=x_axis,
y_axis=y_axis,
num_averages=5,
)

live_plotter = VideoMode(data_acquirer=data_acquirer)
live_plotter.run()
Loading
Loading