0 フォロワー · 61 投稿

Fast Healthcare Interoperability Resources(FHIR、発音は「fire」)は、データフォーマットおよび要素(「リソース」と呼ぶ)と、電子カルテ記録を交換するためのアプリケーションプログラミングインターフェイス(API)を説明する標準規格案です

公式サイト

お知らせ Mihoko Iijima · 4月 24, 2022

開発者のみなさん、こんにちは!

2022年3月9日開催「InterSystems Japan Virtual Summit 2022」のセッション「FHIR SQL Builder」のアーカイブを YouTube に公開いたしました。

(プレイリストはこちら

日本でも徐々に広がりを見せている HL7 FHIR。FHIR を活用したプロジェクトも着実に増えてきています。

取得した FHIR データをどのように利用するのか。その中で、FHIR データを使用して分析したいというニーズは必ず出てくるかと思います。

InterSystems では、FHIR データ分析を容易に可能にする新機能「FHIR SQL Builder」を発表いたしました。

この機能を利用することにより、FHIR リポジトリに格納したデータを通常の SQL で取り出し利用することが可能になります。

この機能の概要と使用方法をデモをまじえてご紹介いたします。

※ FHIR SQL Builder は、現在開発中機能であるため、メニュー名や画面イメージなどが将来変更される場合もあります。予めご了承ください。 
 

【目次】

01:00 FHIRに関する国内の動向

04:00 FHIR SQL Builder のご紹介

10:03 デモ

0
0 189
記事 Toshihiko Minamoto · 4月 19, 2022 9m read

Raspberry を FHIRserver として実行する

一年ほど前、
Raspberry Pi での HAPI FHIRserver のインストールに関する記事を書きました。 当時、FHIR 標準の基本しか知らず、FHIR サーバーの背後にあるテクノロジーや Raspberry についてほとんど知りませんした。 試して、失敗して、諦めて、もう一度試すことで、たくさんのことを学びました。1 年以上が経ち、いまだに「忍耐力に長けるアマチュア」ではありますが、その間、FHIR のフル環境を Raspberry で構築し、HTML/JavaScript/jQuery/Bootstrap によるアプリケーションや PHP アプリケーションを多数作成してきました。 Raspberry の認証サーバーや承認サーバーについてもいくらか経験し、SMART on FHIRを使った実験も行いました。

最後の機能しなかったバージョンと、明らかに私が作成した成功バージョンの違いが判らないまま動作することもありましたが、作業や実験のほとんどは動作しました。 今でも驚いています。 振り返ると、システム開発について適切に学習しておくべきだったと思います(私は山林学専攻で卒業し、現在はその分野を中心にボランティア活動を行っています。 まぁ、本題からは外れてしまいますが)。

Raspberry Pi は実験には十分ですが、本稼働には適していないことに注意してください。 したがって、信頼性、継続性、セキュリティ、プライバシーといった要素が必要である、または期待されているヘルスケアなどの分野で、Raspberry を本稼働システムとして使用しないでください。 実験目的では完璧で安価なコンピュータであり、幾度も私の期待を超えていますが、「産業耐久性」に欠けています。

InterSystems FHIRserver

入手しやすさと、非常に早い段階で結果を得られたことを理由に、当時 HAPI FHIR を選択しました。 以前の同僚で、現在では InterSystems に勤めている人から、InterSystems の FHIRserver でも試用することをすでに提案されていました。

InterSystems については非常によく知っており(というより、「i.know」と言うべきでしょうか 😉)、面白そうに思えましたが、当時、一年以上前は、ARM プロセッサ向けに適したバージョンの Iris は存在していませんでした(Raspberry は ARM で動作します)。 それとは別に、Iris の Community バージョンは Docker コンテナとして配布されていましたが、私には Docker に関する知識がまったくありませんでした。

Raspbian から Ubuntu へ

それから 1 年が過ぎました。 現在では、さらに強力になった新しい Raspberry Pi が登場しています(在庫のある限り…)。 新しい Raspberry 4 は、Raspberry 3 と同様に、64 ビット Unix をサポートしています。 IRIS Community バージョンは ARM にも対応しており、コンテナと Docker についてもいくらかさらに学習しました。

こういった改善すべてを基に、昨年の年末にオランダで施行されたわけのわからない「ロックダウン」が、IRIS Community バージョンを Raspberry Pi で実行させる新しい実験を開始するチャンスとなりました。

振り返ると、これは非常に簡単なことでした。 実際、注意すべき点は 3 つしかありません。

  1. 64 ビットをサポートする Raspberry が必要です。 つまり、Raspberry 3 または 4 が必要となります。
  2. (64 ビット)Raspbian ではうまくいきませんでした(ちなみに非常に新しいものです)。 しかし、64 ビット Ubuntu では成功しました。
  3. InterSystems FHIRserver は、HAPI FHIRserver よりも FHIR 呼び出しに関して厳格さが増しているようです。 これについては別の機会に説明しますが、これを悪いことだとは思っていません。 (ヘルス)ケア環境における中央リポジトリであるため、標準について厳格である必要があるためです。そうでなければ、「ガベージイン・ガベージアウト」になってしまうでしょう。

それでも、HAPI FHIRserver でうまく実行していたアプリケーションが IRIS では失敗することを理解するのには、いくらか時間がかかりました。 ネタバレ注意: 問題は私のアプリケーションにありました。

それにしても、Raspberry Pi のような、100 ユーロもかからない小さなコンピュータで、InterSystems IRIS フルプラットフォームが実行し、管理ポータル、Ensemble、Caché、そして FHIRserver が備わっているのを目の当たりにするのは、楽しく本当に価値以上の価値があります。

以降では、そこに至るまでに私が行ったことを、順を追って説明します。 Ubuntu の歴史、Docker の背後の意ある哲学など、長々とした話にはなりません。 そちらの方に関心のある方は、インターネットをご覧ください。 ここでは「楽しく進められるフロー」に焦点を当て、どこで初めて間違ったのかについて言及する場合にのみ、注釈したいと思います。

InterSystems FHIRserver のインストール

フェーズ 1: Ubuntu 64 ビット

  1. _SD カードをフォーマット_し、そこに ARM プロセッサ用 64 ビット Ubuntu を配置します。 私の場合、圧縮バージョンの名前は「ubuntu-20.04.3-preinstalled-server-arm64+raspi.img.xz」でした。これは http://cdimage.ubuntu.com にあります。 (もちろん、SD カードに置く前に、.img ファイルを解凍する必要があります!)

RaspberryPi-imager は、誤ったバージョンを提供するため、使用しないでください。 私は Win32DiskImager を使用しました。

  1. _新しいイメージで Raspberry を開始_します。 ubuntu-account のパスワードを変更します(そして記憶しましょう!)。 あくまでも ubuntu-account のパスワードです。

  2. この時点で Raspberry は Ubuntu で実行していますが、まだ準備はできていません

以下を見てください。

この Ubuntu-version はまだ 32 ビットになっています!

今すぐこれを直しましょう。

  1. Pi にログインします。

  2. sudo rpi-update

  3. sudo reboot now

  4. sudo copy /boot/config.txt /boot/config-ok.txt(検出したエラーを逃してしまった場合に備えます)

  5. sudo nano /boot/config.txt   [pi4] の下に次のテキストを追加します: arm_64bit=1

  6. boot/config.txt を保存します。(nano で: <ctrl>O )

  7. nano を終了します。(<ctrl>X)

  8. sudo reboot now

これで、64 ビットで実行するようになりました。 自分で確認してみましょう:

Pi のIP アドレスをメモし(sudo hostname -I。I は大文字のアイです)、Ubuntu では SSH はデフォルトで有効になっているため、別の場所に保管しておきます。

フェーズ 2: Docker

  1. sudo curl -fsSL https://get.docker.com -o get-docker.sh

  2. sudo sh get-docker.sh 

しばらくすると、これは、「non-priviledged user」として使用することに関する Docker の詳細な通知が得られます。

  1. sudo usermod -aG docker $USER

  2. ログオフしてから、もう一度ログインします。

  3. docker container run hello-world

Docker はシステム上の「hello-world」イメージを探すようになりました。 見つからない場合は、Docker リポジトリからダウンロードします。 その後、Docker はイメージを Pi 上のコンテナに配置し、「hello-world」イメージを開始します。

Docker の別のテキストブロックで、「Hello from Docker」のウェルカムメッセージと共に確認できます。

フェーズ 3: InterSystems の IRIS FHIRserver の Docker イメージ

1.  以下のコマンドを一度に発行します。

sudo docker run --name my-iris -d --publish 9091:1972 --publish 9092:52773 containers.intersystems.com/intersystems/irishealth-community-arm64

多数のイベントが順に発生します。

  • Docker は Irishealthから「community edition」を取得し、それをローカルの Docker リポジトリに配置します。
  • Docker は「my-iris」という Docker コンテナで Community エディションを起動します。
  • Docker はコンテナで実行している IRIS のポート 1972 を Raspberry のポート 9091 にマッピングします。
  • 同じパターンに従って、IRIS のポート 52773(コンテナ内)は Raspberry のポート 9092 になります。

以下のようにすると、何が起きたのかを確認できます。

  1. sudo docker container ls  ただし、これを確認するには別のはるかに印象的な方法があります。

フェーズ 4: InterSystems IRIS for Health Fhirserver の起動

ネットワークで Web ブラウザを起動します。英語版 PC の場合は次の場所に移動してください。

    _ <Raspberry の IP アドレス>:9092/csp/sys/UtilHome.csp .

IRIShealth の管理ポータルが表示されます。 このポータルは、自動的にPC の言語設定に調整されます。

標準アカウントは _SYSTEM(先頭のアンダースコアを含む)で、初回パスワードは SYS(アンダースコアはありません)です。 IRIS からすぐにパスワードを変更するように求められます。

これで、次に記載されている指示に従って IRIS for Health FHIRserver を構成し、起動できるようになりました。https://docs.intersystems.com/irisforhealthlatest/csp/docbook/DocBook.UI.Page.cls?KEY=HXFHIR_server_install

「Foundation」を構成して「Endpoint」(FHIR 3 または 4)を定義する必要があります。

「Endpoint」は、FHIRserver にアクセスできる URI となります。 私の場合は、http://192.168.1.29:9092/csp/healthshare/fhironpi/fhir/r4/Patient にある「Patient」リソースです(外部からはアクセスできません!)。

まとめ

手間を取る価値があったでしょうか? そのとおり!それ以上の価値があります。 まず、それほどの手間はありませんでした。 Raspbian ではうまくいきませんでしたが、それは簡単に解決しました。 そして、IRIS-for-health プラットフォームを Raspberry Pi のようなデバイスで実行できるのは素晴らしいことです。 ダッシュボード(DeepSee)、データ変換ツール、Ensemble(Enterprise Service Bus とその他多数のツール)、CSP ページ、および Caché(多次元データベース)すべてを実験できるようですし、自然言語処理の I.know も管理ポータルに表示されています。 IRIS-for-health プラットフォームには、FHIRserver 単体よりもはるかに多くの機能が備わっており、1 つの記事ではとても説明しきれません。

私個人としては、ほぼリリース直後から Ensemble を使用してきましたし(アーキテクトとして)、それとは別に、IRIS-for-health の起源は 20 世紀後半だったため、思い入れがあります。 ヘルスケアアプリケーション向け MUMPS 開発環境(MUMPS/マンプス: マサチューセッツ総合病院ユーティリティマルチプログラミングシステム)は、ほとんどが Digital Corp の Vax コンピュータシステムで実行されていたのですが、私の IT キャリアが始まったのも同時期なのです。

MUMPS、Caché、Ensemble、そして今日には IRIS-for-Health プラットフォームの安定性は非常に高く、必要なサポートとメンテナンスは比較的控え目です。 InterSystems 製品のドキュメントは広範に用意されており、簡単に見つけることができます。

IRIS と FHIRserver での実験をさらに続ていく予定です。最低でも後 1 つ、FHIR 標準への厳格な準拠に対する私の「奮闘」に関する記事を絶対に公開いたします!

健康を大切に、思考を繰り返して、実験し続けましょう! Bob

0
0 301
お知らせ Mihoko Iijima · 4月 6, 2022

開発者のみなさん、こんにちは!

2021年10月に4回シリーズで開催した「InterSystems IRIS 開発者向けウェビナー」第4回目の「FHIR新機能」のアーカイブをYouTubeに公開いたしました。

FHIRに関する開発を行う際、FHIRの規格がどのような内容を決めてくれているのかについて、開発者の視点でご説明します。
また、InterSystems IRIS for Health のバージョン2020.1から2021.1の間で追加されたFHIR新機能についてご紹介します。

ぜひご覧ください!

(IRIS 2021.1新機能全体のご紹介については、こちらのYouTubeをご参照ください。)

【目次】

0:00 開発者からみたFHIRについて

03:29 大手ITによるFHIR規格の取り組みについて

07:27 FHIR新機能

11:35 デモ

0
0 81
記事 Shintaro Kaminaka · 11月 3, 2021 15m read

開発者の皆さん、こんにちは。

この記事は、FHIRの関連技術として、FHIRプロファイル作成ツールであるSUSHIの使い方を紹介するシリーズの第2弾です。パート2である今回まで半年の期間が経ってしまいました。

前回のパート1では、FHIRとは?FHIRプロファイルとは?FHIR Shorthandとは?そしてSUSHIとはどのようなツールなのか?どのような物を作成できるのか?について、サンプルの成果物のスクリーンショットを交えながら説明しました。

今回の記事では、SUSHIで作成したプロファイルの実際の活用例として、SUSHIを使ってPatientリソースに Extension を追加し、さらにそのExtensionの項目に対する新しい SearchParameter を定義し、IRIS for HealthのFHIR Repositoyで新しいSearchParameterが使えるようになるまで、をご紹介します。

SUSHIのアップグレード

いきなり本筋とそれて恐縮ですが、SUSHIを久しぶりに触る私のような方はSUSHIのアップグレードを行いましょう。 この半年の間もSUSHIは精力的な機能Enhancementが行われており、8月にはversion 2.0.0がリリースされています。この記事の執筆段階の最新バージョンは SUSHI 2.1.1 でした。

このリンク先でも紹介されている通り、アップグレードはインストール同様以下のコマンドです。

$ npm install -g fsh-sushi

sushi -versionを実行すればバージョンが確認できます。 同様に、SUSHIで生成されたProfileをベースに、実装ガイドのHTMLファイル群を作成してくれるIG Publisherツールも、_updatePublisher コマンドを実行してアップグレードすることができます。

FISHファイルの作成

まずは、前回同様 sushi --init コマンドを使って、プロジェクトを作成します。この記事ではテンプレートで生成される、patient.fsh ファイルを修正していきます。

今回は、出身都道府県を表現するstring型の birthPlace のExtensionを追加し、さらにそのbirthPlaceに対するSearchParameterも定義することで、その患者の出身都道府県で検索できるような拡張を行います!

Extensionを追加する

まず、Extensionを追加するために以下の定義を追加します。

US CoreやJP Coreのように、通常はAddress型を使うことが多いですが、ここでは単純にstring型にしています。

Extension: BirthPlace
Id: birthPlace
Title: "出身地"
Description: "生まれた場所をstring型で表現する"
* ^url = "http://isc-demo/fhir/StructureDefinition/patient-birthPlace" 
* value[x] only string 

各項目は以下のようにExtensionのStructureDefinitionに対応しています。項目によっては複数の箇所に設定されます。ベースとなるfhirのバージョンや、このExtension自体のバージョンなどの情報は、sushi-config.ymlファイルから取得されているものもあります。

SUSHIの項目対応するStructureDefinitionの項目
Extensionsname
Idid
Titletitle/differencial.element[id=Extension].short
Desctiptiondescription/differencial.element[id=Extension].definition
^urlurl//differencial.element[id=Extension.url].fixedUri
value[x]differencial.element[id=Extension.value[x]].type.code

実際に生成されたExtensionのStructureDefinitionです。 手書きでこれを1から作るのは大変ですが、SUSHIを使えば比較的簡単です。

{
  "resourceType": "StructureDefinition",
  "id": "birthPlace",
  "url": "http://isc-demo/fhir/StructureDefinition/patient-birthPlace",
  "version": "0.1.0",
  "name": "BirthPlace",
  "title": "出身地",
  "status": "active",
  "description": "生まれた場所をstring型で表現する",
  "fhirVersion": "4.0.1",
  "mapping": [
    {
      "identity": "rim",
      "uri": "http://hl7.org/v3",
      "name": "RIM Mapping"
    }
  ],
  "kind": "complex-type",
  "abstract": false,
  "context": [
    {
      "type": "element",
      "expression": "Element"
    }
  ],
  "type": "Extension",
  "baseDefinition": "http://hl7.org/fhir/StructureDefinition/Extension",
  "derivation": "constraint",
  "differential": {
    "element": [
      {
        "id": "Extension",
        "path": "Extension",
        "short": "出身地",
        "definition": "生まれた場所をstring型で表現する"
      },
      {
        "id": "Extension.extension",
        "path": "Extension.extension",
        "max": "0"
      },
      {
        "id": "Extension.url",
        "path": "Extension.url",
        "fixedUri": "http://isc-demo/fhir/StructureDefinition/patient-birthPlace"
      },
      {
        "id": "Extension.value[x]",
        "path": "Extension.value[x]",
        "type": [
          {
            "code": "string"
          }
        ]
      }
    ]
  }
}

このExtensionで追加したPatientリソースへのExtensionデータは、実際はこのようなデータになります。


  "extension": [
    {
      "url": "http://isc-demo/fhir/StructureDefinition/patient-birthPlace",
      "valueString": "鹿児島"
    }
  ],

SearchParamterを追加する

次は、先ほど追加したExtensionの項目をキーにして、リソースを検索できるように、SearchParamter を追加します。FHIRの場合、各リソースには構造化された要素(エレメント)が定義されていますが、 そのすべての要素で検索ができるわけではなく、SearchParamterに定義された項目(≒要素)でのみ検索することができます 。ここがSQLのテーブルとは少し異なる点ですね。

SearchParamter名は要素名とは別に定義されており、Patientリソースで言えば、genderのように要素名=SearchParameter名で一致するものもあれば、要素名=address.country -> SearchParamter名=address-country のように構造化された要素では一致しないものもあります。

Extensionに追加される項目は当然ながら(何がはいってくるかわからないので)デフォルトではSearchParameterにはならないわけですが、あえてExtensionを定義して格納する方針を定めるようなExtensionは重要な項目であることも多いですよね。

以下のようなSearchParameter定義を生成するための内容をpatient.fshファイルに追加します。

Instance: BirthPlaceSearchParameter
InstanceOf: SearchParameter
Usage: #definition
* url = "http://isc-demo/fhir/SearchParameter/patient-birthPlace"
* version = "0.0.1"
* name = "birthPlace"
* status = #active
* description = "出身地検索のパラメータ"
* code = #birthPlace
* base = #Patient
* type = #string
* expression = "Patient.extension.where(url='http://isc-demo/fhir/StructureDefinition/patient-birthPlace').value"
* comparator = #eq

SearchParameterで生成されるStructureDefinitionはこちらです。 比較的シンプルな定義なので、上記SUSHIの情報とのマッピングは理解しやすいと思います。

{
  "resourceType": "SearchParameter",
  "id": "BirthPlaceSearchParameter",
  "url": "http://isc-demo/fhir/SearchParameter/patient-birthPlace",
  "version": "0.0.1",
  "name": "birthPlace",
  "status": "active",
  "description": "出身地検索のパラメータ",
  "code": "birthPlace",
  "base": [
    "Patient"
  ],
  "type": "string",
  "expression": "Patient.extension.where(url='http://isc-demo/fhir/StructureDefinition/patient-birthPlace').value",
  "comparator": [
    "eq"
  ]
}

特にSearchParameterの定義として、重要になるのは expression の項目と comparator になります。 expressionには対象となるSearchParameterへの FHIRPath 式を記述します。FHIRPathも詳しく説明すると長くなるので興味のある方はこちらの公式ページをご覧ください。

今回の定義で使っている

Patient.extension.where(url='http://isc-demo/fhir/StructureDefinition/patient-birthPlace').value"

こちらの式は、PatientリソースのJson構造に従って、階層順にPatient.extensionと指定し、複数存在する可能性があるExtensionの中から、url=(省略) である今回のExtensionを絞り込み、そのvalueを指定しています。

comparatorはどのような比較式が使えるかを指定します。詳細はこちらをご覧下さい。

Patientに作成したExtension定義を追加する

もう一つ大事な変更があります。Patientリソースでこの作成した BirthPlace Extensionを追加することです。元々自動生成されたPatientリソースのProfile定義MyProfileを以下のように変更します。name要素のCardinalityの変更はコメントアウトしました。

Profile: MyPatient
Parent: Patient
Description: "An example profile of the Patient resource."
//* name 1..* MS
* extension contains BirthPlace named birthPlace 0..1

先ほど追加した"BirthPlace"という名前のExtensionを、Patientリソース内にbirthPlaceという名前でCardinality 0..1 で追加しています。

ついでにテスト用リソースを作成

SUSHIでは、例示用などの目的で使用できるリソースのInstanceを作成することもできます。テストのためにこちらも利用しておきましょう。今定義したExtensionも含めることができます。

Instance: KamiExample
InstanceOf: MyPatient
Description: "Patientリソースのサンプル"
* name.family = "山田"
* extension[BirthPlace].valueString = "鹿児島"

どんなデータができたかは最後のテストでご覧いただきたいと思います。

Let's SUSHI!

FSHファイルの用意ができました!それでは SUSHIコマンドで、fshファイルから各定義ファイルを生成しましょう! sushi コマンドを実行し、以下のように2つのProfile(拡張されたPatientとExtension)、二つのInstance(SearchParameterとサンプルリソース)が生成されたら成功です。

C:\Users\kaminaka\Documents\Work\FHIR\SUSHI\TestProject\MyProfileProject>sushi .
info  Running SUSHI v2.1.1 (implements FHIR Shorthand specification v1.2.0)
info  Arguments:
info    C:\Users\kaminaka\Documents\Work\FHIR\SUSHI\TestProject\MyProfileProject
info  No output path specified. Output to .
info  Using configuration file: C:\Users\kaminaka\Documents\Work\FHIR\SUSHI\TestProject\MyProfileProject\sushi-config.yaml
info  Importing FSH text...
info  Preprocessed 1 documents with 0 aliases.
info  Imported 2 definitions and 2 instances.
info  Checking local cache for hl7.fhir.r4.core#4.0.1...
info  Found hl7.fhir.r4.core#4.0.1 in local cache.
info  Loaded package hl7.fhir.r4.core#4.0.1
(node:27132) Warning: Accessing non-existent property 'INVALID_ALT_NUMBER' of module exports inside circular dependency
(Use `node --trace-warnings ...` to show where the warning was created)
(node:27132) Warning: Accessing non-existent property 'INVALID_ALT_NUMBER' of module exports inside circular dependency
info  Converting FSH to FHIR resources...
info  Converted 2 FHIR StructureDefinitions.
info  Converted 2 FHIR instances.
info  Exporting FHIR resources as JSON...
info  Exported 4 FHIR resources as JSON.
info  Assembling Implementation Guide sources...
info  Generated ImplementationGuide-myprofileproject.json
info  Assembled Implementation Guide sources; ready for IG Publisher.

╔════════════════════════ SUSHI RESULTS ══════════════════════════╗
║ ╭───────────────┬──────────────┬──────────────┬───────────────╮ ║
║ │    Profiles   │  Extensions  │   Logicals   │   Resources   │ ║
║ ├───────────────┼──────────────┼──────────────┼───────────────┤ ║
║ │       1       │      1       │      0       │       0       │ ║
║ ╰───────────────┴──────────────┴──────────────┴───────────────╯ ║
║ ╭────────────────────┬───────────────────┬────────────────────╮ ║
║ │      ValueSets     │    CodeSystems    │     Instances      │ ║
║ ├────────────────────┼───────────────────┼────────────────────┤ ║
║ │         0          │         0         │         2          │ ║
║ ╰────────────────────┴───────────────────┴────────────────────╯ ║
║                                                                 ║
╠═════════════════════════════════════════════════════════════════╣
║ FSHing for compliments? Super job!     0 Errors      0 Warnings ║
╚═════════════════════════════════════════════════════════════════╝

C:\Users\kaminaka\Documents\Work\FHIR\SUSHI\TestProject\MyProfileProject>

fsh-generated\resource フォルダには以下のような成果物が作成されました。

ファイル名内容
ImplementationGuide-myprofileproject.json今回の全ての内容を取りまとめたImplemamtionGuide
StructureDefinition-MyPatient.jsonPatientにExtensionを追加したStructureDefinition
StructureDefinition-birthPlace.jsonExtension birthPlaceの定義を含むStructureDefinition
SearchParameter-BirthPlaceSearchParameter.jsonbirthPlace SearchParameterの定義ファイル
Patient-KamiExample.jsonPatientのサンプルインスタンス

IRIS for HealthにFHIR Profileをインポートしてテストしてみる

IRIS for Health のFHIRリポジトリへの適用

前回の記事ではこの後、_updatePublisherを実行してIGファイル群を生成しましたが、今回は、このStuructureDefinitino/SearchParameterファイルをIRIS for HealthのFHIRリポジトリに取り込んで、新しいSearchParameterで検索できるようになるところを見ていきましょう。

FHIR Profileのインポート等について詳細は、こちらの開発者コミュニティ記事 FHIRプロファイルをご覧章ください。 FHIRリポジトリの構築方法などは、こちらの記事も参考になると思います。

インポートの対象となるのは、先ほど生成された5つのファイルのうち、

  • StructureDefinition-MyPatient.json
  • StructureDefinition-birthPlace.json
  • SearchParameter-BirthPlaceSearchParameter.json の3つです。これを別のフォルダにコピーし、さらにパッケージ全体の情報を管理するための package.jsonファイルを用意します。

package.json

{
  "name": "SUSHI Demo",
  "title": "SUSHI Demo",
  "version": "0.0.1",
  "author": {
    "name": "ISC"
  },
  "fhirVersions": [
    "4.0.1"
  ],
  "bundleDependencies": false,
  "date": "20201208205547",
  "dependencies": {
    "hl7.fhir.r4.core": "4.0.1"
  },
  "deprecated": false
}

nameやtitle,author,dateなどの項目は適宜変更して問題ありません。 (注意)各プロファイルを変更してIRISに再インポートする場合は、versionを適切に変更していく(上げていく)必要があります。 (現在のバージョン2021.1ではFHIRリポジトリには、プロファイルを削除する機能がないため、テスト環境で適切に動作確認した上で、本番環境への適用は最小の回数に抑えるなど、本番環境等でプロファイルが増えすぎないように注意をする必要があります。)

IRISの管理ポータルからHealth -> FHIR Configuration -> Package Configurationと進み、Import Packageから上記4ファイルを含むフォルダを選ぶと以下のような画面になります。

image

Importをクリックして、IRISへのインポートを完了します。

次に Server Configuration画面で、新規FHIRリポジトリを作成します。 (既存のFHIRリポジトリへ追加することも可能です。)

image

POSTMANからテストする

先ほどSUSHIで生成された、テスト用リソースをPOSTします。検証のためには他の値のbirthPlaceを含むデータや、そもそもbirthPlaceを含まないPatientリソースなども生成するほうが良いかもしれません。

image

FHIRリポジトリのSearchParameter に正しく birthPlaceが追加されていれば、以下のGETリクエストでこの患者情報を取得できるはずです!

GET http://localhost:52785/csp/healthshare/sushi/fhir/r4/Patient?birthPlace=鹿児島

正しく結果を取得できるようになったでしょうか? 新しいSearchParameterである birthPlaceが正しく追加されていない場合は、GETリクエストの応答の最初に以下の「birthPlaceというパラメータが認識されていません」というエラー情報をが記述されたOperationOutcomeリソースの情報が含まれています。このメッセージがでていないか応答メッセージを確認してみてください。

       {
            "resource": {
                "resourceType": "OperationOutcome",
                "issue": [
                    {
                        "severity": "error",
                        "code": "invalid",
                        "diagnostics": "<HSFHIRErr>ParameterNotSupported",
                        "details": {
                            "text": "Unrecognized parameter 'birthPlace'. 鹿児島"
                        }
                    }
                ]
            },
            "search": {
                "mode": "outcome"
            }
        },

まとめ

SUSHIを使ってFHIRのProfile(StructureDefinition/SearchParameter)を作成し、IRIS for HealthのFHIRリポジトリにインポートして機能を拡張する流れをみていただきました。 今回は、Extensionに追加した項目をSearchParameterに追加しましたが、FHIR標準仕様で存在するが、SearchParameterにはなっていない要素(エレメント)に対して、SearchParameterを追加するということも可能です。

自由度の高いFHIRの開発では、このように機能を拡張することが可能になっていますが、一方ではInteroperabilityを担保するためにどのような拡張を行ったかという情報の共有、つまりImplemantationGuide等の作成も重要になってきます。 このシリーズのPart1,2で見てきたようにSUSHIはその両面をカバーすることができる非常にユニークで強力なオープンソースのツールです。

このようなツールとIRIS for Healthを組み合わせて、新しいFHIRソリューションが構築されることを期待しています。

今回の記事で使用したSUSHIのfshファイルおよび、生成されたStructureDefinition/SearchParameterのサンプルファイルはこちらからダウンロードすることができます。

0
0 1108
記事 Shintaro Kaminaka · 10月 18, 2021 14m read

特報!!

この記事の中でご紹介している、FHIRオペレーションのデモを含め、FHIR PathやFHIRプロファイル対応などの2021.1のFHIR関連新機能をご紹介するウェビナーが、2021年10月21日 12:30~13:00 に開催されます!!ご興味ある方はこちらからご登録ください!!

InterSystems IRIS 開発者向けウェビナーシリーズ

開発者の皆さん、こんにちは。 今日は前回のFHIRリポジトリをカスタマイズしよう!パート1の記事に続き、パート2として、カスタムオペレーションの実装方法をご紹介したいと思います。この記事で紹介している内容のFHIRリポジトリカスタムオペレーションに関するドキュメントマニュアルはこちらになります。 この記事はIRIS for Health 2021.1 をベースに記載しています。バージョンによって実装方法が異なるケースも考えられますので、該当のバージョンのドキュメントをご参照ください。場合によっては新しいバージョンへアップグレードもご検討ください。

FHIRのOperation(オペレーション)とは?

まず、FHIRのOperationについて、簡単にご紹介したいと思います。 HL7 FHIR公式ページのOperationのページには以下のように記載されています。

The RESTful API defines a set of common interactions (read, update, search, etc.) performed on a repository of typed resources. These interactions follow the RESTful paradigm of managing state by Create/Read/Update/Delete actions on a set of identified resources. While this approach solves many use cases, there is some functionality that can be met more efficiently using an RPC-like paradigm, where named operations are performed with inputs and outputs (Execute).

FHIRにおけるデータのアクセスがRESTのCRUDを基本とするのはご存知の通りですが、RPC的なアプローチでより効率的なデータアクセス、データ処理を実現しようというアプローチがFHIRのOperationと言えます。

HL7 FHIR公式ページで規定されているOpeartionはこちら一覧のページに記載されています。 代表的な所では、Patientリソースで指定できる $everything オペレーションや、Observationリソースで指定できる $lastn オペレーションがありますので紹介します。

$everything オペレーション

$everything オペレーションはPatientリソースと組み合わせて使用します。詳細はこちらのページを参照してください。 IRIS for Health のFHIRリポジトリの場合は、リソースの論理IDまで指定して

 GET /Patient/5/$everything

のように指定して実行できます。 この場合、Patientリソースの論理ID=5に紐づいた関連するリソース(Observation, MedicationRequest, Procedure, Encounter など)を自動的に収集してBundle形式でクライアントに返してくれます。 例えばある患者さんの診療情報を一覧として見せたい場合などには便利な機能です。

$lastn オペレーション

$lastn オペレーションはObservationリソースと組み合わせ使用します。詳細はこちらのページを参照してください。 IRIS for Health のFHIRリポジトリの場合は以下のように指定できます。categoryおよびpatient(またsubject)は必須の指定パラメータとなっています。

 GET /Observation/$lastn?max=10&category=vital-signs&patient=Patient/123

このクエリでは、PatientリソースのID=123の患者に関連した、「vital-signs」カテゴリーに含まれる、最新 10件 のObservationリソースがBundle形式でクライアントに返されます。直近のデータだけを使ってグラフを表示したい、というようなニーズにはぴったりですね。

カスタムオペレーションを作成してみよう

FHIRのオペレーションとはどのようなものか?具体例を2つ挙げてご紹介しました。 カスタムオペレーションはこのようなオペレーションを、プロジェクトのニーズに応じて、自分で定義して実装し利用することができるようになる機能です。定義したカスタムオペレーションはCapability Statementに含めて公開することができます。 以下の手順でカスタムオペレーションを構築することができます。

1. 3つのカスタムクラス(Interactions等)を用意する

まず、最初の手順として、前回のFHIRリポジトリをカスタマイズしよう!パート1で記載した、3つのカスタムクラスを用意します。詳しい内容はパート1の記事をご覧ください。

2. カスタムオペレーション用のクラスを用意し、Interactionsクラスから参照する

Interactionsクラス等と同様に、カスタムオペレーション用のクラスを継承します。 HS.FHIRServer.Storage.BuiltInOperationsを継承し、任意の名称のクラスを作成します。この記事ではCustomFS.MyOperationとします。

(場合によっては、HS.FHIRServer.API.OperationHandlerクラスを継承して作成することもありますが、FHIRリポジトリを利用している場合は、HS.FHIRServer.Storage.BuiltInOperationsを継承し、$everythingなどの実装済みのオペレーションが引き続き使用できるようにする必要があります。詳細はドキュメントをご覧ください。)

これでFHIRリポジトリのカスタマイズに関連して作成したクラスは4つになりましたね。

ベースクラス継承して作成したクラス
HS.FHIRServer.Storage.Json.InteractionsCustomFS.MyInteractions
HS.FHIRServer.Storage.Json.InteractionsStrategyCustomFS.MyInteractionsStrategy
HS.FHIRServer.Storage.Json.RepoManagerCustomFS.MyRepoManager
(new!) HS.FHIRServer.Storage.BuiltInOperationsCustomFS.MyOperation

さらに、このFHIRリポジトリのサーバ処理でこのカスタムオペレーション用のクラスが使用されるように、InteractionsクラスのOperationHandlerClassパラメータでこのクラスを指定します。

Class CustomFS.MyInteractions Extends HS.FHIRServer.Storage.Json.Interactions
{

 Parameter OperationHandlerClass As %String = "CustomFS.MyOperations";

3. カスタムオペレーションの処理を実装する

いよいよ、具体的にカスタムオペレーションの処理内容を実装していきます。2.で作成した、CustomFS.MyOperationsクラス内にメソッドを作成して実装します。

まず作成するオペレーションは影響範囲の応じて3つに分けることができます。 この3つの影響範囲=Scope + オペレーション名により、作成するべきメソッド名が決まってきます。

メソッド名命名ルールについて

メソッド名命名には以下のようなルールがあります。

FHIRScopeOpOperationName

まずメソッド名の先頭は FHIR です。

次に Scope には以下の3つのタイプのいずれかが入ります。

Scope説明
System"ベース" の FHIR エンドポイントに追加する操作を指定します (例えば、http://fhirserver.org/fhir)。これらの操作は、サーバ全体に適用されます。
TypeFHIR エンドポイントにリソース・タイプと共に追加する操作を指定します (例えば、http://fhirserver.org/fhir/Patient)。これらの操作は、指定されたリソース・タイプのすべてのインスタンスで動作します。
Instanceリソースの特定のインスタンスを指す FHIR エンドポイントに追加する操作を指定します (例えば、http://fhirserver.org/fhir/Patient/1)。これらの操作は、リソースの特定のインスタンスでのみ動作します。

以下の図も影響範囲の理解の参考になると思います。

image

そして、"Op" に続き、先頭を大文字にしたオペレーション名が続きます。

例えば、「$deleteall」というカスタムオペレーションをSystemレベルで作成したいなら

FHIRSystemOpDeleteall

というメソッドを作成します。

「$anonymize」というカスタムオペレーションをInstanceレベルで作成したいなら

FHIRInstanceOpAnonymize

というメソッドを作成します。

つまり "FHIR" _ (System or Type or Instance) _ "Op" _ (先頭大文字にしたオペレーション名) という命名ルールですね。

メソッドの実装方法

では、実際に、Instanceレベルの$anonymizeオペレーションを作成していきましょう。このオペレーションの目的はPatientリソースのnameエレメントの中身を匿名化)(*******で埋める)を実装することです。

このメソッドは

 GET /Patient/5/$anonymize

のような形で実装されることを想定しています。

上記の例ででてきたように、FHIRInstanceOpAnonymizeメソッドを以下のように実装します。サンプルなので詳細なエラーハンドリングまでは実装していません。

ClassMethod FHIRInstanceOpAnonymize(pService As HS.FHIRServer.API.Service, pRequest As HS.FHIRServer.API.Data.Request, pResponse As HS.FHIRServer.API.Data.Response)
{
    ///RestClientクラスを利用してFHIRサーバへのアクセスを実行。指定された論理IDのPatientリソースを取得する
	Set clientObj = ##class(HS.FHIRServer.RestClient.FHIRService).CreateInstance(pRequest.SessionApplication)
	Do clientObj.SetResponseFormat("JSON")
	set clientResponseObj=clientObj.Read(pRequest.RequestMethod,pRequest.Type,pRequest.Id)
	
	set pResponse.Json=clientResponseObj.Json
	set pResponse.Status=clientResponseObj.Status
	set pResponse.ETag=clientResponseObj.ETag
	set pResponse.LastModified=clientResponseObj.LastModified
	set pResponse.Location=clientResponseObj.Location
	set pResponse.IsPrettyOut=clientResponseObj.IsPrettyOut

		
	//匿名化処理を実行する
	if pResponse.Status="200" {
        //DynamicObjectからnameエレメントのIteratorを取得し繰り返し処理
		set iter=pResponse.Json.name.%GetIterator()
		while iter.%GetNext(.key,.value) {
			do pResponse.Json.name.%Get(key).%Set("text","***********")
			do pResponse.Json.name.%Get(key).%Set("family","***********")
			do pResponse.Json.name.%Get(key).%Set("given","***********")
		}			
	}
}

パート1のカスタマイズ処理では、実際に検索(GET)されたデータや、送信(POST/PUT)されたデータに対してカスタム処理を実施しましたが、オペレーションの場合はベースとなる検索を実行する必要があります。もちろん、オペレーションの実装目的によっては、検索をする必要がない場合もあるでしょう。

このメソッドでは、得られた検索結果に対して、DynamicObjectのデータ操作を使用して、データを更新し匿名化を行っています。

4. 作成したカスタムオペレーションの定義をCapability Statementに追加する

次に、ロジックを作成したカスタムオペレーションの定義をCapability Statementに追加します。まず、先ほどと同じCustomFS.MyOperationクラスにCapability Statement追加用のAddSupportedOperationsメソッドを記述します。

ClassMethod AddSupportedOperations(pMap As %DynamicObject)
{
	Do ##super(pMap)
    Do pMap.%Set("anonymize","http://myfhirserver/fhir/OperationDefinition/patient-anonymize")
}

メソッド内の、pMap.%Setの最初の引数は"オペレーション名"、2番目の引数はそのオペレーションの定義を表すURIを記載します。 2番目の引数は例えば、先述のPatient/[id]/$everything オペレーションであれば、こちらのページに記載されているように

http://hl7.org/fhir/OperationDefinition/Patient-everything

となります。例えば、あるデータ連携プロジェクトに基づいて実装した場合は、そのプロジェクトの実装ガイド内で規定されたURIになるでしょうし、自プロジェクト内で利便性のために構築したということであれば、任意のURIを指定することもできます。

次にコマンドラインユーティリティを起動して、この変更を反映します。 以下はCUSTOMFSネームスペース内で実行した例になります。

USER>zn "customfs"
 
CUSTOMFS>d ##Class(HS.FHIRServer.ConsoleSetup).Setup()
Query returns no results
HS.FHIRServer.Installer:InstallNamespace Created FHIR web application
HS.FHIRServer.Installer:InstallNamespace Created FHIR API web application
What do you want to do?
  0)  Quit
  1)  Create a FHIRServer Endpoint
  2)  Add a profile package to an endpoint
  3)  Display a FHIRServer Endpoint Configuration
  4)  Configure a FHIRServer Endpoint
  5)  Decommission a FHIRServer Endpoint
  6)  Delete a FHIRServer Endpoint
  7)  Update the CapabilityStatement Resource
  8)  Index new SearchParameters for an Endpoint
  9)  Upload a FHIR metadata package
  10) Delete a FHIR metadata package
