{ "cells": [ { "cell_type": "raw", "metadata": { "raw_mimetype": "text/restructuredtext" }, "source": [ ".. _markers:\n", "\n", "Markers\n", "-------" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "In Toyplot, markers are used to show the individual datums in scatterplots:" ] }, { "cell_type": "code", "execution_count": 12, "metadata": { "collapsed": true }, "outputs": [], "source": [ "import numpy\n", "import toyplot\n", "\n", "import logging\n", "logging.basicConfig()" ] }, { "cell_type": "code", "execution_count": 13, "metadata": {}, "outputs": [ { "data": { "text/html": [ "
051015200.00.51.0
" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "y = numpy.linspace(0, 1, 20) ** 2\n", "toyplot.scatterplot(y, width=300);" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Markers can also be added to regular plots to highlight the datums (they are turned-off by default):" ] }, { "cell_type": "code", "execution_count": 14, "metadata": {}, "outputs": [ { "data": { "text/html": [ "
051015200.00.51.0051015200.00.51.0
" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "canvas = toyplot.Canvas(600, 300)\n", "canvas.cartesian(grid=(1, 2, 0)).plot(y)\n", "canvas.cartesian(grid=(1, 2, 1)).plot(y, marker=\"o\");" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "You can use the `size` argument to control the size of the markers:" ] }, { "cell_type": "code", "execution_count": 15, "metadata": {}, "outputs": [ { "data": { "text/html": [ "
051015200.00.51.0051015200.00.51.0
" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "canvas = toyplot.Canvas(600, 300)\n", "canvas.cartesian(grid=(1, 2, 0)).plot(y, marker=\"o\", size=6)\n", "canvas.cartesian(grid=(1, 2, 1)).plot(y, marker=\"o\", size=10);" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Or you can use the `area` argument instead to control the approximate *area* of the markers (this is recommended if you're using per-datum marker sizes to display data)." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "By default, plot and scatterplot markers are small circles, but many other shapes can be specified using a string *shape code*:" ] }, { "cell_type": "code", "execution_count": 16, "metadata": {}, "outputs": [ { "data": { "text/html": [ "
051015200.00.51.0051015200.00.51.0
" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "canvas = toyplot.Canvas(600, 300)\n", "canvas.cartesian(grid=(1, 2, 0)).scatterplot(y, marker=\"x\", size=10)\n", "canvas.cartesian(grid=(1, 2, 1)).scatterplot(y, marker=\"^\", size=10, mstyle={\"stroke\":toyplot.color.black});" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Note the use of the *mstyle* argument to override the appearance of the marker in the second example. For line plots, this allows you to style the lines and the markers separately:" ] }, { "cell_type": "code", "execution_count": 17, "metadata": {}, "outputs": [ { "data": { "text/html": [ "
051015200.00.51.0051015200.00.51.0
" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "canvas = toyplot.Canvas(600, 300)\n", "canvas.cartesian(grid=(1, 2, 0)).plot(y, marker=\"o\", size=8, style={\"stroke\":\"darkgreen\"})\n", "canvas.cartesian(grid=(1, 2, 1)).plot(y, marker=\"o\", size=8, mstyle={\"stroke\":\"darkgreen\"});" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Note that you can pass a sequence of shape codes to the *marker* argument, to specify markers on a per-series or per-datum basis.\n", "\n", "The string shape code is actually a shortcut for a full marker specification, which is an instance of :class:`toyplot.marker.Marker` that contains a set of explicit marker attributes:\n", "\n", "* \"shape\" - marker shape code.\n", "* \"mstyle\" - dictionary of CSS styles to apply to the marker *shape*.\n", "* \"size\" - size of the marker.\n", "* \"angle\" - angle (in degrees) to rotate the marker.\n", "* \"label\" - text label superimposed on the marker.\n", "* \"lstyle\" - dictionary of CSS styles to apply to the marker *label*.\n", "\n", "Using the full marker specification allows you to override the size, style, and appearance of individual markers in a series, if necessary.\n", "\n", "You can use :func:`toyplot.marker.create` to create instances of :class:`toyplot.marker.Marker`, as in the following examples: " ] }, { "cell_type": "code", "execution_count": 18, "metadata": {}, "outputs": [ { "data": { "text/html": [ "
051015200.00.51.0BBBBBBBBBBBBBBBBBBBB051015200.00.51.0
" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "import toyplot.marker\n", "\n", "marker_a = toyplot.marker.create(shape=\"^\", angle=-30, size=15)\n", "marker_b = toyplot.marker.create(shape=\"o\", label=\"B\", lstyle={\"fill\":\"white\"})\n", "\n", "canvas = toyplot.Canvas(600, 300)\n", "canvas.cartesian(grid=(1, 2, 0)).scatterplot(y, marker=marker_a, size=10)\n", "canvas.cartesian(grid=(1, 2, 1)).scatterplot(y, marker=marker_b, size=15);" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "In addition to using markers in plots and scatterplots, markers can be embedded in any figure text, using custom HTML markup. The markup itself can be fairly verbose, so :class:`toyplot.marker.Marker` provides API to make it easier:" ] }, { "cell_type": "code", "execution_count": 19, "metadata": {}, "outputs": [ { "data": { "text/html": [ "
A is a marker and so is
" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "marker_a = toyplot.marker.create(shape=\"s\", label=\"A\", mstyle={\"fill\":\"none\"})\n", "marker_b = toyplot.marker.create(shape=\"*\")\n", "text = marker_a + \" is a marker and so is \" + marker_b\n", "\n", "style = {\"font-size\": \"18px\"}\n", "\n", "canvas = toyplot.Canvas(width=\"5in\", height=\"1.25in\")\n", "axes = canvas.cartesian(show=False)\n", "axes.text(0, 0, text=text, style=style);" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "You can also convert markers to HTML explicitly, if you prefer:" ] }, { "cell_type": "code", "execution_count": 20, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "\n" ] } ], "source": [ "print(marker_a.to_html())" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "This makes it easy to create a table documenting all of the available marker shape codes:" ] }, { "cell_type": "code", "execution_count": 21, "metadata": {}, "outputs": [ { "data": { "text/html": [ "
Shape CodeMarkerNone|/-\\+x*^>v<sdoooo|o/o-o\\o+oxo*r3x1r2x1r1x1r1x2r0.5x1.5
" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "markers = [None, \"|\",\"/\",\"-\",\"\\\\\",\"+\",\"x\",\"*\",\"^\",\">\",\"v\",\"<\",\"s\",\"d\",\n", " \"o\",\"oo\",\"o|\", \"o/\", \"o-\", \"o\\\\\", \"o+\",\"ox\",\"o*\",\"r3x1\",\"r2x1\",\"r1x1\", \"r1x2\", \"r0.5x1.5\"]\n", "mstyle = {\"stroke\":toyplot.color.black, \"fill\":\"#feb\"}\n", "labels = [str(marker) for marker in markers]\n", "markers = [toyplot.marker.create(shape=marker, mstyle=mstyle, size=15).to_html() for marker in markers]\n", "\n", "# This is necessary because \"<\" and \">\" are interpreted as tags when rendering text.\n", "from xml.sax.saxutils import escape\n", "labels = [escape(label) for label in labels]\n", "\n", "canvas, table = toyplot.table(trows=1, rows=len(markers), columns=2, width=400, height=1200)\n", "table.cells.grid.vlines[...,1] = \"single\"\n", "table.cells.grid.hlines[1,...] = \"single\"\n", "table.top.cell[0,...].data = [\"Shape Code\", \"Marker\"]\n", "table.top.cell[0,...].lstyle = {\"font-size\":\"16px\", \"font-weight\":\"bold\"}\n", "table.body.column[0].data = labels\n", "table.body.column[0].lstyle = {\"font-size\":\"16px\", \"font-family\":\"monospace\"}\n", "table.body.column[1].data = markers" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "There are several items here worth noting - first, you can pass *None* or an empty string to produce an invisible marker, if you need to hide a datum or declutter the display. Second, observe that several of the marker shapes contain internal details that require a contrasting stroke and fill to be visible. Finally, the rectangular `rWxH` markers can be specified using any values (including floating point values) for their width and height." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Keep in mind that you can embed markers in *any* text string in Toyplot, including labels, tick marks, and more. And because :class:`toyplot.mark.Mark` objects have a public `markers` attribute that is used when creating legends, you can be very creative when annotating figures:" ] }, { "cell_type": "code", "execution_count": 23, "metadata": {}, "outputs": [ { "data": { "text/html": [ "
DateDeliveredOn Time
15feb20055531.0000
15mar20055071.0000
15apr20055861.0000
15may20054881.0000
15jun20054041.0000
15jul20053061.0000
15aug20053230.9905
15sep20055310.9959
15oct20056770.9600
15nov20056950.9624
15dec20058670.9229
15jan20065570.9888
" ], "text/plain": [ "" ] }, "execution_count": 23, "metadata": {}, "output_type": "execute_result" } ], "source": [ "import toyplot.data\n", "data = toyplot.data.deliveries()\n", "data" ] }, { "cell_type": "code", "execution_count": 24, "metadata": {}, "outputs": [ { "data": { "text/html": [ "
048120300600900Deliveries0.930.950.981.00On TimeDeliveries () vs. On Time ()
" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "canvas = toyplot.Canvas(width=600, height=300)\n", "axes = canvas.cartesian(xlabel=\"Date\", ylabel=\"Deliveries\", ymin=0)\n", "deliveries = axes.plot(data[\"Delivered\"], color=\"darkred\")\n", "\n", "axes = axes.share(\"x\", ylabel=\"On Time\")\n", "on_time = axes.plot(data[\"On Time\"], color=\"steelblue\")\n", "\n", "axes.label.text = \"Deliveries (\" + deliveries.markers[0] + \") vs. On Time (\" + on_time.markers[0] + \")\"" ] } ], "metadata": { "anaconda-cloud": {}, "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.4" } }, "nbformat": 4, "nbformat_minor": 1 }