GeistHaus
log in · sign up

Let's Discuss the Matter Further

Part of feedburner.com

Thoughts and ideas from Brandon Rhodes

stories
Animating Ptolemy’s Equant with Python, SVG, and CSS

[UPDATE: A full Solar System model is now available that you can view, animated using the techniques described in this post! See Ptolemy’s cosmos, to scale.]

You will recall my previous blog post that tried to build the necessary scaffolding for me to finally write up my 2017 PyCon Ireland keynote on the structure of the Medieval universe. It ran into several problems with matplotlib animations — but, having written that post, I realized that the problem ran deeper.

How could any animation show a Solar System, when a Solar System’s motion never exactly repeats? The orbital periods of the planets aren’t exact multiples of each other, and don’t provide a moment when the planets reach their original positions and the animation can start over again. At whatever moment an animation finished and looped back to the beginning, the planets would visibly and jarringly jump back to their original position.

But then I remembered that modern browsers support animation directly, and thought: could a python script produce an SVG diagram with a separate CSS animation for each planet, that repeated each time that specific planet finished a revolution?

The result would be an animated Solar System that fits into a few thousand bytes, would render with perfect clarity, and runs continuously for as long has the viewer was willing to watch!

But there’s a problem.

The CSS animation mechanism is perfect for the simplest possible planetary orbit: uniform circular motion. Here’s a simple SVG diagram in which a planet and the line connecting it to the origin are grouped within a single <g> element.

%pylab inline
from IPython.display import HTML
𝜏 = 2.0 * pi

circular_svg = '''
<svg version="1.1" width=220 height=220>
 <g transform="translate(110, 110)">
  <circle cx=0 cy=0 r=100 stroke=lightgray stroke-width=1 fill=none />
  <g class="anim %s">
   <line x1=0 y1=0 x2=100 y2=0 stroke=lightgray />
   <circle cx=100 cy=0 r=5 fill=#bb0 />
  </g>
  <circle cx=0 cy=0 r=3 fill=#040 />
 </g>
</svg>
'''

HTML(circular_svg % 'stationary')
Populating the interactive namespace from numpy and matplotlib

We use translate() to move (0,0) to the middle of the diagram where it can serve as the circle’s center. We paint a big circle for the orbit, small circles to mark the orbit’s center and a planet, and a line to link them.

Read the full article...

https://rhodesmill.org/brandon/2019/animating-the-equant/
Animating Saturn with matplotlib, a subclass, and mock.patch()
em>Based on my lightning talk at PyOhio 2018

I hope that this comes across not as a complaint about matplotlib, but as a celebration of tools that a dynamic language like Python offers in situations where a library is seriously misbehaving and needs some crucial live-edits to run successfully.

The task had seemed so simple. To support an upcoming series of posts based on my 2014 keynote at PyCon Ireland (“Building the Medieval Universe in 7 Easy Steps with Scientific Python”), I wanted to render an animation of one of the outer planets — I chose Saturn — progressing slowly eastward across the sky over several seasons and several years.

Instead, I got to spend a weekend wrestling with matplotlib.

Read the full article...

https://rhodesmill.org/brandon/2018/matplotlib-blit-repair/
Learning SymPy while eliminating trigonometry from rotations

I have played with Python’s SymPy symbolic math library before, but for the first time last week I used it to solve a real problem! In the process I had to confront three errors in my understanding of how SymPy works:

  1. I had somehow imagined that SymPy was secretly storing all the equations I was writing and would use them automatically later.
  2. I thought I could convince SymPy to eliminate intermediate symbols.
  3. I thought each variable in my problem needed to be a SymPy symbol.

While working through these misunderstandings to a solution, I ran across two features that made SymPy’s results easier to use in my Python code than I had expected!

  1. SymPy not only supports fancy formatting of math formulae, but can print them as pure Python expressions ready to be pasted into a Python program.
  2. SymPy can perform subexpression elimination to prevent your code from computing any sub-result twice.

The sections of this post tackle each of the items above in turn.

Read the full article...

https://rhodesmill.org/brandon/2018/sympy/
Computing a final Tiangong-1 pass with Python

Do you remember the thrilling re-entry scene at the end of the movie Gravity? The Chinese space station Tiangong-1 is orbiting at thousands of miles per hour when (spoiler) it dips fatally into the Earth's upper atmosphere. The drag buffets and tears at the station’s components before the increasing friction finally flashes the air around the station into a glowing plasma, reducing the station to a shredded sparkling field of debris.

Well — tomorrow, it’s actually going to happen.

But before it does, I’d love to see Tiangong-1 from the ground as it makes its final orbits above our planet. Can Python help me find a final pass of Tiangong-1 over my town?

Let’s give it a try!

Read the full article...

https://rhodesmill.org/brandon/2018/tiangong/
A New Driver for the Original Twiddler

The practical take-away from this post is that if you’re ever trying to debug serial communications with a device that — against all tradition — only transmits when the Data Terminal Ready line is clear (devices should normally do the opposite: transmit only when Data Terminal Ready is set), then never run stty on the serial port to double-check your settings.

The original Twiddler one-handed keyboard

Why?

Because stty turns Data Terminal Ready back on. Without even asking you!

So the device will never communicate with you, and you may very nearly conclude that your device is broken before you happen to remove the stty call and see the device finally work. So that’s the take-away. But the full story is a bit longer.

Read the full article...

https://rhodesmill.org/brandon/2018/twiddler/
Fixing OpenConnect’s VPN Search Domains on Ubuntu

A quick technical note about VPN hostnames on Ubuntu Linux, since otherwise I will forget:

