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.