Choose your Option[1] (0-10): 7
 
For which Endpoint do you want to update the CapabilityStatement?
  1) /csp/healthshare/customfs/fhir/r4 [enabled] (for Strategy 'CustomFS' and Metadata Set 'hl7.fhir.r4.core@4.0.1')
Choose the Endpoint[1] (1-1): 1

Update the /csp/healthshare/customfs/fhir/r4 service CapabilityStatement to reflect the endpoint strategy. Proceed? (y/n): yes

以上の手順を実行すると、FHIRリポジトリのCapability Statementにカスタムオペレーションのエントリが追加されます! Capability StatementはFHIRリポジトリに以下のリクエストをすると取得できます。anonymizeオペレーションがちゃんと追加されていますね。

 GET http://fhirserver/csp/healthshare/customfs/fhir/r4/metadata
"operation": [
{
    "name": "everything",
    "definition": "http://hl7.org/fhir/OperationDefinition/Patient-everything"
},
(略)
{
    "name": "anonymize",
    "definition": "http://myfhirserver/fhir/OperationDefinition/patient-anonymize"
},

5. 実行して動作を確認してみよう

以上で、カスタムオペレーション $anoymize の実装は完了です。早速動作確認してみましょう!

まずカスタムオペレーションなしで普通にPatientリソースのデータをリクエストしてみます。

 GET http://localhost:52785/csp/healthshare/customfs/fhir/r4/Patient/2

私のデモ環境では、以下のようなnameエレメントを持つデータが格納されていました。

{
    "resourceType": "Patient",
    "id": "2",
    (略)
    "name": [
        {
            "extension": [
                {
                    "url": "http://hl7.org/fhir/StructureDefinition/iso21090-EN-representation",
                    "valueCode": "IDE"
                }
            ],
            "use": "official",
            "text": "山田 太郎",
            "family": "山田",
            "given": [
                "太郎"
            ]
        },
        {
            "extension": [
                {
                    "url": "http://hl7.org/fhir/StructureDefinition/iso21090-EN-representation",
                    "valueCode": "SYL"
                }
            ],
            "use": "official",
            "text": "ヤマダ タロウ",
            "family": "ヤマダ",
            "given": [
                "タロウ"
            ]
        }

次に、実装した $anonymizeを追加して実行してみます!

 GET http://localhost:52785/csp/healthshare/customfs/fhir/r4/Patient/2/$anonymize

以下のように匿名化されたデータが取得できました!

{
    "resourceType": "Patient",
    "id": "2",
    (略)
    "name": [
        {
            "extension": [
                {
                    "url": "http://hl7.org/fhir/StructureDefinition/iso21090-EN-representation",
                    "valueCode": "IDE"
                }
            ],
            "use": "official",
            "text": "***********",
            "family": "***********",
            "given": "***********"
        },
        {
            "extension": [
                {
                    "url": "http://hl7.org/fhir/StructureDefinition/iso21090-EN-representation",
                    "valueCode": "SYL"
                }
            ],
            "use": "official",
            "text": "***********",
            "family": "***********",
            "given": "***********"
        }
    ],

カスタマイズを実装する際のTips

パート1、パート2とIRIS for HealthのFHIRリポジトリをカスタマイズする方法をご紹介してきました。 ここで、カスタマイズの際のTipsを一つご紹介します。

IRISのFHIRリポジトリ処理では、パフォーマンス最適化のために、個別のプロセス内でFHIR処理用のサービスインスタンスが起動され、再利用される仕組みになっています。そのため、条件によっては、サーバ側のカスタム処理を書き換えたのにそれが反映されないことがあります。そのような際にはいくつかの対応方法があります。

  1. FHIR Server Configurationページで「New Service Instance」のチェックを有効にする

開発環境であれば、この方法をお勧めします。FHIRリクエスト毎に新しいService Instanceが立ち上がるので、必ず変更が反映されます。ただし、パフォーマンスへの影響を考えると、本番環境で設定することはお勧めしません。

image

  1. Web Gateway Management 画面からすべてのセッションをクリアする

 System Status画面ですべてのセッションをクリアすることによって、起動しているIRIS側のプロセスもすべて再起動されます。下記画像の黄色の部分をクリックします。

image

  1. 再起動する(常に最強の手段)

まとめ

いかがでしたでしょうか?

IRIS for HealthのFHIRリポジトリカスタマイズ機能を利用することによって、プロジェクト開発で求められる様々な要件に柔軟に対応することができます。もちろん、カスタマイズを多用することが、FHIRの持つ汎用性に影響を及ぼすことを考慮する必要がありますが、パート1/2の記事でご紹介したカスタマイズ機能を効果的に使えば、より高度なFHIRアプリケーションの構築も可能になります。

パート1、パート2の内容を含むIRISのクラスをこちらのGitHubサイトからダウンロードすることができます。

また新たなカスタマイズ手法が実装されたらこちらの開発者コミュニティで紹介したいと思います。

0
0 563
記事 Shintaro Kaminaka · 10月 10, 2021 10m read

開発者の皆さん、こんにちは。 IRIS for Health 2021.1がリリースされてからしばらくたちますが、多くのユーザさんにFHIRリポジトリ機能をお使いいただいています。 今日はFHIRリポジトリのサーバ側の処理をカスタマイズする機能をご紹介したいと思います。

この記事で紹介している内容のFHIRリポジトリカスタマイズに関するドキュメントマニュアルはこちらになります。

この記事はIRIS for Health 2021.1 をベースに記載しています。バージョンによってはカスタマイズに必要なクラスが異なることがあります(例えば2020.1では後述のRepoManagerクラスはまだありません。)

FHIRサーバカスタマイズの2つのアプローチ

FHIRサーバ機能をカスタマイズするには2つのアプローチがあり、1つはこの記事でご紹介する、Interactionクラス群をカスタマイズしてFHIRリポジトリを拡張する方法、もう一つは、相互運用プロダクションでロジックを実装してサーバとしての動作を変更する方法です。

後者は厳密にはFHIRリポジトリとしての実装はそのままで、リポジトリに受け渡される前、あるいはリポジトリから応答を受けた後に、そのデータを参照、変更してカスタマイズを実装する流れになります。 IRISのInteroperability機能(Ensemble)に慣れているかたはこちらのアプローチがわかりやすいかもしれません。しかし、すべてのFHIRリクエストがトレースされメッセージが保存されるため、データ容量やパフォーマンスには気を配る必要があります。 この方法にご興味がある方は、こちらの相互運用プロダクションのドキュメントマニュアルをご参照ください。

FHIRリポジトリを構築する前の作業

FHIRリポジトリカスタマイズで最も注意しなければいけない点、それはFHIRリポジトリを構築する際にカスタマイズができるように、この後記載する手順を実施しておかなければいけないという点です。つまり、デフォルト設定でFHIRリポジトリを構築し、しばらく運用してから、「こういうカスタマイズ処理を組み込みたいな」と思っても、簡単に追加することができないのです。(新しくカスタマイズ可能なリポジトリを構築し、データ移行するなどの方法は取れます)

この制限があるため、FHIRリポジトリ運用当初はカスタマイズ予定がなくても、下記の手順を実行しカスタマイズ機能を組み込んでおくという選択肢もあります。

それでは、そのカスタマイズ方法をご紹介します。 まず、以下の3つのクラスをそれぞれ継承してカスタムクラスを作成します。この記事では共通のパッケージとしてCustomFSとし、クラス名の先頭にはMyを追加しています。

ベースクラス継承して作成したクラス
HS.FHIRServer.Storage.Json.InteractionsCustomFS.MyInteractions
HS.FHIRServer.Storage.Json.InteractionsStrategyCustomFS.MyInteractionsStrategy
HS.FHIRServer.Storage.Json.RepoManagerCustomFS.MyRepoManager

継承したInteractionStrategyクラスとRepoManagerクラスはロジックを実装したりはしませんが、以下の設定を行う必要があります。

  • 両クラスの StrategyKeyパラメータに共通の一意の識別子(文字列ならなんでも)を設定する
  • IntectionStrategyのInteractionClassで自分の作成したInteractionsクラスを指定する
  • RepoManagerのStrategyClassで自分の作成したInteractionStrategyクラスを指定する

図で関連を表現するとこんな感じになります。

image

実際のカスタマイズ内容は継承したInteractionsクラスの各メソッドをオーバーライドして実装していくことになります。

カスタマイズのクイックスタート

以下の表はドキュメントマニュアルに記載されている内容そのままですが、転載します。 これらのメソッドをオーバライドしてロジックを記述し、カスタマイズを行います。

目標HS.FHIRServer.Storage.Json.Interactions のサブクラスのアクション
特定のFHIR相互作用のカスタマイズ相互作用に対応するメソッド(Add,Read,Update)をオーバーライドします。
すべての要求の処理OnBeforeRequest をオーバーライドして、ユーザに透過的なロジックを実装します。FHIR クライアントに要求の処理が異なることを認識させる場合は、カスタムの FHIR 操作を作成します。
すべての要求の後処理OnAfterRequest をオーバーライドして、ユーザに透過的なロジックを実装します。FHIR クライアントに要求の処理が異なることを認識させる場合は、カスタムの FHIR 操作を作成します。
Read 相互作用の結果の後処理PostProcessRead をオーバーライドします ()。
Search 相互作用の結果の後処理PostProcessSearch をオーバーライドします ()。
カスタムの FHIR 操作の追加OperationHandlerClass パラメータをオーバーライドして、HS.FHIRServer.Storage.BuiltInOperations のサブクラスの名前を指定します。"カスタムの FHIR 操作" を参照してください。
バンドルの処理方法のカスタマイズBatchHandlerClass パラメータをオーバーライドして、カスタム・クラスの名前を指定します。既定のハンドラ・クラスは HS.FHIRServer.DefaultBundleProcessor です。
OAuth トークンの処理方法のカスタマイズOAuth2TokenHandlerClass パラメータをオーバーライドして、カスタム・クラスの名前を指定します。既定のハンドラ・クラスは HS.FHIRServer.Util.OAuth2Token* です。

この表のリンク先ドキュメントマニュアルにもいくつか、実装例が記載されていますが、この記事ではもう少しシンプルなパターンのサンプルを記載していきたいと思います。

OnAfterRequestメソッド

まずはOnAfterRequestメソッドを題材にどんな引数を受け取るのか見てみましょう。

Method OnAfterRequest(pFHIRService As HS.FHIRServer.API.Service, pFHIRRequest As HS.FHIRServer.API.Data.Request, pFHIRResponse As HS.FHIRServer.API.Data.Response)
{

このメソッドは、3つの引数を受け取ります。主に使うのはpFHIRRequestとpFHIRResponseの二つです。 このメソッドは OnAfterRequestメソッドなので、FHIRリポジトリ上での処理が完了した後に起動されるメソッドです。そのため、FHIRリポジトリへの要求であるpFHIRRequestと、これから要求元へ返すpFHIRResponseの二つを参照できます。

FHIRリポジトリへのJSONリクエストおよびレスポンスは

pFHIRRequest.Json
pFHIRResponse.Json

に含まれます。これはJsonの構造通りにデータアクセスできる %DynamicObject型の変数なので、このようにアクセスできます。

pFHIRResponse.Json.resourceType //-> Bundleなど
pFHIRResponse.Json.total //->Bundleの場合にそのBundleに含まれる数(10など)
pFHIRResponse.Json.entry.%Get(0).resource.gender //->Bundle内の最初のPatientリソースの性別を取得

ログなどの目的でこの内容を文字列あるいはストリームに保存しておきたい場合は、%ToJSON()メソッドを使って変換します。 他にもこれらのインスタンスは

プロパティ含んでいるデータ
pFHIRResponse.Id追加・更新されたリソースの論理ID
pFHIRResponse.VId追加・更新されたリソースのバージョンID
pFHIRResponse.Status処理のステータス

など様々な情報を含んでいます。詳細はHS.FHIRServer.API.Data.RequestHS.FHIRServer.API.Data.Responseのクラスリファンレスドキュメントをご覧ください。

OnBeforeRequest/PostProcessReadメソッドを実装してみる

それでは具体的にOnBeforeRequestメソッドを使って実装してみましょう。

IRIS for Health のFHIRリポジトリでは、こちらの記事(IRIS for Health上でFHIRリポジトリ+OAuth2認可サーバ/リソースサーバ構成を構築するパート3(OAuth2スコープ編))で紹介したOAuth2アクセストークンのScopeを使う方法で、このScopeのユーザにはこのリソースの参照権限だけ与える、こちらには更新権限を与える、といったアクセスコントロールが可能です。ただ、これはあくまでもリソース単位のコントロールになるので、「このリソースにこういうデータがあるときは登録させたくない」「このリソースにこういうデータが含まれているときは応答として返したくない」などの要望の実装はこのカスタマイズを使って実現することができます。

ではまず、Patientリソースの登録時に、電話番号情報を格納するtelecom要素の最初のデータに 401,403,400 で始まる電話番号が入っていたらエラーを返す、というロジックを実装してみたいと思います。最初の3桁はエラーとして返すHTTPエラーコードと紐づけています。

以下のようなコードになります。本来はチェックロジックなども含めるべきですが、サンプルのためシンプルなコードにしています。

Method OnBeforeRequest(pFHIRService As HS.FHIRServer.API.Service, pFHIRRequest As HS.FHIRServer.API.Data.Request, pTimeout As %Integer)
{
	//POST or PUTでPatientが対象の場合
	if ((pFHIRRequest.RequestMethod="POST")||(pFHIRRequest.RequestMethod="PUT"))&&(pFHIRRequest.RequestPath["Patient") {
	
		if $IsObject(pFHIRRequest.Json) {			
			s tele=pFHIRRequest.Json.telecom.%Get(0).value
			
			if $Extract(tele,1,3)="401" $$$ThrowFHIR($$$HttpOnlyResponse(401))
			if $Extract(tele,1,3)="403" $$$ThrowFHIR($$$HttpOnlyResponse(403))
			if $Extract(tele,1,3)="400" $$$ThrowFHIR($$$GeneralError, "あなたの電話番号は登録する権利がありません。", $$$OutcomeNotSupported(400))

		}

	}

エラーとして応答を返す場合は、このサンプルのように直接Throwすることができます。

$$$ThrowFHIR($$$HttpOnlyResponse(401))

次はPostProcessReadメソッドです。 先ほどは登録時の電話番号をチェックして応答を返しましたが、今回は返すデータをチェックして40で始まっている場合は、マスクして応答するようにしたいと思います。

Method PostProcessRead(pResourceObject As %DynamicObject) As %Boolean
{
	//40で始まる電話番号を持つPatientのtelecom要素を上書きする
	if pResourceObject.resourceType="Patient" {
		if $Extract(pResourceObject.telecom.%Get(0).value,1,2)="40" {
			//return 0
			set pResourceObject.telecom.%Get(0).value="******"
		}
	}
	
	return 1
}

}

この方法ではあくまで、応答を返す際に値を上書きしているだけなので、リポジトリ上の値は変更していないことに注意してください。 また、このPostProcessReadは、リソースのIDまで指定して検索するようなケースにだけ有効です。

http://localhost:52785/csp/healthshare/customfs/fhir/r4/Patient/3

以下のように全件取得や条件取得の際は応答がBundleとして返されるので、この変換は適用されません。

http://localhost:52785/csp/healthshare/customfs/fhir/r4/Patient
http://localhost:52785/csp/healthshare/customfs/fhir/r4/Patient?gender=female

Bundleに含まれる応答をカスタマイズする場合には OnProcessSearch をカスタイズします。

まとめ

いかがでしたでしょうか? 実際のFHIRアプリケーション開発においては、標準のFHIR仕様の範囲だけで実装することが難しい場合は、今回ご紹介したカスタマイズ機能を適切に使用して、開発に役立てることができます。 次回は、カスタマイズ機能パート2として、カスタムオペレーションの実装例をご紹介したいと思います。

0
1 593
お知らせ Makiko Kokubun · 9月 17, 2021

開発者のみなさん、こんにちは!
インターシステムズ開発者コミュニティでは、4回に渡り、InterSystems IRIS 2021.1の新機能や、開発を行う上で役に立つ機能をご紹介するウェビナーを開催します。10月の火曜と木曜のお昼に、弊社の技術者が30分でインターシステムズの最新テクノロジーについて解説します。
ぜひお気軽にご視聴ください!

※ (2022/4/1更新)YouTubeにアーカイブを公開しました。こちらよりご覧いただけます。

開催予定

第1回:10/12(火)InterSystems IRIS Adaptive Analytics のご紹介
第2回:10/14(木)Python Gateway のご紹介
第3回:10/19(火)SQL から始める機械学習 – IntegratedML のご紹介
第4回:10/21(木)FHIR 新機能

時間:12:30~13:00予定(約30分)
配信形式:ON24を使用したオンライン配信
参加費:無料

詳細・事前登録はこちらから

プレビュー:IRIS & InterSystems IRIS for Health 2021.1 新機能のご紹介

このビデオでは、昨年リリースされたバージョン2020.1から、新バージョン2021.1の間で追加/改善/強化された機能についてご紹介しています。合わせてご覧ください。

0
0 228
お知らせ Shintaro Kaminaka · 7月 8, 2021

開発者の皆さん、こんにちは!

HL7v2メッセージをFHIR(Fast Healthcare Interoperability Resources)に変換するニーズがあり、その変換プロセスが複雑で分かりにくいと感じたことはありませんか?インターシステムズは、HL7v2メッセージをFHIR(Fast Healthcare Interoperability Resources)に変換するプロセスを簡単にする、HealthShareメッセージ変換サービス(HealthShare Message Transformation Services)と呼ばれる新しいクラウドベースのSaaSサービスを展開しています。 この新しいサービスの早期アクセス・プレビュー・プログラムを発表できることを嬉しく思います。 必要なのは、無料のAWSアカウントと、HL7v2メッセージをドロップするためのS3バケット、そしてFHIR出力を得るための別のS3バケットだけです。

この機能の簡単なデモをご覧ください。

<iframe allow="encrypted-media" allowfullscreen="" frameborder="0" gesture="media" height="315" scrolling="no" src="https://www.youtube.com/embed/Js0SDUZbXv8" width="560"></iframe>

インターシステムズ社のラーニングサイトでは、AWS の無料アカウントとインターシステムズ社のクラウド・ポータルの無料アカウントにサインアップして、変換サービスの強力な機能を利用するための簡単なステップ・バイ・ステップ・ガイドを提供しています。 完全なドキュメントは、インターシステムズ社のドキュメントでご覧いただけます。

このサービスは、7月下旬に正式に開始される予定です。プレビューが終了しても、最初の100万件の変換を無料で利用することができます。

インターシステムズ社のこの新しいオファーの詳細は以下の内容です:

HealthShareメッセージ変換サービスの紹介。

医療IT業界では、FHIR® (Fast Healthcare Interoperability Resources)が、ヘルスケアデータを交換するための最新のデータ標準として採用されています。 オンデマンドのHealthShareメッセージ変換サービスを利用することで、医療機関、保険会社、製薬会社は、既存のデータフォーマットをFHIR規格に変換し、データから最大限の価値を引き出すことができます。 インターシステムズは、最新のFHIR規格だけでなく、HL7v2、X12、CDA、C-CDA、DICOMを含むすべての主要なヘルスケア規格を実装しており、ヘルスケアの相互運用性におけるリーダー的存在です。

HealthShareメッセージ変換サービスは、これらの以前の標準からFHIR R4へのメッセージ変換を簡単に行えるように設計されており、初期リリースではHL7 v2メッセージのFHIR R4への変換をサポートしています。 FHIRメッセージは、AWS S3バケットまたはAmazon HealthLake (Preview)に送ることができ、将来的には他のFHIRリポジトリオプションも追加される予定です。

HealthShareメッセージ変換サービスは、HL7v2メッセージをFHIRに変換することを簡単にします。 変換ロジックを気にする必要がないので、メッセージ変換の複雑な作業はインターシステムズに任せて、優れたヘルスケア・アプリケーションの構築に集中することができます。このサービスが提供するのは

  • AWS上での簡単なプロビジョニングと起動
  • インバウンドS3バケットのHL7v2メッセージのチェック
  • HL7コンテンツのバリデーション
  • FHIR R4へのメッセージ変換
  • 変換されたメッセージを、アウトバウンドの S3 バケット、InterSystems FHIR Accelerator (Preview) サービス、または Amazon HealthLake (Preview) リポジトリにルーティングする
  • 変換パイプラインのステータスと統計情報のモニタリング

さらに、このサービスはAWSのインフラ上に構築されているため、ISO 27001:2013およびHIPAAをサポートするHITRUST認証を取得しています。インターシステムズは、このサービスの運用、監視、バックアップを管理しています。

そして何より、このサービスが商業的に開始されると、最初の100万回の変換が無料で提供され、その後は使用した分だけを支払うことになり、変換されたメッセージあたりのコストは非常に低く抑えられます。 このサービスを利用するための長期契約はなく、いつでも解約できます。

皆様からのフィードバックをお待ちしております。 この記事のコメント欄にご意見をお寄せいただくか、 HMTS@InterSystems.com まで直接お問い合わせください。

HL7 ® と FHIR ® は Health Level Seven International の登録商標であり、これらの商標の使用は HL7 による推奨を意味するものではありません。FHIR商標の使用は、HL7によるHealthShare Message Transformation ServicesまたはHealthShare Message Transformation Servicesの推奨を意味するものではありません。

0
0 508
お知らせ Makiko Kokubun · 7月 5, 2021

開発者の皆さん、こんにちは!

インターシステムズでは、7/30(金)に、InterSystems IRIS for Healthを使った FHIR のハンズオンセミナーをオンラインで開催致します。

FHIR R4リソースリポジトリを構築する上で知っておきたい、FHIR リソースのRESTを使った操作を体験し、サンプルアプリケーションを通してFHIRアプリケーション構築方法を学習します。

FHIR ハンズオンセミナー 概要

  • 日時:2021年7月30日(金)16:00~18:00(2時間)
  • 参加費:4,000円(Webからの事前登録制)
  • 開催形式:オンライン(Teams会議+演習環境用システムを利用)
  • 定員:10名

詳細・事前登録はこちらから  
満席となりましたため、受付を締め切らせて頂きました。
キャンセルが出ましたら、受付を再開致します。

 

ハンズオンを通して以下の内容をご理解・ご体験いただけます。

  • IRIS for Health でFHIR R4リソースリポジトリを作成する方法
  • FHIRリソース同士のリファレンスの意味
  • FHIRリソースの検索方法
  • サンプルWebアプリケーションから作成したR4リポジトリへアクセスする方法
  • CSV→FHIR変換処理の操作体験
  • SS-MIX2→FHIR変換処理の操作体験

ぜひご受講ご検討ください!

0
0 226
記事 Makiko Kokubun · 6月 15, 2021 1m read

*この動画は、2021年2月に開催された「InterSystems Japan Virtual Summit 2021」のアーカイブです。

FHIR プラットフォームとして InterSystems IRIS for Health を選択する利点の一つは、クラウド/オンプレミスを含む豊富なプラットフォームの選択肢です。

 

インターシステムズは新しい選択肢の一つとして、FHIRマネージドサービスである”FHIR Accelerator Service”をまずは米国内でリリースします。このサービスを活用するとユーザはすぐにマネージド環境をプロビジョニングしてFHIRサービス開発/実行環境を入手することができます。
この動画では、AWSクラウド上でホストされるこのサービスについてデモを交えてご紹介しています。

この開発者コミュニティでは他にも IRIS の FHIR 機能に関連した多くの記事を公開しています。 FHIR にご興味ある方はぜひご覧ください。

0
0 138
お知らせ Mihoko Iijima · 6月 7, 2021

開発者の皆さん、こんにちは!

第12回 InterSystems IRIS プログラミングコンテスト(FHIR Accelerator)への応募、投票が全て終了しました。コンテストへのご参加、またご興味をお持ちいただきありがとうございました。

今回のお知らせでは、見事受賞されたアプリケーションと開発者の方々を発表します!

🏆 Experts Nomination - 特別に選ばれた審査員から最も多くの票を獲得したアプリケーションに贈られます。  

🥇 1位 - $4,000 は FHIR Data Studio Connector を開発された @Dmitry Maslennikov さんに贈られました!

🥈 2位 - $2,000 は FHIR Simple Demo Application を開発された @Marcello Correa さんに贈られました!

🥈 3位 - $1,000 は iris-on-fhir を開発された @Henrique Dias Dias さんと @José Roberto Pereira さんに贈られました!

🏆 Community Nomination - 最も多くの票を獲得したアプリケーションに贈られます。

0
0 97
お知らせ Mihoko Iijima · 6月 1, 2021

開発者の皆さん、こんにちは!

いよいよ、第12回 InterSystems IRIS プログラミングコンテスト(FHIR Accelerator)の投票が、6月3日(木)US時間 から開始されます!

当初、5月31日(US時間)から投票開始予定でしたが、応募期間を延長し 6月3日が投票開始日となりました。

テーマは、InterSystems IRIS FHIR Accelerator Service (FHIRaaS) on AWS を使用して構築されたソリューションです。関連記事にご利用を開始するための手順を掲載しています。ぜひご参照ください。

➡️ 投票は 6月3日から! これだ 🔥 と思う作品への投票、よろしくお願いします!

投票方法や新機能について:

Experts nomination:

今回は、経験豊富な審査員がベストアプリを選び、Expert Nominationで賞品をノミネートします。

↓審査員↓

0
0 84
記事 Makiko Kokubun · 5月 11, 2021 1m read

*この動画は、2021年2月に開催された「InterSystems Japan Virtual Summit 2021」のアーカイブです。

国や地域のニーズに合わせて何のデータをどこにどのように格納するのかを定める共通ルールである FHIR プロファイルは、FHIR による標準化において、非常に重要な要素です。

この動画では、InterSystems IRIS for Health における FHIR リポジトリの構築・設定~ FHIR プロファイルの追加の方法を、最新バージョンおよび今後のバージョンでのサポート内容を含めてご紹介いたします。

この開発者コミュニティでは他にも IRIS の FHIR 機能に関連した多くの記事を公開しています。 FHIR にご興味ある方はぜひご覧ください。

0
0 322
お知らせ Mihoko Iijima · 5月 5, 2021

開発者の皆さん、こんにちは!GW は、のんびりゆったり良いお休みになりましたでしょうか🎏?

休み明けにぴったりのコンテストテーマが発表されました!今回は 🔥 FHIR Accelerator 🔥 です!

🏆 InterSystems FHIR Accelerator Programming Contest 🏆

InterSystems FHIR-as-a-service on AWS を使用する、または、InterSystems IRIS FHIR Accelerator を使用したソリューションの開発に役立つアプリケーションを開発し、ご応募ください!

応募期間は 2021年5月10日~5月30日 です!

💰 賞金総額: $8,750 💰

(投票期間は 2021年5月31日~6月6日、勝者発表は 6月7日を予定しています)

優勝特典

1、審査員から多く票を集めたアプリケーションには、以下の賞金が贈られます。

🥇 1位 - $4,000 

🥈 2位 - $2,000 

🥉 3位 - $1,000

2、開発者コミュニティで多く票を集めたソリューションには、以下の賞金が贈られます。

🥇 1位 - $1000 

🥈 2位 - $500 

🥉 3位 - $250

複数の参加者が同数の票を獲得した場合、全参加者が勝者となり賞金は勝者間で分配されます。

参加資格

1
0 147
お知らせ Mihoko Iijima · 5月 8, 2021

開発者の皆さん、こんにちは!

いよいよ 🏆 InterSystems FHIR Accelerator Programming Contest 🏆 への応募が開始されます!

今回のコンテストに参加するためには、InterSystems IRIS FHIR Accelerator Service (FHIRaaS) を AWS で利用する必要があります。

FHIRaaS の利用を開始するための最初の手続きとして、特別なコードを含めた URL を使用して ISC Dev FHIR Portal でユーザ情報を登録する必要があります。

「特別なコードを含んだ URL」って?

以下例のように「特別なコード」をクエリパラメータに指定して、ポータルサイトにアクセスします。

👉🏼 https://portal.trial.isccloud.io/account/signup?code=特別なコード
 

ポータルサイトを利用するための「特別なコード」は、以下いずれかの方法で入手できます!

  • コミュニティ上で @Irina Podmazko へダイレクトメッセージを送付する
  • DC Discord channel にアクセスして、またはプライベートメッセージでコンテスト担当者に連絡する
  • このお知らせのコメント欄に「コード希望!」を記入する(担当者からダイレクトメッセージでコードをお知らせします)
0
0 180
記事 Shintaro Kaminaka · 4月 19, 2021 18m read

開発者の皆さん、こんにちは。

このシリーズでは、IRIS for Healthの使い方ではなく、関連技術として、FHIRプロファイル作成ツールであるSUSHIの握り方使い方を紹介していきたいと思います。

このツールをうまく使うことで、FHIRプロジェクトのプロファイル情報(仕様や制限、拡張などの情報)をうまく整理し、公開することができます。

その前にSUSHIとは何でしょうか?簡単にですが、順番に説明していきたいと思います。

FHIR って?

FHIRとは Fast Healthcare Interoperability Resources の略であり、Web通信の一般的技術であるRESTを使用して、可読性が高く取り扱いがし易いJSON/XML形式のデータの集合(=リソース)をやり取りする短期間で実装可能な医療情報交換標準規格、という定義になっています。

簡単に言えば、医療のデータの表現方法として皆で共通したフォーマットを使うことによって、システム間や施設間などでの情報の伝達や交換をやりやすいようにしよう!ということですね。

FHIRには様々なリソースが定義されています。例えば患者さんの情報にはPatientリソースという定義があり、これを使って表現されます。

FHIR公式サイトには多くのサンプルが掲載されていますので、一部抜粋してみます。 例えばこのようなJSON形式で表現されます。患者番号(Identifier)、氏名(name)、性別(gender)などが表現されています。

{
  "resourceType": "Patient",
  "id": "pat1",
  "text": {
    "status": "generated",
    "div": "<div xmlns=\"http://www.w3.org/1999/xhtml\">\n      \n      <p>Patient Donald DUCK @ Acme Healthcare, Inc. MR = 654321</p>\n    \n    </div>"
  },
  "identifier": [
    {
      "use": "usual",
      "type": {
        "coding": [
          {
            "system": "http://terminology.hl7.org/CodeSystem/v2-0203",
            "code": "MR"
          }
        ]
      },
      "system": "urn:oid:0.1.2.3.4.5.6.7",
      "value": "654321"
    }
  ],
  "active": true,
  "name": [
    {
      "use": "official",
      "family": "Donald",
      "given": [
        "Duck"
      ]
    }
  ],
  "gender": "male",
  "以下略"
}


FHIRプロファイルって?

FHIRではJSONやXMLという表現形式だけではなく、何の情報をどのようなJSONキー名称で記載するか、どのようなコードを使用するか、どのような構造で表現するかいった決まりが存在します。それをFHIRプロファイルと呼んでいます。

プロファイルは用語として色々な意味で使われています。

広義では・・・
FHIRリソースおよびFHIRサーバに関する制約の定義の集合。それを表すアーティファクト(成果物)。
狭義では・・・
あるリソースに対して、特定の制約を適用したコンフォーマンス・リソース(適合性リソース) 。 この場合、プロファイルはリソース単位に存在する(例)Pateintプロファイル、Observationプロファイル…

                    詳細については、こちらのFHIRプロファイルに関するJapan Virtual Summit 2021動画をご覧ください。(約20分)

FHIRの公式Webサイトでは各リソースについて既定の仕様が開示されています。ですが、各リソースの使い方の自由度がとても高く、そのままでは実際に相互運用性のあるデータ交換をすることはこ困難です。ですので、事前の「申し合わせ」にもとづいて、リソースの記述に「規則」を改めて設ける必要があります。この「申し合わせ」「規則」に相当するのは、実装ガイドライン(Implementation Guide)とプロファイル(Profile)に相当します。

実装ガイドラインは主に文章で記述されたもので、WordやExcel、HTML等でも記述されています。一方、ProfileはFHIRのStructureDefinitionリソースを使って計算可能なJSON形式で記述をしています。このFHIRのプロファイル自体もFHIRのリソースで表現できる、というのがFHIRの特徴の一つでもあります。例えばIRIS for Healthのような製品でその定義を取り込んで、機能拡張ができるように、JSON形式で仕様まで表現できるようになっているのです。

実装ガイドラインは様々なツールで作れますが、米国HL7協会はProfileから実装ガイドラインを自動的に生成するIG Publisherを公開しています。このツールを使えば、米国HL7協会が出しているフォーマットで実装ガイドラインのHTMLファイル等を生成することができます。この記事後半ではその方法についても紹介しています。

例えばこれは、US Coreと呼ばれる米国で標準的に使用されることが推奨されたPatientリソースの記法上の規約を表現した、「StructureDefinition」というリソースです。 (引用元)

{
  "resourceType" : "StructureDefinition",
  "id" : "us-core-patient",
  "text" : {
    "status" : "extensions",
    "div" : "省略"
  },
  "url" : "http://hl7.org/fhir/us/core/StructureDefinition/us-core-patient",
  "version" : "3.1.1",
  "name" : "USCorePatientProfile",
  "title" : "US Core Patient Profile",
  "status" : "active",
  "experimental" : false,
  "date" : "2020-06-27",
  "publisher" : "HL7 US Realm Steering Committee",
  "contact" : [
    {
      "telecom" : [
        {
          "system" : "url",
          "value" : "http://www.healthit.gov"
        }
      ]
    }
  ],
  "以下略"

FHIRプロファイルを表現されるリソースとしては他にもImplementationGuideやFHIRサーバの一連の機能をまとめたCapabilityStatementなどがあります。

FHIR Shorthand とは?

というわけで、ではFHIRプロファイルを作成するには↑のJSON構造を作っていけばいいんだな!?ということになる訳ですが、これを手作業でやるのはどう考えて難しいし煩雑ですよね。間違えそうです。

これを補助するためのアプリケーションやツールが公開されており、商用製品やオープンソースなどいくつかの選択肢があります。 こちらのページをご覧ください。

例えばオランダのFirely社のForgeなどは有名ですが、最近ではFHIR Shorthand (リンク)というFHIRアーティファクトを定義するためのドメイン固有の言語も広く使われるようになってきています。

FHIR Shorthandは言語の一種であり、例えば以下のような定義ファイル=FSH(フィッシュ)ファイルを作成しながら、FHIRプロファイルを作成することができます。 以下にサンプルのFSHファイルを例示します。引用元 例えば、このプロファイルの名前(Profile: CancerDiseaseStatus)、ベースとなる元のFHIRリソース(Parent: Observation)、カーディナリティを変更するエレメントの指定(bodySite 0..0)などの内容を含んでいます。

Alias: LNC = http://loinc.org
Alias: SCT = http://snomed.info/sct

Profile:  CancerDiseaseStatus
Parent:   Observation
Id:       mcode-cancer-disease-status
Title:    "Cancer Disease Status"
Description: "A clinician's qualitative judgment on the current trend of the cancer, e.g., whether it is stable, worsening (progressing), or improving (responding)."
* ^status = #draft
* extension contains EvidenceType named evidenceType 0..*
* extension[evidenceType].valueCodeableConcept from CancerDiseaseStatusEvidenceTypeVS (required)
* status and code and subject and effective[x] and valueCodeableConcept MS
* bodySite 0..0
* specimen 0..0
* device 0..0
* referenceRange 0..0
* hasMember 0..0
* component 0..0
* interpretation 0..1
* subject 1..1
* basedOn only Reference(ServiceRequest or MedicationRequest)
 (省略)

SUSHIって?

FHIR/FHIRプロファイル/FHIR Shorthandと順に説明してきましたが、ついにSUSHIの説明です。

SUSHI (an acronym for “SUSHI Unshortens SHorthand Inputs”) (4) is a reference implementation of a FSH compiler that translates FSH into FHIR artifacts such as profiles, extensions, and value sets. SUSHI is installed on your own computer and runs locally from the command line. (引用元)

(訳)SUSHI("SUSHI Unshortens SHorthand Inputs "の略)は、FSHファイルをプロファイル、エクステンション、バリューセットなどのFHIRアーティファクトに変換するFSHコンパイラのリファレンス実装である。SUSHIは自分のコンピュータにインストールされ、コマンドラインからローカルに実行される。

つまり、先ほどのFHIR Shorthandを記述したFSH(フィッシュ)ファイルを、SUSHIで処理すると、StructureDefinitionなどのファイルが生成される、ということです。

この仕組みを説明したわかりやいようで、ちょっとわかりにくい一枚の絵があります!引用元

image

(この絵では、魚を処理(=コンパイル)して、寿司ができるようなイメージで書かれてるんですが、実際はコンパイルをしているのが「SUSHIコンパイラ」で、できあがるのは「プロファイルなどのFHIRアーティファクト」なのでちょっと違うと思うんですよね・・・。お寿司の説明にProfilesやExtensions等の記載はありますけども。)

駆け足でSUSHIとは何か、までご紹介してきましたがご理解いただけたでしょうか?

FSH Schoolに行こう

肝心なSUSHIのインストール方法や基本的な使い方ですが、それらについてはここで説明するよりも、非常に丁寧に紹介されたオフィシャルサイトがありますので、そちらをご紹介したいと思います。 その名もFSH Schoolです。

SUSHIを使って生成されるのは、StrudctureDefinitionなどのリソース(JSONファイル)ですが、同じくこのサイトで紹介されている、"IG Publisherツール"を使うことによって、それらを取りまとめたHTMLのソースまで生成することができます。

image

まずはこのSUSHI Tutorialに内容に沿って、基本的な機能の確認をされることをお勧めします。

うまくいかないときは、ダウンロードできるフォルダに含まれる完成版FSH Tank(!)であるFishExampleCompleteディレクトリを参照されると良いと思います。

私はWindows環境で試しました。Node.jsもインストールされていなかったので、こちらのサイトの情報を参考にさせていただきました。 また、チュートリアルに以下の記載がある通り、IG Publisherを使ったHTMLファイルの出力には Jekyll というツールが必要になります。

Warning
Before proceeding to the next command: If you have never run the IG Publisher, you may need to install Jekyll first. See Installing the IG Publisher for details.

こちらのサイトからJekyllのキット等は入手できます。

SUSHI実行例

私の環境で、チュートリアルの完成版を使ったsushiコマンド実行結果を掲載します。 コマンド等の詳細はこちらのサイト(Running SUSHI)をご覧ください。

>sushi .
info  Running SUSHI v1.2.0 (implements FHIR Shorthand specification v1.1.0)
info  Arguments:
info    C:\Users\kaminaka\Documents\Work\FHIR\SUSHI\fsh-tutorial-master\FishExampleComplete
info  No output path specified. Output to .
info  Using configuration file: C:\Users\kaminaka\Documents\Work\FHIR\SUSHI\fsh-tutorial-master\FishExampleComplete\sushi-config.yaml
info  Importing FSH text...
info  Preprocessed 2 documents with 3 aliases.
info  Imported 4 definitions and 1 instances.
info  Checking local cache for hl7.fhir.r4.core#4.0.1...
info  Found hl7.fhir.r4.core#4.0.1 in local cache.
info  Loaded package hl7.fhir.r4.core#4.0.1
(node:26584) Warning: Accessing non-existent property 'INVALID_ALT_NUMBER' of module exports inside circular dependency
(Use `node --trace-warnings ...` to show where the warning was created)
(node:26584) Warning: Accessing non-existent property 'INVALID_ALT_NUMBER' of module exports inside circular dependency
info  Converting FSH to FHIR resources...
info  Converted 3 FHIR StructureDefinitions.
info  Converted 1 FHIR ValueSets.
info  Converted 1 FHIR instances.
info  Exporting FHIR resources as JSON...
info  Exported 5 FHIR resources as JSON.
info  Assembling Implementation Guide sources...
info  Generated ImplementationGuide-fish.json
info  Assembled Implementation Guide sources; ready for IG Publisher.

╔════════════════════════ SUSHI RESULTS ══════════════════════════╗
║ ╭──────────┬────────────┬───────────┬─────────────┬───────────╮ ║
║ │ Profiles │ Extensions │ ValueSets │ CodeSystems │ Instances │ ║
║ ├──────────┼────────────┼───────────┼─────────────┼───────────┤ ║
║ │    2     │     1      │     1     │      0      │     1     │ ║
║ ╰──────────┴────────────┴───────────┴─────────────┴───────────╯ ║
║                                                                 ║
╠═════════════════════════════════════════════════════════════════╣
║ It doesn't get any betta than this!    0 Errors      0 Warnings ║
╚═════════════════════════════════════════════════════════════════╝

実行するとFSHファイルのコンパイルが実行され、最後にいくつのProfilesやExtensionが生成されたか、表示されます。問題なければ、"info"だけが表示されますが、FSHファイルの定義に誤りがあると、WarningやErrorも表示されます。エラーメッセージは比較的親切で何が問題が把握しやすいと思います。(個人的には最後の表に掲載される、なぞの「魚一言?」みたいな一文が楽しみです。)

実行後には、プロジェクトフォルダ内のfsh-generatedフォルダにStructureDefinitionのJSONファイルが生成されているのが確認できます。

続いて、「_updatePublisher」コマンドで、IG Publisherツールを入手し、「_genonce」コマンドでIG Publisherを起動し、HTMLファイル群も生成してみます。この実行ログは長いので割愛します。

実行後、同じプロジェクトフォルダ内の output フォルダを確認すると多くのファイルが生成されているのがわかります。index.htmlファイルを開くと以下のようなページが生成されていることが確認できます。

image

このようなFHIR公式サイトでも見慣れた、リソースの説明ページなども自動生成されます。

image


## Implementation Guide(実装ガイド)を書いてみよう

私もこのツール群を触り始めて日が浅いですが、簡単なスタートアップとして、実装ガイドを記述していく方法をご紹介したいと思います。

詳細な使い方についてはFSH Schoolサイト内の情報をご覧ください。こちらで紹介されているのFHIR DevDaysのスライド等も大変参考になると思います。

まず sushi --init コマンドでプロジェクト構造のひな型を作りましょう。

C:\Users\kaminaka\Documents\Work\FHIR\SUSHI\TestProject>sushi --init

╭───────────────────────────────────────────────────────────╮
│ This interactive tool will use your answers to create a   │
│ working SUSHI project configured with your project's      │
│ basic information.                                        │
╰───────────────────────────────────────────────────────────╯

Name (Default: ExampleIG): MyFirstSUSHIProject
Id (Default: fhir.example): myfirstsushi
Canonical (Default: http://example.org): http://example.org/myfirstsushi
Status (Default: draft):
Version (Default: 0.1.0):
Initialize SUSHI project in C:\Users\kaminaka\Documents\Work\FHIR\SUSHI\TestProject\MyFirstSUSHIProject? [y/n]: y
Downloading publisher scripts from https://github.com/HL7/ig-publisher-scripts
(node:13972) Warning: Accessing non-existent property 'INVALID_ALT_NUMBER' of module exports inside circular dependency
(Use `node --trace-warnings ...` to show where the warning was created)
(node:13972) Warning: Accessing non-existent property 'INVALID_ALT_NUMBER' of module exports inside circular dependency

╭───────────────────────────────────────────────────────────╮
│ Project initialized at: ./MyFirstSUSHIProject             │
├───────────────────────────────────────────────────────────┤
│ Now try this:                                             │
│                                                           │
│ > cd MyFirstSUSHIProject                                  │
│ > sushi .                                                 │
│                                                           │
│ For guidance on project structure and configuration see   │
│ the SUSHI documentation: https://fshschool.org/docs/sushi │
╰───────────────────────────────────────────────────────────╯


実行すると必要最低限の設定ファイルやFSHファイルが作成されます。 次に少し修正をしてみましょう。

その前にエディタの紹介です。fshファイルを修正するためのExtensionが公開されているので、Visual Studio Codeの使用がおすすめです。

せっかくなので、日本語の情報を入力してどのように反映されるか見ていきたいと思います。

まず、sushi-config.yaml を修正します。実装ガイドのタイトルを追加し、メニュー画面も日本語表記に変更した上で、コンテンツ一覧ページ(tuc.html)とカスタムページ(mycustompage.html)を追加しています。

sushi-config.yaml

# ╭──────────────────────────────────────ImplementationGuide───────────────────────────────────────╮
# │  The properties below are used to create the ImplementationGuide resource. For a list of       │
# │  supported properties, see: https://fshschool.org/sushi/configuration/                         │
# ╰────────────────────────────────────────────────────────────────────────────────────────────────╯
id: myfirstsushi
canonical: http://example.org/myfirstsushi
name: MyFirstSUSHIProject
# titleを追加して、ページ上部に表示されるようにします。
title: ○○FHIRプロジェクト 実装ガイド
status: draft
publisher: InterSystems Japan/S.Kaminaka
description: SUSHIを使ったFHIRプロジェクト実装ガイドのサンプルです。
version: 0.1.0
fhirVersion: 4.0.1
copyrightYear: 2021+
releaseLabel: ci-build

# ╭────────────────────────────────────────────menu.xml────────────────────────────────────────────╮
# │  To use a provided input/includes/menu.xml file, delete the "menu" property below.             │
# ╰────────────────────────────────────────────────────────────────────────────────────────────────╯
# メニューを日本語表示されるように変更します。
menu:
  実装ガイドホーム: index.html
  コンテンツ一覧: toc.html
  FHIRアーティファクトサマリ: artifacts.html
  カスタムページ: mycustompage.html

インデックスページや、カスタムページはマークダウンで記述できます。

index.md

# MyFirstSUSHIProject

Feel free to modify this index page with your own awesome content!

### プロジェクトの背景

pagecontent/index.md ファイルを変更して、htmlファイル内の記載内容を変更できます。

ページを記述にはマークダウン記法を使用することができます。

### 参考情報へのリンク
 (略)

mycustompage.md

## これはカスタムページです。

マークダウンファイルを用意しておくとhtmlファイルが生成されます。

プロジェクトに応じたページを生成し、実装ガイドに含めることができます。

最後に最も重要なFSHファイルを修正します。このひな形には、Patientプロファイル用のFSHファイルが含まれているので、それを少しだけ修正しました。

patient.fsh

// This is a simple example of a FSH file.
// This file can be renamed, and additional FSH files can be added.
// SUSHI will look for definitions in any file using the .fsh ending.
Profile: MyPatient
Parent: Patient
Title: "○○プロジェクトのPatientプロファイル"
* name 1..* MS
// ^shortを変更して、一覧表示画面の説明部分を変更できます。
* name ^short = "患者さんの氏名を格納します。"
* name ^definition = "患者さんの氏名を格納するエレメント。NeXEHRS JP COREに準拠した漢字・カナ記法を使用します。"

それでは、以下のコマンドを実行して、生成された実装ガイドページを確認してみましょう。

sushi.

_updatePublisher

_genonce

以下のような情報を含むページが簡単に生成できます。

あわせてStructureDefinitionやImplementationGuideなどのJSONファイルももちろん生成されています。

image

image

まとめ

いかがでしたでしょうか? 単にFHIRプロファイルのJSONファイルを生成するだけでなく、HTMLファイルを生成する機能も付随しているので、このツールをうまく使えばFHIRの仕様を分かりやすく伝えることが可能なコンテンツが簡単に作成できるのではないかと考えています。

このツール自体はInterSystemsとは直接関係ない製品ではありますが、FHIRプロジェクトの情報交換に役立つツールということで、この開発者コミュニティでご紹介させていただきました。

この記事を見て試していただいた方、あるいはすでに使いこなしている方、使い方のコツや便利な機能やシンタックスなどをご紹介いただけると嬉しく思います。

次回のこのシリーズでは、SUSHIで生成したSearch Parameterの定義ファイルをIRIS for Healthで読み込んで、検索パラメータを拡張する内容に取り組んでみたいと考えています。

(2021/4/20 特にプロファイルの説明について、説明が曖昧な箇所をご指摘いただきましたので修正しました。ご指摘ありがとうございました。)

0
2 2623
記事 Shintaro Kaminaka · 4月 15, 2021 9m read

開発者の皆さん、こんにちは。 以前の記事でIRIS for Health上でFHIRリポジトリを構築し、OAuth2認証を構成する方法をご紹介しました。

この代行認証編では、IRIS for HealthのFHIRリポジトリに組み込まれた認証機能ではなく、IRISの代行認証機能+ZAUTHENTICATEルーチンを使用して認証を行う方法をご紹介します。

前回記事でご紹介したように、標準のFHIRリポジトリの認証機構では、アクセストークンの発行先を追加するためのAudienceの指定(aud=https://~) や、アクセストークンだけではなくベーシック認証の情報を送付するなどの対応が必要でした。

スクラッチでFHIRクライアントを開発するのではなく、既成の製品やアプリケーションからアクセスする場合、上記のような処理の実装ができないことがあるかもしれません。 そのような場合には、この代行認証+ZAUTHENTICATEルーチンを使用して、カスタマイズした認証の仕組みを構築することができます。

この記事に含まれる情報のドキュメントについて

この記事で記載されている情報はIRIS for Healthのドキュメントにも含まれている内容をわかりやすく再構成したものです。

RESTサービスの保護:RESTアプリケーションおよびOAuth2.0

OAuth 2.0 クライアントとしての InterSystems IRIS Web アプリケーションの使用法


代行認証を有効にする

まず使用しているIRIS環境で「代行認証」機能を有効にし、アクセスするFHIRリポジトリの「Webアプリケーション設定」で「代行認証」機能を使える用に構成します。


認証/ウェブセッションオプション画面

まずシステムとして「代行認証」が使用できるように構成します。

管理ポータルの システム管理→セキュリティ→システム・セキュリティ→認証/ウェブセッションオプション と進み、「代行認証を許可」をチェックします。 「代行認証によるOS認証を許可」ではありませんのでご注意ください。

image


%Service_WebGatewayサービス 画面

次に、CSPゲートウェイを経由したWebのアクセスに対して、「代行認証」が有効になるよう構成します。

管理ポータルの システム管理→セキュリティ→サービス と進み、「%Service_WebGateway」をクリックして、許可された認証方法の「代行」にチェックがついていることを確認します。もしチェックされていなければ、チェックして保存を実行してください。

image


FHIRリポジトリの ウェブアプリケーションの編集 画面

最後に、アクセスするFHIRリポジトリの ウェブ・アプリケーションの編集画面で「代行認証」を有効にします。

管理ポータルの システム管理→セキュリティ→アプリケーション→ウェブ・アプリケーション と進み、該当のFHIRリポジトリアプリケーションを選択します。 特に変更をしていなければ、/csp/healthshare/<namespace>/fhir/r4 となっています。

この画面で、セキュリティの設定:許可された認証方法の「代行」をチェックして保存します。

image

これで、「代行認証」を利用する準備はOKです。次は、実際に代行認証のためのロジックが記載されたZAUTHENTICATEルーチンを用意します。


ZAUTHETICATEルーチンの入手とインポート

ZAUTHENTICATEルーチンのサンプルはInterSystemsのGitHubで公開されています。

GitHub:Samples-Security

この記事ではここで紹介されているREST.ZAUTHENTICATE.macルーチンを利用します。 GitHubのREADMEに記載されているこのルーチンの説明をここにも転載します。

  • REST.ZAUTHENTICATE.mac is another sample routine that demonstrates how to authenticate a REST application using OAuth 2.0. To use this sample:
    1. Configure the resource server containing the REST application as an OAuth 2.0 resource server.
    2. Copy this routine to the %SYS namespace as ZAUTHENTICATE.mac.
    3. Modify value of applicationName in ZAUTHENTICATE.mac.
    4. Allow delegated authentication for %Service.CSP.
    5. Make sure that the web application for the REST application is using delegated authentication.

この記事では、先に手順の4.,5.を済ませているので、ルーチンのインポートを実施しましょう。 (上記READMEでは、%Service.CSPと記載されていますが、現在は%Service_WebGatewayになっています。)

GitHubからルーチンをダウンロードしてインポートするか、あるいは、このリンクから直接ルーチンを表示し、中身をStudioやVS Codeのエディタを使ってコピーしてZAUTHENTICATEルーチンをつくることもできます。%SYSネームスペースに作成します。

(注意:2021/4/16時点ではこのルーチンをスタジオからインポートするとエラーが発生してしまいます。お手数ですが、ファイルの中身をコピーしてZAUTHENTICATEルーチンを作成する方法で回避してください。)

ZAUTHENTICATEルーチンを作成したら、applicationNameを変更します。これは前回の記事で記載したOAuth2クライアントアプリケーションの クライアント構成 画面で作成した「アプリケーション名」を指定します。

image

ここでは前回の記事にならい「FHIRResource」としています。コードの一部を紹介します。

// Usually you will need to modify at least the roles to be assigned.
set roles="%DB_DEFAULT,%Operator"

$$$SysLog(3,"OAuth2","[ZAUTHENTICATE]","ServiceName="_ServiceName_", Username="_Username_", roles="_roles)

// MUST BE MODIFIED FOR EACH INSTANCE WHICH USES OAuth 2.0 for REST.
// The application name used to define the authorization server to this resource server.
set applicationName="FHIRResource"

set loginSuccessful=0
set errorText=""

コードを変更したらコンパイルを実行します。

このZAUTHENTICATEルーチンで重要なのは以下のコード部分です。 GetAccessTokenFromRequestメソッドを使用してHTTPリクエストからアクセストークンを取り出し、ValidateJWTメソッドを使用してValidationを実施し正しいアクセストークンであることを確認しています。

// This ZAUTHENTICATE routine will support OAuth 2.0 based
// delegated authentication for subclasses of %CSP.REST.
set accessToken=##class(%SYS.OAuth2.AccessToken).GetAccessTokenFromRequest(.sc)

// Check if authorized.
// if the access token is not a JWT, we would need to validate the access token
// using another means such as the introspection or userinfo endpoint.
if $$$ISOK(sc) {
	set valid=##class(%SYS.OAuth2.Validation).ValidateJWT(applicationName,accessToken,,,.jsonObject,,.sc)
}

POSTMANからのテスト

それでは前回同様、RESTクライアントツールのPOSTMANからテストしてみましょう。 前回同様、まずはアクセストークンを取得します。

前回とは異なり、Auth URLにaudパラメータを追加する必要はありません。トークンを取得できたら、「Use Token」ボタンをクリックし、そのトークンを使用できるようにします。

次は、FHIRリポジトリへのアクセスです。今回は前回と異なり、ベーシック認証と組み合わせる必要はありませんので、そのままFHIRリポジトリにアクセスするRESTのURLのみを入力し、実行します。

FHIRリソースが取得できたら成功です。

2020.4以降の対応

IRIS for Health 2020.4ではこちらの記事に掲載したように、FHIRリポジトリ上でアクセストークンのスコープ情報がチェックされるようになりました。 このため、セキュリティ用件にも依存しますが、ZAUTHENTICATEルーチンで必ずしもアクセストークンのValidationチェックを行う必要はありません。 これまでこのシリーズで紹介してきましたように、IRIS for HealthがOAuth2認可サーバの役割も兼ねている場合、2020.4上で動かす最も単純な方法は、ZAUTHENTICATEルーチンのGetCredentialsラベルで、アクセストークンを取得する際にも指定したIRISパスワードユーザを返すようにすることです。

例:アクセストークンを取得した際のユーザと image

同じユーザを返すようにする。(このdaikoユーザには%All権限を与えています)

GetCredentials(ServiceName,Namespace,Username,Password,Credentials) Public {
	if ServiceName="%Service_WebGateway" {
		// Supply user name and password for authentication via a subclass of %CSP.REST
		set Username="daiko"
		set Password="xxxxx"
	}
	quit $$$OK
}

こちらの代行認証に関するドキュメントに記載があるように、GetCredentialsラベルで実在するIRISパスワードユーザが返された場合はそのユーザに認証が行われるため、ZAUTHENTICATEルーチンで実行されていたアクセストークンのValidationチェックのロジックは実施されなくなります。 ただし、アクセストークンの検証はその後FHIRリポジトリ上で実施されるため不正なアクセストークンでアクセスしたりすることはできません。 なお、2020.4では、スコープのチェックやAudience情報のチェックも行われるため、このバージョンの代行認証では aud=https://~ の情報の追加や適切なスコープ指定も必要になります。

テストとしてはこの方法で動作を確認することができると思いますが、もちろん実際のアプリケーションで実装する場合は、より複雑な状況を考慮に入れる必要があるでしょう。例えば、アクセスするユーザごとに異なるIRISパスワードユーザをもつケースもあれば、そもそもアクセストークンの発行元であOAuth2認可サーバが、IRISではなく他のサービスである可能性もあります。後者のようなケースでは、このZAUTHENTICATEルーチン上で代行ユーザを作成する必要があり、さらにそのユーザ名はアクセストークン内のユーザ情報(sub)と一致する必要があります。

残念ながらこの記事でそれらの状況をすべてカバーすることはできませんが、この記事に記載されている情報がIRIS for HealthのFHIRリポジトリを活用したセキュアなアプリケーション構築の一助となれば幸いです。

0
0 474
記事 Shintaro Kaminaka · 4月 15, 2021 7m read

開発者の皆さん、こんにちは。

以前の記事でIRIS for Health上でFHIRリポジトリを構築し、OAuth2認証を構成する方法をご紹介しました。 IRIS for Health 2020.4がリリースされ、FHIRリポジトリのアクセストークンをチェックする機能が追加になりました。

ドキュメントはAccess Token Scopesです。

この記事ではドキュメントの記載も抜粋しながらこの機能を紹介していきます。

Basic Processing

The access token that accompanies a request must include at least one patient clinical scope or user clinical scope, or else the request is rejected with an HTTP 403 error. If an access token contains both a patient clinical scope and a user clinical scope, the FHIR server enforces the patient clinical scope while ignoring the user clinical scope.

(訳)リクエストに添付されるアクセストークンには、患者のクリニカル・スコープまたはユーザーのクリニカル・スコープが少なくとも1つ含まれていなければならず、そうでなければリクエストはHTTP 403エラーで拒否されます。アクセストークンに患者のクリニカル・スコープとユーザーのクリニカル・スコープの両方が含まれている場合、FHIRサーバーは患者のクリニカル・スコープを強制し、ユーザーのクリニカル・スコープを無視します。

この機能が追加になったことで、以前の記事でご紹介していたような、"scope1"のようなスコープ指定では403エラーとなり、FHIRリポジトリから応答を受け取ることはできなくなりました。(前回の構成が残っている方はぜひ2020.4にアップグレードして403エラーになることを試してみてください。)

この記事では、正しいスコープを指定して、FHIRリポジトリにアクセスする方法をご紹介します。 ベースとなるOAuth2サーバ構成やクライアント構成に関しては以前と変わりませんので、以前の記事を参考にしてください。


SMART on FHIR : Scopes and Launch Context

今回のIRISの実装は、SMART on FHIRプロジェクトのスコープ定義をベースにしています。

SMART App Launch: Scopes and Launch Context

このサイトのQuick Startに記載されている以下のスコープをベースにこの記事の検証を進めてみたいと思います。 詳細についてはSMART on FHIRの上記解説サイトをご覧ください。

ScopeGrant
patient/*.read現在の患者のあらゆるリソースを読むことができる許可
user/*.*現在のユーザーがアクセスできるすべてのリソースの読み取りと書き込みの許可


OAuth 2.0 認可サーバ構成の変更

まず、OAuth2認可サーバ構成で、サポートしていないスコープが許可されるように構成します。 OAuth2認可サーバの「スコープ」タブで、「サポートしていないスコープを許可」にチェックを入れます。

image


スコープを指定してPatientリソースを登録する

それでまず、Patientリソースを登録してみましょう。 Create Interactionを行う場合には、user clinical scope が必要になります。以下はIRIS for Healthのドキュメントからの抜粋です。

Create Interaction

Requests to create a new Patient resource must include a user clinical scope that gives write permissions (user/Patient.write or user/Patient.*). You cannot perform a create interaction for a Patient resource with a patient clinical scope; patient clinical scopes must include a patient context value, and the create interaction cannot include a resource id.

(訳)新規にPatientリソースを作成する要求には、書き込み権限(user/Patient.writeまたはuser/Patient.*)を与えるユーザークリニカルスコープを含める必要があります。患者臨床スコープには患者コンテキスト値を含める必要があり、作成インタラクションにリソースIDを含めることはできません

先ほど、でてきたスコープ「user/*.*」を追加して、アクセストークンを取得し、Patientリソースを登録してみましょう。

以下の図はRESTツールPOSTMAN上で、スコープを指定している画面です。

image

任意のスコープを許可する設定が正しく動作していれば以下のような確認画面が表示されます。

image

「許可」をクリックして、アクセストークンを取得します。このアクセストークンを使ってPatientリソースを登録してみましょう。 まず登録するPatientリソースを用意してください。FHIR公式ページから取得しても良いですし、過去のコミュニティ記事から取得しても良いです。

POSTMANを使う場合、Bodyタブに登録したいリソースを貼り付けます。

image

前回記事同様、アクセストークン+ベーシック認証を行う必要があるので、取得したアクセストークンを access_toke=eyXXX としてパラメータに追加し、Authorizationタブではベーシック認証を選択してください。

image

メソッドがPOSTであること、リクエストURLが正しくPatientを指定していることなども確認出来たら、登録を実行してみてください。Status 201 Created が返ってきたら登録は成功です。

登録が成功したら、続いてGETも試してみてください。 このスコープは読み取りの権限もありますから取得できるはずです。

リソースが取得できたら、今登録したPatientリソースのリソースIDも確認してください。以下の例では 1 になります。

image


スコープを指定してPatientリソースを取得する

では、Patientリソースが登録できたので、今度は異なるスコープを指定して先ほどのPatientリソースを取得してみましょう。

患者に紐づく情報を取得する場合、patient clinical scope が必要になります。

Patient Clinical Scope / Patient Context Value

If an access token includes a patient clinical scope, it must also include a patient context value (also known as “launch context”) that is the id of a Patient resource. This patient context value provides access to the specified Patient and its related resources.

(訳)アクセストークンに患者の臨床範囲が含まれる場合、Patient リソースの ID である患者コンテキスト値(「起動コンテキスト」とも呼ばれる)も含まれなければならない。この患者コンテキスト値は、指定された患者及びその関連リソースへのアクセスを提供する。

今回はスコープに「patient/*.read」を追加します。もう一点どの患者情報にアクセスできるのか判断するために、PatientリソースのリソースID情報を含むPatient Context Valueをスコープとして渡します。具体的には、「launch/patient/1」(リソースID=1の場合)もスコープとして指定します。

POSTMANでは以下のように指定します。スコープの間は半角スペースで区切ります。

image

アクセストークンを取得できたら、先ほどと同じ手順でリクエストを投げてみましょう。 ただし、今回取得したアクセストークンで取得できるFHIRリソースはリソースID=1のPatientリソースに紐づく情報だけであることにご注意ください。ということは、取得するためにRESTのパスは Patient/1 となります。

例:https://<server>/csp/healthshare/fhirserver/fhir/r4/Patient/1?access_token=eyXXX

無事に先ほどのPatientリソースが取得できたらアクセス成功です! 次は、このトークンが本当にリソースID=1だけに制限されているかも確認してみましょう。他のリソースIDを指定するか、Patientリソース全体を取得するようなリクエストを投げてみてください(ただし存在しないPatientのリソースIDを指定するとそのリソースは存在しませんという別のエラーになります。)

例:https://<server>/csp/healthshare/fhirserver/fhir/r4/Patient/2?access_token=eyXXX 例:https://<server>/csp/healthshare/fhirserver/fhir/r4/Patient?access_token=eyXXX

Status 403エラーになりましたか?エラーが返れば確認は成功です。


まとめ

どのようなFHIRリソースをFHIRリポジトリに格納しているのか?また、どのようなアプリケーションを構築して、どのようにユーザにアクセス制限を設定したいのか?等により、利用すべきスコープの使い方は異なってきます。

安全なFHIRアプリケーションを構築するために、この新しいアクセストークンスコープ機能(とあとこの記事が)活用されると幸いです。

0
0 510
記事 Makiko Kokubun · 4月 6, 2021 1m read

*この動画は、2021年2月に開催された「InterSystems Japan Virtual Summit 2021」のアーカイブです。

既に運用されている電子カルテ・処方のデータや蓄積されているデータを、FHIR に変換して活用したいというニーズは、FHIR アプリケーションを構築するにあたり最も多いご要望の一つです。

この動画では、InterSystems IRIS for Health を使用して、HL7/SS-MIX2 やCSV など他形式のデータから FHIR データへ変換する方法について、デモをまじえてご紹介いたします。

この開発者コミュニティでは他にも IRIS の FHIR 機能に関連した多くの記事を公開しています。
FHIR にご興味ある方はぜひご覧ください。

0
1 517
記事 Makiko Kokubun · 3月 30, 2021 1m read

*この動画は、2021年2月に開催された「InterSystems Japan Virtual Summit 2021」のアーカイブです。
 

この動画では、FHIR をご存じない方に向けて FHIR の概要を解説し、日本における FHIR 標準化活動の状況や国内外の事例を紹介しています。

後半の16分~くらいからは、InterSystems IRIS for Health が提供する FHIR リポジトリに代表される FHIR 関連機能と、今後の機能ロードマップを紹介しています。

この開発者コミュニティでは他にも IRIS の FHIR 機能に関連した多くの記事を公開しています。
FHIR にご興味ある方はぜひご覧ください。

0
0 540
記事 Toshihiko Minamoto · 3月 29, 2021 10m read

FHIR Terminology Serviceの仕様には、 CodeSystemValueSet、およびConceptMapリソースでの一連の演算子が記述されています。 これらの演算子の内、以下の4つの演算子が最も広く採用されているようです。

IRIS for Health 2020.1で導入された新しいFHIRフレームワークを学ぶには、仕様の部分的な実装を開発するのが最も効果的と言えます。 実装には上記の4つの演算が含まれており、CodeSystemValueSetリソースでreadsearch操作がサポートされています。

実装には単純なObjectScript永続クラスがソース用語テーブルとして使用されていることに注意することが重要です。

サンプルストラテジーを使ったインストールとテスト

以下のリストでは、インストールと基本的なテスト手順を説明しています。

  1. IRIS for Health 2020.1以降をインストールします。
  2. ポータルの システム管理 > 構成 > システム構成 > ネームスペース メニューを使用して、またはHSLIBネームスペースで do ##class(HS.HC.Util.Installer).InstallFoundation("<name for the new namespace>") コマンドを実行して、新しいネームスペースをセットアップします。 その後、 intersystems-ru/fhir-terminology-service GitHubリポジトリのsrc/clssamples/clsフォルダからクラスをインポートします。
  3. dummy-search-parameters.jsonで定義された追加の検索パラメーターを使って、R4セットに基づく独自のFHIRメタデータセットを作成します。 これは、##class(HS.FHIRServer.ConsoleSetup).Setup() インタラクティブユーティリティを使うか、次のコマンドを実行します。
do ##class(HS.FHIRServer.Installer).InstallMetadataSet("", "", "HL7v40", $lb("<directory with dummy-search-parameters.json>"), 1)
  • これは、$expand$validate-code 演算子がHTTP GETリクエストをサポートするため必要な手順です。
  • InterSystems IRISにパッケージ化されたFHIRメタデータセットファイルは、<installation directory>/dev/fhir/fhir-metadata ディレクトリにあります。
  1. 新しいメタデータセットとSample.iscru.fhir.fts.SimpleStrategyクラスに基づく新しいFHIRエンドポイントを作成します。 これについても、インタラクティブユーティリティを使用するか、次のコマンドを実行します。
do ##class(HS.FHIRServer.Installer).InstallInstance("<web app URI, e.g. /csp/terminology>", "Sample.iscru.fhir.fts.SimpleStrategy", "")
  1. 新しいエンドポイントに認証なしアクセスを許可します。インタラクティブユーティリティを使用するか、次のコマンドを実行してください。
set strategy = ##class(HS.FHIRServer.API.InteractionsStrategy).GetStrategyForEndpoint("<web app URI>")
set config = strategy.GetServiceConfigData()
set config.DebugMode = 4
do strategy.SaveServiceConfigData(config)
  1. Sample.iscru.fhir.fts.model.CodeTableにデータを入力します。
do ##class(Sample.iscru.fhir.fts.model.CodeTable).Populate(10)
  1. fhir-terminology-service.postman_collection.jsonファイルをPostmanにインポートし、コレクション内に定義されている url 変数を調整して、単純な永続クラスである Sample.iscru.fhir.fts.model.CodeTable に対してサービスをテストします。

サポートされているFHIR操作

CodeSystemとValueSetで現在サポートされている検索パラメーターは、url のみです。

HTTP GETとHTTP POSTメソッドは、上記の4つの演算子でサポートされています。

以下の表には、Sample.iscru.fhir.fts.model.CodeTableクラスに対して行えるHTTP GETリクエストをいくつか示しています。

URI
http://<server>:<port><web app URI> の後に続く)
説明
/metadataエンドポイントの機能宣言リソースを取得します。
/CodeSystem/Sample.iscru.fhir.fts.model.CodeTableSample.iscru.fhir.fts.model.CodeTableクラスに対応するCodeSystemリソースを読み取ります。
/ValueSet/Sample.iscru.fhir.fts.model.CodeTableSample.iscru.fhir.fts.model.CodeTableクラスに対応するValueSetリソースを読み取ります。
/CodeSystem?url=urn:CodeSystem:CodeTableCodeSystemリソースをURLで検索します。
/CodeSystem使用可能なすべてのCodeSystemリソースを出力します。
/ValueSet?url=urn:ValueSet:CodeTableValueSetリソースをURLで検索します。
/ValueSet使用可能なすべてのValueSetリソースを出力します。
/CodeSystem/$lookup?system=urn:CodeSystem:CodeTable&code=TESTあるシステムとコードで、概念に関するすべての詳細を取得します。
/ValueSet/$expand?url=urn:ValueSet:CodeTableValueSetを展開します。
/CodeSystem/Sample.iscru.fhir.fts.model.CodeTable/$validate-code?code=TESTコードがコードシステムにあることを検証します。

カスタムストラテジーの作成

独自の永続クラスをFHIRコードシステム/値セットとして公開するには、iscru.fhir.fts.FTSStrategyをサブクラス化してカスタムストラテジークラスを作成し、その新しいカスタムストラテジーに基づいてFHIRエンドポイントを作成する必要があります(上記手順4のインストール手順を参照)。

1つのクラスパラメーターと少なくとも3つのメソッドをストラテジークラスでオーバーライドする必要があります。

  • StrategyKey クラスパラメーター: いくつかの一意の値を割り当てる必要があります。 現在のクラスの名前が適当でしょう。
  • getCodeTablePackage() クラスメソッド: 正規URLで識別される特定のコードシステム(または値セット)のパッケージ名を返す必要があります。 一般的に、すべての用語クラスは1つのパッケージに属しているため、このメソッドは通常、引数の値に関係なく1つの同じパッケージ名を返します。
  • getCodePropertyName() および getDisplayPropertyName() クラスメソッド: codedisplay 概念要素に対応するクラスプロパティの名前を返します。 各クラスには、用語コード/ディスプレイ要素にマッピングされたそれぞれのプロパティがあります。

以下は、オーバーライドした方が適切だと思われる iscru.fhir.fts.FTSStrategy のその他のメソッドとパラメーターです。

  • listCodeTableClasses() クラスメソッド: 使用可能なすべてのコードシステム(または値セット)を返す検索リクエストをサポートするには、オーバーライドする必要があります。 このメソッドは、使用可能なすべての用語クラスのクラス名のリストを返します。 Sample.iscru.fhir.fts.SimpleStrategyには、次のように、このメソッドの基本的な実装が含まれます。
/// 使用可能なすべてのコードテーブルクラスのリストを返します。
ClassMethod listCodeTableClasses() As %List
{
    #dim sql As %String = "SELECT name FROM %Dictionary.ClassDefinition WHERE name LIKE '" _ ..#codeTablePACKAGE _ ".%' ORDER BY name"
    #dim resultSet As %SQL.StatementResult = ##class(%SQL.Statement).%ExecDirect(, sql)
    if (resultSet.%SQLCODE '= 0) && (resultSet.%SQLCODE '= 100) $$$ThrowStatus($$$ERROR($$$SQLError, resultSet.%SQLCODE, resultSet.%Message))

    #dim return As %List = ""
    while resultSet.%Next()
    {
        set return = return _ $lb(resultSet.name)
    }

    quit return
}
  • isExcludedProperty() クラスメソッド: 永続クラスの特定のプロパティをCodeSystemリソースに表示されないようにするには、オーバーライドする必要があります。 デフォルトでは、このメソッドは、CollectionIdentityInternalMultiDimensional、およびPrivateプロパティを除外します。 フレームワークでは、オブジェクト参照とストリームプロパティは現在サポートされていないため、無視されることに注意してください。

  • codeSystemUrlPREFIXvalueSetUrlPREFIX クラスパラメーター、および getCodeSystemForClassname()getValueSetForClassname()determineCodeTableClassname()、および determineCodeSystemForValueSet() メソッド: クラス名をどのように 正規URLと関連付けるかを制御します。 デフォルトでは、正規URLには、次の命名スキームが使用されています。 | CodeSystem | ValueSet | | ----------------------------------------- | --------------------------------------- | | urn:CodeSystem:<short class name> | urn:ValueSet:<short class name> |

CodeSystem/ValueSetリソースの論理ID(またはサーバーID)は、対応するクラスの完全な名前と同じです。

今後の課題

現在不足しているのは、コードシステムのバージョン管理、概念階層と $subsumes 演算子、ConceptMapリソースなど多くのものに対するサポートです。 皆さんのアイデア、そしてプルリクエストをぜひお待ちしています!

0
0 301
お知らせ Makiko Kokubun · 2月 18, 2021

開発者のみなさん、こんにちは!

2/16-2/18に開催しましたインターシステムズの年次カンファレンス「InterSystems Japan Virtual Summit 2021」のオンデマンド配信を開始しました。3/19(金)までご視聴いただけます。

⚡️ ご視聴はこちらから ⚡️

テーマは「データプラットフォーム最前線 ニューノーマル時代に求められるアジリティとレジリエンス」です。
InterSystems IRIS 、IRIS for Health の最新技術情報を多くのセッションを通してお届け致します。ぜひご視聴ください。*本セミナーは日本語での開催となります。

オンデマンド配信プログラム

  • 基調講演:適応力と柔軟性を高めるデータプラットフォームの最新情報について(2月16日ライブ配信)
0
0 139
お知らせ Makiko Kokubun · 1月 28, 2021

開発者のみなさん、こんにちは!

インターシステムズは、2/16(火)~ 2/18日(木)の3日間にかけて、オンラインカンファレンス「InterSystems Japan Virtual Summit 2021」を開催致します。

⚡️ 現在、事前登録受付中です! ⚡️
 

テーマは「データプラットフォーム最前線 ニューノーマル時代に求められるアジリティとレジリエンス」です。
InterSystems IRIS 、IRIS for Health の最新技術情報を多くのセッションを通してお届け致します。ぜひご参加ください。*本セミナーは日本語での開催となります。

  InterSystems Japan Virtual Summit 2021

DAY1 2/16(火)10:00-11:40 

  • 基調講演:適応力と柔軟性を高めるデータプラットフォームの最新情報について

DAY2 2/17(水)15:00-17:30

  • 先進データテクノロジーセッション:既にインターシステムズ製品をお使いの方向けに、IRISへのマイグレーションやパフォーマンスについての技術セッション
  • HL7® FHIR® によるインターオペラビリティセッション: FHIR の概要や最新情報と、IRIS for Healthでの医療データ共有、最新機能について

DAY3 2/18(木)15:00-17:15

0
0 163
記事 Shintaro Kaminaka · 9月 11, 2020 8m read

開発者の皆さん、こんにちは。

今回の記事では前回の記事に引き続き、IRIS for Health上で、FHIRリポジトリ+OAuth2認可サーバ/リソースサーバを構成する方法をご案内します。

(注意:2020.4以降のバージョンではこの記事に記載されているスコープ指定では正しくリソースが取得できません。詳細はこちらの記事をご覧ください。)

パート1では、事前準備と、OAuth2認可サーバを構成し、アクセストークンを取得するとこまでをご紹介しました。
このパート2では、FHIRリポジトリの構築方法と、OAuth2クライアント/リソースサーバの構成方法をご紹介していきます。

今日構成する、FHIRリポジトリおよび、OAuth2クライアント/リソースサーバの構成は、前回パート1で構成したOAuth2認可サーバのIRISインスタンスと分けることもできますし、同じインスタンスに同居させることもできます。
この記事の中では前回と同じインスタンス上に構成していきます。

FHIRリポジトリの構築とOAuth Client Nameの指定

FHIRリポジトリの構築方法は、過去の記事「Azure上でIRIS for Healthをデプロイし、FHIR リポジトリを構築する方法」で紹介しています。

5
0 794
記事 Shintaro Kaminaka · 9月 4, 2020 13m read

開発者の皆さん、こんにちは。

今回の記事ではFHIRと組み合わせて使用されるケースが増えてきている、権限の認可(Authorization)を行うためのOAuth2について取り上げます。

まずこのパート1では、IRIS for HealthおよびApacheのDockerコンテナの起動と、IRIS for Health上で、OAuth2認可サーバ機能を構成し、REST開発ツールPostmanからアクセスし、アクセストークンを取得する方法について解説します。
さらにパート2以降では、IRIS for HealthにFHIRリポジトリ機能を追加し、OAuth2リソースサーバ構成を追加して、Postmanからアクセストークンを使用したFHIRリクエストの実行方法まで解説します。

InterSystems製品のOAuth2機能の解説については、すでにいくつかの記事が開発者コミュニティ上に公開されていますが、今回は改めて最新バージョンでの構成方法を解説したいと思います。
InterSystems IRIS Open Authorization Framework(OAuth 2.0)の実装 - パート1

1
0 1436
お知らせ Mihoko Iijima · 9月 1, 2020

皆さん、こんにちは!

FHIR コンテストで🎊優勝🎊された Henrique Gonçalves Dias さんの優勝作品 IRIS FHIR Portal をビデオでご紹介します。

Henrique Gonçalves Dias さんが日本語訳を付けてくれた IRIS FHIR Portal 概要ページもあります。ぜひご参照ください。

過去のコンテストも含めコードは全て OpenExchange で公開されています。

ダウンロードやコンテナ開始までの手順は、OpenExchange の IRIS FHIR Portal ページをご参照いただくか、コンテスト用テンプレートの使い方ビデオの 0:28~1:04/3:04~ をご参照ください(コンテスト用テンプレートをベースに開発いただいているので、基本的な手順は同じです)。

Henriqueさん、おめでとうございます!!

1
0 206
お知らせ Mihoko Iijima · 8月 31, 2020

皆さんこんにちは。

第5回 InterSystems IRIS プログラミングコンテスト(FHIRコンテスト) への応募は終了しました。コンテストへのご参加、またご興味をお持ちいただきありがとうございました。

今回のお知らせでは、見事受賞されたアプリケーションと開発者の方々を発表します!

🏆 審査員賞 - 特別に選ばれた審査員から最も多くの票を獲得したアプリケーションに贈られます。

🥇 1位 - $1,500 は iris-fhir-portal を開発された Henrique Gonçalves Dias さんに贈られました!

🥇 1位  - $1,500 は iris4health-fhir-analytics を開発された José Roberto Pereira さんに贈られました!

🥉 3位  - $500 は fhir-chatbot を開発された Renato Banzai さんに贈られました!

🏆 開発者コミュニティ賞 - 最も多くの票を獲得したアプリケーションに贈られます。

🥇 1位 - $1,000 は iris-fhir-portal を開発された Henrique Gonçalves Dias さんに贈られました!

🥈 2位 - $500 は iris4health-fhir-analytics を開発された José Roberto Pereira さんに贈られました!

0
0 133
お知らせ Mihoko Iijima · 8月 6, 2020

開発者のみなさん、こんにちは!

InterSystems IRIS Data Platform を使用してオープンソースソリューションを作成するコンテストへようこそ!

今回のコンテスト用テンプレートはこちら!(8/10 更新) ➡️ IRIS-FHIR-Template ⬅️
(InterSystems IRIS for Health のプレビューリリース版:2020.3 が利用されている開発テンプレートです)

テンプレートの日本語 Readme をご用意しています。

応募期間は 2020年8月10日~23日 です!

優勝特典

1、審査員から多く票を集めたアプリケーションには、以下の賞金が贈られます。

🥇 1位 - $2,000 

🥈 2位 - $1,000 

🥉 3位 - $500

2、Developer Community で多く票を集めたソリューションには、以下の賞金が贈られます。

🥇 1位 - $1,000 

🥈 2位 - $500 

複数の参加者が同数の票を獲得した場合、全参加者が勝者となり賞金は勝者間で分配されます。

参加資格

どなたでもご参加いただけます!(InterSystems 開発者コミュニティのアカウントを作成するだけでご応募いただけます)

コンテストのスケジュール

8月10日~23日 応募期間
8月24日~30日 投票
8月31日 優秀者発表

コンテストのテーマ

1
0 415
記事 Shintaro Kaminaka · 8月 7, 2020 5m read

開発者の皆さん、こんにちは。

今日はAzure上でIRIS for Healthをデプロイし、FHIRリポジトリを構築する方法をご紹介したいと思います。

AzureのMarketPlaceで「InterSystems」をキーワードに検索していただくと、以下のように複数のInterSystems製品がヒットします。

今日はこの製品の中から、InterSystems IRIS for Health Community Editionを選択し、FHIRリポジトリを構築します。

仮想マシンのサイズや、ディスク、ネットワーク等には特に制約や条件はありません。
Azureで提供されている最小の構成でもIRIS for Healthを動かすこともできます。

IRIS for Health Community Editionのデプロイに成功するとこのような画面に遷移します。
私の例では、コンピュータ名をIRIS4HFHIRSERVERとしています。
パブリックIPアドレスはマスクしていますが、このIPアドレスを使ってIRIS管理ポータルにアクセスしてみましょう。
http://<パブリックIPアドレス>:52773/csp/sys/UtilHome.csp

52773は管理ポータルにアクセスするためのポート番号であり、Azure上でデプロイするとこのポート経由でアクセスできるように既に構成が変更されています。

0
0 949