Tuesday, August 21, 2007

Final SoC Report

I've written a final SoC report and posted it in the SymPy wiki. Click here to read it. You will also find similar documents from other SymPy SoC participants here.

Saturday, August 18, 2007

VIDEO: Key Bank Tower Implosion (Downtown Salt Lake City, UT)

This is the video I shot of the Key Bank Tower controlled demolition/implosion in downtown Salt Lake City, UT, earlier this morning. We were standing on the East side of the parking lot across the street from the Triad center and the unfortunately re-branded Energy Solutions Arena (formerly the Delta Center). Digg It.

Update: Full HD-res H.264 version.

Thursday, August 9, 2007

SymPy Plotting: Custom Colors Tutorial

One of the most-requested features for SymPy plotting has been the ability to use custom color schemes. I've now implemented this with the syntax described in this post. The upshot is that you can now use any color scheme expressible as a function of x, y, z, u, and/or v. I'll give some concrete examples to get you started, and then you can do something cool with it. We'll start by setting up a plot:

>>> from sympy import symbols, Plot
>>> x,y,z,u,v = symbols('xyzuv')
>>> p = Plot(axes='none')

Now let's plot a saddle and color it by the magnitude of its gradient:

>>> fz = x**2-y**2
>>> Fx, Fy, Fz = fz.diff(x), fz.diff(y), 0
>>> p[1] = fz, 'style=solid'
>>> p[1].color = (Fx**2 + Fy**2 + Fz**2)**(0.5)

Remember that the algorithm for coloring works like this:
  1. Evaluate the color function(s) across the curve or surface.
  2. Find the minimum and maximum value of each component.
  3. Scale each component to the color gradient.
When not specified explicitly, the default color gradient is (r,g,b) = (0.4,0.4,0.4)->(0.9,0.9,0.9). In our case, everything is gray-scale because we have applied the default color gradient uniformly for each color component. When defining a color scheme in this way, you might want to supply a color gradient as well:

>>> p[1].color = (Fx**2 + Fy**2 + Fz**2)**(0.5),
................ (0.1,0.1,0.9), (0.9,0.1,0.1)

Next, let's try a color gradient with four steps:

>>> gradient = [ 0.0, (0.1,0.1,0.9), 0.3, (0.1,0.9,0.1),
................ 0.7, (0.9,0.9,0.1), 1.0, (1.0,0.0,0.0) ]
>>> p[1].color = (Fx**2 + Fy**2 + Fz**2)**(0.5), gradient

The other way to specify a color scheme is to give a separate function for each component r, g, b. With this syntax, the default color scheme is defined:

>>> p[1].color = z,y,x, (0.4,0.4,0.4), (0.9,0.9,0.9)

This maps z->red, y->green, and x->blue. In some cases, you might prefer to use the following alternative syntax:

>>> p[1].color = z,(0.4,0.9), y,(0.4,0.9), x,(0.4,0.9)

You can still use multi-step gradients with three-function color schemes. When somebody uses this to visualize something useful like curvature, I'd really like to hear about it.

Saturday, August 4, 2007

New Plotting Examples

Try running examples/plotting.py in an interactive shell:

