Graph and node tips#

This notebook is about helpful tips or tricks you can use when working with nodes of a custom interface graph you have built.

It assumes that you have already explored the notebook on creating custom interfaces, which is a pre-requisite to understanding the content here.

[1]:
%matplotlib widget
import plopp as pp
import scipp as sc
import numpy as np

Node operators#

6461d24b4ed6434b8fe367f1b54b837f   New in version 23.04.0.

We have seen in the previous notebook how functions/callables wrapped in a Node are used to represent operations between different data sources.

It can sometimes be useful to know that nodes also have operators, and simple operations can be implemented in a short-hand way, instead of defining functions such as add or multiply.

Consider for example

[2]:
a = pp.Node(np.array([1, 2, 3, 4, 5]))
b = pp.Node(np.array([6, 7, 8, 9, 10]))

The ‘classical’ way of adding the data from a and b would be to wrap an add function in a Node as follows:

[3]:
def add(x, y):
    return x + y


c = pp.Node(add, a, b)
c()
[3]:
array([ 7,  9, 11, 13, 15])

However, this short-hand is also possible:

[4]:
c = a + b
c()
[4]:
array([ 7,  9, 11, 13, 15])

Operators also work with normal Python objects, which simply get wrapped in a Node:

[5]:
c = a * 33.0
c()
[5]:
array([ 33.,  66.,  99., 132., 165.])

A short example#

[6]:
noise = 0.5 * (np.random.random(100) - 0.5)
signal = np.sin(0.1 * np.arange(100.0)) + noise

# Noisy data
a = pp.Node(
    sc.DataArray(
        data=sc.array(dims=['time'], values=signal),
        coords={'time': sc.arange('time', 100.0, unit='s')},
    )
)
fig = pp.linefigure(a)
fig
[6]:
[7]:
b = pp.Node(
    sc.DataArray(
        data=sc.array(dims=['time'], values=noise),
        coords={'time': sc.arange('time', 100.0, unit='s')},
    )
)

# Remove noise from signal
diff = a - b
pp.linefigure(diff)
[7]:

Using plotting functions in a graph#

199abdaa27dc497f9129490ad4880cc4   New in version 23.10.0.

All the examples for working with nodes and graphs presented so far have been using the lower-level linefigure, imagefigure and scatter3dfigure as views for the data.

These functions accept graph nodes as input, and provide visualizations for 1D, 2D or scatter 3D data.

However, say that at the end point of a graph, in the node that is providing the final result, the data still has three dimensions. One common way of visualizing such data is as a 2D image with a slider to navigate the third dimension.

Instead of having to manually set up a slider and a node for the slicing, it is possible to use Plopp’s higher-level plotting functions directly as part of a graph. In our present example, this would be the slicer plot.

[8]:
# Make a 3D array with random values
da = pp.data.random((100, 150, 200))
da
[8]:
Show/Hide data repr Show/Hide attributes
scipp.DataArray (22.89 MB)
    • z: 100
    • y: 150
    • x: 200
    • x
      (x)
      float64
      m
      0.0, 1.0, ..., 198.0, 199.0
      Values:
      array([ 0., 1., 2., 3., 4., 5., 6., 7., 8., 9., 10., 11., 12., 13., 14., 15., 16., 17., 18., 19., 20., 21., 22., 23., 24., 25., 26., 27., 28., 29., 30., 31., 32., 33., 34., 35., 36., 37., 38., 39., 40., 41., 42., 43., 44., 45., 46., 47., 48., 49., 50., 51., 52., 53., 54., 55., 56., 57., 58., 59., 60., 61., 62., 63., 64., 65., 66., 67., 68., 69., 70., 71., 72., 73., 74., 75., 76., 77., 78., 79., 80., 81., 82., 83., 84., 85., 86., 87., 88., 89., 90., 91., 92., 93., 94., 95., 96., 97., 98., 99., 100., 101., 102., 103., 104., 105., 106., 107., 108., 109., 110., 111., 112., 113., 114., 115., 116., 117., 118., 119., 120., 121., 122., 123., 124., 125., 126., 127., 128., 129., 130., 131., 132., 133., 134., 135., 136., 137., 138., 139., 140., 141., 142., 143., 144., 145., 146., 147., 148., 149., 150., 151., 152., 153., 154., 155., 156., 157., 158., 159., 160., 161., 162., 163., 164., 165., 166., 167., 168., 169., 170., 171., 172., 173., 174., 175., 176., 177., 178., 179., 180., 181., 182., 183., 184., 185., 186., 187., 188., 189., 190., 191., 192., 193., 194., 195., 196., 197., 198., 199.])
    • y
      (y)
      float64
      m
      0.0, 1.0, ..., 148.0, 149.0
      Values:
      array([ 0., 1., 2., 3., 4., 5., 6., 7., 8., 9., 10., 11., 12., 13., 14., 15., 16., 17., 18., 19., 20., 21., 22., 23., 24., 25., 26., 27., 28., 29., 30., 31., 32., 33., 34., 35., 36., 37., 38., 39., 40., 41., 42., 43., 44., 45., 46., 47., 48., 49., 50., 51., 52., 53., 54., 55., 56., 57., 58., 59., 60., 61., 62., 63., 64., 65., 66., 67., 68., 69., 70., 71., 72., 73., 74., 75., 76., 77., 78., 79., 80., 81., 82., 83., 84., 85., 86., 87., 88., 89., 90., 91., 92., 93., 94., 95., 96., 97., 98., 99., 100., 101., 102., 103., 104., 105., 106., 107., 108., 109., 110., 111., 112., 113., 114., 115., 116., 117., 118., 119., 120., 121., 122., 123., 124., 125., 126., 127., 128., 129., 130., 131., 132., 133., 134., 135., 136., 137., 138., 139., 140., 141., 142., 143., 144., 145., 146., 147., 148., 149.])
    • z
      (z)
      float64
      m
      0.0, 1.0, ..., 98.0, 99.0
      Values:
      array([ 0., 1., 2., 3., 4., 5., 6., 7., 8., 9., 10., 11., 12., 13., 14., 15., 16., 17., 18., 19., 20., 21., 22., 23., 24., 25., 26., 27., 28., 29., 30., 31., 32., 33., 34., 35., 36., 37., 38., 39., 40., 41., 42., 43., 44., 45., 46., 47., 48., 49., 50., 51., 52., 53., 54., 55., 56., 57., 58., 59., 60., 61., 62., 63., 64., 65., 66., 67., 68., 69., 70., 71., 72., 73., 74., 75., 76., 77., 78., 79., 80., 81., 82., 83., 84., 85., 86., 87., 88., 89., 90., 91., 92., 93., 94., 95., 96., 97., 98., 99.])
    • (z, y, x)
      float64
      𝟙
      0.656, 0.796, ..., 0.109, 0.382
      Values:
      array([[[0.6557288 , 0.79559656, 0.77376124, ..., 0.70536452, 0.3098133 , 0.10647613], [0.15102129, 0.04052719, 0.44851693, ..., 0.94095694, 0.07465051, 0.64191172], [0.86450441, 0.23402508, 0.21599189, ..., 0.67143056, 0.60702505, 0.38044449], ..., [0.18832268, 0.41546863, 0.19115693, ..., 0.90568138, 0.7814324 , 0.05693186], [0.61408074, 0.3181783 , 0.05287868, ..., 0.6371697 , 0.92348657, 0.70697235], [0.44049423, 0.4184316 , 0.51887289, ..., 0.48688732, 0.69018869, 0.03477747]], [[0.6740006 , 0.58163184, 0.70583324, ..., 0.55982354, 0.24916193, 0.75205471], [0.74296315, 0.42763593, 0.70351563, ..., 0.34802906, 0.05248652, 0.50192622], [0.63137161, 0.68911234, 0.62286534, ..., 0.43148193, 0.84325225, 0.43119742], ..., [0.2130536 , 0.55588928, 0.15262487, ..., 0.67690408, 0.03664205, 0.47688721], [0.58420395, 0.11663982, 0.01407642, ..., 0.64223171, 0.3099841 , 0.01684951], [0.005396 , 0.5530187 , 0.75826506, ..., 0.48213395, 0.77992835, 0.26002905]], [[0.38520048, 0.13471115, 0.3569556 , ..., 0.29351453, 0.33157369, 0.0009993 ], [0.95112757, 0.70371743, 0.43204324, ..., 0.87760248, 0.18223969, 0.46354448], [0.02903544, 0.87756153, 0.42701607, ..., 0.33214742, 0.29967825, 0.6164208 ], ..., [0.38674798, 0.21862189, 0.35889805, ..., 0.97526298, 0.92662659, 0.6870757 ], [0.03440373, 0.43410315, 0.85647302, ..., 0.47313304, 0.23167298, 0.67287596], [0.14124485, 0.41139577, 0.73824184, ..., 0.40748669, 0.78129046, 0.03067225]], ..., [[0.38986713, 0.09381546, 0.53128517, ..., 0.13289986, 0.88271516, 0.09802476], [0.69946986, 0.87306504, 0.04128101, ..., 0.72061054, 0.99131256, 0.5517304 ], [0.85218966, 0.07943033, 0.55610961, ..., 0.10213399, 0.43658355, 0.24275198], ..., [0.83376483, 0.92717107, 0.09753822, ..., 0.50298853, 0.66681078, 0.92597859], [0.86410201, 0.85367574, 0.91505416, ..., 0.42473845, 0.27898036, 0.14517 ], [0.9505426 , 0.36857613, 0.92176265, ..., 0.26942618, 0.62697458, 0.46743122]], [[0.52981581, 0.32951347, 0.54245346, ..., 0.95524336, 0.0172843 , 0.7870004 ], [0.05668498, 0.4349562 , 0.82738086, ..., 0.74168304, 0.41443086, 0.13233868], [0.15075624, 0.79054006, 0.2812247 , ..., 0.17450658, 0.75162017, 0.55018879], ..., [0.04355953, 0.37594301, 0.55952702, ..., 0.58884483, 0.95841002, 0.70385894], [0.74544973, 0.17578729, 0.99661254, ..., 0.96544027, 0.36687256, 0.80138764], [0.90746967, 0.52101219, 0.78597529, ..., 0.9486248 , 0.74230953, 0.06341802]], [[0.82011116, 0.1724361 , 0.6841525 , ..., 0.20381511, 0.32044813, 0.73580653], [0.45829887, 0.85133445, 0.11982079, ..., 0.45751269, 0.74176854, 0.89163203], [0.90613669, 0.66733524, 0.65028214, ..., 0.67279262, 0.62460789, 0.57090738], ..., [0.54704062, 0.8916678 , 0.5070522 , ..., 0.31285532, 0.92274415, 0.19957127], [0.03637577, 0.60905479, 0.07444285, ..., 0.84792081, 0.97597043, 0.20337672], [0.66472514, 0.09285469, 0.64294023, ..., 0.69459233, 0.10933072, 0.38164381]]])
[9]:
import ipywidgets as ipw
from scipp.scipy.ndimage import gaussian_filter

# Raw data root node
data_node = pp.Node(da)

# Slider to control width of smoothing kernel
slider = ipw.IntSlider(min=1, max=20, description="Smoothing")
slider_node = pp.widget_node(slider)

# Node that performs the gaussian smoothing
smooth_node = pp.Node(gaussian_filter, data_node, sigma=slider_node)

pp.show_graph(smooth_node)
[9]:
../../_images/user-guide_customization_graph-node-tips_15_0.svg
[10]:
# Attach the `slicer` plot to the bottom node
fig = pp.slicer(smooth_node)
ipw.VBox([slider, fig])
[10]:

We now have a slider at the top that controls the width of the smoothing kernel, and a second slider at the bottom that can navigate the z dimension.

The final node graph is

[11]:
pp.show_graph(data_node)
[11]:
../../_images/user-guide_customization_graph-node-tips_18_0.svg