電子カルテ

当院では,電子カルテとして,オープンソースの OpenDolphin 1.3.0(デジタルグローブ社)を使用させていただいています。素晴らしいソフトをオープンソースで公開されているデジタルグローブ社には,とても感謝しています。

 どんな素晴らしい電子カルテも,実際に運用するには個々の医院に合わせたカスタマイズが必要だと思います。その場合,オープンソースなら,自院のためだけに自由にカスタマイズすることができます。このブログでは,OpenDolphin を当院で運用するにあたって,色々カスタマイズした内容を公開しています。


  • カスタマイズしたソースは公開しています
  • デジタルグローブ社はライフサイエンスコンピューティング(株)と合併し,現在同社のオープンドルフィンラボとなっています
  • 本家オープンドルフィンラボの OpenDolphin は既に ver. 2.x になっています

2017年2月23日 (木)

TransferHandler#getVisualRepresentation から setDragImage へ

Java 1.6 の時代から,Drag & Drop の際に,ドラッグ中のイメージを表示するのに,PatchedTransferHandler を使って,getVisualRepresentation を使用していた。
 しかし,最近 PatchedTransferHandler が頻繁に InvalidDnDOperationException ("Drag and drop in progress" exception) を出すようになったため,TransferHandler のソースを読んで解決策を探っていたところ,TransferHandler#setDragImage なるメソッドがあることに気付いた。調べてみたら Java 1.7 からこんな素敵なメソッドが標準で用意されていたのであった。早速,これを使ってソースリファクタリングして,PatchedTransferHandler は引退となった。
 なお,Windows では TransferHandler#setDragImageOffset の offset 方向が Mac と逆になるのに気付いて,そんなところにも文化の違いがあるのだなと思った。
 ちなみに,最近はダブルクリックCodeHelper での入力が多く,Drag & Drop はほとんど使わなくなってしまっている。

2017年2月 9日 (木)

9年目の運用まとめ

9年目はクライアントの結構大きな改造,OS X Sierra へのアップグレード, Retina iMac の購入プリンタの更新などがあった。トラブルとしては,Orca がメモリ不足で止まったのが最大のトラブルだったが,downtime は5分くらいで済んだ。あとは Ethernet が突然つながらなくなったり,iMac のヒンジが折れたりしたが,診療には影響がなかった。
いよいよ今月から OpenDolphin 運用 10年目に突入である。

  • データベースの PatientModel の件数
    dolphin=# select count(*) from d_patient;
     count
    -------
     26879
    (1 row)
    
  • データベースの ModuleModel の件数
    dolphin=# select count(*) from d_module;
     count
    --------
     1023447
    (1 row)
    
  • Dolphin サーバの df。used が 14G→15G に増加。
    Filesystem      Size  Used Avail Use% Mounted on
    udev            971M  4.0K  971M   1% /dev
    tmpfs           200M  196K  200M   1% /run
    /dev/xvda1       46G   15G   30G  33% /
    none            4.0K     0  4.0K   0% /sys/fs/cgroup
    none            5.0M     0  5.0M   0% /run/lock
    none            997M     0  997M   0% /run/shm
    none            100M     0  100M   0% /run/user
    
  • Orca サーバの df。used が 12G → 19G に増加。
    Filesystem      Size  Used Avail Use% Mounted on
    udev            3.0G  4.0K  3.0G   1% /dev
    tmpfs           601M  228K  601M   1% /run
    /dev/xvda1       46G   19G   25G  43% /
    none            4.0K     0  4.0K   0% /sys/fs/cgroup
    none            5.0M     0  5.0M   0% /run/lock
    none            3.0G     0  3.0G   0% /run/shm
    none            100M     0  100M   0% /run/user
    
  • データベースの dump ファイルのサイズ。
    dolphin_db.dump.gpg 2,046,631,802 
    orca_db.dump.gpg 101,284,291
    
  • 作成したスタンプ数。CodeHelper の改造に伴って,スタンプを整理したため,昨年の 2104 から減少した。
    $ grep -c stampInfo stamp.xml 
    1984
    

2017年2月 7日 (火)

カレンダーの改造

カレンダーのコードを大幅に改造した。
  • 年月は,インスペクタのタイトル部分に西暦と,薄くバックグランドで和暦も出すようにした。1ヶ月送り(Mdfb2Mdfb1)だけでなく,1週送り(Mdb2Mdb1)もできるようにした。ボタンクリックだけでなく,マウスホイールでも1週毎にスクロールできるようにした。イベントを表すバックグランドは円で出すようにした。

    Calendar1

    3週戻したところ。ピンクは受診日。

    Calendar2_2

  • 休日データベースを更新して,自院の休日も出るようにした(自分だけ使うものなので当然ハードコード)。ToolTip で休日名も出るようにした。

    Obon_3

  • Mdejectで1年分のカレンダーが出るようにした。

    Oneyear_2

  • インスペクタのカレンダー(LiteCalendarPanel/CalendarCardPanel系)と CareMapDocument のカレンダー(SimpleCalendarPanel系)が,別々のシステムになっていたのを,今回作成したカレンダーパッケージで統一した。

    Caremap_2

2017年2月 6日 (月)

DiagnosisInspector の ToolTipText

DiagnosisInspector で開始日/終了日を,年号で ToolTip 表示するようにした。

Tooltips

ToolTip 情報を見ながら書類を書いているときなどに ToolTip が消えてしまうとストレスたまるので,ToolTip を自動で消えないようにした。
// ToolTip を自然に消えないようにする
ToolTipManager manager = ToolTipManager.sharedInstance();
manager.setDismissDelay(Integer.MAX_VALUE);

2017年1月31日 (火)

Dock のアイコンに待ち人数表示

カルテ画面に待ち人数のバッジ表示をするようにしていたが,これをドックのアイコンにも表示するようにした。
// Dock のアイコンにバッジを出す
com.apple.eawt.Application app = com.apple.eawt.Application.getApplication();
app.setDockIconBadge(waitingCount == 0? null: String.valueOf(waitingCount));

Screenshot

2017年1月23日 (月)

デザインの結構大幅な変更

  • メインウインドウに常に検索フィールドが出るようにした。検索フィールド(CompletableSearcField)は,バックグランドに薄く「患者検索」という文字が出るようになっていて,この文字は検索語を入力すると消える。
    ほとんど出番がなくなった更新ボタンは,ステータスバーの左端に持っていった。

    Mainwindow

  • 患者検索フィールドに入力すると,自動的に患者検索パネルに切り替わる。
    検索語を入力するとフィールドの右端に X がでて,ここをクリックすると検索語がクリアされるようになっている。

    Mainwindow2

  • インスペクタ画面。アイコンをシックな白黒アイコン(DefaultIcon ver 2.0)に変えた。
    ツールパネルに病名検索フィールドを付けた。

    Inspector

  • 病名スタンプをここから検索して入力することができる。コードヘルパーのスタンプ検索入力を知ってから,入力スタイルが一変してしまった。入力するものが決まっているときは,検索入力の方がずっと速い。一方,迷いながら入力するような時はスタンプ箱の方が便利である。

    Inspector1   Inspector2_2

  • メニューとスタンプ箱のアイコンも白黒のシックなものにした。

    Menu   Stampbox

2017年1月20日 (金)

OS X Sierra

本日から Sierra (10.12.2)で診療開始。今のところ何も問題なし。

2017年1月18日 (水)

Code Helper の改造

Code Helper というのは,カルテ入力中,文頭から登録したキーワード(tx, rp 等)を打って ctrl + return でスタンプ箱の内容がポップアップメニューとして表示されるという機能である。この使い方しかしていなかったのだが,リファクタリング中にコードを読んでいて,実は Code Helper の機能はこれだけではないことが分かって驚いた。なんと,入力文字列がキーワードに一致しない場合,そのテキストを検索文字として解釈し,スタンプ箱からスタンプを検索して,ポップアップメニューにまとめて表示してくれるという機能が組み込まれていたのだ。OpenDolphin を使い始めて 9年になるが,まだ知らない機能があったとは。
 オリジナルでは,"^text.*" の検索をするようになっていたが,これを ".*text.*" に変えて,さらに大文字・小文字を無視するようにした。また,SOA pane で病名にも対応するように改造した。

Codehelper_2

右上:P pane で「創処置」と入れると創処置を含むポップアップメニューが出る(これは今まで知らなかったオリジナルの機能)。右下:「hs」と入力すると,大文字小文字は無視して「hs]を含んでいるスタンプを全て表示する。左上:SOA pane で dx を入れると病名ポップアップが表示される。左下:SOA pane での検索は,テキストスタンプだけでなく病名も検索し,ポップアップに表示する。

2017年1月15日 (日)

BasicInfoInspecter の表示

BasicInfoInspecter でカナ名も出すことにした。名前が長いと欠けてしまうので,deriveFont で無理矢理詰め込む処理を組み込んだ。

Jugem

// 名前が長い場合は,カナ名を圧縮する
if (kanjiName.length() + kanaName.length() > 15) {
  float sy = (float) (15.5 - kanjiName.length()) / kanaName.length();
  Font font = nameLabel.getFont().deriveFont(AffineTransform.getScaleInstance(sy, 1));
  kanaLabel.setFont(font);
}

2017年1月14日 (土)

フォーカス処理の見直し

文書入力の際に,フォーカス処理はとても重要で,ウインドウが開いたらすぐに必要な場所に入力できないとかなりストレスがたまる。今まで,気がついたときに色々フォーカス処理()を加えてきたのだが,行き当たりばったりで組み込んできたので,どこでどのようなフォーカス処理をしているのか把握できなくなってしまっていた。フォーカスの取り合い?かもしれない動作が見られるようにもなっていたので,フォーカス処理を全部見直しすることにした。フォーカスは Focuser というクラスを使って,必ずここにフォーカス請求するようにリファクタリングした。案の定,不要なフォーカス請求をかなり入れてしまっていることが判明して,すっきりさせることができた。
package open.dolphin.ui;

import java.awt.Component;
import java.awt.KeyboardFocusManager;
import javax.swing.SwingUtilities;
import org.apache.log4j.Logger;

public class Focuser {
    private static final Logger logger = Logger.getLogger(Focuser.class);
    private static Component component;

    public static void requestFocus(Component c) {
        component = c;
        KeyboardFocusManager.getCurrentKeyboardFocusManager().clearGlobalFocusOwner();
        SwingUtilities.invokeLater(Focuser::request);
    }

    private static void request() {
        boolean result = component.requestFocusInWindow();
        logger.info(component.getClass().toString() + ": request focus " + ((result)? "succeeded" : "failed"));
    }
}

«JTextComponent の undo