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.7653

OK, 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]:
[ ]: