{ "metadata": { "name": "" }, "nbformat": 3, "nbformat_minor": 0, "worksheets": [ { "cells": [ { "cell_type": "heading", "level": 2, "metadata": {}, "source": [ "Warning!" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "This example notebook is not up-to-date with the latest version of Plotly's Python API (version 1.0.\\*). \n", "\n", "Refer to Plotly's Python [User Guide](http://nbviewer.ipython.org/github/plotly/python-user-guide/blob/master/s00_homepage/s00_homepage.ipynb) \n", "and more specifically [section 7.2](http://nbviewer.ipython.org/github/plotly/python-user-guide/blob/master/s7_streaming/s7_streaming_p2-double-pendulum.ipynb) for an updated version of this notebook.\n", "\n", "
" ] }, { "cell_type": "heading", "level": 3, "metadata": {}, "source": [ "Graphing the Double Pendulum Trajectory
\n", "with Plotly's Real-time Streaming API" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Plotly's Streaming API enables your plotly graphs to update in real-time, without refreshing your browser.\n", "\n", "All viewers of the graph see the same data, at the same time.\n", "\n", "Learn more about real-time streaming graphs with plotly here:\n", "\n", "[https://github.com/plotly/streaming-demos](https://github.com/plotly/streaming-demos)" ] }, { "cell_type": "code", "collapsed": false, "input": [ "import plotly\n", "import time\n", "import json\n", "import math\n", "from numpy import sin, cos, pi, array\n", "import numpy as np\n", "import scipy.integrate as integrate" ], "language": "python", "metadata": {}, "outputs": [], "prompt_number": 1 }, { "cell_type": "code", "collapsed": false, "input": [ "# Fill in the config.json file in this directory with your plotly username, \n", "# plotly API key, and your generated plotly streaming tokens\n", "# Sign up to plotly here: https://plot.ly/ssu\n", "# View your API key and streaming tokens here: https://plot.ly/settings\n", "\n", "with open('./config.json') as config_file:\n", " plotly_user_config = json.load(config_file)\n", "\n", "username = \"Streaming-Demos\" # plotly_user_config['plotly_username'] \n", "api_key = plotly_user_config['plotly_api_key']\n", "stream_tokens = plotly_user_config['plotly_streaming_tokens']" ], "language": "python", "metadata": {}, "outputs": [], "prompt_number": 2 }, { "cell_type": "code", "collapsed": false, "input": [ "# Initialize your plotly object\n", "p = plotly.plotly(username, api_key)" ], "language": "python", "metadata": {}, "outputs": [], "prompt_number": 3 }, { "cell_type": "code", "collapsed": false, "input": [ "# Define the Double Pendulum state equations and parameters\n", "# Code adapted from http://matplotlib.org/examples/animation/double_pendulum_animated.html (Thx!)\n", "\n", "G = 9.8 # acceleration due to gravity, in m/s^2\n", "L1 = 1.0 # length of pendulum 1 in m\n", "L2 = 1.0 # length of pendulum 2 in m\n", "M1 = 1.0 # mass of pendulum 1 in kg\n", "M2 = 1.0 # mass of pendulum 2 in kg\n", "\n", "\n", "def derivs(state, t):\n", "\n", " dydx = np.zeros_like(state)\n", " dydx[0] = state[1]\n", "\n", " del_ = state[2]-state[0]\n", " den1 = (M1+M2)*L1 - M2*L1*cos(del_)*cos(del_)\n", " dydx[1] = (M2*L1*state[1]*state[1]*sin(del_)*cos(del_)\n", " + M2*G*sin(state[2])*cos(del_) + M2*L2*state[3]*state[3]*sin(del_)\n", " - (M1+M2)*G*sin(state[0]))/den1\n", "\n", " dydx[2] = state[3]\n", "\n", " den2 = (L2/L1)*den1\n", " dydx[3] = (-M2*L2*state[3]*state[3]*sin(del_)*cos(del_)\n", " + (M1+M2)*G*sin(state[0])*cos(del_)\n", " - (M1+M2)*L1*state[1]*state[1]*sin(del_)\n", " - (M1+M2)*G*sin(state[2]))/den2\n", "\n", " return dydx\n", "\n", "# th1 and th2 are the initial angles (degrees)\n", "# w10 and w20 are the initial angular velocities (degrees per second)\n", "th1 = 120.0\n", "w1 = 0.0\n", "th2 = -10.0\n", "w2 = 0.0\n", "\n", "rad = pi/180" ], "language": "python", "metadata": {}, "outputs": [], "prompt_number": 4 }, { "cell_type": "code", "collapsed": false, "input": [ "# Initialize your plotly real-time streaming graph with a REST API call\n", "# Embed your stream token in one of the traces of a plotly-data object - one token per trace\n", "# Also embed 'maxpoints', the number of points that you want plotted at a time\n", "\n", "# The `iplot` command will embed our plotly graph as an iframe in this notebook\n", "# Each plotly graph has a unique url that you can share \n", "# Anyone can view your streaming graph in real-time - \n", "# viewers see the same data at the same time \n", "# (try it! Open up this notebook up in two different browser windows and observer\n", "# that the graphs are plotting identical data!)\n", "\n", "# The unique URL for this graph is https://plot.ly/~streaming-demos/4\n", "\n", "def axes(range):\n", " return {\n", " \"autotick\" : True,\n", " \"showgrid\" : False,\n", " \"showline\" : False,\n", " \"zeroline\" : False,\n", " \"ticks\": '', \n", " \"range\": range\n", " }\n", "p.iplot([\n", " {\n", " 'x': [], \n", " 'y': [], \n", " 'type': 'scatter', \n", " 'mode': 'lines+markers', \n", " 'line': {\n", " 'opacity': 0.8\n", " },\n", " 'marker': {\n", " 'size': 12\n", " },\n", " 'stream': {\n", " 'token': stream_tokens[4], \n", " }\n", " },\n", " {\n", " 'x': [], \n", " 'y': [], \n", " 'type': 'scatter', \n", " 'mode': 'lines', \n", " 'line': {\n", " 'color': 'rgba(31, 119, 180, 0.15)'\n", " },\n", " 'stream': {\n", " 'token': stream_tokens[5], \n", " 'maxpoints': 100\n", " }\n", " }],\n", " layout = {\n", " 'xaxis': axes([-2, 2]), \n", " 'yaxis': axes([-2, 0.5]), \n", " 'title': 'Double Pendulum Simulation',\n", " 'showlegend': False\n", " },\n", " filename='streaming double pendulum', fileopt='overwrite')" ], "language": "python", "metadata": {}, "outputs": [ { "html": [ "" ], "metadata": {}, "output_type": "pyout", "prompt_number": 5, "text": [ "" ] } ], "prompt_number": 5 }, { "cell_type": "code", "collapsed": false, "input": [ "# Now stream data to this plot!\n", "# Write to a plotly stream with plotly-formatted data\n", "# In this case, we'll continually integrate the double pendulum equations 20 points a time, \n", "# and write the solution, one point at a time\n", "\n", "# Our plotly-object is formatted as: {'x': x_data, 'y': y_data}\n", "\n", "s0 = plotly.stream(stream_tokens[4])\n", "s1 = plotly.stream(stream_tokens[5])\n", "state = np.array([th1, w1, th2, w2])*pi/180.\n", "while True:\n", " # create a time array from 0..100 sampled at 0.1 second steps\n", " dt = 0.05\n", " t = np.arange(0.0, 20, dt)\n", " # solve!\n", " y = integrate.odeint(derivs, state, t)\n", " x1 = L1*sin(y[:,0])\n", " y1 = -L1*cos(y[:,0])\n", " x2 = L2*sin(y[:,2]) + x1\n", " y2 = -L2*cos(y[:,2]) + y1\n", " # Write the solution to plotly's servers, one point at a time\n", " for (x1i, y1i, x2i, y2i) in zip(x1, y1, x2, y2):\n", " s0.write({'x': [0, x1i, x2i], 'y': [0, y1i, y2i]})\n", " s1.write({'x': x2i, 'y': y2i})\n", " time.sleep(0.08) # plot points 80 ms at a time\n", "\n", " # Set the new initial state\n", " state = np.array([y[-1,0], y[-1, 1], y[-1, 2], y[-1, 3]])" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "code", "collapsed": false, "input": [ "# When you're done, close your stream!\n", "s.close()" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Give it a try yourself!\n", "\n", "##### More Streaming IPython Notebooks:\n", "\n", "[http://nbviewer.ipython.org/github/plotly/Streaming-Demos/tree/master/IPython%20examples/](http://nbviewer.ipython.org/github/plotly/Streaming-Demos/tree/master/IPython%20examples/)\n", "\n", "##### More about Plotly Streaming \n", "\n", "[https://github.com/plotly/Streaming-Demos](https://github.com/plotly/Streaming-Demos)\n", "\n", "##### Get in touch!\n", "\n", "[http://twitter.com/plotlygraphs](@plotlygraphs)\n", "\n", "[https://facebook.com/plotly](https://facebook.com/plotly)\n", "\n", "" ] }, { "cell_type": "code", "collapsed": false, "input": [ "# CSS styling within IPython notebook\n", "from IPython.core.display import HTML\n", "import urllib2\n", "def css_styling():\n", " url = 'https://raw.githubusercontent.com/plotly/python-user-guide/master/custom.css'\n", " styles = urllib2.urlopen(url).read()\n", " return HTML(styles)\n", "\n", "css_styling()" ], "language": "python", "metadata": {}, "outputs": [ { "html": [ "\n", "\n" ], "metadata": {}, "output_type": "pyout", "prompt_number": 2, "text": [ "" ] } ], "prompt_number": 2 }, { "cell_type": "code", "collapsed": false, "input": [], "language": "python", "metadata": {}, "outputs": [] } ], "metadata": {} } ] }