{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "[![Binder](https://mybinder.org/badge_logo.svg)](https://mybinder.org/v2/gh/PyLops/pylops_transform2022/HEAD?labpath=PyLops_v2.ipynb)\n", "\n", "[![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/PyLops/pylops_transform2022/blob/main/PyLops_v2.ipynb)" ] }, { "cell_type": "markdown", "metadata": { "id": "fvzDiWgxrEbB" }, "source": [ "# Building Operators in PyLops V2: What's New? \n", "\n", "**Author: C. Costa, PyLops Dev Team**" ] }, { "cell_type": "markdown", "metadata": { "id": "JXwvtkqirEbE" }, "source": [ "The aim of this second tutorial is to introduce you to some features in our latest creation (still in the making): **PyLops V2**\n", "\n", "As any new Major version, there will be breaking changes! \n", "\n", "Nevetheless, this is the very first time since the initial creation of PyLops that we decided to sit back and revisit some the early design choices. We hope the benefit introduced by such changes outweights the pain of making a few changes to your codes.\n", "\n", "In the following we want to give you a taste of some new features and highlight along the way if (and how) these have required breaking changes.\n", "\n", "For more details on how to quickly migrate your PyLops v1.x codes into PyLops v2.x codes please refer to this [document](https://github.com/PyLops/pylops/blob/dev/MIGRATION_V1_V2.md)." ] }, { "cell_type": "markdown", "metadata": { "id": "hvtyDt5KrEbF" }, "source": [ "## Useful links\n", "\n", "- Tutorial Github repository: https://github.com/PyLops/pylops_transform2022\n", " \n", "- PyLops Github repository: https://github.com/PyLops/pylops\n", "\n", "- PyLops reference documentation: https://pylops.readthedocs.io/en/latest/" ] }, { "cell_type": "markdown", "metadata": { "id": "d4BKiX3mrEbG" }, "source": [ "## Let's Get Shifty\n", "\n", "To get started, let's suppose we want to implement a simple shift operator.\n", "Stating the problem more descriptively, we want an operator that\n", "\n", "1. Depends on a (possibly fractional) parameter `shift`\n", "2. Can be applied to a vector along a certain given `axis`.\n", "3. A positive `shift` should shift the vector to the right; a negative `shift` to the left.\n", "4. The shift is not circular, that is, when shifting to the right, the last samples will not appear in the beginning of the array.\n", "\n", "PyLops already features a much fancier [Shift operator](https://pylops.readthedocs.io/en/stable/api/generated/pylops.signalprocessing.Shift.html) that works in the Fourier domain, but it is circular.\n", "Numpy offers the `roll` function, but on its own, it does not support fractional shifts and is also circular.\n", "Note that both of these options could be made non-circular by padding, but for now we're gonna \"roll\" our own! 😉\n", "\n", "\n", "---------------------\n", "\n", "Before we jump on creating the operator, let's code a function to do the shift.\n", "After we have the workhorse, it will be easier to write the boilerplate code required for the `LinearOperator`." ] }, { "cell_type": "code", "execution_count": 1, "metadata": { "colab": { "base_uri": "https://localhost:8080/" }, "id": "uumt2jRqrI_L", "outputId": "141a4b16-64cf-45f7-fad0-93260ceb87e4" }, "outputs": [], "source": [ "!pip install --upgrade git+https://github.com/PyLops/pylops.git@dev numba==0.55.1" ] }, { "cell_type": "code", "execution_count": 3, "metadata": { "id": "rVj---WSrEbG" }, "outputs": [], "source": [ "%matplotlib inline\n", "\n", "import logging\n", "import matplotlib.pyplot as plt\n", "import numba\n", "import numpy as np\n", "import numpy.typing as npt\n", "import pylops\n", "\n", "from typing import Tuple\n", "\n", "logger = logging.getLogger()\n", "logger.setLevel(logging.INFO)\n", "try:\n", " import cupy as cp # Remove if no GPU\n", "except ImportError:\n", " logger.warning(\"Could not import CuPy\")\n", "\n", "plt.style.use('tableau-colorblind10')\n", "np.random.seed(0)" ] }, { "cell_type": "code", "execution_count": 5, "metadata": { "colab": { "base_uri": "https://localhost:8080/" }, "id": "x6gkOnozv0Pj", "outputId": "4fd3bb10-4164-4dee-edc5-1f805d465085" }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "numba : 0.55.1\n", "google : 2.0.3\n", "matplotlib: 3.5.1\n", "numpy : 1.21.5\n", "IPython : 5.5.0\n", "cupy : 9.4.0\n", "pylops : 1.13.1.dev405+g7eda999\n", "\n", "Watermark: 2.3.0\n", "\n" ] } ], "source": [ "#!pip install -q --upgrade watermark\n", "#%load_ext watermark\n", "#%watermark --iversions -w" ] }, { "cell_type": "markdown", "metadata": { "id": "K8BNlzHcrEbI" }, "source": [ "We're going to start with an integer-based shifting function, which we will exploit later to convert into a fractional shifter. We want this function to be pretty fast, so we're going to pad the original array and pad it with the correct number of zeros.\n", "\n", "