{ "metadata": { "name": "" }, "nbformat": 3, "nbformat_minor": 0, "worksheets": [ { "cells": [ { "cell_type": "code", "collapsed": false, "input": [ "take_screenshots = True" ], "language": "python", "metadata": {}, "outputs": [], "prompt_number": 1 }, { "cell_type": "code", "collapsed": false, "input": [ "%pylab wx\n", "if take_screenshots:\n", " %pylab inline\n", " rcParams['figure.figsize'] = (8.0, 8.0)" ], "language": "python", "metadata": {}, "outputs": [ { "output_type": "stream", "stream": "stdout", "text": [ "Populating the interactive namespace from numpy and matplotlib\n", "Populating the interactive namespace from numpy and matplotlib" ] }, { "output_type": "stream", "stream": "stdout", "text": [ "\n" ] } ], "prompt_number": 2 }, { "cell_type": "code", "collapsed": false, "input": [ "from mayavi import mlab\n", "\n", "ocean_blue = (0.4, 0.5, 1.0)\n", "yellow = (1.0, 1.0, 0.0)\n", "\n", "start_date = (2013, 1, 11, 15, 45, 0)" ], "language": "python", "metadata": {}, "outputs": [], "prompt_number": 3 }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Load earth satellite database\n", "\n", "We use the `sgp4` Python library\n", "to interpret CelesTrak two-line orbital element entries from a text file." ] }, { "cell_type": "code", "collapsed": false, "input": [ "from skyfield.api import JulianDate, earth, now" ], "language": "python", "metadata": {}, "outputs": [], "prompt_number": 4 }, { "cell_type": "code", "collapsed": false, "input": [ "def find_satellites(lines, earth=earth):\n", " \"\"\"Yield up satellites found in a sequence of text lines.\n", "\n", " Each item yielded is a tuple ``('name', satellite)`` or\n", " ``(None, satellite)`` if the satellite TLE entry does not\n", " appear to have been preceded by a name on the line above.\n", "\n", " \"\"\"\n", " line0 = line1 = None\n", " for line2 in lines:\n", " line2 = line2.rstrip('\\r\\n')\n", " if (line1 and line1.startswith('1 ')\n", " and line2.startswith('2 ')\n", " and len(line1) == len(line2) == 69):\n", " if line0 and len(line0) == 24:\n", " name = line0.strip()\n", " else:\n", " name = None\n", " sat = earth.satellite(line1 + '\\n' + line2)\n", " yield name, sat\n", " line0 = line1\n", " line1 = line2" ], "language": "python", "metadata": {}, "outputs": [], "prompt_number": 5 }, { "cell_type": "code", "collapsed": false, "input": [ "with open('data/visual.txt') as lines:\n", " names, satellites = zip(*find_satellites(lines))\n", "\n", "print 'Successfully loaded', len(satellites), 'satellites'" ], "language": "python", "metadata": {}, "outputs": [ { "output_type": "stream", "stream": "stdout", "text": [ "Successfully loaded 145 satellites\n" ] } ], "prompt_number": 6 }, { "cell_type": "code", "collapsed": false, "input": [ "from sgp4.earth_gravity import wgs72\n", "r = wgs72.radiusearthkm\n", "\n", "class Geocenter(object):\n", " \"\"\"Coordinates of the geocenter.\"\"\"\n", " rGCRS = array([0, 0, 0])\n", " vGCRS = array([0, 0, 0])\n", " \n", "geocenter = Geocenter()\n", "geocenter.jd = now()" ], "language": "python", "metadata": {}, "outputs": [], "prompt_number": 7 }, { "cell_type": "code", "collapsed": false, "input": [ "def positions_at(jd):\n", " geocenter.jd = jd\n", " positions = []\n", " for sat in satellites:\n", " try:\n", " position = sat.observe_from(geocenter).position.km\n", " except TypeError:\n", " pass\n", " else:\n", " positions.append(position)\n", " return array(positions).T" ], "language": "python", "metadata": {}, "outputs": [], "prompt_number": 8 }, { "cell_type": "code", "collapsed": false, "input": [ "tt0 = now().tt\n", "minute = 1.0 / 24.0 / 60.0\n", "second = minute / 60.0\n", "jd = JulianDate(tt=arange(tt0, tt0 + 2 * minute, second * 5))\n", "print jd.shape" ], "language": "python", "metadata": {}, "outputs": [ { "output_type": "stream", "stream": "stdout", "text": [ "(24,)\n" ] } ], "prompt_number": 9 }, { "cell_type": "code", "collapsed": false, "input": [ "position_list = []\n", "\n", "for tt in jd.tt:\n", " position_list.append(positions_at(JulianDate(tt=tt)))" ], "language": "python", "metadata": {}, "outputs": [], "prompt_number": 10 }, { "cell_type": "markdown", "metadata": {}, "source": [ "## A simple animation\n", "\n", "The simplest possible satellite display\n", "uses a single `mlab.points3d` call\n", "to set up a graphics pipeline." ] }, { "cell_type": "code", "collapsed": false, "input": [ "from tvtk.api import tvtk\n", "style = tvtk.InteractorStyleTerrain()\n", "fig = mlab.gcf()\n", "fig.scene.interactor.interactor_style = style\n", "mlab.clf()" ], "language": "python", "metadata": {}, "outputs": [], "prompt_number": 11 }, { "cell_type": "code", "collapsed": false, "input": [ "def recenter():\n", " mlab.view(distance=3e4, focalpoint=(0.0, 0.0, 0.0))\n", " if take_screenshots:\n", " imshow(mlab.screenshot(antialiased=True))\n", " axis('off')" ], "language": "python", "metadata": {}, "outputs": [], "prompt_number": 12 }, { "cell_type": "code", "collapsed": false, "input": [ "from mayavi.sources.builtin_surface import BuiltinSurface\n", "\n", "def draw_globe():\n", " sphere = mlab.points3d(0, 0, 0, name='Globe',\n", " scale_mode='none', scale_factor=r * 2.0,\n", " color=ocean_blue, resolution=50)\n", "\n", " sphere.actor.property.specular = 0.20\n", " sphere.actor.property.specular_power = 10\n", "\n", " continents_src = BuiltinSurface(\n", " source='earth', name='Continents')\n", " continents_src.data_source.on_ratio = 1 # detail level\n", " continents_src.data_source.radius = r\n", " continents = mlab.pipeline.surface(\n", " continents_src, color=(0, 0, 0))" ], "language": "python", "metadata": {}, "outputs": [], "prompt_number": 13 }, { "cell_type": "code", "collapsed": false, "input": [ "draw_globe()\n", "recenter()" ], "language": "python", "metadata": {}, "outputs": [ { "metadata": {}, "output_type": "display_data", "png": "iVBORw0KGgoAAAANSUhEUgAAAeIAAAGICAYAAACdhuOfAAAABHNCSVQICAgIfAhkiAAAAAlwSFlz\nAAALEgAACxIB0t1+/AAABh9JREFUeJzt3LENgEAMBEGMvv+WTQXEi8RMA/fZysnP7u4FACTu+gEA\n8GdCDAAhIQaAkBADQEiIASAkxAAQEmIACAkxAISEGABCQgwAoVOMzkwxCwCZtx+lXcQAEBJiAAgJ\nMQCEhBgAQkIMACEhBoCQEANASIgBICTEABASYgAICTEAhIQYAEJCDAAhIQaAkBADQEiIASAkxAAQ\nEmIACAkxAISEGABCQgwAISEGgJAQA0BIiAEgJMQAEBJiAAgJMQCEhBgAQkIMACEhBoCQEANASIgB\nICTEABASYgAICTEAhIQYAEJCDAAhIQaAkBADQEiIASAkxAAQEmIACAkxAISEGABCQgwAISEGgJAQ\nA0BIiAEgJMQAEBJiAAgJMQCEhBgAQkIMACEhBoCQEANASIgBICTEABASYgAICTEAhIQYAEJCDAAh\nIQaAkBADQEiIASAkxAAQEmIACAkxAISEGABCQgwAISEGgJAQA0BIiAEgJMQAEBJiAAgJMQCEhBgA\nQkIMACEhBoCQEANASIgBICTEABASYgAICTEAhIQYAEJCDAAhIQaAkBADQEiIASAkxAAQEmIACAkx\nAISEGABCQgwAISEGgJAQA0BIiAEgJMQAEBJiAAgJMQCEhBgAQkIMACEhBoCQEANASIgBICTEABAS\nYgAICTEAhIQYAEJCDAAhIQaAkBADQEiIASAkxAAQEmIACAkxAISEGABCQgwAISEGgJAQA0BIiAEg\nJMQAEBJiAAgJMQCEhBgAQkIMACEhBoCQEANASIgBICTEABASYgAICTEAhIQYAEJCDAAhIQaAkBAD\nQEiIASAkxAAQEmIACAkxAISEGABCQgwAISEGgJAQA0BIiAEgJMQAEBJiAAgJMQCEhBgAQkIMACEh\nBoCQEANASIgBICTEABASYgAICTEAhIQYAEJCDAAhIQaAkBADQEiIASAkxAAQEmIACAkxAISEGABC\nQgwAISEGgJAQA0BIiAEgJMQAEBJiAAgJMQCEhBgAQkIMACEhBoCQEANASIgBICTEABASYgAICTEA\nhIQYAEJCDAAhIQaAkBADQEiIASAkxAAQEmIACAkxAISEGABCQgwAISEGgJAQA0BIiAEgJMQAEBJi\nAAgJMQCEhBgAQkIMACEhBoCQEANASIgBICTEABASYgAICTEAhIQYAEJCDAAhIQaAkBADQEiIASAk\nxAAQEmIACAkxAISEGABCQgwAISEGgJAQA0BIiAEgJMQAEBJiAAgJMQCEhBgAQkIMACEhBoCQEANA\nSIgBICTEABASYgAICTEAhIQYAEJCDAAhIQaAkBADQEiIASAkxAAQEmIACAkxAISEGABCQgwAISEG\ngJAQA0BIiAEgJMQAEBJiAAgJMQCEhBgAQkIMACEhBoCQEANASIgBICTEABASYgAICTEAhIQYAEJC\nDAAhIQaAkBADQEiIASAkxAAQEmIACAkxAISEGABCQgwAISEGgJAQA0BIiAEgJMQAEBJiAAgJMQCE\nhBgAQkIMACEhBoCQEANASIgBICTEABASYgAICTEAhIQYAEJCDAAhIQaAkBADQEiIASAkxAAQEmIA\nCAkxAISEGABCQgwAISEGgJAQA0BIiAEgJMQAEBJiAAgJMQCEhBgAQkIMACEhBoCQEANASIgBICTE\nABASYgAICTEAhIQYAEJCDAAhIQaAkBADQEiIASAkxAAQEmIACAkxAISEGABCQgwAISEGgJAQA0BI\niAEgJMQAEBJiAAgJMQCEhBgAQkIMACEhBoCQEANASIgBICTEABASYgAICTEAhIQYAEJCDAAhIQaA\nkBADQEiIASAkxAAQEmIACAkxAISEGABCQgwAISEGgJAQA0BIiAEgJMQAEBJiAAgJMQCEhBgAQkIM\nACEhBoCQEANASIgBICTEABASYgAICTEAhIQYAEJCDAAhIQaAkBADQEiIASAkxAAQEmIACAkxAISE\nGABCQgwAISEGgJAQA0DoFKO7W8wCwOe4iAEgJMQAEBJiAAgJMQCEhBgAQkIMACEhBoCQEANASIgB\nICTEABASYgAICTEAhIQYAEJCDAAhIQaAkBADQEiIASAkxAAQEmIACAkxAIQe1sMNDRInXCEAAAAA\nSUVORK5CYII=\n", "text": [ "" ] } ], "prompt_number": 14 }, { "cell_type": "code", "collapsed": false, "input": [ "x, y, z = position_list[0]\n", "\n", "points_glyph = mlab.points3d(\n", " x, y, z, x * 0.0 + 0.01,\n", " mode='sphere', color=(1.0, 1.0, 0.8),\n", " scale_mode='scalar', scale_factor=30000.0)\n", "\n", "recenter()" ], "language": "python", "metadata": {}, "outputs": [ { "metadata": {}, "output_type": "display_data", "png": "iVBORw0KGgoAAAANSUhEUgAAAeIAAAGICAYAAACdhuOfAAAABHNCSVQICAgIfAhkiAAAAAlwSFlz\nAAALEgAACxIB0t1+/AAABh9JREFUeJzt3LENgEAMBEGMvv+WTQXEi8RMA/fZysnP7u4FACTu+gEA\n8GdCDAAhIQaAkBADQEiIASAkxAAQEmIACAkxAISEGABCQgwAoVOMzkwxCwCZtx+lXcQAEBJiAAgJ\nMQCEhBgAQkIMACEhBoCQEANASIgBICTEABASYgAICTEAhIQYAEJCDAAhIQaAkBADQEiIASAkxAAQ\nEmIACAkxAISEGABCQgwAISEGgJAQA0BIiAEgJMQAEBJiAAgJMQCEhBgAQkIMACEhBoCQEANASIgB\nICTEABASYgAICTEAhIQYAEJCDAAhIQaAkBADQEiIASAkxAAQEmIACAkxAISEGABCQgwAISEGgJAQ\nA0BIiAEgJMQAEBJiAAgJMQCEhBgAQkIMACEhBoCQEANASIgBICTEABASYgAICTEAhIQYAEJCDAAh\nIQaAkBADQEiIASAkxAAQEmIACAkxAISEGABCQgwAISEGgJAQA0BIiAEgJMQAEBJiAAgJMQCEhBgA\nQkIMACEhBoCQEANASIgBICTEABASYgAICTEAhIQYAEJCDAAhIQaAkBADQEiIASAkxAAQEmIACAkx\nAISEGABCQgwAISEGgJAQA0BIiAEgJMQAEBJiAAgJMQCEhBgAQkIMACEhBoCQEANASIgBICTEABAS\nYgAICTEAhIQYAEJCDAAhIQaAkBADQEiIASAkxAAQEmIACAkxAISEGABCQgwAISEGgJAQA0BIiAEg\nJMQAEBJiAAgJMQCEhBgAQkIMACEhBoCQEANASIgBICTEABASYgAICTEAhIQYAEJCDAAhIQaAkBAD\nQEiIASAkxAAQEmIACAkxAISEGABCQgwAISEGgJAQA0BIiAEgJMQAEBJiAAgJMQCEhBgAQkIMACEh\nBoCQEANASIgBICTEABASYgAICTEAhIQYAEJCDAAhIQaAkBADQEiIASAkxAAQEmIACAkxAISEGABC\nQgwAISEGgJAQA0BIiAEgJMQAEBJiAAgJMQCEhBgAQkIMACEhBoCQEANASIgBICTEABASYgAICTEA\nhIQYAEJCDAAhIQaAkBADQEiIASAkxAAQEmIACAkxAISEGABCQgwAISEGgJAQA0BIiAEgJMQAEBJi\nAAgJMQCEhBgAQkIMACEhBoCQEANASIgBICTEABASYgAICTEAhIQYAEJCDAAhIQaAkBADQEiIASAk\nxAAQEmIACAkxAISEGABCQgwAISEGgJAQA0BIiAEgJMQAEBJiAAgJMQCEhBgAQkIMACEhBoCQEANA\nSIgBICTEABASYgAICTEAhIQYAEJCDAAhIQaAkBADQEiIASAkxAAQEmIACAkxAISEGABCQgwAISEG\ngJAQA0BIiAEgJMQAEBJiAAgJMQCEhBgAQkIMACEhBoCQEANASIgBICTEABASYgAICTEAhIQYAEJC\nDAAhIQaAkBADQEiIASAkxAAQEmIACAkxAISEGABCQgwAISEGgJAQA0BIiAEgJMQAEBJiAAgJMQCE\nhBgAQkIMACEhBoCQEANASIgBICTEABASYgAICTEAhIQYAEJCDAAhIQaAkBADQEiIASAkxAAQEmIA\nCAkxAISEGABCQgwAISEGgJAQA0BIiAEgJMQAEBJiAAgJMQCEhBgAQkIMACEhBoCQEANASIgBICTE\nABASYgAICTEAhIQYAEJCDAAhIQaAkBADQEiIASAkxAAQEmIACAkxAISEGABCQgwAISEGgJAQA0BI\niAEgJMQAEBJiAAgJMQCEhBgAQkIMACEhBoCQEANASIgBICTEABASYgAICTEAhIQYAEJCDAAhIQaA\nkBADQEiIASAkxAAQEmIACAkxAISEGABCQgwAISEGgJAQA0BIiAEgJMQAEBJiAAgJMQCEhBgAQkIM\nACEhBoCQEANASIgBICTEABASYgAICTEAhIQYAEJCDAAhIQaAkBADQEiIASAkxAAQEmIACAkxAISE\nGABCQgwAISEGgJAQA0DoFKO7W8wCwOe4iAEgJMQAEBJiAAgJMQCEhBgAQkIMACEhBoCQEANASIgB\nICTEABASYgAICTEAhIQYAEJCDAAhIQaAkBADQEiIASAkxAAQEmIACAkxAIQe1sMNDRInXCEAAAAA\nSUVORK5CYII=\n", "text": [ "" ] } ], "prompt_number": 15 }, { "cell_type": "markdown", "metadata": {}, "source": [ "One can interact with (that is, navigate in) the Mayavi window with mouse and keyboard as documented on the [Using the Mayavi application](http://docs.enthought.com/mayavi/mayavi/application.html#interaction-with-the-scene) web page. " ] }, { "cell_type": "code", "collapsed": false, "input": [ "for position in position_list:\n", " x, y, z = position\n", " radius = x * 0.0 + 0.01\n", " points_glyph.mlab_source.set(x=x, y=y, z=z, s=radius)" ], "language": "python", "metadata": {}, "outputs": [], "prompt_number": 16 }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Add stalks\n", "\n", "This makes it easier to see the altitude of each satellite." ] }, { "cell_type": "code", "collapsed": false, "input": [ "# Compute `distance` of each satellite\n", "# from the center of the earth.\n", "\n", "distance = np.sqrt((position * position).sum(axis=0))\n", "xb, yb, zb = position / distance * r\n", "\n", "print 'Satellite #0 is', distance[0], 'km from the geocenter'\n", "print 'The base of its stalk will be at:'\n", "print xb[0], yb[0], zb[0]" ], "language": "python", "metadata": {}, "outputs": [ { "output_type": "stream", "stream": "stdout", "text": [ "Satellite #0 is 6836.24046832 km from the geocenter\n", "The base of its stalk will be at:\n", "-2098.28789652 -5835.13265204 1492.9905943\n" ] } ], "prompt_number": 17 }, { "cell_type": "code", "collapsed": false, "input": [ "x, y, z = position\n", "\n", "src = mlab.pipeline.scalar_scatter(\n", " np.hstack([xb, x]),\n", " np.hstack([yb, y]),\n", " np.hstack([zb, z]),\n", " )\n", "\n", "src.mlab_source.dataset.lines = np.array([\n", " [i, i + len(x)] for i in range(len(x))\n", " ])\n", "\n", "# The stripper filter cleans up connected lines\n", "lines = mlab.pipeline.stripper(src)\n", "\n", "# Finally, display the set of lines\n", "mlab.pipeline.surface(lines, color=yellow, line_width=3,\n", " opacity=0.4)\n", "\n", "recenter()" ], "language": "python", "metadata": {}, "outputs": [ { "metadata": {}, "output_type": "display_data", "png": "iVBORw0KGgoAAAANSUhEUgAAAeIAAAGICAYAAACdhuOfAAAABHNCSVQICAgIfAhkiAAAAAlwSFlz\nAAALEgAACxIB0t1+/AAABh9JREFUeJzt3LENgEAMBEGMvv+WTQXEi8RMA/fZysnP7u4FACTu+gEA\n8GdCDAAhIQaAkBADQEiIASAkxAAQEmIACAkxAISEGABCQgwAoVOMzkwxCwCZtx+lXcQAEBJiAAgJ\nMQCEhBgAQkIMACEhBoCQEANASIgBICTEABASYgAICTEAhIQYAEJCDAAhIQaAkBADQEiIASAkxAAQ\nEmIACAkxAISEGABCQgwAISEGgJAQA0BIiAEgJMQAEBJiAAgJMQCEhBgAQkIMACEhBoCQEANASIgB\nICTEABASYgAICTEAhIQYAEJCDAAhIQaAkBADQEiIASAkxAAQEmIACAkxAISEGABCQgwAISEGgJAQ\nA0BIiAEgJMQAEBJiAAgJMQCEhBgAQkIMACEhBoCQEANASIgBICTEABASYgAICTEAhIQYAEJCDAAh\nIQaAkBADQEiIASAkxAAQEmIACAkxAISEGABCQgwAISEGgJAQA0BIiAEgJMQAEBJiAAgJMQCEhBgA\nQkIMACEhBoCQEANASIgBICTEABASYgAICTEAhIQYAEJCDAAhIQaAkBADQEiIASAkxAAQEmIACAkx\nAISEGABCQgwAISEGgJAQA0BIiAEgJMQAEBJiAAgJMQCEhBgAQkIMACEhBoCQEANASIgBICTEABAS\nYgAICTEAhIQYAEJCDAAhIQaAkBADQEiIASAkxAAQEmIACAkxAISEGABCQgwAISEGgJAQA0BIiAEg\nJMQAEBJiAAgJMQCEhBgAQkIMACEhBoCQEANASIgBICTEABASYgAICTEAhIQYAEJCDAAhIQaAkBAD\nQEiIASAkxAAQEmIACAkxAISEGABCQgwAISEGgJAQA0BIiAEgJMQAEBJiAAgJMQCEhBgAQkIMACEh\nBoCQEANASIgBICTEABASYgAICTEAhIQYAEJCDAAhIQaAkBADQEiIASAkxAAQEmIACAkxAISEGABC\nQgwAISEGgJAQA0BIiAEgJMQAEBJiAAgJMQCEhBgAQkIMACEhBoCQEANASIgBICTEABASYgAICTEA\nhIQYAEJCDAAhIQaAkBADQEiIASAkxAAQEmIACAkxAISEGABCQgwAISEGgJAQA0BIiAEgJMQAEBJi\nAAgJMQCEhBgAQkIMACEhBoCQEANASIgBICTEABASYgAICTEAhIQYAEJCDAAhIQaAkBADQEiIASAk\nxAAQEmIACAkxAISEGABCQgwAISEGgJAQA0BIiAEgJMQAEBJiAAgJMQCEhBgAQkIMACEhBoCQEANA\nSIgBICTEABASYgAICTEAhIQYAEJCDAAhIQaAkBADQEiIASAkxAAQEmIACAkxAISEGABCQgwAISEG\ngJAQA0BIiAEgJMQAEBJiAAgJMQCEhBgAQkIMACEhBoCQEANASIgBICTEABASYgAICTEAhIQYAEJC\nDAAhIQaAkBADQEiIASAkxAAQEmIACAkxAISEGABCQgwAISEGgJAQA0BIiAEgJMQAEBJiAAgJMQCE\nhBgAQkIMACEhBoCQEANASIgBICTEABASYgAICTEAhIQYAEJCDAAhIQaAkBADQEiIASAkxAAQEmIA\nCAkxAISEGABCQgwAISEGgJAQA0BIiAEgJMQAEBJiAAgJMQCEhBgAQkIMACEhBoCQEANASIgBICTE\nABASYgAICTEAhIQYAEJCDAAhIQaAkBADQEiIASAkxAAQEmIACAkxAISEGABCQgwAISEGgJAQA0BI\niAEgJMQAEBJiAAgJMQCEhBgAQkIMACEhBoCQEANASIgBICTEABASYgAICTEAhIQYAEJCDAAhIQaA\nkBADQEiIASAkxAAQEmIACAkxAISEGABCQgwAISEGgJAQA0BIiAEgJMQAEBJiAAgJMQCEhBgAQkIM\nACEhBoCQEANASIgBICTEABASYgAICTEAhIQYAEJCDAAhIQaAkBADQEiIASAkxAAQEmIACAkxAISE\nGABCQgwAISEGgJAQA0DoFKO7W8wCwOe4iAEgJMQAEBJiAAgJMQCEhBgAQkIMACEhBoCQEANASIgB\nICTEABASYgAICTEAhIQYAEJCDAAhIQaAkBADQEiIASAkxAAQEmIACAkxAIQe1sMNDRInXCEAAAAA\nSUVORK5CYII=\n", "text": [ "" ] } ], "prompt_number": 18 } ], "metadata": {} } ] }