{ "cells": [ { "cell_type": "markdown", "source": [ "# Examples\n", "\n", "This page illustrates the Julia package\n", "[`MIRTjim`](https://github.com/JeffFessler/MIRTjim.jl)." ], "metadata": {} }, { "cell_type": "markdown", "source": [ "### Setup" ], "metadata": {} }, { "cell_type": "markdown", "source": [ "Packages needed here." ], "metadata": {} }, { "outputs": [], "cell_type": "code", "source": [ "using MIRTjim: jim, prompt, mid3\n", "using AxisArrays: AxisArray\n", "using ColorTypes: RGB\n", "using OffsetArrays: OffsetArray\n", "using Unitful\n", "using Unitful: μm, s\n", "import Plots\n", "using InteractiveUtils: versioninfo" ], "metadata": {}, "execution_count": null }, { "cell_type": "markdown", "source": [ "The following line is helpful when running this file as a script;\n", "this way it will prompt user to hit a key after each figure is displayed." ], "metadata": {} }, { "outputs": [], "cell_type": "code", "source": [ "isinteractive() ? jim(:prompt, true) : prompt(:draw);" ], "metadata": {}, "execution_count": null }, { "cell_type": "markdown", "source": [ "## Simple 2D image\n", "\n", "The simplest example is a 2D array.\n", "Note that `jim` is designed to show a function `f(x,y)`\n", "sampled as an array `z[x,y]` so the 1st index is horizontal direction." ], "metadata": {} }, { "outputs": [], "cell_type": "code", "source": [ "x, y = 1:9, 1:7\n", "f(x,y) = x * (y-4)^2\n", "z = f.(x, y') # 9 × 7 array\n", "jim(z ; xlabel=\"x\", ylabel=\"y\", title=\"f(x,y) = x * (y-4)^2\")" ], "metadata": {}, "execution_count": null }, { "cell_type": "markdown", "source": [ "Compare with `Plots.heatmap` to see the differences\n", "(transpose, color, wrong aspect ratio, distractingly many ticks):" ], "metadata": {} }, { "outputs": [], "cell_type": "code", "source": [ "Plots.heatmap(z, title=\"heatmap\")" ], "metadata": {}, "execution_count": null }, { "outputs": [], "cell_type": "code", "source": [ "isinteractive() && prompt();" ], "metadata": {}, "execution_count": null }, { "cell_type": "markdown", "source": [ "Images often should include a title, so `title =` is optional." ], "metadata": {} }, { "outputs": [], "cell_type": "code", "source": [ "jim(z, \"hello\")" ], "metadata": {}, "execution_count": null }, { "cell_type": "markdown", "source": [ "## OffsetArrays\n", "\n", "`jim` displays the axes naturally." ], "metadata": {} }, { "outputs": [], "cell_type": "code", "source": [ "zo = OffsetArray(z, (-3,-1))\n", "jim(zo, \"OffsetArray example\")" ], "metadata": {}, "execution_count": null }, { "cell_type": "markdown", "source": [ "## 3D arrays\n", "\n", "`jim` automatically makes 3D arrays into a mosaic." ], "metadata": {} }, { "outputs": [], "cell_type": "code", "source": [ "f3 = reshape(1:(9*7*6), (9, 7, 6))\n", "jim(f3, \"3D\"; size=(600, 300))" ], "metadata": {}, "execution_count": null }, { "cell_type": "markdown", "source": [ "One can specify how many images per row or column for such a mosaic." ], "metadata": {} }, { "outputs": [], "cell_type": "code", "source": [ "x11 = reshape(1:(5*6*11), (5, 6, 11))\n", "jim(x11, \"nrow=3\"; nrow=3)" ], "metadata": {}, "execution_count": null }, { "outputs": [], "cell_type": "code", "source": [ "jim(x11, \"ncol=6\"; ncol=6, size=(600, 200))" ], "metadata": {}, "execution_count": null }, { "cell_type": "markdown", "source": [ "## Central slices with `mid3`\n", "The `mid3` function shows the central x-y, y-z, and x-z slices\n", "[(axial, coronal, sagittal) planes](https://en.wikipedia.org/wiki/Anatomical_plane).\n", "Making useful `xticks` and `yticks` in this case takes some fiddling." ], "metadata": {} }, { "outputs": [], "cell_type": "code", "source": [ "x,y,z = -20:20, -10:10, 1:30\n", "xc = reshape(x, :, 1, 1)\n", "yc = reshape(y, 1, :, 1)\n", "zc = reshape(z, 1, 1, :)\n", "rx = reshape(range(2, 19, length(z)), size(zc))\n", "ry = reshape(range(2, 9, length(z)), size(zc))\n", "cone = @. abs2(xc / rx) + abs2(yc / ry) < 1\n", "jim(mid3(cone); color=:cividis, title=\"mid3\")\n", "xticks = ([1, length(x), length(x)+length(z)],\n", " [\"$(x[begin])\", \"$(x[end]), $(z[begin])\", \"$(z[end])\"])\n", "yticks = ([1, length(y), length(y)+length(z)],\n", " [\"$(y[begin])\", \"$(y[end]), $(z[begin])\", \"$(z[end])\"])\n", "Plots.plot!(;xticks , yticks)" ], "metadata": {}, "execution_count": null }, { "cell_type": "markdown", "source": [ "## Arrays of images\n", "\n", "`jim` automatically makes arrays of images into a mosaic." ], "metadata": {} }, { "outputs": [], "cell_type": "code", "source": [ "z3 = reshape(1:(9*7*6), (7, 9, 6))\n", "z4 = [z3[:,:,(j-1)*3+i] for i=1:3, j=1:2]\n", "jim(z4, \"Arrays of images\")" ], "metadata": {}, "execution_count": null }, { "cell_type": "markdown", "source": [ "## Units\n", "\n", "`jim` supports units, with axis and colorbar units appended naturally." ], "metadata": {} }, { "outputs": [], "cell_type": "code", "source": [ "x = 0.1*(1:9)u\"m/s\"\n", "y = (1:7)u\"s\"\n", "zu = x * y'\n", "jim(x, y, zu, \"units\" ;\n", " clim=(0,7).*u\"m\", xlabel=\"rate\", ylabel=\"time\", colorbar_title=\"distance\")" ], "metadata": {}, "execution_count": null }, { "cell_type": "markdown", "source": [ "Note that `aspect_ratio` reverts to `:auto` when axis units differ." ], "metadata": {} }, { "cell_type": "markdown", "source": [ "Image spacing is appropriate even for non-square pixels\n", "if Δx and Δy have matching units." ], "metadata": {} }, { "outputs": [], "cell_type": "code", "source": [ "x = range(-2,2,201) * 1u\"m\"\n", "y = range(-1.2,1.2,150) * 1u\"m\" # Δy ≢ Δx\n", "z = @. sqrt(x^2 + (y')^2) ≤ 1u\"m\"\n", "jim(x, y, z, \"Axis units with unequal spacing\"; color=:cividis, size=(600,350))" ], "metadata": {}, "execution_count": null }, { "cell_type": "markdown", "source": [ "Units are also supported for 3D arrays,\n", "but the z-axis is ignored for plotting." ], "metadata": {} }, { "outputs": [], "cell_type": "code", "source": [ "x = (2:9) * 1μm\n", "y = (3:8) * 1/s\n", "z = (4:7) * 1μm * 1s\n", "f3d = rand(8, 6, 4) # * s^2\n", "jim(x, y, z, f3d, \"3D with axis units\")" ], "metadata": {}, "execution_count": null }, { "cell_type": "markdown", "source": [ "One can use a tuple for the `axes` instead;\n", "only the `x` and `y` axes are used." ], "metadata": {} }, { "outputs": [], "cell_type": "code", "source": [ "jim((x, y, z), f3d, \"axes tuple\")" ], "metadata": {}, "execution_count": null }, { "cell_type": "markdown", "source": [ "## AxisArrays" ], "metadata": {} }, { "cell_type": "markdown", "source": [ "`jim` displays the axes (names and units) naturally by default:" ], "metadata": {} }, { "outputs": [], "cell_type": "code", "source": [ "x = (1:9)μm\n", "y = (1:7)μm/s\n", "za = AxisArray(x * y'; x, y)\n", "jim(za, \"AxisArray\")" ], "metadata": {}, "execution_count": null }, { "cell_type": "markdown", "source": [ "## Color images" ], "metadata": {} }, { "outputs": [], "cell_type": "code", "source": [ "jim(rand(RGB{Float32}, 8, 6); title=\"RGB image\")" ], "metadata": {}, "execution_count": null }, { "cell_type": "markdown", "source": [ "## Options" ], "metadata": {} }, { "cell_type": "markdown", "source": [ "See the docstring for `jim` for its many options.\n", "Here are some defaults." ], "metadata": {} }, { "outputs": [], "cell_type": "code", "source": [ "jim(:defs)" ], "metadata": {}, "execution_count": null }, { "cell_type": "markdown", "source": [ "One can set \"global\" defaults using appropriate keywords from above list.\n", "Use `:push!` and `:pop!` for such changes to be temporary." ], "metadata": {} }, { "outputs": [], "cell_type": "code", "source": [ "jim(:push!) # save current defaults\n", "jim(:colorbar, :none) # disable colorbar for subsequent figures\n", "jim(:yflip, false) # have \"y\" axis increase upward\n", "jim(rand(9,7), \"rand\", color=:viridis) # kwargs... passed to heatmap()" ], "metadata": {}, "execution_count": null }, { "outputs": [], "cell_type": "code", "source": [ "jim(:pop!); # restore" ], "metadata": {}, "execution_count": null }, { "cell_type": "markdown", "source": [ "## Layout\n", "\n", "One can use `jim` just like `plot` with a layout of subplots.\n", "The `gui=true` option is useful when you want a figure to appear\n", "even when other code follows.\n", "Often it is used with the `prompt=true` option (not shown here).\n", "The `size` option helps avoid excess borders." ], "metadata": {} }, { "outputs": [], "cell_type": "code", "source": [ "p1 = jim(rand(5,7); prompt=false)\n", "p2 = jim(rand(6,8); color=:viridis, prompt=false)\n", "p3 = jim(rand(9,7); color=:cividis, title=\"plot 3\", prompt=false)\n", "jim(p1, p2, p3; layout=(1,3), gui=true, size = (600,200))" ], "metadata": {}, "execution_count": null }, { "cell_type": "markdown", "source": [ "---\n", "\n", "*This notebook was generated using [Literate.jl](https://github.com/fredrikekre/Literate.jl).*" ], "metadata": {} } ], "nbformat_minor": 3, "metadata": { "language_info": { "file_extension": ".jl", "mimetype": "application/julia", "name": "julia", "version": "1.10.3" }, "kernelspec": { "name": "julia-1.10", "display_name": "Julia 1.10.3", "language": "julia" } }, "nbformat": 4 }