{ "metadata": { "kernelspec": { "codemirror_mode": { "name": "python", "version": 3 }, "display_name": "Python 3", "language": "python", "name": "python3" }, "name": "", "signature": "sha256:b96370f24a9a5a165868140ec56de267eb05745979d06da2de65f7c035a38d1c" }, "nbformat": 3, "nbformat_minor": 0, "worksheets": [ { "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "> This is one of the 100 recipes of the [IPython Cookbook](http://ipython-books.github.io/), the definitive guide to high-performance scientific computing and data science in Python." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# 6.6. Getting started with Vispy for high-performance interactive data visualizations" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Vispy depends on NumPy and PyOpenGL. A backend library is necessary (PyQt4 or PySide for example)." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "This recipe has been tested with the [development version of Vispy](https://github.com/vispy/vispy). You should clone the GitHub repository and install Vispy with `python setup.py install`." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The API used in this recipe might change in future versions." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "1. Let's import NumPy, **vispy.app** (to display a canvas) and **vispy.gloo** (object-oriented interface to OpenGL)." ] }, { "cell_type": "code", "collapsed": false, "input": [ "import numpy as np\n", "from vispy import app\n", "from vispy import gloo" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "2. In order to display a window, we need to create a **Canvas**." ] }, { "cell_type": "code", "collapsed": false, "input": [ "c = app.Canvas(keys='interactive')" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "3. When using `vispy.gloo`, we need to write **shaders**. These programs written in a C-like language run on the GPU and give us full flexibility for our visualizations. Here, we create a trivial **vertex shader** that directly displays 2D data points (stored in the `a_position` variable) in the canvas. We give more details in *There's more*." ] }, { "cell_type": "code", "collapsed": false, "input": [ "vertex = \"\"\"\n", "attribute vec2 a_position;\n", "void main (void)\n", "{\n", " gl_Position = vec4(a_position, 0.0, 1.0);\n", "}\n", "\"\"\"" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "4. The other shader we need to create is the **fragment shader**. It lets us control the pixels' color. Here, we display all data points in black." ] }, { "cell_type": "code", "collapsed": false, "input": [ "fragment = \"\"\"\n", "void main()\n", "{\n", " gl_FragColor = vec4(0.0, 0.0, 0.0, 1.0);\n", "}\n", "\"\"\"" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "5. Next, we create an **OpenGL Program**. This object contains shaders and links the shader variables to NumPy data." ] }, { "cell_type": "code", "collapsed": false, "input": [ "program = gloo.Program(vertex, fragment)" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "6. We link the variable `a_position` to a `(1000, 2)` NumPy array containing the coordinates of 1000 data points. In the default coordinate system, the coordinates of the four canvas corners are `(+/-1, +/-1)`." ] }, { "cell_type": "code", "collapsed": false, "input": [ "program['a_position'] = np.c_[\n", " np.linspace(-1.0, +1.0, 1000),\n", " np.random.uniform(-0.5, +0.5, 1000)]" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "7. We create a callback function for when the window is being resized. Updating the **OpenGL viewport** lets us ensure that Vispy uses the entire canvas." ] }, { "cell_type": "code", "collapsed": false, "input": [ "@c.connect\n", "def on_resize(event):\n", " gloo.set_viewport(0, 0, *event.size)" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "8. We create a callback function when the canvas needs to be refreshed. This `on_draw` function renders the entire scene. First, we clear the window in white (it is necessary to do that at every frame). Then, we draw a succession of line segments using our OpenGL program." ] }, { "cell_type": "code", "collapsed": false, "input": [ "@c.connect\n", "def on_draw(event):\n", " gloo.clear((1,1,1,1))\n", " program.draw('line_strip')" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "9. Finally, we show the canvas and we run the application." ] }, { "cell_type": "code", "collapsed": false, "input": [ "c.show()\n", "app.run();" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "> You'll find all the explanations, figures, references, and much more in the book (to be released later this summer).\n", "\n", "> [IPython Cookbook](http://ipython-books.github.io/), by [Cyrille Rossant](http://cyrille.rossant.net), Packt Publishing, 2014 (500 pages)." ] } ], "metadata": {} } ] }