Intro to our Holoviz apps#
[5]:
import numpy as np
import xarray as xr
import panel as pn
pn.extension()
from labcore.testing.dispersive_qubit_readout_data import chevron_dataset
from labcore.data.datadict import datadict_to_meshgrid, dd2xr
from labcore.analysis import split_complex
from labcore.analysis.hvplotting import Node
Nodes#
let’s have a look at what Nodes are. To work with them, we create some dummy data.
[7]:
# generate some generic Rabi-like data
raw_data = chevron_dataset(
Omega_0=1e6,
Delta_vals=np.linspace(-1e6, 1e6, 20),
t_vals=np.linspace(0, 3e-6, 20),
n=100, # number of shots
)
# convert directly to xarray.
# also: with the holoviz (or all pydata) tools, complex data isn't always the most convenient, so we split it immediately.
xrdata = split_complex(dd2xr(datadict_to_meshgrid(raw_data.expand())))
[ ]:
A trivial example#
By default, nodes don’t do anything but pass data around between them if they’re connected correctly. In this example we just create a node and display it. Nothing is seen…
[8]:
n = Node()
n
[8]:
Note: there is no input data, so we have also no output data:
[10]:
n.data_out
Now, let’s set some data:
[13]:
n.data_in = xrdata
n.data_out
[13]:
<xarray.Dataset>
Dimensions: (repetition: 100, detuning: 20, time: 20)
Coordinates:
* repetition (repetition) int64 1 2 3 4 5 6 7 8 ... 93 94 95 96 97 98 99 100
* detuning (detuning) float64 -1e+06 -8.947e+05 ... 8.947e+05 1e+06
* time (time) float64 0.0 1.579e-07 3.158e-07 ... 2.842e-06 3e-06
Data variables:
signal_Re (repetition, detuning, time) float64 2.394 2.416 ... 1.473 2.239
signal_Im (repetition, detuning, time) float64 0.6124 0.5184 ... 0.7653OK, not very exciting yet. But internally stuff has happened – the data went through the processing routine, and the output of that routine is now available as output data.
Note: we always look at the data and plot it; that holds for every node. When we embed the .plot object into a viewable (like a panel layout) we get our custom plot app we can use to slice our data.
[17]:
pn.Column(
n.plot
)
[17]:
[ ]:
A basic loader node#
Loaders are specific nodes that load data. That means, they do not have any input data, only output data. Every loader node must have a method load_data that returns a DataDict.
The base class for loaders already comes with a set of preprocessing options: averaging over dimension that can be specified (you have to type in the name, and it’ll average over it if it’s there), auto-gridding, and auto-refresh.
In the example below, you can either load a freshly generated set of data by pressing the Load Data button, or repeatedly by setting Auto-refresh to some value (disabling will stop it).
TODO Stuff that’s been set on the dimension sliders is currently being reset everytime the data is reloaded.
[18]:
from labcore.data.datadict import DataDict
from labcore.analysis.hvplotting import LoaderNodeBase
class RabiSimulation(LoaderNodeBase):
def load_data(self) -> DataDict:
Omega_0 = 1
Delta_vals = np.linspace(-2, 2, 20)
t_vals = np.linspace(0, 3, 20)
nreps = 10
dd = chevron_dataset(Omega_0, Delta_vals, t_vals, nreps).expand()
return dd
s = RabiSimulation(name='sim')
app = pn.Column(
s,
s.plot,
)
app
[18]:
[ ]: