Thursday, April 30, 2009

Vmware Tools in Ubuntu Linux

There seems to be an number of tutorials availalble. Most are outdated.

sudo apt-get install xserver-xorg-input-vmmouse open-vm-tools

is all you need.

Wednesday, April 29, 2009

GNUmed plugin development - part 10

It has taken some time to tackle part 10 of my way to a GNUmed plugin. A new GNUmed version has been released. Release dude duties have taken up most of my freetime.

Anyway I am back. The widget user interface loads in GNUmed but does not do anything useful yet. The time for clicking UI elements is over. The hard labor to code in python is about to begin. Here is where most idealists have left off and left GNUmed.

I was fortunate enough to have a face to face meeting with Karsten to ask all my newbie questions.

1.) How to proceed ?
2.) How to extend the database tables to house my data ?

His answer wasn't straight forward. First he wanted to know exactly what I intended to do. I told him my vision but visions don't amount to code. I had to break the vision down into manageable pieces.

Turns out there are many ways to store the input gathered via the the plugin user interface. There is the option to extend the database structure which is more work for him and involves a lot of new code (potentially buggy that is) or store the input as a XML document like any other document.

I did not understand the concept of storing the input as a document at first so he had to explain the concept to me. It comes down to this. Instead of storing any value gotten from the user interface in a table/field in the database one stores the values in an xml file and stores the xml file in the database. The xml file is a datbase more or less which gets stored in the the PostgreSQL database.

This means I can reuse the document plugin's classes and functions and do the content storage via python's XML routines.

I first constructed an XML file to work with. The editor used was EditiX - a cross-platform and multi-purpose XML editor, XSLT debugger and Visual Schema Editor. It provides editing support for XML, DTD, XHTML, XSLT, XSD, XML RelaxNG, ...

Here is the manually crafted XML file.

<?xml version="1.0" encoding="UTF-8"?>

<!-- New document created with EditiX at Wed Apr 29 15:37:23 CEST 2009 -->

<CardicacDevices>
        <DevicePart type="generator">
                <class>AID</class>
                <type>generator</type>
                <isactive>yes</isactive>
                <dateofimplant></dateofimplant>
                <dateofexplant></dateofexplant>
                <isexplanted>no</isexplanted>
                <comment></comment>
                <implantsite>subpectoral</implantsite>
                <implantregion>right subclavian</implantregion>
                        <GeneratorPart type="CPU" >
                                <manufacturer>SJM</manufacturer>
                                <model></model>
                                <serial></serial>
                        </GeneratorPart>
                        <GeneratorPart type="Battery">
                        <manufacturer></manufacturer>
                        <serial></serial>
                </GeneratorPart>
        </DevicePart>

        <DevicePart type="lead">
                <manufacturer>          </manufacturer>
                <model></model>
                <polarity></polarity>
                <serial></serial>
                <isactive>yes</isactive>
                <hasYconnector>yes</hasYconnector>
                <dateofimplant></dateofimplant>
                <dateofexplant></dateofexplant>
                <isexplanted>   no</isexplanted>
                <leadposition>RV</leadposition>
                <leadslot>RA</leadslot>
                <comment></comment>
                        <connectedtodevice>aid</connectedtodevice>
                        <connectedtodevice>RVlead</connectedtodevice>
        </DevicePart>

</CardicacDevices>
This is a simplified version. It lacks the actual measurements. Next step is to learn how to transfer that XML to a human readable form so I can display it in the left upper section of the plugin.

Monday, April 27, 2009

Order your GNUmed USB drive today

We are now offering ready to run USB thumbdrives to let you experience GNUmed. One has the choice between GNUmed in Windows Portable Apps (TM) format or GNUmed for Linux ready to boot from the USB drive.

The thumbdrives are 4GB devices which can be reused in case GNUmed does not fit. They come at a price of 20 Euros excluding shipping.

We will try to fulfill internationational orders. Payment methods can be negotiated but PayPal is preferred. Contact me directly at sebastian.hilbert@gmx.net. A dedicated website will be up later.

GNUmed Wiki updated to TWiki 4.3

