Python wedding vows
Kevin Day, February 24th, 2008I was inspired by this valentine’s day card, and a quote by Blake Ross in Founders at Work. So this wasn’t my original idea, but I still consider my implementation to be heartfelt and sincere.
I asked Kristen if I could use these vows in the wedding, but she didn’t seem thrilled about it. I’ll have to work on her some more.
conditions = ["better", "worse", "richer", "poorer", "sickness", "health"]
while(True):
for time in [time for time in life if time in conditions]:
have = True
hold = True
love = True
cherish = True
if death:
break
Google apps and Microsoft’s file format
Kevin Day, February 21st, 2008Yet another post about a Google app and Joel on Software… anyways…
I don’t know if it’s my imagination, but Google Spreadsheets always seems to be a little bit faster and snappier each time I use it. Right now I’m working from a coffee shop with spotty internet connection, but it’s working as good as ever.
That made me think about how Google must know absolutely every tiny trick about optimizing Javascript in ways that no other company can even fathom. It seems like a good parallel to how Joel says Microsoft was light-years ahead of most other software companies for knowing how to write the fastest code possible on the hardware of the time.
Maybe in 10 years we’ll see Google release their specifications for how they store and update a spreadsheet and complain about how complex it is. However it’ll be that way because it includes hacks to work around IE6’s bugs.
Wanted: Smarter Gmail filtering
Kevin Day, February 20th, 2008A while ago when I first saw Gmail’s option for “Filter messages like these,” I thought that it would use Bayesian statistics to automatically determine which category an email falls into. I was disappointed that it just starts the filter menu with the “To” field pre-populated.
Joel Spolsky mentioned that his company’s software filters email that way and it works effectively.
It just seems like a lot more Google-like way of organizing things rather than filtering based on To/From addresses.
Car wrecks and high school physics
Kevin Day, February 15th, 2008Did you realize that increasing your driving speed from 60 mph to 80 mph nearly doubles your kinetic energy? I never thought about it, but it’s simple KE = 1/2 mv^2.
Try doing billiard ball collision problems with double the energy and see how they go. Not that car accidents are elastic collisions, but that energy has to go somewhere.
PyGTK Hello World program for images
Kevin Day, February 2nd, 2008I’m learning PyGTK to create GUIs with python, but it’s been slow going. My current application primarily uses images, but most of the beginning tutorials for PyGTK use buttons for their “hello world” applications. The PyGTK tutorial is thorough, but I find it easier to work with lots of smaller examples that aren’t as in-depth.
Below is my simple “hello world” application for working with images. When it runs, it displays the first image of a directory. When you click on the image, the next image in the directory is displayed. I kept it basic so that it would be easy to pick up on the PyGTK stuff without getting caught up in other details.
Here’s the code, and below it is a description:
#!/usr/bin/env python
# hello_world_image.py
import pygtk
pygtk.require('2.0')
import gtk
class image:
def __init__(self):
self.window = gtk.Window()
self.event_box = gtk.EventBox()
self.image = gtk.Image()
self.image_num = 0
self.image.set_from_file(self.make_image_name(self.image_num))
self.event_box.connect("button_release_event", self.change_image)
self.event_box.add(self.image)
self.window.add(self.event_box)
self.window.show_all()
def make_image_name(self, image_number):
return "photos/img_" + str(image_number) + ".jpg"
def change_image(self, widget, event):
self.image_num += 1
self.image.set_from_file(self.make_image_name(self.image_num))
return True
def main():
gtk.main()
return 0
if __name__ == "__main__":
image()
main()
To add an image to a PyGTK application, just create an Image widget with gtk.Image() and tell it where to find the image with the set_from_file method.
The trick is that Image widgets do not react to events (button clicks, key strokes, etc.) so you have to put the Image widget in an Event Box widget. The event box doesn’t take up space in the GUI; it’s just an invisible container that will emit a signal when an event occurs. In this application, the change_image callback function is bound to the event box, but it still operates directly on the Image widget.
For this program to work it assumes that the images are in a folder named “photos” which is in the same directory the application is running in. Also, the images have to be named sequentially: img_0, img_1, img_2, etc. This is how I plan to use the program, but you could just as easily read the contents of the folder into a list and use that for the image names.
Here’s my directory of images:

And here’s my working program:

