Wednesday, June 27, 2007

Work with Open Flash Charts

After a longer-than-expected struggle to find a decent charting library, it looks like we will building our own, using Open Flash Charts as a starting point.

OFC already comes with a nice set of features... Plus, and most importantly, it's open-source and free, meaning we can do whatever we want with it (or at least whatever GPL allows us to do).

Although a great part of the library is organized in classes, a significant part of OFC is just bundled on the .FLA file, namely code that is shared by all types of charts available. This has some disadvantages:
  1. Encourages "spaghetti code", stuffing everything with no specific organization into the Flash file instead of in a separate ActionScript file.
  2. Doesn't make concurrent development easy: having a diff done on an Actionscript file is readable, while doing it on a .FLA file isn't.
  3. Does not allow development inside Eclipse. See below why coding Actionscript is much easier in Eclipse than in the Flash authoring environment itself.
Having said this, I have already successfully translated all the code in the .FLA into a separate class file, maintaining all existing functionalities, plus the ability to have Javascript links associated to each chart value. Such a simple task took a lot of my time, until I found that when embedding flash objects in HTML, you need to set:
<param name="allowScriptAccess" value="always" />

instead of

<param name="allowScriptAccess" value="sameDomain" />
if you want to test your files locally. Otherwise SWF movies will not be able to communicate with Javascript through getURL() or ExternalInterface.call(). Unfortunately it took a long time to find this on the web:P
I also changed the way in wich parameters are passed to the SWF movie. Instead of loading them from an external file as it's done in OFC, e.g. using:

<param name="movie" value="open-flash-chart.swf?data=mydata.txt" />

they are now passed as flashVars themselves, e.g.:

<param name="movie" value="open-flash-chart.swf?values=2,5,1&x_labels=Mon,Tues,Wed" />

This allows us to fetch information dynamically, for example with AJAX, and pass it directly to the movie without the need to create an external file.


As for the question "Why is it better to code Actionscript in Eclipse IDE?", once you try the FDT Eclipse plugin you'll understand... In short, it gives you all the functionalities you would have if you were programming in Java. Actually, there's no advantage in using it if you don't go object-oriented, but otherwise it gives you auto-completion, error highlighting, quickfixes, among others... I really recommend this, or at least some other tool that does the same job (if you know of some open-source alternative let me know).
You'll end up using the Flash authoring environment just for publishing your files.

Next steps:
  • decide on the best way to pass parameters to Flash from Javascript (this is already possible but it can probably be improved)
  • have OpenMRS building the code to include the open flash chart
  • create pie charts! (not available in OFC)
  • whatever else comes...

Thursday, June 21, 2007

Playing around with charts...

Just as I suspected, maintaining a blog is not so easy... But after a long time, here are some more updates.

The interface and first charts to implement are now outlined. There will be a default List display of the cohort patients. It will be possible to switch between different visualizations, to start with these will focus on a Gender & Age patient distribution, and some kind of yet-to-be-defined encounter distribution for the patients in the cohort.

I have been working on building an abstraction for provide a simple way to include charts in any OpenMRS page. The original idea was to create a chart tag that will take the chart parameters and return the formatted chart code to include directly on the JSP page:

For example:
<openmrs:showchart width=" height="200" type="genderAndAge" patients="listOfCommaSeparatedPatientIds" />

would be replaced at runtime with the chart itself, keeping things transparent and to the programmer and general enough to be reused in different places.

As simple as this may seem, I ran into some problems, namely the fact that openmrs: tags seem to be replaced before page load, so something like:


$('cohort_contents').innerHTML = '<openmrs:showchart patients="'+listOfCommaSeparatedIds+'">';

would be loaded by the browser as:

$('cohort_contents').innerHTML = '<object><chart_contents_here></object>';

making it impossible to have run-time updates to the chart.


So the alternative (still "pending approval") is to have a function on DWRPatientSetSetvice (or possibly in another specific chart service), that will be invoked with all the parameters necessary, plus the ID for the DIV that will hold the chart, and return the Javascript code that will render the chart. This has been successfully tested with the gender and age charts, with good results (screenshots to come) and seems to be the way to go.



Another thing that's been troubling me is which chart library to use. I have tested both Dojo and FusionCharts.
Even though Dojo charting widget is FOSS and uses SVG, it's quite rudimentary in my opinion, and lacks in looks (poor chart design) and functionalities (no pie charts, no hyperlinks on series, no values over columns, ...). It works fine with the existing functionalities though.

As for FusionCharts, it looked like the perfect thing... while it worked. I played around with it for some days with no problems. Then is stopped rendering charts inside OpenMRS pages. Some days later worked fine again, then stopped rendering again, with no apparent reason. I've spent endless hours around this, clearing every possible cached files, reverting source files, redeploying, even reinstalled Tomcat, but no luck. It just works randomly (other more rational suggestions are welcome:P). The demo for the commercial version seems to have a more stable behavior, but the problem remains. If the cause of this isn't found, the FusionCharts alternative will have to be abandoned...

There is another worthwhile option: Open Flash Charts. I heard about them before from Sashikanth (a fellow SoCcer), but since they use PHP libraries I thought it would be hard to implement. However, when I looked into the source code today, I realized it should be fairly easy to translate it to Javascript, and this is worth a try.

So the current TODO list is:
  • Define which service to use to deliver charts to JSP pages, move the existing code into it, clean it up and evolve from it.
  • Check out Open Flash Charts, possibly translate into Javascript and try it (ping Sash about his progress with this)
  • Improve performance of Gender & Age chart, and start working on the other relevant charts.