In an effort to increase security our main source of information - our wiki - has been updated to release 4.3. Along comes a new skin.

Take a look at our wiki now.

Friday, April 24, 2009

Live CD: updated to GNUmed Version 0.4.3

Since GNUmed 0.4 has been released a new Live-CD was needed. Thanks to the Debian-Live tools a CD containing GNUmed 0.4.3 and database 10.3 was quickly made available. It boots right into a graphical Desktop environment (XFCE) ready to run GNUmed.

Thursday, April 23, 2009

Installationspaket für MS Windows

Die Installationspaket für den Klienten und Server sind in der aktuellen Version 0.4.3 und v10.3 verfügbar.

Jetzt Klient und Server herunterladen.

Video: Installation unter Windows

Die Installation unter Windows ist noch einfacher geworden. Demonstriert wird das in einem Video auf Blip.tv


ARRIBA - Risikorechner auch unter Linux lauffähig

Die in JAVA programmierte Software ARRIBA zur Abschätzung des Risikos sowie Beratung im Rahmen der Herzinfarkt- und Schlaganfallvorsorge läuft problemlos auch unter GNU/Linux.

Auf Anfrage kann direkt unter arriba-hausarzt.de ein JAR-Archiv bezogen werden. Pakete für Fedora, openSUSE sowie Mandriva habe ich erstellt. Ob ich diese verteilen darf muss erst noch mit den Autoren geklärt werden.



Wednesday, April 22, 2009

Video: Einführung in GNUmed

Unter http://releasedude.blip.tv/#2033307 finden sich zwei neue Videos. Das erste Video gibt allgemein Auskunft zu GNUmed. Das zweite Video zeigt wie die Live-CD unter Windows ausprobiert werden kann. Am Besten ist die Darstellung im Vollbildmodus.


GNUmed lab measurements

The measurements plugin received a small goodie recently. In the upper left corner there is now a configurable link. Clicking on it will open a webbrowser and take you to the configured website.

Why is this worth the blog entry. While looking at lab results I sometimes want to know more a bout a test itself. So I configure the link to point at a lab encyclopedia to look up the information.



Monday, April 20, 2009

PDFshuffler for GNUmed

Today I found out about pdfshuffler. It is a tool to split, merge or generally manipulate PDF files.

For GNUmed this can be handy when archiving documents.

Sometimes there is the issue of having information on multiple patients in one documents. For scans of paper documents this is less of an issue since you can split the content while scanning.

For FAX transmissions this is not so easy. I am not aware of a tool (on Linux) that can split documents by content.

Here is one possible workflow:

1.) Receive fax transmission and have it convert to pdf. Hylafax can do this or one could use tiff2pdf.
2.) Have it displayed in the GNUmed inbox - how does one do that ?
3.) on double click open pdfshuffler, actually two instances of it as you might want to drag 'n drop files between the windows for splitting the document.
4.) save the pdf in a folder on your harddrive
5.) open the pdf in the document archive plugin or drag it there

A few things come to mind.

1.) pdfshuffler has not been tested on windows.
2.) pdfshuffler should be 3rd-party (GNUmed) aware. much like with OpenOffice there should be a way to open a pdf in pdfshuffler from within GNUmed. Pdfshuffler needs a button 'save to GNUmed' next to 'save to file'. One would then feed the pdf back to GNUmed and associate it with the currently active patient.

PDFshuffler actually does not need to know anything about GNUmed. It should simply have the feature to hand the pdf to any program. GNUmed running in remote-control mode should then detect the call (made by a shell script 'gm-fax-importer'), raise the document archive plugin for the currently active patient and display the pdf as document part. Later versions could even extract the pdf metadata and hand those to GNUmed as well.

Monday, April 13, 2009

GNUmed plugin development - part 9

Karsten Hilbert and I had a little chat to help me plan the next steps. The current status of the plugin is as follows

a) it loads fine in GNUmed
b) it crashes when trying to load data
c) an incomplete class cCardiacDevicePluginPnl has been partially implemented

Karsten advised me to move the device specific bits to a seperate file called gmDeviceWidgets in /usr/foo/gnumed/gnumed/client/wxpython

I did so. I forgot to add the import of gmDeviceWidgets to the top of gmCardiacDevicePlugin in /usr/foo/gnumed/gnumed/client/wxpython/gui but that was quickly resolved after reading about the 'global gmDeviceWidgets undefined' stuff in the log file.

It now does not crash anymore but does not yet load the SOAP notebook. Apart from missing soap entry which does not need to be a notebook but rather a single soap editor the right column needs to house an ICD data entry widget.

This widget will be produced in the next step in the wxg file. See screenshot below for current state of the plugin.


GNUmed plugin development - part 8

Remember I left off with a problem rather than a solution ? Well I had a little chat face to face with Karsten who happens to be the author of the SOAP plugin I borrowed so much code from.

Turns out he added some special code to the file wxgSoapPluginPnl.py which normally gets autogenerated from the wxg file. Looking at the file I found I had to add

class wxgCardiacDevicePluginPnl(wx.ScrolledWindow):
    def __init__(self, *args, **kwds):

        from Gnumed.wxpython.gmNarrativeWidgets import cSoapNoteInputNotebook
        from Gnumed.wxpython.gmDateTimeInput import cFuzzyTimestampInput
        from Gnumed.wxpython.gmEMRStructWidgets import cEncounterTypePhraseWheel
        from Gnumed.wxpython import gmListWidgets

        # begin wxGlade: wxgCardiacDevicePluginPnl.__init__

The import statements to my wxgCardiacDevicePluginPnl.py. It now actually shows up in GNUmed. Horray. But it crashes when trying to load data. this should be easy to fix.

Here is the error:

