Twice as fast. Half the battery life.

July 13th, 2008

I’m enjoying my new iPhone 3G, though I haven’t gotten much time on a 3G network with it yet (at the summer cottage this weekend). Had to get a white one to get 16 gig (even though I was about 30th in line, the AT&T store had already sold out of black). It has noticeably worse battery life when 3G is turned on. Not a big surprise, but increasing the need for certain accessories. Rather than wondering what phone he used before the iPhone, I’m very curious if Steve Jobs is going to use an iPhone 3G as his day-to-day cell phone. That might be our best chance of finally getting a replaceable battery.

So far, Paul has been holding out for an Android phone. I’m too much of an early adopter. Steve Jobs has already milked me out of about five iPods, a MacBook Pro, and two iPhones. It won’t take much for me to switch to an Android phone if it can compete (or improve…can you say “cut and paste?”) on the iPhone.

New server for OpenMRS.org

June 8th, 2008

We just migrated to a new server (thanks atomicturtle, bwolfe!).  Writing a quick blog to test the feed aggregator.  Hopefully the website will be a bit faster on the new server.

ReviewBoard for OpenMRS GSoC 2008

May 5th, 2008

Thanks to the generous folks at Review Board, OpenMRS has the opportunity to try out Review Board for performing code reviews for our GSoC projects.

Students can download post -review (a python script) and submit changes for review simply by issuing the command “post-review” within the root of their local copy.

Mentors can review the changes and attach comments to specific parts of the code for the student to review prior to submitting the code.

NOTE: since this feature is being generously hosted by Review Board, this feature should only be used for student projects at this time. If we decide that we want to continue using Review Board, then OpenMRS will host our own instance.

Thanks to chipx86 for his help in getting this set up. And thanks to r0bby for letting us know about the opportunity!

Firefox Incorrect Window Position

April 25th, 2008

Okay. I’ve been enjoying Firefox 3 Beta, but today it started opening up its window way off to the right of my desktop and about the height and width of a stamp. WTF? A little Googling led me to a fix: Corrupt localstore.rdf. So if you’re Firefox window starts misbehaving, try deleting localstore.rdf in your Firefox profile folder and letting Firefox re-create it.

So, why am I blogging about something mundane like this? A few reasons:

  1. I’m trying out the latest update to ScribeFire
  2. Trying to get more in the habit of blogging.
  3. Sometimes it’s nice to have stuff like this tip blogged for the next time around

Determine a the JDK version used to make a JAR file

April 25th, 2008

Maybe there’s already a tool to do this, but a quick Google search only yield this tip.  So, I made a quick little JAR reader to fetch the estimated version from the manifest:

import java.util.*;
import java.util.jar.*;
import java.io.*;
 
/*
 * Sends the "estimated" JDK version (expected to be in the jar manifest "Created-By" attribute)
 * to System.out.
 */
public class JarJDKVersion {
 
	public static void main(String[] args) {
 
		JarFile jarFile = null;
		Manifest manifest = null;
		String version = null;
 
		// Report usage if no parameters given
		if (args.length < 1) {
			System.out.println("usage: java JarJDKVersion <jarfile>");
			System.exit(0);
		}
 
		// Open specified jar file
		try {
			jarFile = new JarFile(args[0]);
		} catch (IOException e) {
			System.err.println("Unable to read jar file: " + args[0]);
			System.exit(1);
		}
 
		// Fetch manifest from jar file
		try {
			manifest = jarFile.getManifest();
		} catch (IOException e) {
			System.err.println("Unable to read manifest from jar file: " + args[0]);
			System.exit(2);
		}
 
		// Display version from jar manifest
		Attributes attributes = manifest.getMainAttributes();
		version = attributes.getValue("Created-By").toString();
		if (version != null)
			System.out.println(version);
		else {
			System.err.println("Unable to determine version from jar manifest.");
			System.exit(3);
		}
 
	}
 
}

Download the source code or the class file.

Now anyone can join #openmrs on IRC

March 30th, 2008

Thanks to the strong work of the folks at Mibbit.com, you can now join the #openmrs IRC channel directly from the OpenMRS.org website!  Just visit irc.openmrs.org to try it out.

Making a groovy module for OpenMRS

December 13th, 2007

No, I’m not smoking anything and I’m not trying to do a Greg Brady impersonation. By “groovy” module…I mean a Groovy module. :P

Groovy has the potential to bring the fun and rapid prototyping benefits of languages like Ruby to the Java scene. But a big advantage of Groovy is that it’s built in Java and designed to both work with Java and give Java programmers a fairly easy introduction to the fun of higher level scripting.

So, this Groovy module is a just testing the waters. Groovy is incredibly easy to embed into any Java application (they make it ridiculously simple…a single JAR library is all it takes). So, I made a simple little module that embeds Groovy into OpenMRS and gives a single web page with a textarea where you can play with Groovy scripting. The module adds a “Groovy Scripting” privilege to OpenMRS that you could assign to users…but I wouldn’t recommend it. Currently, this is for testing only and shouldn’t be used in production until we have some more experience with it.

So, fire up a copy of OpenMRS, install the new Groovy module and let’s take it for a spin.

Groovy Scripting

Once the Groovy module is installed, you should see a link in the OpenMRS administration page under a new “Groovy Module” section. Clicking on that link should bring up a simple textarea dialog like the one shown above. Sorry…but that’s about as fancy as it gets for now.

There are several special variables automatically bound to the context for you: cohort, concept, encounter, form, locale, logic, obs, patient, person, and user. Most of these are bound to the corresponding service; locale is the locale of the current context, which is handy for some API calls.

So, type the following into the textarea and click the GO button:

p = patient.getPatient(2)
println p.givenName

That should display the given name of patient #2 from your database. Here are a few more examples of Groovy scripts you can copy and paste into the textarea:

Want to see a 100 concepts?

import groovy.xml.*
 
writer = new StringWriter()
b = new MarkupBuilder(writer)
 
b.table(border: 1) {
  for (i in 1..100) {
    c = concept.getConcept(i)
    tr { td(c.name, style:"font-weight:bold"); td(c.name.description) }
  }
}
 
println writer.toString()

How about some encounters?

p = patient.getPatient(2)
println "&lt;h2&gt;${p.givenName} ${p.familyName} Encounters&lt;/h2&gt;"
for (e in encounter.getEncounters(p)) {
  println "${String.format('%tF', e.encounterDatetime)} - ${e.creator}&lt;br /&gt;"
  println "&lt;ul&gt;"
  for (o in e.getObs()) {
    println "&lt;li&gt;${o.concept.name}&lt;/li&gt;"
  }
  println "&lt;/ul&gt;"
}

Or dump out some observations.

p = patient.getPatient(2)
println "&lt;h2&gt;${p.givenName} ${p.familyName}&lt;/h2&gt;"
for (o in obs.getObservations(p, false)) {
  println "${o.concept.name} &rarr; ${o.getValueAsString(locale)}&lt;br /&gt;"
}

Any patients with “nga” in their name?

s = "nga"
for (p in patient.getPatientsByName(s)) {
  n = "${p.givenName} ${p.familyName}".replaceAll("(?i)($s)", "&lt;b&gt;&#92;$1&lt;/b&gt;")
  println "${n}&lt;br /&gt;"
}

You can even manage modules…but don’t stop the Groovy module!

import org.openmrs.module.*
 
// Uncomment the next line to start the printing module
// ModuleFactory.startModule(ModuleFactory.getModuleById("printing"))
 
// list out your running modules
for (m in ModuleFactory.startedModules) {
  println "${m.name} : ${m.started}&lt;br /&gt;"
  // uncomment the next line to stop the printing module
  // if (m.name == "Printing") ModuleFactory.stopModule(m)
}

As you may gather from trying the examples above, I’m redirecting the stdout from the script into a <div> on the page as HTML, so you can play with formatted output. If you want to simply print some text within Groovy and preserve whitespace, then just put println “<pre>” and println “</pre>” around your println statements. Or use <textarea></textarea> instead.

Learning Groovy (especially for Java developers) is pretty easy. See the Groovy documentation for more about the language. Remember that you don’t need get and set — e.g., person.givenName will execute person.getGivenName() for you. And you can enjoy a break from the semicolons. :)

The real fun with Groovy is that you can throw in good ol’ import statements and directly reference java classes whenever you want.

What next?

While the ability to execute some scripts on the fly can be fun…maybe even handy for testing out code during development, my real hope is to evolve toward a Grails module that could facilitate rapid prototyping of web forms or quick & dirty report pages. The ultimate would be a Grails module that provides a quick and easy starting point, let’s you edit and extend it without any re-compile steps, and then provides a button to download a snapshot of the current state of the module as a new omod file to facilitate rapid prototyping of OpenMRS modules to target quick & dirty development needs and/or prototype new functionality.

Now that would be groovy!

The 5 B’s of user interface design

December 5th, 2007

I’m sitting in Nairobi at the WHO Standards Meeting listening to Mike McCay presenting about user interface design. He introduced the five B’s (which he attributed to Christian Allen). Users are attracted to parts of a user interface in this order:

  1. Bikinis — people are attracted to images, so make sure that images are used judiciously
  2. Buttons — buttons indicate what’s next; how can the user progress
  3. Boxes — boxes contain important stuff
  4. Blue links — links indicate the most important part(s) of the text
  5. B.S. — bogus stuff is all the other stuff on the page, which the user looks at last

OpenMRS Transformation

October 8th, 2007

Paul and I gave a presentation on OpenMRS at the 10th Biennial Regenstrief Conference. The conference topic was “Transformational Change in Healthcare Systems.” What we learned (and what got us to this talk) came out a gift from Tom Inui: a book called Getting To Maybe. We discovered that there’s smarter people than us who have defined the process we’ve been experiencing over the past few years. Reading the book is a little scary, since it describes our journey so well.

Preparing this talk was very helpful, since it helped us reflect and define the values that have helped us get this far. Of course, we’re still (and always will be) learning and making mistakes. Lately, I’ve been saying “How do you succeed when the only way to learn is through failure?” Maybe we’re just managing to fail at failing. :)

Lessons from the Google Summer of Code Mentor Summit 2007

October 6th, 2007

We’re just getting started at the Google Summer of Code Mentor Summit 2007 at Google Headquarters. There are hundreds of participants here from 114 different organizations. At the moment, I’m sitting in a talk on how to turn students/interns into successful committers and beyond.

The SilverStripe folks shared some nice ideas, a couple that I didn’t want to forget…

  • Having a basic coding test for applicants to help measure/understand coding skills
  • Ask students to make a screencast showing their work

NOTE: I started a wiki page to log these and other ideas.