Author Archives: Corran Webster


About Corran Webster

Corran is Enthought's European consulting director, and has been with Enthought as a scientific software developer and Python instructor since 2008. Corran has a B.S. from the University of New South Wales and a Ph.D. in pure mathematics from UCLA and has held positions at the University of Nevada, Las Vegas and Texas A&M University, working primarily in operator algebras and functional analysis. Prior to joining Enthought, he was Chief Scientist at Compudigm International working on machine learning with self-organizing maps and large data visualization methods. Corran wrote his first Python code back in the days of Python 1.3 and has used it as his primary programming language for over 20 years.

Traits and TraitsUI: Reactive User Interfaces for Rapid Application Development in Python

 The open-source pi3Diamond application built with Traits, TraitsUI and Chaco by Swabian Instruments.The Enthought Tool Suite team is pleased to announce the release of Traits 4.6. Together with the release of TraitsUI 5.1 last year, these core packages of Enthought’s open-source rapid application development tools are now compatible with Python 3 as well as Python 2.7.  Long-time fans of Enthought’s open-source offerings will be happy to hear about the recent updates and modernization we’ve been working on, including the recent release of Mayavi 4.5 with Python 3 support, while newcomers to Python will be pleased that there is an easy way to get started with GUI programming which grows to allow you to build applications with sophisticated, interactive 2D and 3D visualizations.

A Brief Introduction to Traits and TraitsUI

Traits is a mature reactive programming library for Python that allows application code to respond to changes on Python objects, greatly simplifying the logic of an application.  TraitsUI is a tool for building desktop applications on top of the Qt or WxWidgets cross-platform GUI toolkits. Traits, together with TraitsUI, provides a programming model for Python that is similar in concept to modern and popular Javascript frameworks like React, Vue and Angular but targeting desktop applications rather than the browser.

Continue reading

PyCon 2010 Report

I just got back from PyCon, where I gave my tutorial on Traits, met all sorts of smart and interesting people, listened to some great talks, ate more food than I probably should have, and got less sleep than I probably needed. It was really nice to see talks and posters about things that people are doing with Python in science at a general-purpose conference.

Highlights for me:
Dave Beazley’s awesome talk on Python’s Global Interpreter Lock (GIL) and its curious behaviour. If you do any programming with threads in Python you have to make sure that you watch the video it’s a clear, understandable and unflinching look at some of the weird behaviour that you can get from CPU-bound threads in Python. The take-home message of his talk for scientific programmers: With current versions of Python, there is little point of running intensive pure-Python computations in parallel using threads and doing so on multiple core machines may severely degrade computation time. Dave showed a simple example where a computation split into two threads on two cores took twice as long as the same computation in one thread on one core. Fortunately NumPy releases the GIL for most of its operations, but his talk highlights something that we should all keep in mind.

Wes McKinney’s new Pandas package for data series analysis. I didn’t get to see his talk, but I got to spend a fair amount of time talking to Wes and his package was generating quite a bit of buzz in the financial and numerical computing open spaces. It’s an early release, but there have been several projects I’ve been involved in over the past couple of years where the Pandas data structures would have been invaluable. I’m looking forward to being able to use it in the future in projects that I’m working on.

Altogether, a great time. Thanks to everyone who dropped by the Enthought booth and talked with us, and we’ll see you in Atlanta at PyCon 2011 next year!

A Perspective on Numpy

In a former life, before joining Enthought, I was a researcher in operator algebras, a field of mathematics which can be briefly summed up as the study of certain sets of “infinite-dimensional matrices.” My first reaction when seeing numpy (actually, numerical python, this was a while back) was “A matrix module! In Python! Show me more!”

But then I looked a little deeper, and my second reaction was “Why on earth would you not have the product of two arrays be the matrix product?” And then: “And why is function application element-wise?”

From the point of view of an operator algebraist everything interesting comes out of non-commutative multiplication, and clearly the “right” way to apply a function to a matrix is

f(A) = U f(D) U *

where A = U D U * is a unitary diagonalization of A, and f is applied just to entries on the diagonal of D. The fact that this only works for unitarily diagonalizable matrices was a minor concern for me at the time… after all I was a pure mathematician!

Since then, particularly in a more recent life as a scientist at a data visualization company, I’ve come to appreciate the way that numpy slices and dices arrays of numbers. And numpy now meets me half-way with a first-class matrix type, so I can at least write A*B and have it mean what I want it to.

But for those who still think that numpy made the wrong choice for applying functions to arrays…

from numpy import *
def mfunc(func):
    def new_func(x):
        x = mat(x)
        if not allclose(x*x.H, x.H*x):
            # matrix is not normal-ish
            raise ValueError, "matrix must be normal"
        # matrix is normal-ish
        e, U = linalg.eig(x)
        return U*mat(diag(func(e)))*U.H
    return new_func

Which you can then use as:

mexp = mfunc(exp)

for any ufunc, or as a decorator on your own functions:

def f(x):
    return cos(x) + 1.0j*sin(x)

When I showed this to Travis Oliphant, he pointed out that scipy already has a function linalg.funm which does something similar to the above, but not as a decorator. So if you have scipy, you can instead use:

import scipy.linalg
def mfunc(func):
    def new_func(x):
        return scipy.linalg.funm(x, func)
    return new_func