gm.gui (/home/basti/sources/gnumed/gnumed/Gnumed/wxpython/gmExceptionHandlingWidgets.py::handle_uncaught_exception_wx() #49): unhandled exception caught:
Traceback (most recent call last):
  File "/home/basti/sources/gnumed/gnumed/Gnumed/wxpython/gmHorstSpace.py", line 231, in _on_notebook_page_changed
    new_page.receive_focus()
  File "/home/basti/sources/gnumed/gnumed/Gnumed/wxpython/gmPlugin.py", line 183, in receive_focus
    self._widget.repopulate_ui()
  File "/home/basti/sources/gnumed/gnumed/Gnumed/wxpython/gmRegetMixin.py", line 128, in repopulate_ui
    self.__repopulate_ui()
  File "/home/basti/sources/gnumed/gnumed/Gnumed/wxpython/gmRegetMixin.py", line 66, in __repopulate_ui
    self._data_stale = not self._populate_with_data()
  File "/home/basti/sources/gnumed/gnumed/Gnumed/wxpython/gmRegetMixin.py", line 79, in _populate_with_data
    raise NotImplementedError, "[%s] _populate_with_data() not implemented" % self.__class__.__name__
NotImplementedError: [cCardiacDeviceMeasurementsPnl] _populate_with_data() not implemented

That is no surprise since I decided to put the class cCardiacDeviceMeasurementsPnl into gmMeasurementWidgets.py and did not copy all stuff from gmSoapWidgets. What I effectively missed is to copy all the needed functions like _populate_with_data().

What this effectively shows is that I need to get a better idea on what to put where. Up till now it has mainly been a process of duplicating content of other files.

One issue is if it makes sense to put more stuff into gmMeasurementWidgets or rather a seperate file along the lines of gmDeviceAssessmentWidgets.

From the feedback received on the mailing list it is recommended to leave it in gmMeasurementWidgets and import the relevant stuff from gmNarrativeWidgets in order to avoid code duplication.

It was further recommended to rename cCardiacDeviceMeasurementsPnl into cCardiacDevicePluginPnl to avoid namespace confusion for the day I really want a class representing the measurement specific bits.

Thursday, April 09, 2009

GNUmed plugin development - part 7

Now on to the real stuff. Looking at

class gmCardiacDevicePlugin(gmPlugin.cNotebookPlugin):

        def GetWidget (self, parent):
                self._widget = gmMedDocWidgets.cSelectablySortedDocTreePnl(parent, -1)
                return self._widget
in gmCardiacDevicePlugin.py tells me that in the case of the Document archive plugin we borrowed from the class cSelectablySortedDocTreePnl is located in the file gmMedDocWidgets. The name implies that this is a collection of classes of medical document widgets. The device parameters are essentially measurements.

There is a file called gmMeasurementWidgets available and I am going to extend that one. I added a class cCardiacDeviceMeasurementsPnl to the file gmMeasurementWidgets.py just before the __main__ statement.

#================================================================
class cCardiacDeviceMeasurementsPnl(wxgCardiacDevicePluginPnl.wxgCardiacDevicePluginPnl, gmRegetMixin.cRegetOnPaintMixin):

        """Panel holding a number of widgets to manage implanted cardiac devices. Used as notebook page."""

        def __init__(self, *args, **kwargs):

                wxgCardiacDevicePluginPnl.wxgCardiacDevicePluginPnl.__init__(self, *args, **kwargs)
                gmRegetMixin.cRegetOnPaintMixin.__init__(self)
                self.__init_ui()
                self.__register_interests()
        #--------------------------------------------------------
        # event handling
        #--------------------------------------------------------

An extended import is needed as well.

from Gnumed.wxGladeWidgets import wxgMeasurementsPnl, wxgMeasurementsReviewDlg
from Gnumed.wxGladeWidgets import wxgMeasurementEditAreaPnl
from Gnumed.wxGladeWidgets import wxgCardiacDevicePluginPnl

Now back to gmCardiacDevicePlugin.py to reflect the changes.

class gmCardiacDevicePlugin(gmPlugin.cNotebookPlugin):

        def GetWidget (self, parent):
                self._widget = gmMeasurementWidgets.cCardiacDeviceMeasurementsPnl(parent, -1)
                return self._widget

A change in the import statements is needed here too.
from Gnumed.wxpython import gmMeasurementWidgets, gmPlugin
instead of

from Gnumed.wxpython import gmMedDocWidgets, gmPlugin, images_Archive_plugin
If you followed the above steps you might notice that the plugin throws many errors in the file gnumed.log. This file can be viewed directly from within GNUmed. It does not show up. The reason is simple. I use a complex set of widgets that are scattered across the files gmMeasurementWidgets and gmNarrativeWidgets.

The errors are that widgets found in gmNarrativeWidgets are not found, most likely because I put the class cCardiacDeviceMeasurementsPnl(parent, -1) in gmMeasurementWidgets. It could help to move the class into narrative widgets but that is not what I want. I could as well start another file called gmDeviceWidgets.

Lets see what the mailing list has to say about that.


What I have learned so far. First I need to create a mockup gui, store it in the wxg directory, create python code from it and store it in the directory wxGladeWidgets. Then in the wxpython/gui directory a file called gmPluginName is needed. When created from scratch or copied over from a template make sure to have the class name reflect the filename, the tab name set and the menu entry configured.  Last but not least the GetWidget line needs to be filled to reflect what GUI code to load.

GNUmed plugin development - part 6

So I joined the GNUmed mailing list and immediately received feedback. The data storage aspect will be tough to tackle but we will get to that later.

The goal for today is to get our mockup GUI displayed within GNUmed. There will be no database connection but at least it will display (hopefully).

I selected /home/user/sources/gnumed/gnumed/client/wxGladeWidgets/wxgCardiacDevicePluginPnl.py and pressed 'generate code'.

This code cannot be simply run inside GNUmed so I need to find out how GNUmed makes use of the code inside its plugins. There is a slight chance that this is documented in the development section of the GNUmed wiki. There seems to be no relevant information so I will try to piece it togehter and document it.

There are example plugins. Let's take a look and learn from there. The names of the plugins to load are stored in the database.



I reason since I got some code from existing plugins I should look there. The file is called gmShowMedDocs.py. I copied that file to gmCardiacDevicePlugin.py.

Now it is time to run a local instance of GNUmed and a local database. You should really install it now. Do not try to cut corners by not bootstraping a local database. We need that to work on our plugin.

I recommend you run GNUmed via the script gm-from-cvs.sh in the CVS source tree and bootstrap a database from the CVS tree as well. Change to the server/bootstrap directory and run bootstrap-latest.sh. Extensive information is available here and here.

Be aware that the source code in a CVS tree is a moving target. You might want to consider getting the source for the stable version 0.4.2 and server v10. All files mentioned before like the wxg files and the renamed plugin file should be created in that cvs directory then. The benefit is that your plugin will be developed against the latest stable version.

However if your plugin requires database changes there is no way around using the latest development code since changes to the database made against the stable version might not work with the latest development code.

I did not run into trouble but if you do don't hesitate to contact gnumed-devel@gnu.org.

I started GNUmed (from CVS) with the local database (v11) and added my new plugin (still containing the SOAP stuff) to the database. GNUmed evidently scans the directory foo/gnumed/client/wxpython/gui for available plugins. If the file is there it will show up for activiation. I activated it from within GNUmed via 'Office' > 'manage master data' > 'Workplace profiles'.

GNUmed does not show it immediately. A restart of GNUmed is neccessary. The plugin does does not show up and throws an error in the log file.

Traceback (most recent call last):
File "/home/basti/sources/gnumed/gnumed/Gnumed/wxpython/gmHorstSpace.py", line 121, in __load_plugins
plugin = gmPlugin.instantiate_plugin('gui', curr_plugin)
File "/home/basti/sources/gnumed/gnumed/Gnumed/wxpython/gmPlugin.py", line 333, in instantiate_plugin
plugin_class = module_from_package.__dict__[plugin_name]
KeyError: u'gmCardiacDevicePlugin'

This is due to the fact that the class name and the file name (gmCardiacDevicePlugin) due not match. Open the file and change the class name.
class gmCardiacDevicePlugin(gmPlugin.cNotebookPlugin):
"""Plugin to encapsulate document tree."""

tab_name = _("Documents")

def name (self):
return gmCardiacDevicePlugin.tab_name

The section 'Menu Info' is responsible for the name of the plugin in the GNUmed menu. I changed it like this and while we are at it the notebook tab name as well.
class gmCardiacDevicePlugin(gmPlugin.cNotebookPlugin):
"""Plugin to encapsulate document tree."""

tab_name = _("Cardiac Device")

def name (self):
return gmCardiacDevicePlugin.tab_name
#--------------------------------------------------------
def GetWidget (self, parent):
self._widget = gmMedDocWidgets.cSelectablySortedDocTreePnl(parent, -1)
return self._widget
#--------------------------------------------------------
def MenuInfo (self):
return ('tools', _('Show &cardiac devices'))

I restarted GNUmed and saw the new Cardiac Device plugin. Next step is to load my GUI instead of the Document archive stuff. The line starting self._widget = ' ' needs to be changed.

But this will be the next part of our journey towards a GNUmed plugin. So far it wasn't that hard and I learned quite a bit where files are located in the source tree , what files are involved in creating a plugin and how to add a plugin to the workplace in a database.

GNUmed plugin development - part 5

Now that I have the source code available I can load an existing wxg file in wxglade as a start for my own plugin.

I opened /home/user/source/gnumed/gnumed/client/wxg/wxSoapPluginPnl.wxg and started to changed it to my fit my needs. I then saved it as /home/user/source/gnumed/gnumed/client/wxg/wxCardiacDevicePluginPnl.wxg

The result looks like this:




What you can see here is the complexity we are getting into. There can be more than one device not to mention a combination of active and inactive devices. Active and inactive leads. Why is all this important ? Because the life of a patient may depend on it. Hospital might call in and ask how long the leads have been in to decide whether to cap or extract a lead. There should be a device history. It is important to know which of you patients have which leads and generators when a recall is issued.

Now that we have a GUI we need to produce python code for it. There is a feature in wxglade to produce python code. This will be described in the next part.

Wednesday, April 08, 2009

GNUmed plugin development - part 4

Paper is great but we need code to make it appear on screen. At this stage the vision has not yet fully developed. Different from what traditional IT/IS university taught specialists might want to do now I will develop and reshape the code instead of defining detailed specs first.

This is the medical approach. I could try to learn tools like UML to model the plugin with the added benefit of using sophisticated tools to produce code from the model but that is not my preferred approach.

Anyway I downloaded wxglade from https://bitbucket.org/agriggio/wxglade/ as zip file. Unpack it into a directory like /home/user/wxglade and you are good to go. Find the wxglade shell script and change it to make it find wxglade.py in the same directory. Just remove the /usr/lib/foo stuff.

Fire it up and either start a new project or start from one of the wxg in the GNUmed CVS source tree. Oh I don't have the CVS tree copied yet. So lets do that now.

Heading over to wiki.gnumed.de in the Dowload section I am presented with the option to either download a snapshot package or get a copy of the CVS tree. SInce I will probably need to get updates often I will go for the CVS option.

I followed this guide and retrieved a copy of the source for local storage.

Update: GNUmed has swithed to GIT for source code management. New guide is available.

GNUmed plugin development - part 3

Computers are great but paper is unbeaten for quick GUI mockups. While putting down a few sketches the ideas develop to a clearer vision.

I want to

a) provide a quick glance overview over the currently active programmed device settings, number of devices, caveats regarding leads, battery
b) provide a quick overview over the previous interrogations and previous , active as well as future problems
c) display the individual encounter/interrogation as well as changes during that session
d) document the current session (device data, programmed settings)
e) document patient's health with regards to the device
f) document EKG findings with and without the device active
g) display reference info such as the information supplied by manufacturers (lead recalls, current scientific studies)