If you’re wondering, it’s not my dog. It’s just an image I found on Flickr.
Hope this little program helps other people starting off with PyGTK.
Bring them the game to them and like score a lot of touchdowns
Kevin Day, February 1st, 2008I’ve already broken my New Year’s Resolution to write a blog post every week, but I’ve been sick and haven’t had the energy to do anything blog-worthy.
I’m better now, and here’s something funny to make up for the lull. It’s from We The Robots, a comic I just discovered and is a close second to xkcd for my favorite online comic strip. Click on the image to see the full version if it’s too small to read.
But seriously, if you relate to Chad Jeffries as well as I do, try finding a Toastmasters group in your area. It’s a fun way to improve your communication skills.
Great blogging quote
Kevin Day, January 12th, 2008From Jeff Atwood, Thirteen Blog Clichés:
It’s always been deeply disappointing to me that we have the whole of human history to talk about, and most people can’t get past what happened today.
Asimov’s animated adjectives and adverbs
Kevin Day, January 6th, 2008I’ve noticed that I typically don’t use vivid words when describing things or events. My speech and writing are dry and tend to be strictly factual. It’s probably because that’s how most of my communication is expected to be.
While reading “I, Robot,” I was impressed with the way that Asimov combines provocative descriptions along with technical information, like this:
It was in the last room, the one nearest the nose, that the monotony broke. A curving window of non-reflecting glass was the first break in the universal metal, and below it was a single large dial, with a single motionless needle hard against the zero mark.
Or this:
The alarm system raised its fearful clangor with a horrifying suddenness. Lanning clicked on communications with an almost paralytic spasm. The breathless words froze him.
At work I would get weird looks if I said ”the single motionless needle was hard against the zero mark” instead of “the gage read zero.” Nonetheless, I am going to make an effort to be more descriptive when I get a chance.
Here’s a first attempt. The weather was pretty good today in Clevleand. Perhaps Asimov would describe it this way:
The sun heroically burst through the cloudy sky to rescue the tired city from its cold icy captor.
Obligatory “got a new toy” post
Kevin Day, December 29th, 2007For Christmas I received a Nokia N800 internet tablet, which was at the top of my wish list. So far it’s been great to use. Couldn’t be happier.
My initial ideas for applications to write for it are (in increasing order of complexity):
- Digital picture frame that pulls images from Flickr based on tags supplied by the user.
- Fantasy football live stats calculator
- Grocery store helper that suggests what food to buy based on the food I have in my apartment, cost, and nutritional value.
I’m just starting with the Flickr-frame application for my desktop, and once it’s finished then I’ll try porting it to the N800. At the moment I’m using PyGTK for the GUI.
Reverse-engineering Gmail’s spam filter
Kevin Day, December 21st, 2007I gave a speech at Toastmasters two weeks ago about how a spam filter works. The audience was non-technical, so the speech was mostly a summary of Paul Graham’s essay, A Plan for Spam.
To personalize the speech, I wanted to add some examples from my email. But in order calculate spam probabilities for emails, I needed to find how many times each word in an email appears in my normal email and how many times it appears in my spam.
Hacking Gmail
Since I use Gmail, I couldn’t easily write a program to search my emails so I had to rely on Gmail’s search capability. I wasn’t able to count the total occurrences of each word, but I was able to count the number of emails in which a given word occurs.
I used this url to go to the last search page for the word “google” in my good email:
https://mail.google.com/mail/#search/google/p999
And this url goes to the last search page for the word “google” in my spam:
https://mail.google.com/mail/#search/in%3Aspam+google/p999
The total number of emails in the search is in the upper right-hand corner. This hack isn’t needed for rare words; there is usually a link for “Oldest” on the search results page. Commonly occurring words, however, don’t have that link.
Only the email body is searched. Headers are ignored.
Calculating spam scores by hand
By modifying the urls above for each word in an email, I was able to count the total number of emails each word appeared in for spam and non-spam. Then I used the simple Bayesian statistics outlined by Graham to calculate the spam scores for three emails:
- A spam, correctly filtered as spam
- A normal email, correctly not filtered as spam
- A spam that slipped through the filter and appeared in my inbox
The correctly identified spam had a spam probability of 100%. The normal email had a spam probability of 0%. And the spam that got through had a spam probability of 44%.
Hmm… it’s interesting that this simple hack almost correctly identified the spam that Google didn’t catch.
Here is the spam:
Your new Diploma!
No examinations!
NO classes!
NO textbooks!
AND
100% Discrete!
Satisfaction guaranteed!
+1 206 30 90 336Regards!
and each word sorted by its spam probability:
satisfaction 73% diploma 68% discrete 61% examinations 53% and 46% your 45% regards 44% no 40% guaranteed 39% new 38% textbooks 36%
I think they key to this getting through was that I was recently a student and the word “textbooks” was in some of my normal emails. Otherwise it might have been tagged as spam.
Getting more data
Based on these three data points, I can conclude that Gmail’s spam filter isn’t any more sophisticated than the one Paul Graham outlined in 2002. Well, maybe more than three emails should be analyzed before making an assertion like that.
Since it’s tedious doing it all by hand, I’d like to see a Greasemonkey script do the work for me. I’m curious how closely the results of this simple filter would compare to Gmail’s. If my curiosity stays high I might try writing the script myself. I haven’t written a Greasemonkey script before though so I don’t know how much work it will be.

