{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# Plotting 2-D data\n", "\n", "Scipp uses the `imshow` function from the `matplotlib` library to visualize 2-D data." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "import numpy as np\n", "import scipp as sc" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Basic image plot\n", "\n", "2-D variables are plotted as images, with a colormap:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "N = 100\n", "M = 50\n", "xx = np.arange(N, dtype=np.float64)\n", "yy = np.arange(M, dtype=np.float64)\n", "x, y = np.meshgrid(xx, yy)\n", "b = N/20.0\n", "c = M/2.0\n", "r = np.sqrt(((x-c)/b)**2 + (y/b)**2)\n", "a = np.sin(r)\n", "d1 = sc.Dataset()\n", "d1['Signal'] = sc.Variable(dims=['y', 'x'], values=a, unit=sc.units.K)\n", "d1.coords['x'] = sc.Variable(dims=['x'], values=xx, unit=sc.units.m)\n", "d1.coords['y'] = sc.Variable(dims=['y'], values=yy, unit=sc.units.m)\n", "sc.plot(d1)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The dimension displayed along each axis of the image can changed using the tranpose buttons in the toolbar to the left of the figure, or by transposing the input data:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "d1['Signal'].transpose().plot()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Changing the colorscale\n", "\n", "Changing the colorscale is handled in a similar way to [Matplotlib syntax](https://matplotlib.org/tutorials/colors/colormaps.html).\n", "The colormap is defined by the `cmap` argument:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "sc.plot(d1, cmap='magma')" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "A logarithmic colorscale is obtained by setting `norm` to `'log'`:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "sc.plot(d1, norm='log')" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Upper and lower limits on the colorscale can be placed using `vmin` and `vmax`:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "sc.plot(d1, vmin=0*sc.Unit('K'), vmax=0.5*sc.Unit('K'))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Using labels along some axis\n", "\n", "Just like in the 1d plots, we can use labels along a chosen dimension:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "d1.coords['somelabels'] = sc.Variable(dims=['x'],\n", " values=np.linspace(101., 155., N),\n", " unit=sc.units.s)\n", "sc.plot(d1, labels={'x': 'somelabels'})" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Collapsing dimensions\n", "\n", "Sometimes it is useful to collapse one or more of the data's dimensions, if for instance most detector pixels contain noise, but one specific channel contains a strong signal. This is done by specifying the dimension to be displayed along the x axis as a keyword argument to `sc.collapse`. All other dimensions will be collapsed." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "N = 40\n", "M = 5\n", "x = np.arange(N).astype(np.float64)\n", "b = 0.5 * N\n", "a = 4.0*np.random.rand(M, N)\n", "a[2, :] = np.abs(10.0 * np.cos((x-b)*2.0/b))\n", "d2 = sc.Dataset()\n", "d2['sample'] = sc.Variable(dims=['x', 'tof'], values=a,\n", " variances=0.1*np.random.rand(M, N))\n", "d2.coords['tof'] = sc.Variable(dims=['tof'], values=x, unit=sc.units.us)\n", "d2.coords['x'] = sc.Variable(dims=['x'], values=np.arange(M).astype(np.float64),\n", " unit=sc.units.m)\n", "sc.plot(d2)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "sc.plot(sc.collapse(d2['sample'], keep='tof'))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Image aspect ratio\n", "By default, the aspect ratio of 2D images is not preserved; images are stretched to the size of the figure.\n", "You can choose to preserve the aspect ratio via the `aspect` keyword argument.\n", "The default value for `aspect` is `auto` which allows for scaling." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "sc.plot(d2, aspect='equal')" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "You can also make this a permanent setting by editing the [config file](../../reference/runtime-configuration.ipynb) (possible options are `'equal'` and `'auto'`):" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "sc.config.update({'plot.aspect': 'equal'})\n", "sc.config.update({'plot.aspect': 'auto'})" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Plotting masks\n", "\n", "If a dataset contains masks, they will appear as greyed out on the image:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "N = 100\n", "M = 50\n", "xx = np.arange(N, dtype=np.float64)\n", "yy = np.arange(M, dtype=np.float64)\n", "x, y = np.meshgrid(xx, yy)\n", "b = N/20.0\n", "c = M/2.0\n", "r = np.sqrt(((x-c)/b)**2 + (y/b)**2)\n", "a = np.sin(r)\n", "d3 = sc.DataArray(data=sc.Variable(dims=['y', 'x'], values=a, unit=sc.units.K))\n", "d3.coords['x'] = sc.Variable(dims=['x'], values=xx, unit=sc.units.m)\n", "d3.coords['y'] = sc.Variable(dims=['y'], values=yy, unit=sc.units.m)\n", "d3.masks['mask1'] = sc.Variable(dims=['y', 'x'], values=np.where(a < 0, True, False))\n", "sc.plot(d3)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Note that hovering over a masked region still yields the underlying value of the element on the display.\n", "\n", "A toggle button below the plot can be used to hide/show the masks.\n", "\n", "The mask can be represented as a solid color with" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "sc.plot(d3, masks={'color': 'magenta'})" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We also note that any 1D mask will automatically broadcast onto a 2D image.\n", "This is due to underlying behavior of scipp around broadcasting rather than special handling in plotting:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "d3.masks['mask1'] = sc.Variable(dims=['x'], values=np.where(np.abs(xx-50) < 10, True, False))\n", "sc.plot(d3)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Saving figures\n", "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:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "sc.plot(d3, filename='my_2d_figure.pdf')" ] } ], "metadata": { "kernelspec": { "display_name": "Python 3", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.7.10" } }, "nbformat": 4, "nbformat_minor": 4 }