I started GNUmed and took a look if any plugin comes close to what I want. I chose the new progress notes editor and printed a screenshot taken by GNUmed's screenshot feature.

Tuesday, April 07, 2009

GNUmed plugin development - part 2

Hi all,

Here is what I decided to do.

0.) document what we would like to achieve
1.) develop a mockup GUI on paper
2.) whip up the mockup GUI in wxglade
3.) join and tell the GNUmed mailing list about it
4.) discuss and change the GUI mockup so it will be a *first usable version*
5.) check out the GNUmed source code
6.) take a good look at the source of the plugins already in GNUmed
7.) start hacking on the plugin to get the plugin displayed in GNUmed and basics like patient name
8.) announce the code and share the code with the GNUmed mailing list
9.) start documentation for our plugin in the GNUmed manual

This part is about documenting what I would like to achieve. It is most helpful to document this in the GNUmed wiki. I started a new GNUmed Enhancement Proposal (GEP). The proposal is at GNUmed_{01}_CardiacDevicePlugin.

GNUmed plugin development - part 1

Hi all,

I decided I want to add some features to GNUmed. I could ask on the mailing list but there is really only one or two people who do the coding. I decided to learn it myself.

Part one will describe what I would like to achieve and what I need. All later stories will hopefully show my progress or lack thereof.

