Python Programming, news on the Voidspace Python Projects and all things techie.
Gadgets and Computer Hardware
I love gadgets and I regularly have to restrain myself from buying new toys that I not only don't need, but will probably never use. Often my restraint fails...
One of the difficulties of buying computer hardware is finding unbiased reviews of products that I can actually get hold of. My favourite magazine for peripheral reviews (UK) is Computer Shopper. Unfortunately, the models they review are rarely the models I can purchase, and the models for sale are rarely the models reviewed... sigh
In terms of buying gadgets and hardware, I've often engaged in price comparisons and almost always return to my preferred triumvirate of suppliers (again UK biased):
- Dabs - great returns support, but terrible pre-sales tech support
- Amazon - surprisingly cheap for mainstream devices
- Ebuyer - I've never had problems, but my boss had great difficulties trying to return goods - so I try to avoid them
In the past I've also used Scan, but recently they seem to be more expensive than the competition. Often I will compare prices with Ebay shops to check that I am not getting ripped off, but they rarely seem to be cheaper.
I have purchased several major items in the last year, most of which I'm very happy with:
Now this I have been pleased with. Less than 100 pounds for a black and white laser printer with scanner. It comes with drum and toner (something Dabs couldn't or wouldn't tell me pre-purchase). The best feature is that the scanner (colour) enables the printer to act as a photocopier, even when the computer is switched off. I can't tell you how useful this has been.
As always replacement toner is expensive, but with moderate use the included one has lasted a year. I am just replacing it now. I have had no problems with this printer and am very happy with the print quality.
We don't very often print photos, but I wanted a colour printer to go with the black and white. The print quality on glossy paper is fantastic, amazingly sharp. For a printer that cost around sixty quid I am very impressed. Again, no problems but I haven't used it heavily. The 'quality' ink is expensive, but I haven't yet finished the included cartridge.
I bought this because my wife kept complaining about the clattering of my previous keyboard whilst we were watching films.
Expensive for a keyboard, but good looking and quiet. The Enter key is smaller than I am used to, but I adapted very quickly and am pleased with the keyboard.
(Affectionately known as 'the slug' by its fans.) A small server for putting hard drives on a network. Unfortunately accessing the drive attached to this baby is painfully slow; now I have a gadget I don't use and an ext3 formatted 300gig hard drive...
The slug is customizable as a mail-server, web-server or whatever you want through the NSLU2-Linux project. This is enormously appealing, but not actually that useful...
I bought this to replace an IBM Thinkpad T30 (nice laptop). The Fujitsu is better looking, but despite having twice as much memory (1 GB) and an AMD 64 bit twin core processor (Turion) it actually seems slower than the Thinkpad. For example, it can't cope with showing a movie on an external monitor whilst I work on it (which the Thinkpad could, despite a lower specced graphics card). This laptop is basically fine for my commuting and travelling use, but ultimately I'm a bit disappointed.
I will 'upgrade' to a Mac soon and am wondering if it is worth the extra for a Macbook Pro. I'd like the extra speed, but would prefer a smaller laptop. I'm also reluctant to buy before the release of Leopard, but don't want to wait too long either.
Very nice. Does what it says on the box. Straightforward to configure and never had any problems with it. So much so that I basically forget it is there. My wife uses the wireless with the laptop, but this is usually in the same room as the router so I haven't tested the range.
I actually bought this from a far-eastern shop called Onestop-Digital. It arrived within three days and was marked as a warranty repair so I was charged no import duty (very naughty!).
This was a massive step up from our previous camera and cost perhaps a little more than I should have spent given how amateur my photography is... The performance in low light levels isn't quite as good as I was led to believe (only pretty good instead of awesome). It has a nice big LCD display and the hardware anti-jitter works well. It's a very nice camera and the battery life is awesome.
Aren't large monitors ridiculously cheap these days? It has a standard 1280x1024 resolution and is my main monitor. It doesn't have an adjustable stand, but the picture quality is fine (perfect as far as my uneducated eyes can tell). No dead pixels and another problem free purchase.
Another Syncmaster, this time a wide screen for watching movies. This one has a decent stand! Same display quality (1680x1050 resolution) as the 913V.
That'll do for now...
Python and the Robots Companies - Python in Accelerando
Python certainly turns up in some odd places. Here it features in Accelerando, a Science Fiction novel by Charles Stross. Python powers some robotic shell companies, which create new robotic shell companies, which create...
"Yeah?" Manfred struggles to sit up. His mouth feels like the inside of a tomb, and his eyes don't want to open.
"My name is Alan Glashwiecz, of Smoot, Sedgwick Associates. Am I correct in thinking that you are the Manfred Macx who is a director of a company called, uh, agalmic dot holdings dot root dot one-eight-four dot ninety-seven dot A-for-able dot B-for-baker dot five, incorporated?"
"Uh." Manfred blinks and rubs his eyes. "Hold on a moment." When the retinal patterns fade, he pulls on his glasses and powers them up. "Just a second now." Browsers and menus ricochet through his sleep-laden eyes. "Can you repeat the company name?"
"Sure." Glashwiecz repeats himself patiently. He sounds as tired as Manfred feels.
"Um." Manfred finds it, floating three tiers down an elaborate object hierarchy. It's flashing for attention. There's a priority interrupt, an incoming lawsuit that hasn't propagated up the inheritance tree yet. He prods at the object with a property browser. "I'm afraid I'm not a director of that company, Mr. Glashwiecz. I appear to be retained by it as a technical contractor with non-executive power, reporting to the president, but frankly, this is the first time I've ever heard of the company. However, I can tell you who's in charge if you want."
"Yes?" The attorney sounds almost interested. Manfred figures it out; the guy's in New Jersey, it must be about three in the morning over there.
Malice - revenge for waking him up - sharpens Manfred's voice. "The president of agalmic.holdings.root.184.97.AB5 is agalmic.holdings.root.184.97.201. The secretary is agalmic.holdings.root.184.D5, and the chair is agalmic.holdings.root.184.E8.FF. All the shares are owned by those companies in equal measure, and I can tell you that their regulations are written in Python. Have a nice day, now!" He thumps the bedside phone control and sits up, yawning, then pushes the do-not-disturb button before it can interrupt again. After a moment he stands up and stretches, then heads to the bathroom to brush his teeth, comb his hair, and figure out where the lawsuit originated and how a human being managed to get far enough through his web of robot companies to bug him.
Hey, even programmers have personality - and now we can prove it.
According to the Programmer's Personality Test I'm a DHTC.
I love these online tests, they always say the nicest things.
- You're a Doer (as opposed to a planner).
- You like coding at a High level.
- You work best in a Team.
- You are a Conservative programmer. (Less code is best...)
Curves from Contour Map
I have a CSV data set which I wish to draw contours from. Effectively this is a 3 dimensional map (they are actually risk contours with the third dimension representing risk).
-10 -5 0 5 10 -10 1 3 7 3 1 -5 2 4 9 4 2 0 3 5 12 6 5 5 2 4 9 4 2 10 1 3 7 3 1
Made up data - but you get the idea. I could just colour each co-ordinate, but it will look yucky.
Any idea for an algorithm (or library) to convert these points into curves?
The approach I can think of (not tried yet) is to group co-ordinates of similar 'height' and connect them - but detecting the order, and also disconnected pools, feels like it will be difficult.
I know that some charting libraries will eat this data for me, but I am looking for a .NET solution that looks attractive... It seems like a challenging and interesting problem anyway.
For reference this is what matplotlib produces:
Pretty good, shame I can't use it directly from IronPython. The imports take around a second, which means that launching it as a subprocess makes dynamically generating the images a pain. I'm not convinced my CPythonServer is such a good idea... Maybe I need to dig into the contour source code and see if I can replace numpy arrays with .NET ones.
This is what gnuplot produces, which is also not bad (but painful to produce):
Gnuplot executes very quickly, so would be fine launched as a subprocess.
ZedGraph draws contours using lines, so although it produces much more attractive looking images it isn't ideal for this job unless I can convert the coordinates into line data.
Looks like the marching squares algorithm (patented!) is what I need if I want to do this myself.
On the other hand my Dad likes the gnuplot output and the interactive mode is good for over coming the 'complete lack of error reporting from the command line'. (Presumably because it is compiled as a Windows application and not a console application - so hopefully easy to fix.)
IronPython Charting and ZedGraph
Ok, last entry on charting for a while I promise.
It doesn't look like I can generate vector images from it (easily), but I may be wrong and decent image files will still be better than the current situation.
You'll need the zedgraph.dll, you can download it from the sourceforge project.
Although the samples are generally focussed on using a Windows Forms control, adapting them to produce images instead is easy. This sample produces multi-colored bars  (using a five color gradient fill):
from ZedGraph import GraphPane, PointPairList, Fill, FillType
from System.Drawing import Bitmap, Color, Graphics, RectangleF
from System.Drawing.Imaging import ImageFormat
from System import Array, Math, Random
title = "Multi-Colored Bar Chart"
xAxisTitle = "Bar Number"
yAxisTitle = "Value"
pane = GraphPane(RectangleF(0, 0, 640, 480), title, xAxisTitle, yAxisTitle)
# The ZedGraph data collection class
ppl = PointPairList()
# A .NET random number generator
rand = Random()
for i in range(16):
x = float(i + 1)
y = rand.NextDouble() * 1000
# The Z axis is the color, from 0.0 to 4.0
z = i / 4.0
ppl.Add(x, y, z)
colorList = [Color.Red, Color.Yellow, Color.Green, Color.Blue, Color.Purple]
colors = Array[Color](colorList)
curve = pane.AddBar("Multi-Colored Bars", ppl, Color.Blue)
curve.Bar.Fill = Fill(colors)
curve.Bar.Fill.Type = FillType.GradientByZ
curve.Bar.Fill.RangeMin = 0
curve.Bar.Fill.RangeMax = 4
paleBlue = Color.FromArgb(220, 220, 255)
pane.Chart.Fill = Fill(Color.White, paleBlue, 45)
pane.Fill = Fill(Color.White, paleBlue, 45)
# A hack because the axis change needs a real
# image if we aren't using a control
bm = Bitmap(1, 1)
g = Graphics.FromImage(bm)
The output is:
|||Looks like my CPythonServer won't be going into production use.|
|||Adapted from this example.|
CPythonServer: Executing CPython Code from IronPython
As you may have gathered I am trying to generate charts from an IronPython application, and none of the free .NET charting libraries do quite what I want. The CPython Server executes arbitrary Python code sent to it in a POST request.
The code sent should set a 'response' variable, and an optional 'filename' variable to determine the mime type of the response. Both of these should be strings.
When sent a simple pylab script, the first request takes 500 milliseconds from request to completion of reading the image. The second takes less than a hundred milliseconds (the first takes longer because it has to execute the imports).
Ok, so it's a hack (BaseHTTPServer is too easy to extend), but you can use it to interface IronPython code (or uhm... anything) to CPython code.
|||Uhm... that was a joke.|
Generating Images with Matplotlib
As I mentioned before, I'm experimenting with generating chart images.
For the moment I'm experimenting with generating images from matplotlib.
The requirements are:
The docs seem to assume you are using matplotlib with a GUI toolkit, but there is a nice cookbook recipe on generating images for Django.
This snippet generates a JPG image, it then launches it with the default Windows image viewer:
from PIL import Image
from matplotlib.backends.backend_agg import FigureCanvasAgg as FigureCanvas
from matplotlib.figure import Figure
def SaveImageFromBuffer(size, buffer, filename, format='JPEG'):
im = Image.fromstring('RGB', size, buffer, 'raw', 'RGB', 0, 1)
filename = 'test.jpg'
fig = Figure()
canvas = FigureCanvas(fig)
ax = fig.add_subplot(111)
size = canvas.get_renderer().get_canvas_width_height()
buf = canvas.tostring_rgb()
SaveImageFromBuffer(size, buf, filename)
So far so good.
This work is licensed under a Creative Commons Attribution-Share Alike 2.0 License.