{ "metadata": { "language": "Julia", "name": "", "signature": "sha256:c9f241411a20ab5566f6fa6ce9ab5ea78b7d08063a76e1e6e2d9031f6459e6db" }, "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": [ "# 5.12. Trying the Julia language in the notebook" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "For this recipe, you need to install Julia and IJulia. You'll find the installation instructions in the book." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "1. We can't avoid the customary *Hello World* example. The `println()` function displays a string and adds a line break at the end." ] }, { "cell_type": "code", "collapsed": false, "input": [ "println(\"Hello world!\")" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "2. We create a polymorphic function `f` that computes the expression $z*z+c$. We will notably evaluate this function on arrays, so we use elementwise operators with a dot (`.`) prefix." ] }, { "cell_type": "code", "collapsed": false, "input": [ "f(z, c) = z.*z .+ c" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "3. Let's evaluate `f` on scalar complex numbers (the imaginary number $i$ is `1im`)." ] }, { "cell_type": "code", "collapsed": false, "input": [ "f(2.0 + 1.0im, 1.0)" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "4. Now, we create a `(2, 2)` matrix. Components are separated by a space, rows are separated by a semicolon (`;`). The type of this `Array` is automatically inferred from its components. The `Array` type is a built-in data type in Julia, similar, but not identical, to NumPy's `ndarray` type." ] }, { "cell_type": "code", "collapsed": false, "input": [ "z = [-1.0 - 1.0im 1.0 - 1.0im;\n", " -1.0 + 1.0im 1.0 + 1.0im]" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "5. We can index arrays with brackets `[]`. A notable difference with Python is that indexing starts from 1 instead of 0. MATLAB has the same convention. Besides, the keyword `end` refers to the last item in that dimension." ] }, { "cell_type": "code", "collapsed": false, "input": [ "z[1,end]" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "6. We can evaluate `f` on the matrix `z` and a scalar `c` (polymorphism)." ] }, { "cell_type": "code", "collapsed": false, "input": [ "f(z, 0)" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "7. Now, we create a function `julia` that computes a Julia set. Optional named arguments are separated from positional arguments by a semicolon (`;`). Julia's syntax for flow control is close from Python's, except that colons are dropped, indentation doesn't count, and block `end` keywords are mandatory." ] }, { "cell_type": "code", "collapsed": false, "input": [ "function julia(z, c; maxiter=200)\n", " for n = 1:maxiter\n", " if abs2(z) > 4.0\n", " return n-1\n", " end\n", " z = f(z, c)\n", " end\n", " return maxiter\n", "end" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "8. We can use Python packages from Julia. First, we have to install the `PyCall` package by using Julia's built-in package manager (`Pkg`). Once the package is installed, we can use it in the interactive session with `using PyCall`." ] }, { "cell_type": "code", "collapsed": false, "input": [ "Pkg.add(\"PyCall\")\n", "using PyCall" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "9. We can import Python packages with the `@pyimport` **macro** (a metaprogramming feature in Julia). This macro is the equivalent of Python's `import` command." ] }, { "cell_type": "code", "collapsed": false, "input": [ "@pyimport numpy as np" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "10. The `np` namespace is now available in the Julia interactive session. NumPy arrays are automatically converted to Julia `Array`s." ] }, { "cell_type": "code", "collapsed": false, "input": [ "z = np.linspace(-1., 1., 100)" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "11. We can use list comprehensions to evaluate the function `julia` on many arguments." ] }, { "cell_type": "code", "collapsed": false, "input": [ "m = [julia(z[i], 0.5) for i=1:100]" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "12. Let's try the Gadfly plotting package. This library offers a high-level plotting interface inspired by Grammar of Graphics. In the notebook, plots are interactive thanks to the **d3.js** library." ] }, { "cell_type": "code", "collapsed": false, "input": [ "Pkg.add(\"Gadfly\")\n", "using Gadfly" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "code", "collapsed": false, "input": [ "plot(x=1:100, y=m, Geom.point, Geom.line)" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "13. Now, we compute a Julia set by using two nested loops. In general, and unlike Python, there is no significant performance penalty using `for` loops instead of vectorized operations in Julia. High-performance code can be written either with vectorized operations or `for` loops." ] }, { "cell_type": "code", "collapsed": false, "input": [ "@time m = [julia(complex(r, i), complex(-0.06, 0.67)) \n", " for i = 1:-.001:-1,\n", " r = -1.5:.001:1.5];" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "14. Finally, we use the `PyPlot` package to draw matplotlib figures in Julia." ] }, { "cell_type": "code", "collapsed": false, "input": [ "Pkg.add(\"PyPlot\")\n", "using PyPlot" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "code", "collapsed": false, "input": [ "imshow(m, cmap=\"RdGy\", \n", " extent=[-1.5, 1.5, -1, 1]);" ], "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": {} } ] }