Other updates:
  • New experimental option 'use_lambda', which speeds up calculation by an order of magnitude (used in most of the examples, but doesn't work in every case yet).

  • Custom coloring can be applied in real-time:
    >>> p[1].color = 0.3,0.3,0.9 # any solid color
    >>> p[1].color = 'z,y,x' # lambda-based (fast)
    >>> p[1].color = x,y,z # sympy expr of x,y,z
    >>> p[1].color = u,v,u*v, (u,v) # or of parameters

  • Style property:
    >>> p[1].style = 'wireframe'
    >>> p[1].style = 'solid'
    >>> p[1].style = 'both'

  • Natural right-click translation in the plane of the screen.
  • Middle-click drag zoom.
  • Progress percentage displayed in window caption for long calculations.
  • z,c and numpad 1,3 rotate about the z axis regardless of camera angle.
  • x and numpad 5 reset view.

Sunday, July 29, 2007

Mathematicians are a Hungry Bunch

After yesterday's donut, today it's the Ding Dong Surface. Thanks to Alex who originally pointed me to the Kiss Surface (also named after junk food).

>>> p = Plot()
>>> p[1] = sqrt(1-y)*y, [x,0,2*pi,60], [y,-1,4,100], 'mode=cylindrical'

By the way, the torus shown yesterday can be plotted with:

>>> a,b = 1, 0.5
>>> p[2] = (a+b*cos(x))*cos(y), (a+b*cos(x))*sin(y), b*sin(x), [x,0,2*pi,20], [y,0,2*pi,20]

However, at writing there is a hang bug with trig functions in the new SymPy core, so this may or may not work when you try it.

Saturday, July 28, 2007

Just in time for the Simpson's Movie

After weeks of working mostly on the UI, I've spent three or four days reworking the calculation and display code. One result of that effort is support for parametric surfaces (x,y,z) = f(u,v).

Other things:
  • Now using GL display lists for faster rendering.
  • Support for wireframe, solid, and wireframe superimposed on solid rendering modes.
  • Smaller and more readable code base, since all surface and curve modes are now defined in terms of base parametric modes.
  • Preliminary support for custom coloring.
The new code is not hooked up to the Plot interface yet, so that is my goal for today. Hopefully you will see this in SVN by the end of the weekend, possibly tonight.

Tuesday, July 24, 2007

SymPy Plot: First Screenshot of Labeled Axes

Good thing a picture is worth 10**3 words; I'm burnt out. Among other things, it took me way too long to figure out how to automatically position the axis labels after camera rotations. It still isn't perfect. I also need to add in grid lines. I need a break, I've been coding for a nearly unbroken week.

Saturday, July 21, 2007

Some thoughts on Plot coloring (with pics)

I want to support two modes for custom coloring schemes in SymPy Plot. The first mode will allow you to supply a single function and a color gradient (pseudo-code):

>>> p[1].color_function = z, (0.0,0.0,1.0), (1.0,0.0,0.0)

This calculates the min and max z-value across the surface, then interpolates from (min, blue) to (max, red). A variation on this syntax allows you to specify more nodes on the color gradient (the fourth component is the linear position [0,1] on the gradient):

>>> p[1].color_function = z, (0.0,0.0,1.0,0.0), (0.0,1.0,0.0,0.5), (1.0,0.0,0.0,1.0)

As you can see, this fades from (min, blue) to (mid, green) to (max, red).

The second coloring mode will allow you to map each RGB component to separate functions. This can be used to colormap three-space vectors, such as surface normals. The simplest usage of this would be:

>>> p[1].color_function = x, y, z

However, this would look pretty bad. In fact, all of the above images used a slightly different color range than was written in the accompanying pseudocode, but they were simplified for clarity. For example, the top one was really more like:

>>> p[1].color_function = z, (0.3,0.3,0.9), (0.9,0.3,0.3)

So in RGB-parametric mode, there will be an enhanced syntax for playing with the dynamic range independently of whatever functions you are using. The current default coloring could be represented with something like:

>>> p[1].color_function = x, (0.5,0.9), y, (0.5,0.9), z, (0.5,0.9)

Anecdotal Evidence that Linux Sucks

So I've been trying to figure out why the new Plot implementation works perfectly on windows, but totally craps out on Linux. Unfortunately, I've started getting more hard disk errors. This time it's a persistent (within 5 minutes of booting) 'kernel panic: journal commit i/o error.' Of course, this error message is preceded by a complete lockup of 3-5 minutes, and sometimes it never shows up, and halts or reboots instead. Beeeeautiful. This is a different hard disk than the one I had a similar problem with in June. The machine is an Alienware Aurora, running on an Asus A8N-32 with an AMD 4800+ X2.

For most of my life, I've suffered the reputation of being able to fix computer problems with only my proximity. Lately, the universe seems to have found balance. In the past three years, I've lost three hard drives, two motherboards, and a CPU at exceedingly inopportune times. Call it terrible coincidence, but each time, I had recently began dual-booting one or another Linux distro after a long period of brutish but relatively problem-free Windows-only celibacy. Now, I can't PROVE nor should I be taken to imply that the Linux kernel is directly to blame. But regardless of statistical (im)probability, this seems to happen to me all the time.

In one such instance, my motherboard DIED after a nasty, bone-grinding, system-fan-maxed-out, cold-sweat-inducing system halt during a Knoppix session--yes, the mobo DIED. I had JUST BUILT the computer a few months prior (based on an AMD 3500+ and an A8N SLI Deluxe). A few months later the CPU died while I was trying to learn Slackware. Maybe I ESD'd something when I was building it, who knows? (I did in fact use a wrist strap, though)

In another instance, I had recently started using Ubuntu Warty on my Dell Inspiron 8200, after pleasantly (to the extent possible) running windows on the machine for months. The system ate it, and I had to replace the hard drive (which was less than a year old).

In June of this year, when I got "grub error 17," I had been using a new Feisty installation for just a few days. Had to replace the drive. Note also that there have been several other incidents _only_ resulting in serious data corruption and loss (i.e. a simple low-level format and reinstall fixed it).

I consider myself of above average hardware, software, and OS literacy, but there is nothing in my knowledge base which explains these hardware failures. But consider this: I use only Windows for probably 80% of the year on average (because it takes me a while to reinstall Linux after each incident, then I just have another one soon after), and these failures seem to happen in Linux. For clarity, I like Linux a great deal, but it's increasingly making me want to smash all of my gadgets and move to Walden Pond.

Multiple Choice:
A. The Linux Kernel and/or Drivers are killing my computers.
B. I'm using my system in some strange and scary way that causes massive hardware failures.
C. I have an electro-static aura which is only activated when I'm feelin' the penguin love.
D. AMD and/or ASUS hardware is the common thread.
E. Solipsism; I'm the only person with free will, and the rest of you are lying about how problem-free your Linux installations are.

I'll have to choose E unless someone can give me a better explanation. Either way, I think I'm going to invest some of my GSoC earnings into a MacBook Pro.

Tuesday, July 17, 2007

SymPy Plotting: Improved Usability with Pyglet

One of my personal goals for the SymPy plotting module is to introduce non-programmers to Python. This means it needs to have a familiar interface, and that it should "just work" straight out-of-the-box. With the latest code in SVN, you can now use Plot in Python 2.5 without installing any additional dependencies. In Python 2.4 and 2.3, the only external dependency is ctypes.

PyOpenGL is no longer used at all (no offense to Mike Fletcher and his loyal followers). After it was suggested last week, I'm now including a (stripped-down) version of Pyglet, which provides a ctypes-only OpenGL wrapper, in addition to excellent windowing, keyboard, and mouse support. Pyglet's event model is also compatible with the multi-threaded interface I described last week. That means you can now do this:
>>> from sympy import Symbol
>>> from sympy.modules.plotting import Plot
>>> x,y = Symbol('x'),Symbol('y')
>>> p = Plot(width=300, height=250, bbox=True)

>>> p[1] = x**2-y**2, [x,-1,1], [y,-1,1]

>>> p[1] =  x**2+y**2, [x,-1.0,1.0], [y,-1.0,1.0]
>>> p[2] = -x**2-y**2, [x,-1.0,1.0], [y,-1.0,1.0]
>>> print p
[1]: x**2+y**2, [x,-1.0,1.0], [y,-1.0,1.0]
[2]: -x**2-y**2, [x,-1.0,1.0], [y,-1.0,1.0]
Also new:
  • Rotation mechanism based on a virtual trackball.
  • Scroll-wheel zoom.
  • Holding the shift key allows more precise movement.
  • Smooth time-based keyboard movement.
  • Added arrow and page up/down key control (ASDWRF is still there).
  • X,Y, and Z-blended coloring scheme.
In progress:
  • Configurable coloring.
  • Labeled coordinate axes.
  • Translation in the plane of the screen.
  • Automatic intervals.
  • Intuitive 2d support, including dynamic intervals.
  • Display lists (maybe faster for higher-resolution rendering, we'll see).
  • Anti-aliasing.
Let me know when you get a chance to try it out!

GEB Week MU: A koan

Lisa: Remember, it is better to remain silent and be thought a fool than open your mouth and remove all doubt.
Homer: Takes one to know one!
Brian: If I ever get around to completing my List of Unfinished Summer Projects, I need to remember the Book Club.

Tuesday, July 10, 2007

PyOpenGL is Dead to Me (Where Are All the 3d Graphics Python Enthusiasts?)

Right now, displaying a plot permanently blocks the main thread; in other words, you can't do:
p = Plot( x**2, [x, -5, 5, 10] ) #never returns
p.append(x**3) #execution never gets here!
I've tried desperately to get this to work using threading, but GLUT is not meant to be used in this way. GLUT basically forces the user to put all application logic into event callback functions which are called by the non-reentrant glutMainLoop. This won't work for either of my use cases, which are graphing from interactively from the console and embedding plotting functionality in larger applications/scripts.

The bottom line is that GLUT is not meant for real-world OpenGL applications, it's meant for learning OpenGL and and tangentially for writing simple demos and games. TOGL, a Tk Widget for OpenGL rendering which is also supported in PyOpenGL (though I couldn't get it to work right in less than an hour), suffers from essentially the same problem (Tk.mainloop is non-reentrant). As far as I can tell, these are really the only two interfaces which are available out-of-the-box in PyOpenGL.

So imagine my hope when I learned that another implementation of GLUT called Freeglut has a workaround for the inflexible event model problem. Tantalizingly, PyOpenGL 3.0 (a rewrite which uses ctypes instead of SWIG) supports Freeglut, as well as Python 2.5 (not currently supported by any functional version of PyOpenGL). I spent most of yesterday trying to get PyOpenGL 3.0 to work on Windows. Unfortunately, it just doesn't work yet, and PyOpenGL development is painfully slow.

As far as I can tell, PyOpenGL 3.0 has only one core developer, and he doesn't seem to have much time to work on it (search for 'OpenGL' on his blog, most of the results are from 2004 and 2005). I don't blame him personally, I'm just utterly shocked that Python doesn't have an actively maintained OpenGL interface library (next year's SoC?). A lag time of more than two years in producing a build for Python 2.5 on Windows is unacceptable in my view, given the size of the Python community and the traditional strength of its library support. [/Rant]

Today, I investigated a variety of new approaches (vaguely in reverse order of my preference):
  • Using Visual Python (annoyingly high-level, hideous website ;-)
  • Using PyOGRE (huge, probably unacceptable overhead)
  • Using the DirectX binding for Python on Windows, and PyOpenGL 3.0 elsewhere (disgusting platform dependency, PyOpenGL 3.0 is quite unstable and not expected to improve anytime soon)
  • Fixing PyOpenGL to work on Windows (probably a monumental task worthy of its own SoC project)
  • Creating my own limited ctypes wrapper for OpenGL (jury still out)
  • Hacking PyOpenGL 2.0 to work with Freeglut (possibly feasible?)
  • Creating a C or C++ Python rendering extension (how Visual Python works under the hood; has hacker sex appeal)
  • Writing my own event loop with PyOpenGL 2.0, but without using GLUT (after exhaustive searching I couldn't find any examples or mention of this, but I want to keep looking. You'd think this would be the most reasonable option)
I don't particularly like any of these, though several might work. Anything good which I missed?

Post script: I'm particularly interested in hearing about anything not listed here, though I'd still like to know if there is a gem on there which I have overlooked.

Monday, July 2, 2007

SymPy Plot: Mouse Support

Now in SVN. Left-click controls rotation, right-click controls zoom. Eventually I want to change it so that right-click controls translation and middle-scroll controls zoom. Right now this does not seem to be possible, because the scroll wheel is not supported by GLUT's mouse handler. I'm looking into it.

Although it has been a while, I never mentioned that basis vectors were added. They still need some tweaking. Also 'q' is added as a quit key.

Right now I'm at a family reunion for the 4th of July holiday. Each summer, my extended family meets for a week to act out our own miniaturized take on Burning Man. FYI, my contract delivery went well on Thursday. However, I'm not quite off the hook yet as I had speculated; it turns out they need additional work.

Wednesday, June 27, 2007

Briefly reporting in

Tomorrow morning, I'm making an important (semi-final) code delivery to my (non-GSoC) client. I've been focusing on this for the last few days. After this, SymPy will be my only major project. Expect an update sometime next week.

Book club (Gail and Martin): sorry for the lapse, I will get back into this soon. Thanks for your loyal and unwaivering support ;-)

Tuesday, June 19, 2007

SymPy 0.4.1 released, with windows installer

This is the first release to include SymPy Plot.

0.4.1 source tarball
0.4.1 windows installer
SymPy homepage

PyOpenGL is required for SymPy plotting support. While *nix users should have no problem (apt-get install python-opengl), Windows users will find it difficult, if not impossible, to use PyOpenGL with Python 2.5. I recommend setting up your Python environment as follows:
  1. Install Python 2.4.4 to C:\Python24 (the default location)
    I normally like to install all of my programs in C:\Program Files, but unfortunately PyOpenGL depends on the default install path.
  2. Install Numeric-23.7.win32-py2.4.exe
  3. Install numarray-1.1.1.win32-py2.4.exe
  4. Install PyOpenGL-
  5. Install sympy-0.4.1.win32.exe
  6. >>> from sympy import Symbol
    >>> from sympy.modules.graphing import Plot
    >>> x = Symbol('x')
    >>> Plot(x**2, [x, -1, 1, 10])

If you get a dll not found error relating to GLUT, obtain glut32.dll and put it in C:\Python24\Lib\site-packages\OpenGL.

Thursday, June 14, 2007

SymPy Plot: Now available in SVN

To try it out, check out or update from SVN and look at examples\plotting.py. You'll need to download and setup PyOpenGL for your platform: on ubuntu, apt-get install python-opengl; on windows, you might have luck with the instructions here. So far, I've only tried it on Windows with Python 2.4.

Enjoy, and let me know how it goes!

Wednesday, June 13, 2007

SymPy Plot: First screenshots

>>> f1 = 0.1+x**2+y**2
>>> f2 = -0.1-x**2-y**2
>>> Plot( f1, f2, [x, -0.75, 0.75, 8], [y, -0.75, 0.75, 8] )

>>> Plot( x*y**3-y*x**3, [x, -1, 1, 20], [y, -1, 1, 20] )

Tuesday, June 12, 2007

Book club, time to regroup?

To the GEB Book Club:

The weekly GEB posts are quickly becoming really hard for me to keep up with. I've also noticed that discussion has tapered off significantly. I don't want to give it up just yet, but I do want to regauge the interest level. If you are participating, or have a suggestion, I'd really like to hear from you. Thanks!


Thursday, June 7, 2007

Vision for an extensible visualization tool

In addition to providing standard 2d and 3d function graphing capabilities, the SymPy graphing module will be able to render 2d and 3d geometric entities on the plot, such as lines, vectors, and triangles. While the rendering system will be completely hidden from the casual user who simply wants to plot a few curves or surfaces, advanced users will be able to extend or create new kinds of renderable objects.

A new submodule called sympy.modules.graphing.scene makes this possible by providing a high-level rendering abstraction on top of OpenGL through the Scene class. A Scene handles the boilerplate OpenGL setup and teardown code. It also maintains a list of objects to be rendered, which are represented by objects which implement the Renderable interface. Renderable is a base class providing the render() function, which retrieves the object's primitive representation for rendering. This representation is something that OpenGL can render directly, such as a line list or a tri strip.

For example, consider the Renderable called CartesianCurve, which represents a plane curve in the form y = f(x); when CartesianCurve's render() function is called by a Scene which contains it, it returns a representative list of coordinate pairs, which are then used to render an OpenGL line list. The various other types of plots will be implemented as subclasses of Renderable in the same way. Here are some examples of possible constructor syntax for function plot Renderables:

# y = f(x)
CartesianCurve( x**3, [x, -10, 10, 20] )

# x = f(t), y = f(t)
ParametricCurve( cos(t), sin(t), [t, 0, 2*pi, 32] )

# r = f(theta)
PolarCurve( t, [t, 0, 2*pi, 32] )

# z = f(x, y)
CartesianSurface( x**2+y**2, [x, -1, 1, 5], [y, -1, 1, 5] )

# radius = f(z, theta)
CylindricalShell( 1.0, [z, 0, 1, 2], [t, 0, 2*pi, 32] )
CylindricalShell( t*sqrt(z), [z, 0, 1, 2] )

# radius = f(theta, rho)
SphericalShell( 1.0, [t], [p] )

Tuesday, June 5, 2007

Grub Error 17?!

My desktop has died. Looks like hard drive failure (long delays on hdd detection, then grub error 17, can't mount partition). I'm pretty used to this, seems to happen to me biannually. The Ubuntu live CD won't even come up, so my chances for data recovery seem pretty slim. The worst thing is that I just downloaded but have not yet watched two iTunes purchases (yesterday's Daily Show and Colbert). I also stand to lose quite a bit of work for my contracts as well as GSoC. Time to get out the screwdriver...

Thursday, May 31, 2007

Migrating from Wireless-G to 10-Base-T

For almost a week now, I've been working with my wife on a total conversion for our apartment. Since we spend most of our day in the computer room, we decided to try swapping it with the larger room that used to be our bedroom. It's been hard work moving furniture and reorganizing, but I think it will be worth it. Finally, I have the elements of a real office: printer, filing cabinet, and a mini-fridge stocked with red bull. I never got Ubuntu to connect to my WPA2 network (my best hypothesis is that I'm using the wrong driver for my specific chipset, though I had no luck with ndiswrapper either). With the new set up, I can connect to my wired LAN.

GEB Week 2: Chapter 4, Consistency

It's been a crazy week. Surprisingly, I found time to read this week's assignment. In the last few chapters, the author has tactfully introduced many of the important concepts in studying and understanding formal systems. One particular argument he has made is that the form of a formal system is completely disconnected from its meaning. Here's an excerpt which takes this further:

It now becomes clear that consistency is not a property of any formal system per se, but depends on the interpretation which is proposed for it. By the same token, inconsistency is not an intrinsic property of any formal system. (GEB20 94)

An alternative conclusion might have been that "all formal systems are consistent by definition," but the author disagrees with this characterization. Instead, he makes the stronger claim that it is completely improper to assign "consistency" or "inconsistency" to a formal system. What distinction is he making, and to what end?

Saturday, May 26, 2007

GEB Week 1: Ch 1-3

This week's reading contains an infinite hierarchy of meaning and fun. There are many explicit and hidden puzzles to be solved, and I won't ruin them for you, but certainly encourage you to work through them yourself. Here is an excerpt from Chapter 2 which I found interesting:

People enjoy inventing slogans which violate basic arithmetic but which illustrate "deeper" truths, such as "1 and 1 make 1" (for lovers), or "1 plus 1 plus 1 equals 1" (The Trinity). You can easily pick holes in those slogans, showing why, for instance, using the plus-sign is inappropriate in both cases. But such cases proliferate. Two raindrops running down a window-pane merge; does one plus one make one? A cloud breaks up into two clouds--more evidence for the same? It is not at all easy to draw a sharp line between cases where what is happening could be called "addition", and where some other word is wanted. (GEB99 56)

This hints at a very important theme of the book; that counting in hierarchical systems can be "fuzzy." Does this reflect a deep aspect of reality, or rather, the function and organization of the brain?

Wednesday, May 23, 2007

GSoC Book Club: Format and a Challenge

If you aren't reading GEB with us by now, you just might be the only one! I've gotten quite a few questions and comments about the format of the book club, so let's set a few things straight:

First, each date on the schedule represents the start of the week in which the specified chapter will be discussed. I've updated the Google calendar to reflect this by making each chapter extend a week. Originally, I assumed putting each chapter on one day would look less cluttered for someone importing the calendar, but I think it was more confusing than helpful.

Secondly, the schedule is designed to pace the reader to finish by the end of summer. If you don't follow it, great! Still visit now and then and add your thoughts. You can comment on anything at any time, with one exception: don't give any spoilers for puzzles, riddles, etc.

Several people have also asked about the format of discussions. I decided against a web forum or weekly IRC chat for two reasons: chances are it would be underutilized in the long run, and we already have the GSoC blog community, which I feel to be a great discussion medium. The central place to begin discussions will be my weekly blogs, but it is my hope that discussion will branch out to your blog as well.

...which brings me to the GSoC Book Club 2007 Challenge: at some point during the summer, choose a section or idea that you really liked or were affected by, and blog it! I look forward to reading and linking to your GEB-related posts!

In case you haven't noticed, I'm not planning on posting about the chapters on Monday morning of each week. In general, I hope to post at least once a week on something from the assignment, but with so many interesting things going on this summer, it might take me a few days.

One final note. Last week, I initially posted the wrong assignment for this week. Just in case you missed the correction, chapters one, two, and three are relatively short, so we're reading all three of them this week. Sorry for any confusion.

Monday, May 21, 2007

SymPy Graphing: Starting with PyOpenGL and Feisty

Just a brief update. Progress has been a little slower this week because I've begun working on the new graphing implementation using PyOpenGL and the sample function I wrote about last week. After about a day of tinkering, I had no luck with PyOpenGL on Windows using Python 2.5 (not officially supported yet, apparently). As a result, I've been working in Feisty for the last few days. Unfortunately, I'm having a hard time convincing Feisty to connect to my wpa2-protected wifi, and this is putting a damper on my work flow. Once I get that and a few other nags sorted out, I should be on track.

Tuesday, May 15, 2007

GEB Week 0: Introduction, strange loops

Okay--I'm not exactly Oprah and this isn't going to be like that. With that said, let's start discussion of GEB for the Google Summer of Code 2007. If you don't already have a copy, you still have time to pick it up from amazon or your local library, used book store, obscured dusty shelf in closet, roommate, russian site of questionable legality, etc.

For this week, you should try to read the introduction and the first dialogue, "Three-Part Invention". You should also try to read Chapters 1-3 for next week, if you want to stay completely up to speed (I'm grouping dialogues with the chapters they follow, so that reading for Chapter 1 "includes" the dialogue "Two-Part Invention"). However, like its subject matter, the process of reading GEB is not completely straightforward. Don't worry too much about sticking to the schedule; the book club is primarily about finding motivation to read and think critically about new ideas on a consistent basis this summer.

In the introduction, Hofstadter gives us a first taste of strange loops, a "phenomena [which] occurs whenever, by moving upwards (or downwards) through the levels of some hierarchical system, we unexpectedly find ourselves right back where we started." A simple yet fascinating example of this concept is demonstrated with Bach's "Endlessly Rising Canon," a piece of music which changes key upwards repeatedly until reaching the starting key, implying an infinite progression. The author also demonstrates strange loops in several of Escher's pieces, such as his famous waterfall, fed by a perplexing aqueduct which defies either gravity or reason.

Since I'm currently reading a book of rigorous number theory for the first time, I am reminded of the Peano axioms, which define the natural numbers by induction. How about a quine, a program which outputs itself?

How many strange loops can we list?

Update: Corrected reading assignment for next week.

Sunday, May 13, 2007

New direction for SymPy Graphing

In addition to gaining some new perspective on my project this weekend, I've gotten a lot done.

On Friday, I said I wanted to stop supporting matplotlib and to begin focusing on a fresh OpenGL plotting solution. It turns out that matplotlib has better 3d support than I suggested, though it is buggy and still doesn't have everything I need. Fortunately, it turns out we can have it both ways.

I've moved matplotlib 2d plotting support out of modules/graphing.py and into examples/mplot2d.py. I've also added 3d plotting support in examples/mplot3d.py. In accomplishing this, I created a generic sampling function in modules/graphing.py which generates plotting data from a 2d or 3d function over an interval or rectangle:

>>> from sympy.modules.graphing import sample
>>> from sympy import Symbol
>>> x = Symbol('x')
>>> sample(x, (x, 0, 2, 2))
>>> sample(x**2, (x, 1, 3, 2))
[[1,2,3], [1,4,9]]

This approach will allow me to support multiple plotting solutions. You should now be able to graph many varieties of functions using matplotlib with the implementations in examples/mplot2d.py and examples/mplot3d.py.

>>> mplot3d(x**2-y**2, (x, -10.0, 10.0, 20), (y, -10.0, 10.0, 20))

Friday, May 11, 2007

The Case for Dropping Matplotlib

My pet motivation for SymPy Graphing is to aid in the creation of interactive calculus visualizations. I want to be able to write an example program which visualizes the normal and tangential components of acceleration along a curve. I want to be able to graph a 3d surface subject to a constraint, perhaps to see only the portion of a surface which falls within a cylindrical boundary. Ondrej mentioned that he would like to be able to plot curvature as the vertex color across a 3d surface. All of these things should be doable. At the same time, SymPy Graphing should be simple and intuitive enough for a non-programming Calc III student to use in Python's interactive mode as a graphing calculator.

In my work on 2d graphing this week, I've utilized matplotlib's pylab interface. Using matplotlib to plot functions from SymPy is pretty straightforward, though I find it clunky and have had many frustrations with it. But as the name implies, matplotlib isn't meant to do much beyond plotting, and has only limited 3d support. I want to do a lot more with SymPy Graphing.

As mentioned above, I'd like to support plotting an arbitrary function as the vertex color across a surface; matplotlib has no mechanism for this. Jason and I have discussed allowing geometric figures and line segments from the geometry module to be drawn through the graphing interface; again, not possible. I'd also like to support interactive rotation, zooming, translation, etc., and possibly someday (outside the scope of GSoC) point-picking; to my knowledge, you cannot do these things in matplotlib.

As I said in my proposal, 3d graphing will be supported through PyOpenGL. In general, this is not a very difficult task (there is a good summary of what it entails at the plot3d website) and this approach will provide the flexibility I want.

The upshot of all this is that I am considering a shift away from matplotlib altogether and toward supporting all graphing, 2d and 3d, through a unified OpenGL interface. I only want to support a fraction of the features of matplotlib. (I'm not trying to banish matplotlib from sympy. In any event, one can easily use matplotlib directly. See the current revision of modules/graphing.py in SVN for an example.) If my project goal was simply to write a SymPy wrapper for matplotlib, I'd be done before the official coding period even begins. To do this right, I'm going to need to get my hands a bit dirtier.

The 3d support in Matplotlib is better than I'd thought (it can do interactive rotation and scaling). There is a good example here. It also looks like it might be able to do colormaps. I'm looking into it in more depth right now.

Tuesday, May 8, 2007

Sympy Graphing: Usable Progress, Early Frustrations

Over the weekend, I did a bit of refactoring and added a couple of improvements to sympy/modules/graphing.py (where Fabian had laid a good foundation already). First, I've extended plot() to accept a list of functions in addition to a single function.

from sympy import Symbol
from sympy.modules.graphing import plot
x = Symbol('x')
plot([sqrt(x), log(x), sin(x)], xlabel="x label")

I also added in some code so that functions with discontinuities, such as sqrt where x < 0, are plotted correctly.

f_list = [sqrt(x), sqrt(-x), -sqrt(x), -sqrt(-x)]
plot(f_list, [x, -10.0, 10.0], title="Square Roots")

Unfortunately, this code has hit a snag getting through automated testing. At this point, my best hypothesis is that there is some incompatibility between py.test/doctest and the Tk backend for pylab. I'm going to try a different backend next. Ondrej has opened an issue here.

Monday, April 30, 2007

GEB Reading Schedule

Here's the schedule I've come up with for reading and discussing GEB. Page numbers refer to the 20th-anniversary Edition. You can also add the google calendar.

2007-05-14 Introduction (30 pages)
2007-05-21 Chapter 1-3 (49 pages)
2007-05-28 Chapter 4 (45 pages)
2007-06-04 Chapter 5 (31 pages)
2007-06-11 Chapter 6-7 (46 pages)
2007-06-18 Chapter 8-9 (81 pages)
2007-06-25 Chapter 10 (52 pages)
2007-07-02 Chapter 11-12 (69 pages)
2007-07-09 Chapter 13 (32 pages)
2007-07-16 Chapter 14-15 (57 pages)
2007-07-23 Chapter 16 (64 pages)
2007-07-30 Chapter 17 (35 pages)
2007-08-06 Chapter 18 (47 pages)
2007-08-13 Chapter 19 (43 pages)
2007-08-20 Chapter 20 (58 pages)

Monday, April 23, 2007

GSoC 07 Book Club Selection: GEB

It's been a week, and the clear winner of the poll is Gödel, Escher, Bach: An Eternal Golden Braid (Amazon) , henceforth known as GEB. In the preface to the 20th anniversary edition, the author describes GEB as "a very personal attempt to say how it is that animate beings can come out of inanimate matter."

If you don't already have a copy, you still have at least a couple of weeks before we start. I'm presently working on a discussion schedule, and input is appreciated. One proposal made by Martin Harrigan is to read two chapters per week (for a total of 10 weeks). I think he's almost got it, but I'm thinking I'll spread out the longer chapters to take full advantage of the 12-15 weeks we have available (depending on the start date).

Update: Because of finals, I'm not going to get to this until Wednesday, sorry for the wait.

Tuesday, April 17, 2007

GSoC Book Club Poll

Update: The poll has ended. View the results.

Summer Reading

I am addicted to books. Rather, I am addicted to collecting them--I've never actually found time to read one. This summer, I'm going to make time. Here are some ideas:
Update: Is there interest in a GSoC 07 Book Club? We would choose one or more books (depending on length), read, and discuss. If you're interested or have book suggestions, please leave a comment.

Update 2: Please vote in the poll.

Google Summer of Code 2007 with SymPy

My project proposal Python as a Symbolic Graphing Calculator with SymPy, PIL, and PyOpenGL has been accepted for Google Summer of Code 2007 under the patronage of the Python Software Foundation!

I'll be working with Ondrej Certik, who started the SymPy project, a CAS for Python. I wanted to contribute to the SymPy project for several reasons. Most importantly, I love Python. Even when I'm coding C#, C++, or Java I usually end up metaprogramming in Python much of the time. Secondly, I am a math student. SymPy is useful to me already, and it's only in version 0.3. I don't think I'm the only one who is unsatisfied with other CAS offerings. I think SymPy has a lot of potential, and I'm glad to be part of the team.

Once I get school over with, this project will have my full attention. I'll be updating the blog with my progress and anything interesting I find along the way. I'll also be writing about other summer projects, including my summer reading. More on this soon.