Plotting 1-D data
Contents
Plotting 1-D data#
scipp
offers a number of different ways to plot data from a DataArray
or a Dataset
. It uses the matplotlib
graphing library to do so.
[1]:
import numpy as np
import scipp as sc
Basic plot#
Plotting is done using the plot
function. Generally the information in a dataset is sufficient to produce a useful plot out of the box.
For example, a simple plot from a 1D dataset is produced as follows:
[2]:
d = sc.Dataset()
N = 50
d['Signal'] = sc.Variable(dims=['tof'], values=5.0 + 5.0*np.sin(np.arange(N, dtype=float)/5.0),
unit=sc.units.counts)
d.coords['tof'] = sc.Variable(dims=['tof'], values=np.arange(N).astype(float),
unit=sc.units.us)
sc.plot(d)
With error bars#
Error bars are shown automatically if variances are present in the data:
[3]:
d['Signal'].variances = np.square(np.random.random(N))
sc.plot(d)
Note that the length of the errors bars is the standard-deviation, i.e., the square root of the variances stored in the data.
Multiple variables on the same axes#
Plotting a Dataset with multiple entries#
If a dataset contains more than one 1D variable with the same coordinates, they are plotted on the same axes:
[4]:
d['Background'] = sc.Variable(dims=['tof'], values=3.0*np.random.random(N),
unit=sc.units.counts)
sc.plot(d)
It is possible to hide the error bars with
[5]:
sc.plot(d, errorbars=False)
We can always plot just a single item of the dataset.
[6]:
sc.plot(d['Background'])
Overplotting using a dict of DataArrays#
One can also supply the plot
function with a dict
of data arrays. Compatible data arrays will be overplotted on the same axes:
[7]:
sc.plot({"My sample": d['Signal'], "My background": d["Background"]})
Note that the newly supplied names (keys) have also been adopted as the graph names.
We can also overplot sections of interest with the help of slicing.
[8]:
sc.plot({"My sample": d['Signal']['tof', 10:40], "My background": d["Background"]})
This overplotting is useful for plotting slices of a 2D data array:
[9]:
M = 100
L = 5
xx = np.arange(M, dtype=float)
yy = np.arange(L, dtype=float)
x, y = np.meshgrid(xx, yy)
b = M/20.0
c = M/5.0
e = L/10.0
r = np.sqrt(((x-c)/b)**2 + (y/e)**2)
a = np.sin(r)
d2d = sc.DataArray(data=sc.Variable(dims=['y', 'x'], values=a, unit=sc.units.counts))
d2d.coords['x'] = sc.Variable(dims=['x'], values=xx, unit=sc.units.m)
d2d.coords['y'] = sc.Variable(dims=['y'], values=yy, unit=sc.units.m)
sc.plot({f'slice-{i}': d2d['y', i] for i in range(L)})
Or using the collapse
helper function, which returns a dict
of data arrays:
[10]:
sc.plot(sc.collapse(d2d, keep='x'))
Customizing linestyles, markers and colors#
Linestyles can be customized following the Matplotlib syntax. For instance, it is possible to connect the dots by setting linestyle='solid'
:
[11]:
sc.plot(d, linestyle='solid')
Marker colors and symbols can be changed via the color
and marker
keyword arguments:
[12]:
sc.plot(d, color=['red', '#30D5F9'], marker=['s', 'x'])
The supplied color
and marker
arguments can also be a list of integers, which correspond to one of the pre-defined colors or markers (which were taken from matplotlib). In addition, the grid can also be displayed:
[13]:
sc.plot(d, color=[6, 8], grid=True)
Logarithmic scales#
Use the keyword arguments scale
and norm
to apply logarithmic scales to the horizontal and vertical axes, respectively.
[14]:
sc.plot(d, norm='log', scale={'tof': 'log'})
Histograms#
Histograms are automatically generated if the coordinate is bin edges:
[15]:
histogram = sc.DataArray(data=sc.Variable(dims=['tof'],
values=20.0 + 20.0*np.cos(np.arange(N-1, dtype=float) / 3.0),
unit=sc.units.counts),
coords={'tof':d.coords['tof']})
sc.plot(histogram)
and with error bars
[16]:
histogram.variances = 5.0*np.random.random(N-1)
sc.plot(histogram)
The histogram color can be customized:
[17]:
sc.plot(histogram, color='#000000')
Multiple 1D variables with different dimensions#
scipp.plot
also supports multiple 1-D variables with different dimensions (note that the data entries are grouped onto the same graph if they have the same dimension and unit):
[18]:
M = 60
d['OtherSample'] = sc.Variable(dims=['x'], values=10.0*np.random.rand(M),
unit=sc.units.s)
d['OtherNoise'] = sc.Variable(dims=['x'], values=7.0*np.random.rand(M),
variances=3.0*np.random.rand(M),
unit=sc.units.s)
d['SomeKgs'] = sc.Variable(dims=['x'], values=20.0*np.random.rand(M),
unit=sc.units.kg)
d.coords['x'] = sc.Variable(dims=['x'],
values=np.arange(M).astype(float),
unit=sc.units.m)
sc.plot(d)
Custom labels along x axis#
Sometimes one wishes to have labels along the x
axis instead of the dimension-coordinate. This can be achieved via the labels
keyword argument by specifying which dimension should run along the x
axis:
[19]:
d1 = sc.Dataset()
N = 100
x = np.arange(N, dtype=float)
d1['Sample'] = sc.Variable(dims=['tof'],
values=np.sqrt(x),
unit=sc.units.counts)
d1.coords['tof'] = sc.Variable(dims=['tof'],
values=x,
unit=sc.units.us)
d1.coords['somelabels'] = sc.Variable(dims=['tof'],
values=np.linspace(101., 105., N),
unit=sc.units.s)
sc.plot(d1, labels={'tof': 'somelabels'})
Plotting masks#
If a dataset item contains masks, the symbols of masks data points will have a thick black contour in a 1D plot:
[20]:
d4 = sc.Dataset()
N = 50
x = np.arange(N).astype(float)
d4['Sample'] = sc.Variable(dims=['tof'], values=3*np.sin(x/5)+3,
unit=sc.units.counts)
d4['Background'] = sc.Variable(dims=['tof'], values=1.0*np.random.rand(N),
unit=sc.units.counts)
d4.coords['tof'] = sc.Variable(dims=['tof'], values=x,
unit=sc.units.us)
d4['Sample'].masks['mask1'] = sc.Variable(dims=['tof'],
values=np.where(np.abs(x-40) < 10, True, False))
d4['Background'].masks['mask1'] = ~d4['Sample'].masks['mask1']
d4['Background'].masks['mask1']['tof', 0:20].values = np.zeros(20, dtype=bool)
sc.plot(d4)
Checkboxes below the plot can be used to hide/show the individual masks. A global toggle button is also available to hide/show all masks in one go.
The color of the masks can be changed as follows:
[21]:
sc.plot(d4, masks={'color': 'red'})
Masks on histograms#
Masks on a histogram show up as a thick black line:
[22]:
N = 50
x = np.arange(N+1).astype(float)
d4 = sc.DataArray(data=sc.Variable(dims=['tof'], values=3*np.sin(x[:-1]/5)+3, unit=sc.units.counts))
d4.coords['tof'] = sc.Variable(dims=['tof'], values=x, unit=sc.units.us)
d4.masks['mask1'] = sc.Variable(dims=['tof'], values=np.where(np.abs(x[:-1]-40) < 10, True, False))
sc.plot(d4)
Plotting time series#
When plotting data with time-series (dtype=datetime64
) coordinates, a special axis tick label formatting, which dynamically adapts to the zoom level, is used.
[23]:
time = sc.array(dims=['time'], values=np.arange(np.datetime64('2017-01-01T12:00:00'),
np.datetime64('2017-01-01T13:00:00'), 20))
N = time.sizes['time']
data = sc.DataArray(data=sc.array(dims=['time'],
values=np.arange(N) + 50.*np.random.random(N),
unit="K"),
coords={'time':time})
data.plot(title="Temperature as a function of time")
Saving figures#
Static pdf
or png
copies of the figures can be saved to file (note that any buttons displayed under a figure are not saved to file). This is achieved as follows:
[24]:
sc.plot(d4, filename='my_1d_figure.pdf')