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#
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#
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]:
- z: 100
- y: 150
- x: 200
- x(x)float64m0.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)float64m0.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)float64m0.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.880, 0.541, ..., 0.331, 0.133
Values:
array([[[0.88017166, 0.5411515 , 0.9122424 , ..., 0.7254376 , 0.63786713, 0.40853597], [0.57084622, 0.38956809, 0.29688774, ..., 0.8697255 , 0.75928233, 0.84467625], [0.38705429, 0.7918732 , 0.74384337, ..., 0.74791209, 0.63712072, 0.72967754], ..., [0.03223696, 0.84158997, 0.31889447, ..., 0.38083876, 0.9233783 , 0.02250245], [0.96783475, 0.92286558, 0.52042904, ..., 0.01334944, 0.1565307 , 0.62483089], [0.52064304, 0.16178048, 0.20778734, ..., 0.57630578, 0.61119857, 0.13770448]], [[0.25875281, 0.94112926, 0.22007974, ..., 0.41551116, 0.22335191, 0.12832867], [0.23287427, 0.1211125 , 0.1576034 , ..., 0.37415543, 0.35896494, 0.49726232], [0.04561888, 0.84577166, 0.59623057, ..., 0.77915682, 0.42699347, 0.39521689], ..., [0.90745118, 0.45496064, 0.89344665, ..., 0.43657107, 0.63297929, 0.8470518 ], [0.69744585, 0.35720964, 0.63708381, ..., 0.84693814, 0.22011552, 0.79423092], [0.05857655, 0.58937712, 0.11905083, ..., 0.94763209, 0.73708519, 0.60001733]], [[0.90383385, 0.35282145, 0.77164222, ..., 0.53716249, 0.44149782, 0.57660495], [0.92412252, 0.97211842, 0.78832344, ..., 0.44537886, 0.7981196 , 0.98154062], [0.08250197, 0.49036605, 0.00435855, ..., 0.95151896, 0.92281006, 0.87716722], ..., [0.40305629, 0.07906755, 0.79086366, ..., 0.58750594, 0.63631473, 0.18781146], [0.08344098, 0.42531584, 0.32272153, ..., 0.00729839, 0.10254079, 0.3231904 ], [0.08837184, 0.3651995 , 0.16285274, ..., 0.54922303, 0.3123669 , 0.07898136]], ..., [[0.60819893, 0.4120468 , 0.29288208, ..., 0.94411237, 0.82529726, 0.07308425], [0.86409336, 0.91963546, 0.21430508, ..., 0.13610312, 0.99335614, 0.56629629], [0.3402118 , 0.4924224 , 0.58651416, ..., 0.98602541, 0.04737835, 0.15737418], ..., [0.49323095, 0.76259432, 0.92842183, ..., 0.71094224, 0.15104887, 0.3971194 ], [0.96615432, 0.52472687, 0.37198541, ..., 0.40236323, 0.21060835, 0.50485419], [0.26938798, 0.78415618, 0.5803306 , ..., 0.07631698, 0.49317371, 0.31829576]], [[0.47266367, 0.87555232, 0.74607986, ..., 0.2542019 , 0.7150336 , 0.92763365], [0.22512469, 0.8825362 , 0.73987622, ..., 0.51157248, 0.04042283, 0.87891136], [0.41816176, 0.47812161, 0.18744185, ..., 0.68220807, 0.98085315, 0.41036652], ..., [0.69168535, 0.1841037 , 0.73962547, ..., 0.32235379, 0.05978033, 0.09650043], [0.45635955, 0.5630374 , 0.18851984, ..., 0.72565165, 0.0476521 , 0.4978771 ], [0.26242627, 0.50616126, 0.17695651, ..., 0.15716757, 0.55107924, 0.0558001 ]], [[0.21324646, 0.42173028, 0.06127341, ..., 0.73902329, 0.48443101, 0.08873568], [0.15400338, 0.5815476 , 0.18677223, ..., 0.51172446, 0.71552721, 0.66182013], [0.06725456, 0.03106132, 0.14878238, ..., 0.01441298, 0.56989929, 0.0391503 ], ..., [0.82535453, 0.09532924, 0.61964811, ..., 0.56582253, 0.28107886, 0.47304173], [0.61591402, 0.16803311, 0.72841764, ..., 0.27977669, 0.17212714, 0.24326603], [0.6966804 , 0.12101522, 0.79100957, ..., 0.33040839, 0.33086836, 0.13271361]]])
[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]:
[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]: