{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# 1D Plots Tutorial \n", "\n", "This tutorial is for creating 1D lines plot using [CDAT](https://uvcdat.llnl.gov)'s VCS.\n", "\n", "\n", "The CDAT software was developed by LLNL. This tutorial was written by Charles Doutriaux. This work was performed under the auspices of the U.S. Department of Energy by Lawrence Livermore National Laboratory under Contract DE-AC52-07NA27344.\n", "\n", "[Download the Jupyter Notebook](1D_Multi_line_Plots.ipynb)\n" ] }, { "cell_type": "markdown", "metadata": { "toc": true }, "source": [ "

Table of Contents

\n", "
" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Create VCS canvas\n", "[Back to Top](#top)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "import vcs\n", "x = vcs.init(bg=True,geometry=(800,600))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Prepare input data\n", "[Back to Top](#top)\n", "\n", "Let's start with simple sine function" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "import numpy\n", "angle = numpy.arange(0, 360, 10) # in degrees\n", "s = numpy.sin(angle/180.*numpy.pi) # sin takes radians as input" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Very Basic Plot\n", "[Back to Top](#top)\n", "\n", "In its most basic form VCS does not need anything else to plot:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "x.plot(s)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Basic Controls \n", "[Back to Top](#top)\n", "\n", "Let's change the color of the line and size aspect and size of the markers.\n", "\n", "For this we will need to create a **1D graphic method** and alter some of its attributes\n", "\n", "The following is list of available markers\n", "\n", "\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "line = vcs.create1d()\n", "line.list() # List what we can change" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "line.linecolor = \"red\" # Red color obviously\n", "line.linewidth = 2. # A bit thicker\n", "line.marker = \"circle\" #\n", "line.markersize = 1.25 # A bit bigger\n", "x.clear() # Let's clear the first plot\n", "x.switchfonts(\"default\",\"Clarendon\")\n", "x.plot(s,line)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Altering X Axis\n", "[Back to Top](#top)\n", "\n", "We would like the axis to be shown in radians, since `s` is a pure array the *x* axis is seen by vcs as 0 to 35\n", "\n", "Let's create a dictionary to show a few X points\n", "\n", "0 -> 0\n", "45degrees = 4.5 in our units = $\\pi/4$" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "angles = {0:'0',9:r'$\\pi/2$',18:r'$\\pi$', 27:r'$3\\pi/2$',36:r'$2\\pi$'}\n", "line.xticlabels1 = angles\n", "x.clear()\n", "x.plot(s,line)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "But we would like to have the axis labeled \"angle\" rather than `axis_0` so we need to make s a transient variable" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "import MV2\n", "s = MV2.array(s)\n", "s.id = \"sine\"\n", "xaxis = s.getAxis(0)\n", "xaxis.id = \"angle\"\n", "xaxis.units=\"radians\"\n", "# let's make them radians as well\n", "xaxis[:] = xaxis[:]/18.*numpy.pi\n", "# That means we need to match or symbols to new values\n", "angles = {0:'0',numpy.pi/2.:r'$\\pi/2$',numpy.pi:r'$\\pi$', 3*numpy.pi/2.:r'$3\\pi/2$',2*numpy.pi:r'$2\\pi$'}\n", "line.xticlabels1 = angles\n", "x.clear()\n", "x.plot(s,line)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The last point being exactly 2$pi$ it is not drawn let's extend our *x axis* a bit\n", "Also by default it is using the first and last value to determine the x values, this can be an issue when plotting multiple line (with different x ref for example).\n", "\n", "We recommend setting the x range manually" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "line.datawc_x1 = -0.1\n", "line.datawc_x2 = numpy.pi*2.000001\n", "x.clear()\n", "x.plot(s,line)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Altering Y Axis\n", "[Back to Top](#top)\n", "\n", "We can also tweak the y axis, by default it is using the max and min of the data it is plotting.\n", "If you have mutliple line plot this can be an issue as min/max will change with each plot.\n", "\n", "We recommend setting the y range manually" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "line.datawc_y1 = -1.1\n", "line.datawc_y2 = 1.1\n", "line.yticlabels1 = {-1.:\"-1\",-.5:\"-0.5\",0:\"0\",.5:\"0.5\",1:\"1\"}\n", "x.clear()\n", "x.plot(s,line)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Beautifying the plot some more via templates\n", "[Back to Top](#top)\n", "\n", "Let's draw thick line at tickmarks and dotted ones in between\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "tmpl = vcs.createtemplate()" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "thick = vcs.createline() # for thick ticks\n", "thick.width = 1.5 # A bit thicker\n", "thick.color = [[56,56,56]]\n", "dots = vcs.createline() # for thin/sub ticks\n", "dots.type = [\"dot\"]\n", "dots.color = [[78,78,78]]\n", "tmpl.xtic1.y2 = tmpl.data.y2 # Ticks extends all the way accross the data section\n", "tmpl.xtic1.line = thick\n", "tmpl.xmintic1.y2 = tmpl.data.y2 # Ticks extends all the way accross the data section\n", "tmpl.xmintic1.priority = 1\n", "tmpl.xmintic1.line = dots\n", "tmpl.ytic1.x2 = tmpl.data.x2 # Ticks extends all the way accross the data section\n", "tmpl.ytic1.line = thick\n", "tmpl.ymintic1.x2 = tmpl.data.x2 # Ticks extends all the way accross the data section\n", "tmpl.ymintic1.priority = 1\n", "tmpl.ymintic1.line = dots\n", "line.xmtics1 = {numpy.pi/4.:\"\",3*numpy.pi/4:\"\",5*numpy.pi/4:\"\",7*numpy.pi/4:\"\"}\n", "line.ymtics1 = {-.75:\"\", -.25:\"\", .25:\"\", .75:\"\"}\n", "x.clear()\n", "x.plot(s,line,tmpl)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "black = vcs.createline()\n", "black.width = 2.\n", "tmpl.ymintic2.line = black\n", "tmpl.ymintic2.x1 = tmpl.data.x1\n", "tmpl.ymintic2.x2 = tmpl.data.x2\n", "tmpl.ymintic2.priority = 2 # To be sure it's on top\n", "tmpl.xmintic2.line = black\n", "tmpl.xmintic2.y1 = tmpl.data.y1\n", "tmpl.xmintic2.y2 = tmpl.data.y2\n", "tmpl.xmintic2.priority = 2 # To be sure it's on top\n", "line.ymtics2 = {0:\"\"}\n", "line.xmtics2 = {0:\"\"}\n", "tmpl.box1.line = black # make outer box match thick line\n", "x.clear()\n", "x.plot(s, tmpl, line)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Multiple Lines\n", "[Back to Top](#top)\n", "\n", "Let's plot multiple lines " ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "c = MV2.cos(angle/180.*numpy.pi)\n", "c.id = \"cosine\"\n", "c.setAxis(0,xaxis)\n", "\n", "x.clear()\n", "x.plot(s,tmpl,line)\n", "x.plot(c,line,tmpl) # order does not matter" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We are almost there but we need to blank a few attributes on template (name, min, max, etc.. and legend)\n", "Also we need a different color for the cosine" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "tmpl.blank([\"dataname\",\"min\",\"mean\",\"max\"])\n", "line_cos = vcs.create1d(source=line)\n", "line_cos.linecolor = \"blue\"\n", "line_cos.marker = \"diamond\"\n", "line_cos.markersize = 1.5\n", "line_cos.markercolor = \"black\"\n", "x.clear()\n", "x.plot(s,tmpl,line)\n", "x.plot(c,tmpl,line_cos)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Ok now we still have to tweak the legend, templates have a built in function for this" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# First let's blank the legend default\n", "x.clear()\n", "tmpl.legend.priority=1 # Make sure it is on\n", "tmpl.drawLinesAndMarkersLegend(x, [line.linecolor, line_cos.linecolor], \n", " [line.linetype, line_cos.linetype],\n", " [line.linewidth,line_cos.linewidth],\n", " [line.markercolor, line_cos.markercolor],\n", " [line.marker, line_cos.marker],\n", " [line.markersize, line_cos.markersize],\n", " [s.id, c.id])\n", "tmpl.legend.priority=0\n", "x.plot(s,tmpl,line)\n", "x.plot(c,tmpl,line_cos)\n", "\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "And finally let's use to template to beautify a bit more" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "x2 = .7\n", "tmpl.data.x2 = x2\n", "# We also need to move the other things linked to it\n", "tmpl.box1.x2= x2\n", "tmpl.ymintic1.x2 = x2\n", "tmpl.ymintic2.x2 = x2\n", "tmpl.ytic1.x2 = x2\n", "tmpl.ytic2.x1 = x2\n", "tmpl.ytic2.x2 = x2+.01\n", "\n", "# Let's move the legend\n", "tmpl.legend.x1 = x2+.05\n", "tmpl.legend.x2 = .9\n", "tmpl.legend.y1 = .45\n", "tmpl.legend.y2 = .55\n", "\n", "x.clear()\n", "tmpl.legend.priority=1 # Make sure it is on\n", "# Let's stack it vertically now\n", "tmpl.drawLinesAndMarkersLegend(x, [line.linecolor, line_cos.linecolor], \n", " [line.linetype, line_cos.linetype],\n", " [line.linewidth,line_cos.linewidth],\n", " [line.markercolor, line_cos.markercolor],\n", " [line.marker, line_cos.marker],\n", " [line.markersize, line_cos.markersize],\n", " [s.id, c.id],\n", " stacking=\"vertical\")\n", "tmpl.legend.priority=0\n", "x.plot(s,tmpl,line)\n", "x.plot(c,tmpl,line_cos)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Other types of 1D plots\n", "[Back to Top](#top)\n", "\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Flipping axes (aka x(y) vs y or xyvsy)\n", "[Back to Top](#top)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "line_flip = vcs.create1d(source=line)\n", "line_flip.flip = True\n", "# Note that f = vcs.createxyvsy() creates a 1d plot with flip = True\n", "def flip(gm, attr):\n", " tmp = getattr(gm, \"x\"+attr)\n", " setattr(gm, \"x\"+attr, getattr(gm,\"y\"+attr))\n", " setattr(gm, \"y\"+attr, tmp)\n", " \n", "for att in [\"mtics\",\"ticlabels\"]:\n", " for number in [\"1\", \"2\"]:\n", " flip(line_flip, att + number)\n", "\n", "line_flip.datawc_x1 = -1.1\n", "line_flip.datawc_x2 = 1.1\n", "line_flip.datawc_y1 = -.1\n", "line_flip.datawc_y2 = numpy.pi*2.1\n", "x.clear()\n", "x.plot(s,line_flip, tmpl)\n", " " ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Scatter plots aka y vs x\n", "[Back to Top](#top)\n", "\n", "Let's plot cosine vs sine" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "scatter = vcs.create1d(source=line)\n", "scatter.datawc_x1 = -2.2\n", "scatter.datawc_x2 = 2.2\n", "scatter.xmtics1 = scatter.ymtics1\n", "scatter.xmtics2 = scatter.ymtics2\n", "scatter.xticlabels1 = scatter.yticlabels1\n", "scatter.xticlabels2 = scatter.yticlabels2\n", "x.clear()\n", "# x values passed first\n", "x.plot(2*s,c,scatter)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Let's turn off the lines" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "scatter.linecolor= [0,0,0,0] # no opacity = transparent\n", "x.clear()\n", "# x values passed first\n", "x.plot(2*s,c,scatter)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Or turn off the markers" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "scatter.linecolor = \"red\"\n", "scatter.markercolor = [0,0,0,0]\n", "x.clear()\n", "# x values passed first\n", "x.plot(2*s,c,scatter)" ] } ], "metadata": { "celltoolbar": "Raw Cell Format", "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.3" }, "toc": { "base_numbering": 1, "nav_menu": {}, "number_sections": false, "sideBar": true, "skip_h1_title": false, "title_cell": "Table of Contents", "title_sidebar": "Contents", "toc_cell": true, "toc_position": {}, "toc_section_display": true, "toc_window_display": false } }, "nbformat": 4, "nbformat_minor": 2 }