{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# First step" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "In this tutorial we will use [Brython](http://brython.info/), an implementation of Python written in javascript and Python, to access the Highcharts javascript library and to manage the data to be used in the maps. To integrate Brython in the IPython notebook we are using an extension for the notebook called [brythonmagic](https://github.com/kikocorreoso/brythonmagic) that provides a new magic cell, **%%brython**, that allow us to write and execute Brython code in the notebook." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Installation of the brythonmagic IPython extension" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "As stated before, we will use [Brython](http://www.brython.info), and [brythonmagic](https://github.com/kikocorreoso/brythonmagic) so first of all we need to load the extension and the Brython library.\n", "\n", "So, let's load the extension:" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "%load_ext brythonmagic" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "And the brython js lib:" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "from brythonmagic import load_brython_dev\n", "load_brython_dev()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "**\\[It is highly recommended that, at least, you read the [brythonmagic docs](https://github.com/kikocorreoso/brythonmagic#usage) to understand what it does. It is also recommended to have a quick look at the [Brython docs](http://www.brython.info/static_doc/en/intro.html?lang=en)].**" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# Warning" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "In order to load javascript libraries in a safety way you should try to use https instead of http when possible (read more [here](http://mail.scipy.org/pipermail/ipython-dev/2014-July/014572.html)). If you don't trust the source and/or the source cannot be loaded using https then you could download the javascript library and load it from a local location." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# Conventions used in the following tutorial." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "In the following tutorial I will try to follow several conventions to try to make it more readable.\n", "\n", "Code in cells that are not code cells:\n", "\n", "\n", "* a block of code will appear as follows:\n", "\n", "```python\n", "# This is a block of code\n", "print(\"Hello world!\")\n", "```\n", "\n", "\n", "* Python/Brython code commented in a line of text will appear as follows, **this is a piece of Python/Brython code inline with the text**\n", "\n", "\n", "* Javascript code commented in a line of text will appear as follows, **this is a piece of javascript code inline with the text**\n", "\n", "\n", "* Most of new code used in a code cell will be commented in a paragraph starting with **[NEW CODE]**\n", "\n", "\n", "* When the Python and the javascript code is not exactly the same I will try to comment how the code would be in javascript." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# What is Highcharts?" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "**Highcharts** is an open source, **client side** *JavaScript* library for making **interactive charts**, viewable in nearly any modern web browser. Since it is a client side library, it requires no special server side software or settings — you can use it without even downloading anything!\n", "\n", "This tutorial just try to explain a little bit what can be found in the official documentation and try to introduce this library to Python users.\n", "\n", "The website for Highcharts is located at [http://www.highcharts.com/](http://www.highcharts.com/). To begin, we need to [download](http://www.highcharts.com/download) a copy of Highcharts (or, we can directly link to the library — this is what we will do in the present tutorial). You can download the compressed library as a .zip file.\n", "\n", "So, before continuing let's load the Highcharts library." ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "from brythonmagic import load_js_lib\n", "load_js_lib(\"https://cdnjs.cloudflare.com/ajax/libs/highcharts/5.0.7/highcharts.js\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## First example: A simple line chart" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "First we create some simple HTML code. This HTML code will contain our chart. We will not use complicated HTML code during the tutorial to keep it simple and to be focused in *'How to create interactive charts in the browser with Python'*. There is a lot of amazing [resources](http://www.w3schools.com/) to learn about HTML and CSS." ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "html = \"\"\"
\"\"\"" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Now the interesting part. To make Highcharts available to Brython we need to 'load' the Highchart object/namespace to Brython using **Highcharts = window.Highcharts**. We will use the **new** method injected by Brython to the Javascript object that would behave similarly as if we were using Javascript constructors, (ie functions used with the Javascript keyword **new**).\n", "\n", "The code is as follows:" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "%%brython -h html -p\n", "from browser import window\n", "\n", "Highcharts = window.Highcharts\n", "\n", "hc = Highcharts.Chart.new\n", "\n", "config = {\n", " 'chart':{\n", " 'renderTo': 'hc_ex1'\n", " },\n", " 'title': {\n", " 'text': 'Monthly Average Temperature',\n", " 'x': -20 #center\n", " },\n", " 'subtitle': {\n", " 'text': 'Source: WorldClimate.com',\n", " 'x': -20\n", " },\n", " 'xAxis': {\n", " 'categories': ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun',\n", " 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec']\n", " },\n", " 'yAxis': {\n", " 'title': {\n", " 'text': 'Temperature (°C)'\n", " },\n", " 'plotLines': [{\n", " 'value': 0,\n", " 'width': 1,\n", " 'color': '#808080'\n", " }]\n", " },\n", " 'tooltip': {\n", " 'valueSuffix': '°C'\n", " },\n", " 'legend': {\n", " 'layout': 'vertical',\n", " 'align': 'right',\n", " 'verticalAlign': 'middle',\n", " 'borderWidth': 0\n", " },\n", " 'series': [{\n", " 'name': 'Tokyo',\n", " 'data': [7.0, 6.9, 9.5, 14.5, 18.2, 21.5, 25.2, 26.5, 23.3, 18.3, 13.9, 9.6]\n", " }]\n", "}\n", "\n", "hc(config)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Pretty simple!!\n", "\n", "Ok, let's dissect the code in the Brython cell above.\n", "\n", "**%%brython -h html -p** :\n", "\n", "* Indicates that the code cell is written using Brython and we use some options for the Brython code cell, `-h` to use the HTML code defined in the `html` variable located in the cell above and `-p` to print the final HTML code generated below the generated chart. In this example, the generated code should be something like the following:\n", "\n", "```html\n", " \n", "
\n", " ```\n", "\n", "the `-p` option only provides information and it isn't required to run the Brython code cell.\n", "\n", "**hc = Highcharts.Chart.new**\n", "\n", "* Here we are instantiating the chart, i.e., accessing the function to the Brython namespace.\n", "\n", "**config = { ... }**\n", "\n", "* Here we are defining the options and data to be used in the chart. More on this later.\n", "\n", "**hc(config))**\n", "\n", "* We call the hc function with the data and configuration options defined in the `config` dict." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# Configuring Highcharts" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We can configure how the chart will be shown, layout, dimensions, axis, titles, legends,... All this information can be managed on each plot or using a configuration object (in javascript or dictionary in Python).\n", "\n", "In the previous example we have seen the `config` dict. Let's dedicate some time to understand it. The `config` dict contains a series of dicts and each of these dicts manage several pieces of the chart:\n", "\n", "* `chart` dict ([complete api](http://api.highcharts.com/highcharts#chart)): It contains information related with how the chart is presented (background colors, area plot colors, type of chart to be used, where the chart should be rendered (html element), margins and spacings,...). A more complete example would be something like the following:\n", "\n", "```python\n", "'chart': {\n", " 'renderTo': 'The_id_of_the_html_element',\n", " 'backgroundColor': 'a_valid_html_object',\n", " 'type': 'spline',\n", " 'plotBorderWidth': 1,\n", " 'plotBorderColor': '#3F4044',\n", " ...\n", "}\n", "```\n", "\n", "* `colors` key: The value is a list of strings containing valid html colors. The default colors in the latest highcharts version are:\n", "\n", "```python\n", "'colors': ['#7cb5ec', '#434348', '#90ed7d', '#f7a35c', '#8085e9', \n", " '#f15c80', '#e4d354', '#8085e8', '#8d4653', '#91e8e1']\n", "```\n", "\n", "* `credits` dict ([complete api](http://api.highcharts.com/highcharts#credits)): This dict allows you to control the credits label in the chart. By default will be shown the credits in the bottom left area of the chart. To control the credits you can use the following:\n", "\n", "```python\n", "'credits': {\n", " 'enabled': Boolean,\n", " 'href': String,\n", " 'text': String,\n", " ...\n", "}\n", "```\n", "\n", "* `legend` dict ([complete api](http://api.highcharts.com/highcharts#legend)): This dict allows you to control how the legend is shown:\n", "\n", "```python\n", "'legend': {\n", " 'enabled': Boolean,\n", " 'align': String,\n", " 'backgroundColor': String,\n", " ...\n", "}\n", "```\n", "\n", "* `plotOptions` dict ([complete api](http://api.highcharts.com/highcharts#plotOptions)): The `plotOptions` dict is a wrapper object for config objects for each series type. The config objects for each series can also be overridden for each series item as given in the series array. Configuration options for the series are given in three levels. Options for all series in a chart are given in the `plotOptions['series']` dict. Then options for all series of a specific type are given in the `plotOptions` of that type, for example `plotOptions[`line`]`. Next, options for one single series are given in the specific series array:\n", "\n", "```python\n", "'plotOptions': {\n", " 'enabled': Boolean,\n", " 'align': String,\n", " 'backgroundColor': String,\n", " ...\n", "}\n", "```\n", "\n", "* `title` and `subtitle` dicts ([complete api for title](http://api.highcharts.com/highcharts#title) and [for subtitle](http://api.highcharts.com/highcharts#subtitle)): this options controls the appeareance of the title and subtitle of the chart. The keys are almost similar for both options:\n", "\n", "```python\n", "'title': {\n", " 'align': String,\n", " 'text': String,\n", " ...\n", "}\n", "```\n", "\n", "* `tooltip` dict ([complete api](http://api.highcharts.com/highcharts#tooltip)): Options for the tooltip that appears when the user hovers over a series or point:\n", "\n", "```python\n", "'tooltip': {\n", " 'enabled': Boolean,\n", " 'backgroundColor': 'a_valid_html_color',\n", " 'borderColor': 'a_valid_html_color',\n", " ...\n", "}\n", "```\n", "\n", "* `xAxis` and `yAxis` dicts ([complete api for xAxis](http://api.highcharts.com/highcharts#xAxis) and [for yAxis](http://api.highcharts.com/highcharts#yAxis)): The x axis or category axis and the y axis or the value axis. Normally, `xAxis` is the horizontal axis and `yAxis` the vertical axis except if the chart is inverted. The keys are pretty similar for both options:\n", "\n", "```python\n", "'xAxis': {\n", " 'min': float or int,\n", " 'max': float or int,\n", " 'title': {a dict with options},\n", " 'lineColor': 'A_valid_html_color',\n", " ...\n", "}\n", "```\n", "\n", "* `series` dict ([complete api](http://api.highcharts.com/highcharts#series)): The actual series to append to the chart. In addition to the possible options, any member of the `plotOptions` for that specific type of plot can be added to a series individually. For example, even though a general `lineWidth` is specified in `plotOptions['series']`, an individual `lineWidth` can be specified for each series:\n", "\n", " * `data` list: It is a list that can be one of the following options (we will come back to this later):\n", " \n", " 1. An array of numerical values. In this case, the numerical values will be interpreted as y values, and x values will be automatically calculated, either starting at 0 and incrementing by 1, or from `pointStart` and `pointInterval` given in the `plotOptions` dict. If the axis has categories, these will be used. This option is not available for range series. \n", " \n", " 2. An array of arrays with two values. In this case, the first value is the `x` value and the second is the `y` value. If the first value is a string, it is applied as the name of the point, and the `x` value is incremented following the above rules. For range series, the arrays will be interpreted as `[x, low, high]`. In this cases, the `x` value can be skipped altogether to make use of `pointStart` and `pointRange`.\n", " \n", " 3. An array of objects with named values. In this case the objects are point configuration objects. Range series values are given by `low` and `high`.\n", "\n", "```python\n", "'series': {\n", " 'data': [* see above],\n", " 'name': String,\n", " 'type': String,\n", " ...\n", "}\n", "```" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Let's see a more complete (and ugly) example using several configuration options:" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "html = \"\"\"
\"\"\"" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "%%brython -h html\n", "from browser import window\n", "\n", "Highcharts = window.Highcharts\n", "\n", "hc = Highcharts.Chart.new\n", "\n", "config = {\n", " 'chart': {\n", " 'renderTo': 'hc_ex2',\n", " 'backgroundColor': {\n", " 'linearGradient': [0, 0, 500, 500],\n", " 'stops': [[0, 'rgb(255, 255, 255)'],\n", " [1, 'rgb(200, 200, 255)']]\n", " },\n", " 'borderRadius': 10\n", " },\n", " 'title': {\n", " 'align': 'left',\n", " 'text': 'My dummy title',\n", " 'style': { \"color\": \"green\", \"fontSize\": \"20px\" }\n", " },\n", " 'subtitle': {\n", " 'align': 'right',\n", " 'text': 'Ugly subtitle',\n", " 'style': { \"color\": \"orange\", \"fontSize\": \"12px\" }\n", " },\n", " 'legend': {\n", " 'backgroundColor': 'green',\n", " 'borderColor': 'yellow',\n", " 'borderRadius': 10,\n", " 'borderWidth': 3,\n", " },\n", " 'series': [{\n", " 'data': [1,2,3,4],\n", " 'type': 'line',\n", " 'name': 'Name of the series',\n", " 'color': 'orange',\n", " }],\n", " 'tooltip': {\n", " 'backgroundColor': 'gray',\n", " 'borderColor': 'yellow',\n", " 'borderRadius': 10,\n", " 'borderWidth': 3,\n", " },\n", " 'xAxis': {\n", " 'categories': ['data'] * 4,\n", " 'lineWidth': 5,\n", " 'lineColor': 'violet',\n", " 'gridLineColor': 'violet',\n", " 'gridLineWidth': 3,\n", " 'title': {'text': 'X axis title'}\n", " },\n", " 'yAxis': {\n", " 'lineWidth': 5,\n", " 'lineColor': 'blue',\n", " 'gridLineColor': 'blue',\n", " 'gridLineWidth': 3,\n", " 'title': {'text': 'Y axis title'}\n", " },\n", " 'credits': {\n", " 'text': \"Pybonacci rules!\",\n", " 'href': 'https://twitter.com/pybonacci'\n", " }\n", "}\n", "\n", "hc(config)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "I got it!!! It's the ugliest chart in the world!!!" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Defining options for all the charts" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "If we want we can define some of the options to be used during a complete session so we don't have to define each of the options when defining a new chart.\n", "\n", "We will use **Highcharts.setOptions** to create a set of options that could be overwritten on each individual chart if necessary. You can learn more about how to create themes for highcharts [here](http://www.highcharts.com/docs/chart-design-and-style/themes).\n", "\n", "In general, I don't like some default values for Highcharts and as [Randall Olson has said, sometimes less is more](http://www.randalolson.com/2014/06/28/how-to-make-beautiful-data-visualizations-in-python-with-matplotlib/). Also, as I have some degree of color blindness I will use the ['color blind 10' palette of colors from Tableau](http://public.tableausoftware.com/profile/chris.gerrard#!/vizhome/TableauColors/ColorPaletteswithRGBValues)." ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "%%brython -s globaloptions\n", "from browser import window\n", "\n", "Highcharts = window.Highcharts\n", "\n", "global_options = {\n", " 'colors': ['rgb(0, 107, 164)', 'rgb(255, 128, 114)',\n", " 'rgb(171, 171, 171)', 'rgb(89, 89, 89)',\n", " 'rgb(95, 158, 209)', 'rgb(200, 82, 0)',\n", " 'rgb(137, 137, 137)', 'rgb(162, 200, 236)',\n", " 'rgb(256, 188, 121)', 'rgb(207, 207, 207)'],\n", " 'chart':{\n", " 'plotBackgroundColor': 'rgb(229, 229, 229)'\n", " },\n", " 'credits':{\n", " 'enabled': False\n", " },\n", " 'legend':{\n", " 'align': 'right',\n", " 'verticalAlign': 'middle',\n", " 'layout': 'vertical',\n", " 'borderWidth': 0,\n", " 'enabled': True\n", " },\n", " 'plotOptions':{\n", " 'area': {\n", " 'fillOpacity': 0.5,\n", " 'marker': {'enabled': False},\n", " },\n", " 'arearange': {\n", " 'fillOpacity': 0.5,\n", " 'marker': {'enabled': False},\n", " },\n", " 'areaspline': {\n", " 'fillOpacity': 0.5,\n", " 'marker': {'enabled': False},\n", " },\n", " 'areasplinerange': {\n", " 'fillOpacity': 0.5,\n", " 'marker': {'enabled': False},\n", " },\n", " 'bar': {\n", " 'borderWidth': 0\n", " },\n", " 'boxplot': {\n", " 'fillColor': '#FAFAFA',\n", " 'lineWidth': 2,\n", " 'medianWidth': 4,\n", " 'stemDashStyle': 'line',\n", " 'stemWidth': 1,\n", " 'whiskerLength': '30%',\n", " 'whiskerWidth': 2\n", " },\n", " 'column': {\n", " 'borderWidth': 0\n", " },\n", " 'columnrange': {\n", " 'borderWidth': 0\n", " },\n", " 'errorbar': {\n", " 'color': '#fefefe',\n", " 'lineWidth': 2\n", " },\n", " 'line': {\n", " 'marker': {'enabled': False},\n", " 'lineWidth': 2\n", " },\n", " 'scatter': {\n", " 'marker': {\n", " 'enabled': True,\n", " 'lineWidth': 0,\n", " 'symbol': 'circle',\n", " 'radius': 5\n", " },\n", " },\n", " 'spline': {\n", " 'marker': {'enabled': False},\n", " 'lineWidth': 2\n", " },\n", " 'waterfall': {\n", " 'borderWidth': 0\n", " }\n", " },\n", " 'subtitle': {\n", " 'align': 'center',\n", " 'style': {\n", " 'color': '#555555',\n", " 'fontWeight': 'bold'\n", " }\n", " },\n", " 'title': {\n", " 'align': 'center',\n", " 'text': None,\n", " 'style': {\n", " 'color': '#000000',\n", " 'fontWeight': 'bold'\n", " }\n", " },\n", " 'tooltip': {\n", " 'backgroundColor': 'rgba(255,255,224,0.5)',\n", " 'borderRadius': 5,\n", " 'crosshairs': [{\n", " 'width': 3,\n", " 'color': '#ffffff',\n", " 'dashStyle': 'shortdot'\n", " }, {\n", " 'width': 3,\n", " 'color': '#ffffff',\n", " 'dashStyle': 'shortdot'\n", " }], \n", " 'hideDelay': 200,\n", " 'enabled': True,\n", " 'shadow': False,\n", " \n", " },\n", " 'xAxis': {\n", " 'gridLineColor': '#FFFFFF',\n", " 'gridLineWidth': 1,\n", " 'lineColor': 'rgb(229, 229, 229)',\n", " 'tickColor': 'rgb(229, 229, 229)',\n", " 'shadow': False,\n", " \n", " },\n", " 'yAxis': {\n", " 'gridLineColor': '#FFFFFF',\n", " 'gridLineWidth': 1,\n", " 'lineColor': 'rgb(229, 229, 229)',\n", " 'tickColor': 'rgb(229, 229, 229)',\n", " 'shadow': False,\n", " \n", " }\n", "}\n", "\n", "Highcharts.setOptions.new(global_options)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "And now, let's repeat our first example again after the global configuration:" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "html = \"\"\"
\"\"\"" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "%%brython -h html\n", "from browser import window\n", "\n", "Highcharts = window.Highcharts\n", "\n", "hc = Highcharts.Chart.new\n", "\n", "config = {\n", " 'chart':{'renderTo': 'hc_ex3'},\n", " 'title': {'text': 'Monthly Average Temperature'},\n", " 'subtitle': {'text': 'Source: WorldClimate.com'},\n", " 'xAxis': {'categories': ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun',\n", " 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec']},\n", " 'yAxis': {'title': {'text': 'Temperature (°C)'}},\n", " 'tooltip': {'valueSuffix': '°C'},\n", " 'series': [{'name': 'Tokyo',\n", " 'data': [7.0, 6.9, 9.5, 14.5, 18.2, 21.5, 25.2, 26.5, 23.3, 18.3, 13.9, 9.6]}]\n", "}\n", "\n", "hc(config)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Much better than the ugly chart. \n", "\n", "And other simple charts will look like the following:" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "html = \"\"\"\n", "
\n", "
\n", "
\n", "
\n", "
\n", "
\n", "
\n", "
\"\"\"" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "%%brython -h html\n", "from browser import window\n", "\n", "Highcharts = window.Highcharts\n", "\n", "hc = Highcharts.Chart.new\n", "\n", "# Bar\n", "config = {\n", " 'chart': {'renderTo': 'hc_ex4a', 'type': 'bar'},\n", " 'xAxis': {'categories': ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun',\n", " 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec']},\n", " 'yAxis': {'title': {'text': 'Temperature (°C)'}},\n", " 'tooltip': {'valueSuffix': '°C'},\n", " 'series': [{'name': 'Tokyo',\n", " 'data': [7.0, 6.9, 9.5, 14.5, 18.2, 21.5, 25.2, 26.5, 23.3, 18.3, 13.9, 9.6]}]\n", "}\n", "hc(config)\n", "\n", "# Area\n", "config = {\n", " 'chart': {'renderTo': 'hc_ex4b', 'type': 'area'},\n", " 'xAxis': {'categories': ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun',\n", " 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec']},\n", " 'yAxis': {'title': {'text': 'Temperature (°C)'}},\n", " 'tooltip': {'valueSuffix': '°C'},\n", " 'series': [{'name': 'Tokyo',\n", " 'data': [7.0, 6.9, 9.5, 14.5, 18.2, 21.5, 25.2, 26.5, 23.3, 18.3, 13.9, 9.6]}]\n", "}\n", "hc(config)\n", "\n", "# Bubble\n", "config = {\n", " 'chart': {'renderTo': 'hc_ex4c', 'type': 'scatter', 'zoomType': 'xy'},\n", " 'title': {'text': 'You can pan and zoom'},\n", " 'series': [{'name': 'Tokyo',\n", " 'data': [[7.0, 6.9], [9.5, 14.5], [18.2, 21.5], [25.2, 26.5], [23.3, 18.3], [13.9, 9.6]]}]\n", "}\n", "hc(config)\n", "\n", "# Pie\n", "config = {\n", " 'chart': {'renderTo': 'hc_ex4d', 'type': 'pie', 'plotBackgroundColor': 'white'},\n", " 'series': [{'name': 'Python scientific libs',\n", " 'data': [['scipy', 6.9], ['IPython', 14.5], \n", " ['Matplotlib', 21.5], ['Numpy', 26.5], ['Pandas', 18.3]]}]\n", "}\n", "hc(config)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "**[NEW CODE]** In the previous figures we have included some new options in the `chart` dict:\n", "\n", "* **'type': 'type_of_chart'**. It indicates which chart will be used to render the data.\n", "\n", "* **'zoomType': 'xy'**. It allows us to zoom after the selection of an area with the mouse.\n", "\n", "Also, in the Pie chart, we have used the option **'plotBackgroundColor': 'white'** so the global option defined before is not used." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# Using data" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Before, we have seen three different ways to insert data into a chart. Let's see it again to understand better how it is used:" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "* An array of numerical values. In this case, the numerical values will be interpreted as *y* values, and *x* values will be automatically calculated, either starting at *0* and incrementing by *1*, or from `pointStart` and `pointInterval` given in the `plotOptions` dict. If the axis has categories, these will be used. This option is not available for range series." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We have seen examples before but let's create a more complete example using this way:" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "html = \"\"\"
\"\"\"" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "%%brython -h html\n", "from browser import window\n", "\n", "Highcharts = window.Highcharts\n", "\n", "hc = Highcharts.Chart.new\n", "\n", "config = {\n", " 'chart': {'renderTo': 'hc_ex5'},\n", " 'yAxis': {'title': {'text': 'Temperature (°C)'}},\n", " 'tooltip': {'valueSuffix': '°C'},\n", " 'series': [{'name': 'Tokyo',\n", " 'data': [7.0, 6.9, 9.5, 14.5, 18.2, 21.5, 25.2, 26.5, 23.3, 18.3, 13.9, 9.6]},\n", " {'name': 'Madrid',\n", " 'data': [3.0, 5.4, 6.5, 12.7, 16.8, 21.4, 26.5, 26.2, 24.3, 17.3, 11.8, 6.7]}]\n", "}\n", "hc(config)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "* An array of arrays with two values. In this case, the first value is the *x* value and the second is the *y* value. If the first value is a string, it is applied as the name of the point, and the *x* value is incremented following the above rules and the string will be used in the tooltip of the point. For range series, the arrays will be interpreted as `[x, low, high]`. In this cases, the *x* value can be skipped altogether to make use of `pointStart` and `pointRange`." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "This way has been used in the scatter chart previously. In the example above we have seen that the x values start at 0. If we want a different behaviour we could define the x values as follows:" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "html = \"\"\"
\"\"\"" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "%%brython -h html\n", "from browser import window\n", "\n", "Highcharts = window.Highcharts\n", "\n", "hc = Highcharts.Chart.new\n", "\n", "config = {\n", " 'chart': {'renderTo': 'hc_ex6', 'type': 'line'},\n", " 'yAxis': {'title': {'text': 'Temperature (°C)'}},\n", " 'tooltip': {'valueSuffix': '°C'},\n", " 'series': [{'name': 'Neverland',\n", " 'data': [[1, 6.9], [3, 14.5], [7, 21.5], [8, 26.5], [9, 18.3], [10, 9.6]]}]\n", "}\n", "hc(config)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "If the *x* values are not a valid number it will be used as a label in the tooltip and the *x* values will start by *0* and incrementing by *1*. For example:" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "html = \"\"\"
\"\"\"" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "%%brython -h html\n", "from browser import window\n", "\n", "Highcharts = window.Highcharts\n", "\n", "hc = Highcharts.Chart.new\n", "\n", "config = {\n", " 'chart': {'renderTo': 'hc_ex7', 'type': 'line'},\n", " 'yAxis': {'title': {'text': 'Temperature (°C)'}},\n", " 'tooltip': {'valueSuffix': '°C'},\n", " 'series': [{'name': 'Neverland',\n", " 'data': [['Jan', 6.9], ['Mar', 14.5], ['Jul', 21.5], ['Aug', 26.5], ['Sep', 18.3], ['Oct', 9.6]]}]\n", "}\n", "hc(config)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "* An array of objects with named values. In this case the objects are point configuration objects. Range series values are given by `low` and `high`.\n", "\n", "This is the most complete case as you can define more precisely how the data is displayed." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "[HINT] In the next chart we will use the 'bubble' chart type. We must load a new javascript file as the *highcharts.js* doesn't provide the complete functionality of Highcharts and some type of charts (like 'arearange', 'bubble',...) are included as extras. The new javascript file is *highcharts-more.js*." ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "from brythonmagic import load_js_lib\n", "load_js_lib(\"https://cdnjs.cloudflare.com/ajax/libs/highcharts/5.0.7/highcharts-more.js\")" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "html = \"\"\"
\"\"\"" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "%%brython -h html\n", "\n", "import random\n", "from browser import window\n", "\n", "Highcharts = window.Highcharts\n", "\n", "hc = Highcharts.Chart.new\n", "\n", "# First we create the data to be passed to the plot\n", "data = [{'name': 'Data {}'.format(i+1), \n", " 'color': 'rgb(100,50,{0})'.format(random.randrange(0,255)), \n", " 'y': random.randrange(0,25), \n", " 'x': i+1} for i in range(10)]\n", "\n", "config = {\n", " 'chart': {'renderTo': 'hc_ex8'},\n", " 'yAxis': {'title': {'text': 'Temperature (°C)'}},\n", " 'series': [{'data': data, 'type': 'line', 'color': 'black'},\n", " {'data': data, 'type': 'bubble'}]\n", "}\n", "hc(config)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "On each data value we have used a `name` (shown in the tooltip), a `color` (used in scatter, bar, column, bubble,..., charts but not in line or area charts, for example) and the `x` and `y` values." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# Types of charts" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Line charts" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We already have seen several line charts. Let's see something more advanced. In the following example we will include the data value for each record and we will be able to choose an area of the chart to zoom on the chosen subset." ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "html = \"\"\"
\"\"\"" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "%%brython -h html\n", "import random\n", "from browser import window\n", "\n", "Highcharts = window.Highcharts\n", "\n", "hc = Highcharts.Chart.new\n", "\n", "# First we create the data to be passed to the plot\n", "data = [[i+1, random.randrange(0,35)] for i in range(100)] \n", "\n", "config = {\n", " 'chart': {'renderTo': 'hc_ex9', 'type': 'line', 'zoomType': 'x'},\n", " 'yAxis': {'title': {'text': 'Wind speed (m/s)'}},\n", " 'series': [{'data': data}],\n", " 'plotOptions': {\n", " 'line': {'dataLabels': {'enabled': True}, 'enableMouseTracking': False}\n", " },\n", " 'title': {'text': 'Click and drag to zoom'}\n", "}\n", "hc(config)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "**[NEW CODE]** In the previous figure we have included some new options in the chart dict:\n", "\n", "* **'zoomType': 'x'**. It allows us to zoom after the selection of an area with the mouse. In this case, the zoom is over the *x* axis\n", "\n", "Also, in the **plotOptions** dict, we have included some new options.\n", "\n", "* **'line': {'dataLabels': {'enabled': True}, 'enableMouseTracking': False}**. The **'dataLabels'** option allow us to show the value of each record while the **'enableMouseTracking'** option allows us to disable the default mouse interaction with the plot (tooltip,...)." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "In the following plot we are defining some areas in the background to help highlight some aspects of the dataset:" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "html = \"\"\"
\"\"\"" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "%%brython -h html\n", "import random\n", "from browser import window\n", "\n", "Highcharts = window.Highcharts\n", "\n", "hc = Highcharts.Chart.new\n", "\n", "# First we create the data to be passed to the plot\n", "data = [[i+1, random.randrange(10,105)] for i in range(100)] \n", "\n", "config = {\n", " 'chart': {'renderTo': 'hc_ex10'},\n", " 'xAxis': {'min': -20},\n", " 'yAxis': {\n", " 'title': {'text': 'Mean Daily NO2 (ug/m3)'},\n", " 'max': 110,\n", " 'minorGridLineWidth': 0,\n", " 'gridLineWidth': 0,\n", " 'alternateGridColor': None,\n", " 'plotBands': [{ \n", " 'from': 0,\n", " 'to': 15,\n", " 'color': 'rgba(100,100,255,0.5)',\n", " 'label': {\n", " 'text': 'Clean air',\n", " 'style': {\n", " 'color': 'black'\n", " }\n", " }\n", " }, { \n", " 'from': 15,\n", " 'to': 40,\n", " 'color': 'rgba(0,255,0,0.5)',\n", " 'label': {\n", " 'text': 'Below EU limit',\n", " 'style': {\n", " 'color': 'black'\n", " }\n", " }\n", " }, { \n", " 'from': 40,\n", " 'to': 120,\n", " 'color': 'rgba(255,0,0,0.5)',\n", " 'label': {\n", " 'text': 'Above EU limit',\n", " 'style': {\n", " 'color': 'black'\n", " }\n", " }\n", " }]\n", " },\n", " 'series': [{'data': data, 'lineWidth': 2, 'color': 'black'}]\n", "}\n", "hc(config)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "**[NEW CODE]** In the previous figure we have included some new options in the `options` dict:\n", "\n", "* **'xAxis': {'min': -20}**. This indicates the minimum value for the *x* axis.\n", "\n", "* With the following code we have suppresed the grid lines for the *y* axis and added some band colors. I think the code is self-explanatory.\n", "\n", "
'yAxis': {\n", " 'title': {'text': 'Mean Daily NO2 (ug/m3)'},\n", " 'max': 110,\n", " 'minorGridLineWidth': 0,\n", " 'gridLineWidth': 0,\n", " 'alternateGridColor': None,\n", " 'plotBands': [{ \n", " 'from': 0,\n", " 'to': 15,\n", " 'color': 'rgba(100,100,255,0.5)',\n", " 'label': {\n", " 'text': 'Clean air',\n", " 'style': {\n", " 'color': 'black'\n", " }\n", " }\n", " }, { \n", " 'from': 15,\n", " 'to': 40,\n", " 'color': 'rgba(0,255,0,0.5)',\n", " 'label': {\n", " 'text': 'Below EU limit',\n", " 'style': {\n", " 'color': 'black'\n", " }\n", " }\n", " }, { \n", " 'from': 40,\n", " 'to': 120,\n", " 'color': 'rgba(255,0,0,0.5)',\n", " 'label': {\n", " 'text': 'Above EU limit',\n", " 'style': {\n", " 'color': 'black'\n", " }\n", " }\n", " }]\n", "}
" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "In the next plot we are going to play a little bit with the axis, where is the `y` axis located?, and the legend?:" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "html = \"\"\"
\"\"\"" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "%%brython -h html\n", "from browser import window\n", "\n", "Highcharts = window.Highcharts\n", "\n", "hc = Highcharts.Chart.new\n", "\n", "# First we create the data to be passed to the plot\n", "data = [[3**i, i] for i in range(1, 10)] \n", "\n", "config = {\n", " 'chart': {'renderTo': 'hc_ex11', 'type': 'spline'},\n", " 'yAxis': {'type': 'logarithmic', 'opposite': True, 'offset': 30},\n", " 'legend': {'align': 'left'},\n", " 'series': [{'data': data, 'lineWidth': 4, 'color': 'black'}]\n", "}\n", "hc(config)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "**[NEW CODE]** In the previous figure we have included some new options to modify the *y* axis:\n", "\n", "* **'yAxis': {'type': 'logarithmic', 'opposite': True, 'offset': 30}**. The axis scale is logarithmic, it is located on the opposite site and is located with an offset of 30px from the plot area." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We can include some interactivity to the plot using some basic controls. With the buttons you can update the plot (every second a new point is created), stop the updates or reset to the original state:" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "html = \"\"\"
\n", "
\n", "
\"\"\"" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "%%brython -h html\n", "from browser.timer import set_interval, clear_interval\n", "from browser import window, document, html\n", "from random import randrange\n", "\n", "Highcharts = window.Highcharts\n", "\n", "hc = Highcharts.Chart.new\n", "\n", "# First we create the data to be passed to the plot\n", "data = [[i, randrange(0,10)] for i in range(0, 20)]\n", "data_tmp = data[:]\n", "\n", "config = {\n", " 'chart': {\n", " 'renderTo': 'hc_ex12', \n", " 'type': 'spline'\n", " },\n", " 'series': [{'data': data, 'lineWidth': 2, 'color': 'black', 'animation': False,\n", " 'marker': {'enabled': True}}]\n", "}\n", "\n", "hc(config)\n", "\n", "### NEW CODE ###\n", "\n", "idtimer = None\n", "\n", "# A button to animate the plot with new data\n", "document['hc_ex12container'] <= html.BUTTON('Animate', Id = 'anim')\n", "\n", "def add_point():\n", " global data_tmp\n", " x = data_tmp[-1][0] + 1\n", " y = randrange(0,10)\n", " data_tmp.append([x, y])\n", " config['series'][0]['data'] = data_tmp[-20:]\n", " hc(config)\n", "\n", "def animate(ev):\n", " global idtimer, config, data_tmp\n", " idtimer = set_interval(add_point, 1000)\n", "\n", "document['anim'].bind('click', animate)\n", "\n", "# A button to stop the plot with new data\n", "document['hc_ex12container'] <= html.BUTTON('Stop', Id = 'stop')\n", "\n", "def stop(ev):\n", " global idtimer\n", " clear_interval(idtimer)\n", "\n", "document['stop'].bind('click', stop)\n", "\n", "# A button to reset the plot with the original values\n", "document['hc_ex12container'] <= html.BUTTON('Reset', Id = 'reset')\n", "\n", "def reset(ev):\n", " global idtimer, config, data, data_tmp\n", " if idtimer:\n", " clear_interval(idtimer)\n", " data_tmp = data[:]\n", " config['series'][0]['data'] = data\n", " hc(config)\n", " \n", "document['reset'].bind('click', reset)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "**[NEW CODE]** In the previous figure we have included some Brython specific code to animate the figure:\n", "\n", "* **document['hc_ex12container'].append(html.BUTTON('xxx', Id = 'xxx'))**. With this code we are appending some buttons to the html div with `id` 'hc_ex12container', i.e., the html div element that contains the chart and the buttons. See the [Brython docs for more info](http://brython.info/doc/en/static_index.html?page=html).\n", "\n", "* **document['xxx'].bind('click', xxx)**. With this code we are attaching some functionality (events) to some DOM elements. See the [Brython docs for more info](http://brython.info/doc/en/static_index.html?page=events).\n", "\n", "* Finally, we have defined some functions to manage the events using the `browser.timer` module. See the [Brython docs for more info](http://brython.info/doc/en/static_index.html?page=timer)." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Area charts" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "As some area charts are quite similar to line plots I will write some examples and I will only explain the code that is relevant:" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "A simple area chart:" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "html = \"\"\"
\"\"\"" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "%%brython -h html\n", "from random import randrange\n", "from browser import window\n", "\n", "Highcharts = window.Highcharts\n", "\n", "hc = Highcharts.Chart.new\n", "\n", "# First we create the data to be passed to the plot\n", "data1 = [[i, randrange(0,10)] for i in range(0, 20)]\n", "data2 = [[i, randrange(0,10)] for i in range(0, 20)]\n", "\n", "config = {\n", " 'chart': {\n", " 'renderTo': 'hc_ex13', \n", " 'type': 'area'\n", " },\n", " 'series': [{'data': data1, 'dashStyle': 'ShortDot', 'lineWidth': 3},\n", " {'data': data2}]\n", "}\n", "\n", "hc(config)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "**[NEW CODE]**\n", "\n", "* **'dashStyle': 'ShortDot'**. This option in the first data series modifies the line defining the area. In this case we have used 'ShortDot' but [there are ather options](http://api.highcharts.com/highcharts#plotOptions.area.dashStyle)." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "A simple stacked area chart:" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "html = \"\"\"
\"\"\"" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "%%brython -h html\n", "from random import randrange\n", "from browser import window\n", "\n", "Highcharts = window.Highcharts\n", "\n", "hc = Highcharts.Chart.new\n", "\n", "# First we create the data to be passed to the plot\n", "data1 = [[i, randrange(0,10)] for i in range(0, 20)]\n", "data2 = [[i, randrange(0,10)] for i in range(0, 20)]\n", "\n", "config = {\n", " 'chart': {\n", " 'renderTo': 'hc_ex14', \n", " 'type': 'area'\n", " },\n", " 'series': [{'data': data1, 'lineWidth': 3},\n", " {'data': data2}],\n", " 'plotOptions': {'area': {'stacking': 'normal'}},\n", " 'tooltip': {'shared': True},\n", "}\n", "\n", "hc(config)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "**[NEW CODE]**\n", "\n", "* **'plotOptions': {'area': {'stacking': 'normal'}}**. This indicates that the areas will be stacked. We can choose a 'normal' or a 'percent' stacking. Other chart types like line, bar, columns,.., can be [stacked](http://api.highcharts.com/highcharts#plotOptions.area.stacking).\n", "\n", "* **'tooltip': {'shared': True}**. This option indicates that the tooltip is shared between the datasets so the tooltip will show the information from all the available datasets." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "A simple arearange chart combined with a line plot:" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "html = \"\"\"
\"\"\"" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "%%brython -h html\n", "from random import randrange\n", "from browser import window\n", "\n", "Highcharts = window.Highcharts\n", "\n", "hc = Highcharts.Chart.new\n", "\n", "# First we create the data to be passed to the plot\n", "data1 = [[i, randrange(5,10), randrange(10,15)] for i in range(0, 20)]\n", "data2 = [[i, (lst[1] + lst[2]) / 2.] for i, lst in enumerate(data1)]\n", "\n", "config = {\n", " 'chart': {\n", " 'renderTo': 'hc_ex15'\n", " },\n", " 'series': [{'data': data2, 'type': 'line', 'name': 'mean', 'lineWidth': 3, 'color': 'black'},\n", " {'data': data1, 'lineWidth': 1, 'type': 'arearange', 'name': 'extremes'}],\n", " 'tooltip': {'shared': True}\n", "}\n", "\n", "hc(config)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Column and bar charts" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "A bar plot with positive and negative values:" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "html = \"\"\"
\"\"\"" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "%%brython -h html\n", "from random import randrange\n", "from browser import window\n", "\n", "Highcharts = window.Highcharts\n", "\n", "hc = Highcharts.Chart.new\n", "\n", "# First we create the data to be passed to the plot\n", "data1 = [[i, -randrange(1,15)] for i in range(0, 20)]\n", "data2 = [[i, randrange(1,15)] for i in range(0, 20)]\n", "\n", "config = {\n", " 'chart': {\n", " 'renderTo': 'hc_ex16',\n", " 'type': 'bar'\n", " },\n", " 'series': [{'data': data1, 'name': 'negative'},\n", " {'data': data2, 'name': 'positive'}],\n", " 'plotOptions': {'bar': {'stacking': 'normal'}},\n", " 'tooltip': {'shared': True},\n", " 'xAxis': [{'opposite': False}, {'opposite': True, 'linkedTo': 0}]\n", "}\n", "\n", "hc(config)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "**[NEW CODE]**\n", "\n", "* **'xAxis': [{'opposite': False}, {'opposite': True, 'linkedTo': 0}]**. We are defining two *x* axis, the second one in the opposite side of the plot area and the values are linked to the first axis, i.e., both axis are the same but each one on one side of the chart." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "A bar plot with interactive values:" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "html = \"\"\"
\n", "
\n", "
\n", "
\"\"\"" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "%%brython -h html\n", "from browser import window, document, html\n", "from random import randrange\n", "\n", "Highcharts = window.Highcharts\n", "\n", "# first we create a table with two series of data, X and Y:\n", "tab = html.TABLE()\n", "tab.style = {'textAlign': 'center', 'width': '50px'}\n", "tab <= html.TR(html.TD('X') + html.TD('Y'))\n", "for i in range(5):\n", " tab <= html.TR(\n", " html.TD(\n", " html.INPUT(\n", " Id = 'x' + str(i), value = randrange(1,5), style = {'width': '50px'}\n", " )\n", " ) + \n", " html.TD(\n", " html.INPUT(\n", " Id = 'y' + str(i), value = randrange(1,5), style = {'width': '50px'}\n", " )\n", " )\n", " )\n", " \n", "document['tablediv'] <= tab\n", "\n", "# Function to retrieve the data from the table\n", "def get_data():\n", " data1 = []\n", " data2 = []\n", " for i in range(5):\n", " print('x' + str(i))\n", " data1.append(float(document['x' + str(i)].value))\n", " data2.append(float(document['y' + str(i)].value))\n", " return [data1, data2]\n", "\n", "# Function to update the chart\n", "def update(ev):\n", " global config, hc\n", " datasets = get_data()\n", " config['series'][0]['data'] = datasets[0]\n", " config['series'][1]['data'] = datasets[1]\n", " hc(config)\n", " print(datasets)\n", "\n", "# Button and event\n", "document['hc_ex17container'] <= html.BUTTON('Update', Id = 'btn')\n", "document['btn'].bind('click', update)\n", "\n", "hc = Highcharts.Chart.new\n", "\n", "# First we create the data to be passed to the plot\n", "datasets = get_data()\n", "data1 = datasets[0]\n", "data2 = datasets[1]\n", "\n", "config = {\n", " 'chart': {\n", " 'renderTo': 'hc_ex17',\n", " 'type': 'column'\n", " },\n", " 'series': [{'data': data1, 'name': 'X'},\n", " {'data': data2, 'name': 'Y'}],\n", " 'title': {'text': 'Modify the values in the table and update'}\n", "}\n", "\n", "hc(config)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "**[NEW CODE]**\n", "\n", "* In this case, there is no relevant Highcharts code and the Brython specific code is out of the scope of this tutorial but it is pretty similar to that seen previously in a previous example." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Pie charts" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "In the examples above we have seen a simple pie plot. A donut plot would be quite similar:" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "html = \"\"\"
\"\"\"" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "%%brython -h html\n", "from browser import window\n", "\n", "Highcharts = window.Highcharts\n", "\n", "hc = Highcharts.Chart.new\n", "\n", "# Pie\n", "config = {\n", " 'chart': {'renderTo': 'hc_ex18', 'type': 'pie'},\n", " 'series': [{'name': 'Python scientific libs', 'innerSize': '60%',\n", " 'data': [['scipy', 6.9], ['IPython', 14.5], \n", " ['Matplotlib', 21.5], ['Numpy', 26.5], ['Pandas', 18.3]]}]\n", "}\n", "hc(config)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "**[NEW CODE]**\n", "\n", "* **'innerSize': '50%'**. This is the only difference wth the previous pie plot example. It indicates radius where the pie plot should start from the centre." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Scatter and bubble charts" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "In the examples above we have seen a simple scatter plot. A scatter plot with two datasets is similar:" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "html = \"\"\"
\"\"\"" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "%%brython -h html\n", "from random import randrange\n", "from browser import window\n", "\n", "Highcharts = window.Highcharts\n", "\n", "hc = Highcharts.Chart.new\n", "\n", "# First we create the data to be passed to the plot\n", "data1 = [[i + randrange(-2, 2), randrange(i-3,i+3)] for i in range(0, 20)]\n", "data2 = [[i + randrange(-2, 2) + 2, randrange(i-3,i+3)] for i in range(0, 20)]\n", "\n", "# Scatter\n", "config = {\n", " 'chart': {'renderTo': 'hc_ex19', 'type': 'scatter'},\n", " 'series': [{'name': 'Station 1 vs model', 'data': data1},\n", " {'name': 'Station 2 vs model', 'data': data2}],\n", " 'xAxis': {'title': {'text': 'Station'}},\n", " 'yAxis': {'title': {'text': 'Model'}}\n", "}\n", "hc(config)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "A bubble plot with different colors depending on the size for each record would be as follows:" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "html = \"\"\"
\"\"\"" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "%%brython -h html\n", "from random import randrange\n", "from browser import window\n", "\n", "Highcharts = window.Highcharts\n", "\n", "hc = Highcharts.Chart.new\n", "\n", "# First we create the data to be passed to the plot\n", "data = []\n", "for i in range(20):\n", " x = randrange(-10, 10)\n", " y = randrange(-10, 10)\n", " z = randrange(1, 20)\n", " data.append({'x': x, 'y': y, 'z': z, \n", " 'color': 'rgb(40,40,{0})'.format(int(z * 255 / 20)),\n", " 'marker': {'lineWidth': 1, 'lineColor': 'black'}})\n", "\n", "# Scatter\n", "config = {\n", " 'chart': {'renderTo': 'hc_ex20', 'type': 'bubble'},\n", " 'series': [{'name': 'bubbles', 'data': data}]\n", "}\n", "hc(config)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 3d Charts" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "For this examples we should first load the 3d highcharts library:" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "from brythonmagic import load_js_lib\n", "load_js_lib(\"https://cdnjs.cloudflare.com/ajax/libs/highcharts/5.0.7/highcharts-3d.js\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "With the 3d 'module' loaded we can see a new example where some interactivity is added:" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "html = \"\"\"\n", "
\n", "
\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
Alpha Angle\n", " \n", "
Beta Angle\n", " \n", "
\n", "
\"\"\"" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "%%brython -h html\n", "from browser import window, document\n", "\n", "Highcharts = window.Highcharts\n", "\n", "hc = Highcharts.Chart.new\n", "\n", "config = {\n", " 'chart': {\n", " 'renderTo': 'hc_ex21',\n", " 'plotBackgroundColor': 'white',\n", " 'type': 'column',\n", " 'margin': 100,\n", " 'options3d': {\n", " 'enabled': True,\n", " 'alpha': 15,\n", " 'beta': 15,\n", " 'depth': 50,\n", " 'viewDistance': 50\n", " }\n", " },\n", " 'plotOptions': {'column': {'depth': 25}},\n", " 'series': [{'data': [29.9, 71.5, 106.4, 129.2, 144.0, 176.0, \n", " 135.6, 148.5, 216.4, 194.1, 95.6, 54.4]}],\n", " 'xAxis': {'gridLineColor': '#C0C0C0'},\n", " 'yAxis': {'gridLineColor': '#C0C0C0'}\n", "}\n", "\n", "columns = hc(config)\n", "\n", "def show_values():\n", " document['R0-value'].html = columns.options.chart.options3d.alpha\n", " document['R1-value'].html = columns.options.chart.options3d.beta\n", "\n", "show_values()\n", "\n", "# activate the sliders\n", "def change_alpha(ev):\n", " columns.options.chart.options3d.alpha = ev.target.value\n", " show_values()\n", " columns.redraw(False)\n", "\n", "def change_beta(ev):\n", " columns.options.chart.options3d.beta = ev.target.value\n", " show_values()\n", " columns.redraw(False)\n", "\n", "document['R0'].bind('change', change_alpha)\n", "document['R1'].bind('change', change_beta)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "**[NEW CODE]**\n", "\n", "* **'options3d': {'enabled': True,'alpha': 15,'beta': 15,'depth': 50,'viewDistance': 50}'**. In this case, we are switching on the [3d options](http://api.highcharts.com/highcharts#chart.options3d) and the initial view of the plot.\n", "\n", "You can [create 3D](http://www.highcharts.com/docs/chart-concepts/3d-charts/) pie, donut, scatter,..., plots." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Heat map" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "In this case, as we did it before, we have to add a new module called heatmap:" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "from brythonmagic import load_js_lib\n", "load_js_lib(\"https://cdnjs.cloudflare.com/ajax/libs/highcharts/5.0.7/modules/heatmap.js\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "A simple heatmap would be as follows:" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "html = \"\"\"
\"\"\"" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "%%brython -h html\n", "from random import randrange\n", "from browser import window\n", "\n", "Highcharts = window.Highcharts\n", "\n", "hc = Highcharts.Chart.new\n", "\n", "# First we create the data to be passed to the plot\n", "data = []\n", "for y in range(7):\n", " for x in range(7):\n", " data.append([y, x, randrange(0,150)])\n", " \n", "config = {\n", " 'chart': {\n", " 'renderTo': 'hc_ex22',\n", " 'type': 'heatmap',\n", " 'marginTop': 40,\n", " 'marginBottom': 40\n", " },\n", " 'title': {'text': 'Commits made last week :-P'},\n", " 'xAxis': {'categories': ['Numpy', 'Scipy', 'Matplotlib', 'IPython', \n", " 'Pandas', 'Brython', 'Brythonmagic']},\n", " 'yAxis': {'categories': ['Monday', 'Tuesday', 'Wednesday', \n", " 'Thursday', 'Friday', 'Saturday', 'Sunday'],\n", " 'title': {'text': None}},\n", " 'colorAxis': {'min': 0,\n", " 'minColor': '#FFFFFF',\n", " 'maxColor': JSConstructor(Highcharts.getOptions)().colors[0]},\n", " 'legend': {\n", " 'align': 'right',\n", " 'layout': 'vertical',\n", " 'margin': 0,\n", " 'verticalAlign': 'top',\n", " 'y': 25,\n", " 'symbolHeight': 300\n", " },\n", " 'series': [{\n", " 'borderWidth': 1,\n", " 'data': data,\n", " 'dataLabels': {\n", " 'enabled': True,\n", " 'color': 'black',\n", " 'style': {\n", " 'textShadow': 'none',\n", " 'HcTextStroke': None\n", " }\n", " }\n", " }]\n", "}\n", "\n", "hc(config)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "**[NEW CODE]**\n", "\n", "* **'colorAxis': {'min': 0, 'minColor': '#FFFFFF', 'maxColor': JSConstructor(Highcharts.getOptions)().colors[0]},**. The [colorAxis](http://api.highcharts.com/highmaps#colorAxis) adds a colorbar to the plot." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Other chart types" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We already have seen line, bubble, column, bar, donut, scatter, ..., charts. You can create [Pyramid](http://www.highcharts.com/demo/pyramid), [Funnel](http://www.highcharts.com/demo/funnel), [Waterfall](http://www.highcharts.com/demo/waterfall) or [others](http://www.highcharts.com/demo/renderer)." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# Let's use Highcharts in a more pythonic way" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "All we have seen until now is better that writting plain javascript but the use of Highcharts is not very Pythonic." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Creating a simple wrapper for Highcharts:" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Let's start with something very simple" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "%%brython -s wrapper01\n", "\n", "from browser import window\n", "\n", "Highcharts = window.Highcharts\n", "\n", "hc = Highcharts.Chart.new\n", "\n", "class HC:\n", " def __init__(self, container):\n", " self.options = {}\n", " self.options['chart'] = {}\n", " self.options['chart']['renderTo'] = container\n", " self.options['title'] = {}\n", " self.options['title']['text'] = \"\"\n", " self.options['legend'] = {}\n", " self.options['legend']['enabled'] = False\n", " self.options['subtitle'] = {}\n", " self.options['subtitle']['text'] = \"\"\n", " self.options['series'] = []\n", " \n", " def show(self):\n", " hc(self.options)" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "html = \"\"\"
\"\"\"" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "%%brython -h html -S wrapper01\n", "\n", "plt = HC('hc_ex23')\n", "plt.show()\n", "print(plt.options)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Ok, not very exciting. We initialise with an empty dictionary of options and with the `show` method we pass the options dictionary to Highcharts and we can plot an empty chart. As stated before, not very fascinating. Let's add options to include a title and a subtitle.\n", "\n", "[HINT] The `-s` option in brythonmagic is used to name a brython cell ('wrapper01' is the name for the portion of code defined in the first cell of this section). With the name of that cell the code of the cell can be used in a new Brython cell using the `-S` option. The use of the `-S` option would be like an import of the code of the cell with the defined name ('wrapper01' in this case)." ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "%%brython -s wrapper02\n", "\n", "from browser import window\n", "\n", "Highcharts = window.Highcharts\n", "\n", "hc = Highcharts.Chart.new\n", "\n", "class HC:\n", " def __init__(self, container):\n", " self.options = {}\n", " self.options['chart'] = {}\n", " self.options['chart']['renderTo'] = container\n", " self.options['title'] = {}\n", " self.options['title']['text'] = \"\"\n", " self.options['legend'] = {}\n", " self.options['legend']['enabled'] = False\n", " self.options['subtitle'] = {}\n", " self.options['subtitle']['text'] = \"\"\n", " self.options['series'] = []\n", " \n", " def show(self):\n", " hc(self.options)\n", " \n", " def title(self, text):\n", " self.options['title']['text'] = text\n", " #self.show()\n", " \n", " def subtitle(self, text):\n", " self.options['subtitle']['text'] = text\n", " #self.show()" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "html = \"\"\"
\"\"\"" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "%%brython -h html -S wrapper02\n", "\n", "plt = HC('hc_ex24')\n", "plt.title('Dummy title')\n", "plt.subtitle('Dummy title')\n", "plt.show()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Still not very funny. If you see the two new methods added, `title` and `subtitle`, there is one line commented. We can uncomment these lines if we don't want to call the `show` method but everytime we use a method the chart will be plotted. I didn't see any overhead doing this but let's avoid it for the moment.\n", "\n", "Ok, let's do something more interesting plotting some data in a line chart." ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "%%brython -s wrapper03\n", "\n", "from browser import window\n", "\n", "Highcharts = window.Highcharts\n", "\n", "hc = Highcharts.Chart.new\n", "\n", "class HC:\n", " def __init__(self, container):\n", " self.options = {}\n", " self.options['chart'] = {}\n", " self.options['chart']['renderTo'] = container\n", " self.options['title'] = {}\n", " self.options['title']['text'] = \"\"\n", " self.options['legend'] = {}\n", " self.options['legend']['enabled'] = False\n", " self.options['subtitle'] = {}\n", " self.options['subtitle']['text'] = \"\"\n", " self.options['series'] = []\n", " \n", " def show(self):\n", " hc(self.options)\n", " \n", " def title(self, text):\n", " self.options['title']['text'] = text\n", " #self.draw()\n", " \n", " def subtitle(self, text):\n", " self.options['subtitle']['text'] = text\n", " #self.draw()\n", " \n", " def plot(self, x, y = None, label = None, color = None, linewidth = None):\n", " if y:\n", " data = [[i, j] for i, j in zip(x, y)]\n", " else:\n", " data = x\n", " serie = {'data': data, 'type': 'line'}\n", " if linewidth:\n", " serie['lineWidth'] = linewidth\n", " if label:\n", " serie['name'] = label\n", " if color:\n", " serie['color'] = color\n", " self.options['series'].append(serie)\n", " #self.draw()" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "html = \"\"\"
\"\"\"" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "%%brython -h html -S wrapper03\n", "\n", "plt = HC('hc_ex25')\n", "plt.plot([1,2,4,5], [3,6,4,7], label = 'lineplot1', linewidth = 5, color = 'red')\n", "plt.plot([1,2,4,5], [8,5,9,2], label = 'lineplot2', linewidth = 2, color = 'blue')\n", "plt.title('Some line plots')\n", "plt.show()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Wow!!, with less than 40 lines of Brython code we have a wrapper to do very simple interactive charts using Highcharts in a pythonic way. We added the `label` keyword in the `plot` method. In Matplotlib, the `label` is used by the legend in the case we want to add a legend. Let's add a `legend` method to provide the `label` keyword some utility." ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "%%brython -s wrapper04\n", "\n", "from browser import window\n", "\n", "Highcharts = window.Highcharts\n", "\n", "hc = Highcharts.Chart.new\n", "\n", "class HC:\n", " def __init__(self, container):\n", " self.options = {}\n", " self.options['chart'] = {}\n", " self.options['chart']['renderTo'] = container\n", " self.options['title'] = {}\n", " self.options['title']['text'] = \"\"\n", " self.options['legend'] = {}\n", " self.options['legend']['enabled'] = False\n", " self.options['subtitle'] = {}\n", " self.options['subtitle']['text'] = \"\"\n", " self.options['series'] = []\n", " \n", " def show(self):\n", " hc(self.options)\n", " \n", " def title(self, text):\n", " self.options['title']['text'] = text\n", " #self.draw()\n", " \n", " def subtitle(self, text):\n", " self.options['subtitle']['text'] = text\n", " #self.draw()\n", " \n", " def plot(self, x, y = None, label = None, color = None, linewidth = None):\n", " if y:\n", " data = [[i, j] for i, j in zip(x, y)]\n", " else:\n", " data = x\n", " serie = {'data': data, 'type': 'line'}\n", " if linewidth:\n", " serie['lineWidth'] = linewidth\n", " if label:\n", " serie['name'] = label\n", " if color:\n", " serie['color'] = color\n", " self.options['series'].append(serie)\n", " #self.draw()\n", " \n", " def legend(self, loc = 'right'):\n", " self.options['legend']['enabled'] = True\n", " if loc:\n", " self.options['legend']['align'] = loc\n", " #self.draw()\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "html = \"\"\"
\"\"\"" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "%%brython -h html -S wrapper04\n", "\n", "plt = HC('hc_ex26')\n", "plt.title('Line plots')\n", "plt.plot([1,2,4,5], [3,6,4,7], label = 'lineplot1', linewidth = 5, color = 'red')\n", "plt.plot([1,2,4,5], [8,5,9,2], label = 'lineplot2', linewidth = 2, color = 'blue')\n", "plt.legend(loc = 'left')\n", "plt.show()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The behaviour is not similar to that in the pyplot module of the matplotlib library but we can get some basic functionality. We can add a `scatter` method to combine line plots with scatter plots." ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "%%brython -s wrapper05\n", "\n", "from browser import window\n", "\n", "Highcharts = window.Highcharts\n", "\n", "hc = Highcharts.Chart.new\n", "\n", "class HC:\n", " def __init__(self, container):\n", " self.options = {}\n", " self.options['chart'] = {}\n", " self.options['chart']['renderTo'] = container\n", " self.options['title'] = {}\n", " self.options['title']['text'] = \"\"\n", " self.options['legend'] = {}\n", " self.options['legend']['enabled'] = False\n", " self.options['subtitle'] = {}\n", " self.options['subtitle']['text'] = \"\"\n", " self.options['series'] = []\n", " \n", " def show(self):\n", " hc(self.options)\n", " \n", " def title(self, text):\n", " self.options['title']['text'] = text\n", " #self.draw()\n", " \n", " def subtitle(self, text):\n", " self.options['subtitle']['text'] = text\n", " #self.draw()\n", " \n", " def plot(self, x, y = None, label = None, color = None, linewidth = None):\n", " if y:\n", " data = [[i, j] for i, j in zip(x, y)]\n", " else:\n", " data = x\n", " serie = {'data': data, 'type': 'line'}\n", " if linewidth:\n", " serie['lineWidth'] = linewidth\n", " if label:\n", " serie['name'] = label\n", " if color:\n", " serie['color'] = color\n", " self.options['series'].append(serie)\n", " #self.draw()\n", " \n", " def legend(self, loc = 'right'):\n", " self.options['legend']['enabled'] = True\n", " if loc:\n", " self.options['legend']['align'] = loc\n", " #self.draw()\n", " \n", " def scatter(self, x, y, label = None, color = None):\n", " data = [[i, j] for i, j in zip(x, y)]\n", " serie = {'data': data, 'type': 'scatter'}\n", " if label:\n", " serie['name'] = label\n", " if color:\n", " serie['color'] = color\n", " self.options['series'].append(serie)\n", " #self.draw()" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "html = \"\"\"
\"\"\"" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "%%brython -h html -S wrapper05\n", "\n", "plt = HC('hc_ex27')\n", "plt.title('Line plots')\n", "plt.plot([1,2,4,5], [3,6,4,7], label = 'lineplot1', linewidth = 5, color = 'red')\n", "plt.plot([1,2,4,5], [8,5,9,2], label = 'lineplot2', linewidth = 2, color = 'blue')\n", "plt.scatter([1,2,4,5], [2,4,6,8], label = 'scatter1', color = 'green')\n", "plt.legend(loc = 'left')\n", "plt.show()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Let's stop here the wrapper." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# More than Highcharts!!!" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "You can use [Highstock](http://www.highcharts.com/products/highstock) to create beautiful and interactive time series visualisation. You can create very simple maps using [Highmaps](http://www.highcharts.com/products/highmaps) or check out the [notebook about OpenLayers 2.x](https://github.com/kikocorreoso/brythonmagic/blob/master/notebooks/OpenLayers%20%28python%29%20tutorial.ipynb) we made some time ago." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "If you do something with this information and/or need some help just let me know about it opening an issue in the [repo where this notebook is stored](https://github.com/kikocorreoso/brythonmagic/)." ] } ], "metadata": { "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.5.2" } }, "nbformat": 4, "nbformat_minor": 0 }