Your browser is very old. You might enjoy surfing the web more if you used something newer like:

Google Chrome

Even Firefox would be OK.

If you're being forced at gunpoint to use Internet Explorer, you should at least upgrade it. Version 8 is tolerable and 9 will be OK when it comes out.

Posts from February 2010

Coding for Doctors in Haiti

A colleague of mine who does a lot of programming work in the medical community came to me with an interesting project.

A number of doctors were heading to work at a medical camp in Haiti treating earthquake victims and they needed an easy way to track patient information. Almost all of the doctors there have iPhones so the initial thought was to write a quick iPhone app using Appcelerator. That way, patient information could be stored locally on the iPhone until a network connection was available to sync the data up to a server somewhere.

Unfortunately the turn-around time was too tight to navigate the process of getting an app into the Apple App Store. This is a perfect example of why I dislike the Apple model of only allowing approved apps onto the iPhone. We would had a much wider range of solutions had we been able to easily distribute an app ourselves.

In the end, we had to go with a simple PHP/MySQL web application that used jQtouch to simulate the iPhone look-and-feel (with some tweaks so it would display properly in Firefox and IE). The basic web app was fairly simple. Just a couple of pages with lists of existing patients and a form for entering patient information.

Initially the web app was hosted on a server here in the U.S. but the satellite internet connection in the medical camp in Haiti proved too unreliable. In the end, one of the doctors was able to get a hold of a Windows 2003 which we installed WAMP on. With some minor tweaking, we were able to move the web app from the US-based server over to the WAMP server in Haiti. A team of Google & Apple engineers setup a wireless LAN that covered the medical camp and the doctors were able to move freely about the camp with their mobile devices entering patient information.

Additional features were added over the next several days. The camp is organized into rows of tents so the app has a mechanism to easily list patients in a specific tent or an entire row. A native iPhone app would have been nice because we could’ve used the GPS to do that sort of thing automatically. We also added the ability to upload images (unfortunately not from the iPhone itself) so the doctors now have access to x-rays and other patient photos directly from their devices.

Most of the difficulty with the whole process was related to the lack of infrastructure in Haiti. The lack of reliable Internet meant that most communication and file transfer had to happen via email and we had to make an effort to keep things small. Cell phone/satellite phone service is spotty at best. Being on the phone with these doctors and hearing the chaos in the background and hearing about the condition of the people they’re treating is unreal. I have an enormous amount of respect for these medical professionals who have traveled to Haiti and are doing their best to help.

All in all, an interesting experience with a different set of challenges and I feel privileged to have been able to contribute, albeit in a very small way. Score 1 for the power of technology.

Changing an application’s favicon in CherryPy

While it’s technically simple, I found the documentation about changing the favicon of a CherryPy site to be somewhat confusing. This is my attempt to clear it up a bit.

There are two different ways of supplying config information:

  1. Config information from a text file (you can pass a filename or open file handle).
  2. Config information from a Python dictionary in your code.

I’m going to concentrate on the second method for now.

Here’s my config dictionary.

config = {
    '/': {
        'log.error_file': os.path.join(os.path.dirname(__file__), 'site.log'),
        'environment': 'production',
    },
    '/favicon.ico': {
        'tools.staticfile.on': True,
        'tools.staticfile.filename': '/path/to/favicon.ico',
    }
}

Notice that the dictionary contains two sub-dictionaries, one for ‘/’ and one for ‘/favicon.ico’.

‘/’ is where global application configuration goes. In this case, we’re setting where the error log goes and what type of environment we’re running.

CherryPy has a default favicon.ico that it will use if one isn’t specified. The second part (‘/favicon.ico’) of the dictionary overrides that default and specifies the location of a different file to use.

My last post about configuring CherryPy to run with Apache defined a method called start() that was responsible for starting the CherryPy engine when called from apache.

To use this new config setup, we’re going to change that start() method slightly to this:

def start():
    cherrypy.tree.mount(root, '/', config=config)
    cherrypy.engine.start()

Previously, we passed the ‘/’ config parameters to cherrypy.config.update().

Now we pass the entire config dictionary along. This approach is nice because we can also store application configuration info (that CherryPy doesn’t necessarily care about) and then get values out of it by using the cherrypy.request.app.config dictionary.

Another addition to this approach is to configure an area for serving static content (CSS, javascript, images, etc). That can easily be done by adding the following item to the config dictionary:

'/static': {
        'tools.staticdir.on': True,
        'tools.staticdir.dir': os.path.join(os.path.dirname(__file__), 'static')
    },

This adds the path /static (looking for the directory static in the same directory as the app) and sets it as a static dir. Now anything that uses the url /static will point to files within the static directory.

For example, this will now link to the static file global.css rather than looking for a CherryPy route.

<link rel="stylesheet" type="text/css" href="/static/css/global.css" media="screen"><link>