I am working in a large heart center. I am resident in cardiology. My tasks include pacemaker and defibrillator interrogation. Various software packages exist but rarely are they available in cardiologist's offices. GNUmed has the potential to change that.

While pacemakers are manageable defibrillators are another story. Inconsistent programming is potentially lethal. Sharing of interrogation data hardly happens.

Today we are going to change that.

We need to get skilled in python. We need to find out about the plugin stuff in GNUmed and have someone adapt the database. Karsten Hilbert offered to change the GNUmed middleware. For that to happen we need to tell him exactly what we need.

Here is what we will do.

0.) document what we would like to achieve
1.) develop a mockup GUI on paper
2.) whip up the mockup GUI in wxglade
3.) join and tell the GNUmed mailing list about it
4.) discuss and change the GUI mockup so it will be a *first usable version*
5.) check out the GNUmed source code
6.) take a good look at the source of the plugins already in GNUmed
7.) start hacking on the plugin to get the plugin displayed in GNUmed and basics like patient name
8.) announce the code and share the code with the GNUmed mailing list
9.) start documentation for our plugin in the GNUmed manual

From here on out a discussion will take place which will lead to

10.) changes to the plugin source code and GUI
11.) getting CVS commit rights and checking in the source into CVS

If you did not notice you are by now a GNUmed developer.