{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# Slicing\n", "\n", "This notebook will go over a guide to how slicing works in prysm. We begin by importing some classes which can be sliced, as well as matplotlib. Note that while we use specific prysm clases as examples, virtually every class in prysm can be sliced in the same way." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "%load_ext autoreload\n", "%autoreload 2\n", "import numpy as np\n", "\n", "from prysm import (\n", " config,\n", " sample_files,\n", " Interferogram)\n", "\n", "from matplotlib import pyplot as plt\n", "plt.style.use('bmh')\n", "\n", "plt.rcParams.update({'axes.grid': False, 'mathtext.fontset': 'dejavusans'})\n", "%matplotlib inline" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Now we prepare a few prysm objects for slicing. This code is not relevant to the action of slicing and can be ignored for the purposes of this tutorial. The object is visualised with `.plot2d()` to give an idea of the data we're looking at." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "i = Interferogram.from_zygo_dat(sample_files('dat')).crop()\n", "\n", "print(i)\n", "i.plot2d();\n", "i.recenter()\n", "i.fill()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Slices are accessed by calling the `.slices()` method on a prysm object, which returns a `Slices` object. For a full reference on the `Slices` class, please look at the [API documentation](../api/base_classes.html#prysm._richdata.Slices).\n", "\n", "`.slices` takes only a single parameter, `twosided`. With the default of `None`, an intelligent default is chosen by prysm. This can be accessed (or changed) with `(class)._default_twosided`. Alternatively, just change it in the call to `.slices()` on a case-by-case basis. Here, we will not do so." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "print('interferograms default to two-sided slices?', Interferogram._default_twosided)\n", "\n", "# make a slices object\n", "s = i.slices()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "There are several slices supported, from simple Cartesian ones (`.x` and `.y` for slices along the x and y Cartesian axes, resp.) to more complex azimuthal routines, (`.azavg`, `.azmedian`, `.azmin`, `.azmax`, `.azpv`, `.azvar`, `.azstd`). Each of these returns a tuple of (coordinate, value). We will use only the `.x` slice for example at the moment:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "u, v = s.x\n", "u[:3], v[:3]" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Any of the slices can be plotted with the `.plot` method. It takes either a single slice, or sequence of slices:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "s.plot('x')\n", "\n", "s.plot(['x', 'y', 'azavg'])" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "since `.slices` returns the slices object, it can just be chained:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "i.slices().plot('azpv')\n", "\n", "# here we just get a better example for more plot options\n", "# this can be ignored\n", "psd = i.psd()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "You will rarely want to keep a `Slices` object around, but do note that the azimuthal slice types require computation and are not just views into an array. The radial coordinate transformation is cached on the slice instance, so if you need to perform multiple calls (to get a slice itself, and plot later for example) it can be beneficial to get a slice instance and then reuse it.\n", "\n", "`Slices.plot` has more parameters for customization, for example logarithmic scaling:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# this is going to look pretty blank\n", "psd.slices().plot('azavg', xscale='linear', yscale='linear')\n", "\n", "# this is going to look a lot better\n", "psd.slices().plot('azavg')" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Classes adjust the default to this with their `._slice_xscale` and `._slice_yscale` fields. All of the built-in prysm classes have sane defaults chosen for you. The x axis can also be inverted (i.e., between period and frequency), and x and y limits adjusted:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "psd.slices().plot('azavg', invert_x=True, xlim=(100, 0.1), ylim=(1e-3,1e4))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The line width, alpha (transparency), and zorder can be adjusted, and the axis labels or legend turned off:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# with zorder=3, you can see we end up above the grid\n", "psd.slices().plot('x', lw=5, alpha=.6, zorder=3, show_axlabels=False, show_legend=False)\n", "plt.grid(True)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "linewidth, alpha, and zorder can be sequences in the same order as the slices, and a figure and axis can be passed in:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# you could be fancier here\n", "fig, ax = plt.subplots(figsize=(7,7))\n", "\n", "slices = ('x', 'y', 'azavg')\n", "lw = (1, 1, 2.5)\n", "alpha = (0.3, 0.3, 1)\n", "zorder = (3, 3, 4)\n", "\n", "slices_ = i.psd().slices()\n", "i.psd().slices().plot(slices, lw=lw, alpha=alpha, zorder=zorder,\n", " invert_x=True, xlim=(100, 0.3), ylim=(1e-4, 1e4),\n", " fig=fig, ax=ax)\n", "plt.grid(True)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Last but not least, values are exact coordinates can be extracted through interpolation:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# these work for either single values or arrays\n", "i.exact_x(10), i.exact_y(10), i.exact_x([0, 5, 10])" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "In the multi-dimensional indexing scheme:\n", "\n", "- no value can be used for one of the two coordinates for an implicit 0\n", "- a single value can be used, and it will be duplicated to be the same for the entire slice" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# no value given for y => y=0\n", "print(i.exact_xy(15))\n", "\n", "# can use a sequence for one axis and not the other\n", "print(i.exact_polar([0, 10, 20], 10))" ] } ], "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.4" } }, "nbformat": 4, "nbformat_minor": 2 }