If other users of your VPN can refer to hosts by an unqualified hostname, but an Ubuntu user like you receives a not found error for the same hostname, then try creating the following file (you will need to create the directory by hand).

Read the full article...

https://rhodesmill.org/brandon/2017/openconnect-split-dns/
PyCon Trivia Night, Third Edition

At PyCon 2016 it was my honor, for a third year in a row, to host a Trivia Dinner on the first evening of the conference! This year’s venue was the storied Crystal Ballroom, a music venue in Downtown Portland’s west end. To make sure that our event took full advantage of the big stage, I booked the Adventure Capitalists, who followed up the trivia dinner with a rousing set of punk startup tunes:

Have a conference pass? Come by the Crystal Ballroom and see the Adventure Capitalists! pic.twitter.com/sg0GxqiDpF

— PyCon (@pycon) May 31, 2016

Last year’s trivia night questions focused on such exciting topics as PEP-8 and Python 3, but it turns out that these were fraught topics about which most of the audience were not very familiar. So I made a promise: the PyCon 2016 trivia night would be all Python 2, all the time! The questions below dive into and celebrate the retro roots of the legacy Python language.

Read the full article...

https://rhodesmill.org/brandon/2016/pycon-trivia-night/
PyCon Trivia Night, Second Edition

As was the case during first year that the conference was in Montréal, I was invited for PyCon 2015 to lead an evening dinner trivia contest on the first full conference day.

Wanting to help the audience celebrate all of the advances that are being made in Python 3, I skewed my questions heavily in the direction of the strides that the core developers are taking with the new version of the language. Alas! My focus was not as popular with the audience as I had hoped. It turns out that Python 2.7 is still far more popular than its predecessor, and many contestants were frustrated about being asked so many questions and details about a language hardly anybody used. So I made a promise to the audience: if a third trivia dinner happens at PyCon 2016 in Portland, that I will make it Retro Python Trivia Night and ask all of the questions about the Python 2 series!

The questions follow, then the answers are way down at the bottom of the post so you can try answering on your own before you scroll down and peek. Enjoy!

Read the full article...

https://rhodesmill.org/brandon/2015/pycon-trivia-night/
The First-Ever PyCon Trivia Night

PyCon seems to find new ways of fostering community single every year. This year’s conference in Montréal featured the début of official Friday night dinners which I first learned about from a surprising email entitled Want to MC a trivia night at the PyCon dinner?

I accepted the invitation!

While I have enjoyed other volunteer roles at PyCon, this one was particularly exciting because of the difference that official evening activities can make for newcomers. Remembering my own first conferences, it can be stressful to face that lonely moment when the evening lightning talks have just finished. Everyone else seems to pair up and make dinner plans so quickly. Unless you can somehow involve yourself in someone else’s dinner plans, you picture a long walk back to your hotel to order room service — alone — while everyone else sits at candlelit tables in real restaurants talking and laughing and enjoying Québécois cuisine. I hope that my dinner, plus the one hosted by Greg Brockman, provided a few people with a safe default option who otherwise might have had to fend for themselves.

Read the full article...

https://rhodesmill.org/brandon/2014/pycon-trivia-night/
Learning Pandas through payroll taxes and paystubs

I will admit it: I only thought to pull out Pandas when my Python script was nearly complete, because running print on a Pandas data frame would save me the trouble of formatting 12 rows of data by hand.

But as I added the import statement, it suddenly struck me that Pandas aggregate operations might be able to replace some of the steps inside my big for loop. Half an hour later, my loop had disappeared completely and my entire script was reduced to a short sequence of Pandas method calls!

This post is a brief tour of the final script, written up as an IPython notebook and organized around five basic lessons that I learned about Pandas by applying it to this problem.

1. Pandas lets you bring your own objects

The most surprising feature of tools like the NumPy vector library and the Pandas data series might be that they let you bring your own objects to the party.

Since they were invented to efficiently pack millions of floating-point values into a single Python object, you might think that these libraries would only work with numeric types that they themselves can express as vectors. But in fact they have a clean fallback behavior when faced with alternative numeric types: they essentially turn into Python lists, and keep a separate reference to each object that you have supplied. When asked to perform their famous aggregate operations — this is the crucial step — they simply turn to the objects and call the __add__() or __mul__() method of every single item to build the result.

When doing taxes and pay stubs we always want to use Python Decimal objects to guarantee correctness and careful rounding to cents, which we can implement with a simple c() function:

from decimal import Decimal

one_cent = Decimal('0.01')

def c(value):
    "Convert `value` to Decimal cents."
    return Decimal(value).quantize(one_cent)

You might think that my next step will be building a twelve-element list with which to initialize the monthly wages in our payroll table. But data frames let us do something simpler: we can supply a single value for a column, and Pandas will automatically broadcast it across the whole index that we have defined. Here we set up the twelve calendar months of the year and imagine the simple case of someone who makes the same wage every month:

import pandas as pd
from calendar import month_abbr

df = pd.DataFrame(index=month_abbr[1:])
df['wage'] = c('11000.00')
print df
         wage
Jan  11000.00
Feb  11000.00
Mar  11000.00
Apr  11000.00
May  11000.00
Jun  11000.00
Jul  11000.00
Aug  11000.00
Sep  11000.00
Oct  11000.00
Nov  11000.00
Dec  11000.00

An example wage of $11,000 per month might sound grandiose, but I have chosen it so that this example will reach the Social Security wage limit by the end of the year — to test whether we model the limit correctly in our data frame.

2. Mapping is suddenly worth it

The second surprise of working with Pandas is the convenience of its map() method,

Read the full article...

https://rhodesmill.org/brandon/2014/pandas-payroll/