0 フォロワー · 61 投稿

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

公式サイト

InterSystems公式 Seisuke Nakahashi · 10月 23, 2025

インターシステムズは、InterSystems IRIS® data platformInterSystems IRIS® for HealthTMHealthShare® Health Connect のメンテナンスバージョン 2025.1.2 および 2024.1.5 をリリースしました。今回のリリースでは、最近お知らせした以下の警告や勧告の修正が含まれています。

製品の品質改善のために、開発者コミュニティを通じてぜひご意見をお聞かせください。

ドキュメント

詳細な変更リストとアップグレードチェックリストはこちらのドキュメントをご参照ください(すべて英語, 2025.1):

早期アクセスプログラム (Early Access Programs; EAPs)

0
0 25
記事 Toshihiko Minamoto · 7月 22, 2025 9m read


OMOP Odyssey - InterSystems OMOP、クラウドサービス(トロイ編)

InterSystems OMOP クラウドサービスの期限切れ間近のトライアル版を通じた OHDSI(「オデッセイ」と読む)コミュニティに対する実装者のアプローチ
InterSystems OMOP とは?

InterSystems OMOP は、InterSystems クラウドサービスポータルを介して HealtheShare サービスとして提供されており、HL7® FHIR® データを Observational Medical Outcomes Partnership(OMOP)共通データモデル(CDM)に変換します。 InterSystems OMOP は S3 バケットに格納されている FHIR データを参照し、自動的に変換処理を行って、そのデータを OMOP CDM 形式でクラウドホスト型リポジトリに送信します。 するとユーザーは、ATLAS や HADES などの外部の Observational Health Data Sciences and Informatics(OHDSI)ツールと新しいタブに開く JDBC などのデータベースドライバーを併用して、データの分析タスクを実行できるようになります。

要約: S3 にホストされた FHIR Bulk Export データを OMOP CDM に変換し、クラウドホスト型の IRIS または postgres 構成の任意のデータベースに変換します。

ここでは、上記の「フルコース」を試して、最新の強力なツールと OHDSI コミュニティのアプリケーションの驚くべきエコシステムに囲まれた実装を最初から最後まで実行します。あちらこちらでドキュメントを使いまわさないようにし、その過程で地雷 👣 🔫 を紹介します。

素敵なものはバケットから生まれる

初めてサービスをプロビジョニングし、作成ダイアログにアクセスして入り口でS3の情報を尋ねられると、すぐに鶏と卵の状況にあるように感じられるかもしれません。これをできる限りうまく偽装して後で更新することも、変換用に Amazon S3 バケットをどのようにプロビジョニングするかを理解した上で、落ち着いたアプローチをとることも可能です。これは、データを共有するためにほとんどのクラウド型データソリューションに実装されている最新のアプローチです。ソースの場所を自分でプロビジョニングして、サービスにその場所と対話するためのアクセスを許可します。

  • バケットと初期ポリシースタックのプロビジョニング
  • サービスのデプロイメントの作成
  • デプロイメントに制約されたバケットポリシーの更新

コンソールをクリックして終了するか、サンプルスタックでこれを行うことができます。

 
s3-omop-fhir-stack.yaml
---AWSTemplateFormatVersion:'2010-09-09'Description:AWSCloudformationStackthatwillcreatetheS3BucketandPolicyfortheOMOPServerParameters:  BucketName:    Description:ThenameofthebuckettousetouploadFHIRBundlesforTransformation.    Type:String    AllowedPattern:"^[a-z0-9][a-z0-9-]{1,61}[a-z0-9]$"  PolicyfromOMOPConfiguration:    Description:ThenameofthebuckettousetouploadFHIRBundlesforTransformation.    Default:"arn:aws:iam::1234567890:role/skipper-deployment-*-Role"    Type:StringResources:  OMOPFHIRTransactionBucket:    Type:AWS::S3::Bucket    Properties:      BucketName:!Sub${BucketName}      PublicAccessBlockConfiguration:        BlockPublicAcls:true        BlockPublicPolicy:true        IgnorePublicAcls:true        RestrictPublicBuckets:true  OMOPBucketPolicy:    Type:AWS::S3::BucketPolicy    Properties:      Bucket:!RefOMOPFHIRTransactionBucket      PolicyDocument:        Version:"2012-10-17"        Statement:          - Effect:Allow            Principal:              AWS:                -!Sub${PolicyfromOMOPConfiguration}            Action:              -"s3:GetObject"              -"s3:GetBucketLocation"              -"s3:ListBucket"            Resource:              -!Sub"arn:aws:s3:::${BucketName}"# Bucket itself              -!Sub"arn:aws:s3:::${BucketName}/*"# FHIR Objects within the bucket

 

スタックは任意の方法で作成できます。1 つの方法として AWS CLI を使用できます。

aws cloudformation create-stack --stack-name omopfhir --template-body s3-omop-fhir-bucket.yaml --parameters ParameterKey=BucketName,ParameterValue=omop-fhir

バケットに、プロビジョニングと FHIR 取り込み用のソースフォルダで使用する初期キーを作成します。

aws s3api put-object --bucket omop-fhir --key Transactions/in --profile pidtoo
aws s3api put-object --bucket omop-fhir --key termz --profile pidtoo

これで、次のようにしてサービスをプロビジョニングするように設定できるはずです。arn を要求するフィールドに注意してください。説明では名前を要求しているにもかかわらず、実際にはバケットの arn を要求しています... 小さな 👣🔫 がここにあります。

デプロイメントが作成されたら、「FHIR から OMOP へのパイプライン」内にある「構成」ナビゲーション項目に移動し、ポリシーをクリップボードにコピーします。そこにある指示に従って、これを現在のポリシーに組み込むか、ロールの値を取得してスタックを更新します。

aws cloudformation update-stack --stack-name omopfhir --template-body s3-omop-fhir-bucket.yaml --parameters ParameterKey=PolicyfromOMOPConfiguration,ParameterValue="arn:aws:iam::1234567890:role/skipper-deployment-4a358965ec38ba179ebeeeeeeeeeee-Role"

いずれにしても、ソースバケットのアクセス許可には、このようなポリシーが表示されるはずです... (アカウント番号、ロールは不明瞭です)

 
 推奨ポリシー
{
    "Version": "2012-10-17",
    "Statement": [
    {
      "Principal": {
        "AWS": "arn:aws:iam::123456789099:role/skipper-deployment-33e46da9bf8464bbe5d1411111-Role"
      },
      "Effect": "Allow",
      "Action": [
        "s3:GetObject",
        "s3:ListBucket",
        "s3:GetBucketLocation"
      ],
      "Resource": [
        "arn:aws:s3:::omop-fhir",
        "arn:aws:s3:::omop-fhir/*"
      ],
      "Sid": "IRIS Cloud Bucket Access"
    }
    ]
}

 

私は、ルートアカウントを開くことを許可しながらもバケットを制限する、よりオープンなポリシーを使用しました。こうすることで、1 つのバケット(または複数のバケット)で複数のデプロイメントをサポートできます。あまりお勧めできませんが、IAC の目的で単一のポリシーで複数の環境をサポートするための参考としての 2 番目の例です。

 
ルートアカウント
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Principal": {
                "AWS": [
                    "arn:aws:iam::111:root",  ### Entire accounts(3)
                    "arn:aws:iam::222:root",
                    "arn:aws:iam::333:root"
                ]
            },
            "Action": [
                "s3:GetObject",
                "s3:ListBucket",
                "s3:GetBucketLocation"
            ],
            "Resource": [
                "arn:aws:s3:::omop-fhir",
                "arn:aws:s3:::omop-fhir/*",
                "arn:aws:s3:::omop-fhir2",
                "arn:aws:s3:::omop-fhir2/*"
            ],
            "Condition": {
                "StringLike": {
                    "aws:PrincipalArn": [
                        "arn:aws:iam::111:role/skipper-deployment-*-Role",
                        "arn:aws:iam::222:role/skipper-deployment-*-Role",
                        "arn:aws:iam::333:role/skipper-deployment-*-Role"
                    ]
                }
            }
        }
    ]
}

 

これが変換のソースです。では、ターゲットである OMOP データベースに移りましょう。


OMOP の紹介

もう 1 つのデプロイメントである「IRIS 上の OMOP」を簡単に見ながら共通データモデルをご紹介します。

OMOP(Observational Medical Outcomes Partnership)データベースは、複数のソースをサポートするために途方もない複雑さを、CDM と呼ばれる共通データモデルにまとめる方法を示す記念碑的なものです。コミュニティ外部のさらに詳しい説明は、コピペコンテンツ(またはさらに酷い生成コンテンツ)になりますが、このコミュニティのドキュメントは本当によくできています。

「SQL クエリツール」ナビゲーションに移動すると、InterSystems の共通データモデルの実装を確認できます。これは、OHDSI コミュニティのよく知られた OMOP スキーマの図の横に表示されます。

この作業はここまでです。変換目的のみでサービスを使用するためのもう 1 つのオプションを調べてみましょう。

BYODB(所有データベースの持ち込み)

前回プロビジョニングした際に、データベースを無料で入手しましたが、別のデータベースをターゲットにする場合は、この記事を書いた時点でサービスが Postgres 構成への変換もサポートしたため、確実に行えます。このために、Amazon RDS を介して外部データベースを操作し、サービスに接続する方法を説明します。


計算


ここにフラグを立てて、もう 1 つの 👣🔫 に注意を喚起しようと思います。独自のデータベースを持ち込む場合、サービスに合わせてデータベースのサイズを決定する際に「Biggie Smalls」と呼んでいます。InterSystems は、データベース側に対する変換側のサイズ設定を非常に適切に行うため、変換パフォーマンスの速度は書き込み先の SQL インスタンスに依存するという事実を考慮し、それに応じて行う必要があります。一部の人にとっては当たり前のことかもしれませんが、RDS、Google Cloud SQL などを安く利用​​したため、OMOP データベースへの FHIR バンドルの永続時間に影響が出ました。これを目撃したときに、指摘しておこうと思いました。

そうは言っても、私はまったく逆のことをしています。Jeff Bezos に可能な限り最小限の金額を渡し、db.t4g.micro postgres RDS インスタンスを使用しています。

これを公開して、データベースに対応するリージョンの証明書バンドルのダウンロードに移ります。 .pem 形式であることを確認してください。
次に、データベースとの対話方法に関係なく、データベースインスタンスに接続し、DATABASE と SCHEMA を作成します。


OMOP CDM 5.4 のロード

では、OHDSI コミュニティの友人たちの協力を得て、OHDSI ツールを使用して、OMOP 共通データ モデル スキーマを含む RStudio バージョン 5.4 でサポートされているスキーマをプロビジョニングしましょう。

install.packages("devtools")
devtools::install_github("OHDSI/CommonDataModel")
install.packages("DatabaseConnector")
install.packages("SqlRender")
Sys.setenv("DATABASECONNECTOR_JAR_FOLDER" = "/home/sween/Desktop/OMOP/iris-omop-extdb/jars")
library(DatabaseConnector)
downloadJdbcDrivers("postgresql")

必要なものが揃ったので、postgres インスタンスに接続し、上記でプロビジョニングした OMOPCDM54 にテーブルを作成しました。
接続

cd <- DatabaseConnector::createConnectionDetails(dbms = "postgresql",
                                                 server = "extrdp-ops.biggie-smalls.us-east-2.rds.amazonaws.com/OMOPCDM54",
                                                 user = "postgres",
                                                 password = "REDACTED",
                                                 pathToDriver = "./jars"
                                                 )


作成

CommonDataModel::executeDdl(connectionDetails = cd,
                            cdmVersion = "5.4",
                            cdmDatabaseSchema = "omopcdm54"
                            )

「赤い海」を除けば、正しく実行できたことでしょう。

では、作業内容を確認しましょう。サービスとの使用に適した外部の postgres OMOP データベースがあるはずです。


OMOP Cloud Service の構成

ソースもあり、ターゲットもあります。では、サービスを構成したこれらを繋ぎ合わせ、FHIR から外部データベースへの変換パイプラインを完成させましょう。

InterSystems OMOP Cloud Service の準備が完了しました!
OMOP の旅はまだまだ続きます...

0
0 37
記事 Toshihiko Minamoto · 5月 16, 2025 5m read

Auth0 と InterSystems IRIS FHIR リポジトリ使った SMART On FHIR に関する連載最終回では、Angular 16 で開発したアプリケーションをレビューします。

このソリューションに定義されたアーキテクチャがどのように構成されているかを思い出しましょう。

フロントエンドのアプリケーションは 2 列目で、ご覧のように 2 つのことを行います。

  1. ログインリクエストを Auth0 にリダイレクトし、レスポンスを受信する。
  2. REST 経由でリクエストを FHIR サーバーに送信し、そのレスポンスを受信する。

Angular

Angular は TypeScript が開発し、Google が管理するオープンソースの Web アプリケーションフレームワークで、シングルページ Web アプリケーションの作成と管理に使用されます。 この「シングルページアプリケーション」デザイン手法によって、はるかに動的なユーザー向けアプリケーションを設計することができます。 最初の記事で説明したとおり、ここではアプリケーションサーバーとリバースプロキシとして NGINX を使用し、呼び出しヘッダーがサーバーの呼び出しヘッダーに一致するように変更して、CORS から派生する問題を回避します。

アプリケーションのデザイン

モバイルアプリケーションのデザインをシミュレートするように、Angular Material を使ってアプリケーションを設計しました。 この例では、アプリケーションは心拍数、血圧、および体重などの一連の患者データを記録することを目的としており、このために、2 種類の FHIR リソースをサーバーに送信します。1 つ目はユーザーがデータを登録する Patient タイプリソースで、2 つ目は、送信しようとしている各タイプのデータを送信する Observation リソースに対応します。

アプリケーションには、記録されたデータの変化がグラフで表示されます。

ログイン画面

ユーザーがパス https:\\localhost にアクセスすると最初の画面が表示され、そこからログインをリクエストできます。

 

ログインボタンをクリックすると、アプリケーションは構成済みの API に対して有効化された Auth0 ページに自動的にユーザーをリダイレクトします。

ユーザー名とパスワードを入力すると、Auth0 はデータへのアクセス許可をアプリケーションに付与するよう求めます。 データへのアクセスが確認されたら、Auth0 は、構成プロセス中に指定した URL にリダイレクトします。 アクセストークンが生成されると、Auth0 ライブラリは、サーバーに対して発行するすべての呼び出しのヘッダーにそのトークンを含めるようになります。 これは以下の図で確認できます。

最初の画面

ログインが完了すると、ログインユーザーが使用できる情報を FHIR サーバーにリクエストする最初の通信が発生します。これには、パラメーターによるクエリを使用して、次のような GET 呼び出しを送信します。

https://localhost:8443/smart/fhir/r5/Patient?email=lperezra%40intersystems.com

サーバーのレスポンスは次の情報を含む Bundle タイプリソースです。

{
    "resourceType":"Bundle",
    "id":"8c5b1efd-cfdd-11ee-a06b-0242ac190002",
    "type":"searchset",
    "timestamp":"2024-02-20T10:48:14Z",
    "total":0,
    "link":[
        {
            "relation":"self",
            "url":"https://localhost:8443/smart/fhir/r5/Patient?email=lperezra%40intersystems.com"
        }
    ]
}

ご覧のように、そのメールアドレスを使用する患者は合計 0 人であるため、アプリケーションにはデータを登録できる最初の画面が表示されます。

 

ご覧のように、メールアドレスのフィールドにはログインユーザーのアドレスが入力されています。これは、最初のクエリで見たように、メールアドレスを ID として使用するためです。 フォームの入力が完了したら、POST 経由で次のような呼び出しを送信します。

https://localhost:8443/smart/fhir/r5/Patient

Patient リソースによって形成されたメッセージ本文:

{
    "resourceType":"Patient",
    "birthDate":"1982-03-08",
    "gender":"male",
    "identifier":[
        {
            "type":{
                "text":"ID"
            },
            "value":"12345678A"
        }
    ],
    "name":[
        {
            "family":"PÉREZ RAMOS",
            "given":[
                "LUIS ÁNGEL"
                ]
        }
    ],
    "telecom":[
        {
            "system":"phone",
            "value":"600102030"
        },
        {
            "system":"email",
            "value":"lperezra@intersystems.com"
        }
    ]
}

患者データがサーバーに登録され、患者のクエリによって結果が返されるようになったため、さまざまな経過観察を記録できる準備が整いました。 最初の画面がどのように表示されるか見てみましょう。

経過観察画面

患者のデータを送信したのと同じ方法で、特定の画面から経過観察を送信します。

サーバーに送信されたリソースごとに、アプリケーションは新しい点をグラフに追加します。

これを行うために、そのユーザーに属する Observation タイプリソースをリクエストするクエリをサーバーに発行します。

https://localhost/smart/fhir/r5/Observation?patient=Patient/1

すると、サーバーはもう一度、その患者に対して記録されたすべての経過観察を含む Bundle タイプリソースを返します。

結果が取得されたので、アプリケーションはすべての数値を抽出し、関連するグラフを構築します。

まとめ

この記事と前回の 2 つの記事で確認したように、SMART On FHIR アプリケーションの設計と作成はそれほど複雑ではなく、FHIR サーバーで使用できるすべての機能を利用するアプリケーションを素早くアジャイルに構築することができます。

この種のアプリケーションでは、データに対する CRUD タイプの操作を管理する複雑なバックエンドの開発が不要であり、OAuth2 を使用することで、アプリケーションのユーザーを管理する必要もありません。その機能は Auth0 または選択した認証・承認サーバーに任せることができます。

SMART On FHIR では、簡単かつ単純な方法で、患者と医療専門家に対し医療データ管理に必要なツールを提供することができます。

お読みいただきありがとうございました!

0
0 40
お知らせ Mihoko Iijima · 5月 7, 2025

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

次のコンテストの詳細が発表されましたのでご案内します。

🏆 InterSystems FHIR とデジタルヘルスの相互運用性コンテスト 2025 🏆

期間:2025年5月12日~6月1日

賞金総額:$12,000


0
0 37
記事 Yusuke Kojima · 9月 17, 2024 5m read

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

突然ですが、2024年6月25日に開発者向けセミナー「FHIR 新機能のご紹介~2024.1~」が開催されました。
ご視聴になられた方も多数いらっしゃると思います。
まだご視聴になられていない方は是非一度、ご覧になってみてください。
YouTubeリンク

さて、こちらのセミナーにおいてご紹介された、IRIS for Health 2024.1からの新機能「FHIR Object Model」を用いて、リポジトリタイプのInteroperability開発の具体的なサンプルを作成してみました。
自身の備忘のため、すぐ開発環境を構築できるよう、コンテナ環境かつGitHubの公開もしております。
利用方法は、GitHub内のREADMEを参照ください。
GitHubリンク

目次

  1. FHIR Object Modelとは?

  2. メリット・デメリットを深堀り

  3. GitHub公開ソースについて

  4. 所感

1. FHIR Object Modelとは?

0
0 193
記事 Toshihiko Minamoto · 8月 6, 2024 7m read

前回の記事でSMART On FHIRプロジェクトのアーキテクチャを紹介したので、いよいよ本題に入り、必要となる全ての要素の設定を始めましょう。

まずはAuth0から始めます。

Auth0の設定

登録が完了したら、左側のメニューから最初のアプリケーションを作成します

Application menu

この例では、Angular 16で開発されたアプリケーションなので、Single Page Web Applicationタイプとなります。このオプションを選択し、Createをクリックします。

Single Page Web Application

次の画面では以下のフィールドを定義する必要があります。

注意: URLはすべてHTTPSでなければなりません。これはOAuth2接続要件の1つです。

これはOAuth2接続の要件の1つです。これでAuth0が認証と認可プロセスの後にユーザーをリダイレクトするために必要なURLを設定しました。このURLにはポートが定義されていませんが、これはNGINXを通してAngularプロジェクトをDockerにデプロイする際に、デフォルトのHTTPSポート443からアクセスするように指定したためです。好きな名前を付けてください。

Application configuration

この後のAngularプロジェクトの設定について、DomainClient IDの両方にある値を書き出します。

アプリケーションの設定が完了したら、次はAngularアプリケーションからのリクエストを受け取るAPIを定義します。

このオプションを選択すると、必要なデータを入力する画面が表示されます。

API configuration

後でAngularアプリケーションが適切に接続するための "環境 "として使用するAPIの識別子を定義する必要があります。見ての通り、URLを入力することが推奨されていますが、このURLは識別子として使用されるだけなので、実際に機能する必要はありません。この場合、以下のように定義できます。

https://localhost/smart/fhir/r5

最後に、署名アルゴリズムをRS256に設定し、接続ユーザーのFHIRのスコープを定義するPermissionsタブに進みます

API permission

FHIRコンテキストのトピックをより深く知りたい場合は、[ここ](http://hl7.org/fhir/smart-app-launch/1.0.0/scopes-and-launch-context/index.html)をクリックして公式ページのURLを参照してください。この例では、user/*.*スコープを定義し、認証されたユーザーがすべての FHIR サーバーリソースに対して CRUD 操作を実行できるようにしています。

完璧です!Auth0アカウントがOAuth2サーバとして機能するように設定できました。

Angularアプリの設定

このアプリケーションはAngular 17で開発したかったのですが、残念ながらAuth0とそのライブラリの関連ドキュメントはAngular 16のものしかないので、簡単な方を選ぶこととしバージョン16で開発しました。

Angularプロジェクトを設定するには、app.module.tsページを開き、以下のコードを探します

設定する各パラメータの意味を見てみましょう。

  • domain:Auth0 でアプリケーションを作成したときに生成された ドメイン値
  • clientId: 上と同じく生成されたClient ID
  • audience: APIの識別子として設定したURL
  • uri: Auth0 TypeScriptライブラリに、そのURIを含むURLへのすべての呼び出しをインターセプトし、Auth0が検証時に返すAccess_tokenを組み込むように指示します(呼び出しのヘッダにAuthorizationパラメータを追加します: Bearer...)

これらの値を変更すると、AngularアプリケーションがAuth0で動作するように設定されます。次の記事では、ユーザーインターフェースからAuth0を呼び出す方法を詳しく説明します。

InterSystems IRIS for Healthの設定

このプロジェクトは、デプロイプロセス中にFHIRサーバーを自動的にインストールするように設定されているため、手順を省くことができます。今回のケースでは、FHIRサーバーのエンドポイントとして/smart/fhir/r5というURIを定義しました。FHIRの用語に馴染みのない方のために説明すると、r5とはFHIRの最新バージョンのことで、IRISで数ヶ月前から利用可能です。

IRISインスタンスを設定するには、まずDockerを起動し、プロジェクトで利用可能な3つのコンテナをデプロイする必要があります。プロジェクトのルートからターミナルで以下のコマンドを実行するだけです。

docker-compose up -d --build

これで、プロジェクトに存在するコンテナをビルドして実行できるようになります。Windowsユーザーの場合、Docker Desktopを使えば、このような画面が表示されるはずです。

Docker Desktop

ここでは3つのコンテナがあります。

  • iris: FHIRサーバが配置されているIRISインスタンス
  • smart-ui: NGINXからデプロイされたウェブアプリケーションのコードで、すべての接続が関連する証明書とSSLを経由するよう設定されています。
  • webgateway: 関連するApacheサーバー(正式版2023.1以降、プライベートWebサーバーは廃止されましたが、コミュニティ版ではまだ利用可能であることを覚えておいてください)。

ウェブゲートウェイ

繰り返しになりますが、OAuth2をFHIRサーバーで使用するためには、すべての接続がHTTPS経由で行われることが必須であるため、Apacheサーバーはそのタイプの呼び出しのみを受け付けるように設定する必要があります。 webgateway/shared/CSP.confファイルをみると、Apacheサーバの設定を担当する以下のセクションがあります

# SSL SECTION #
# Enable SSL/TLS (https://) on the Apache web server.
# The user is responsible for providing valid SSL certificates.
LoadModule ssl_module /usr/lib/apache2/modules/mod_ssl.so
LoadModule headers_module /usr/lib/apache2/modules/mod_headers.so
<VirtualHost *:443>
SSLEngine on
SSLCertificateFile "/webgateway-shared/apache_webgateway.cer"
SSLCertificateKeyFile "/webgateway-shared/apache_webgateway.key"
Header add ACCESS-CONTROL-ALLOW-ORIGIN "*"
</VirtualHost>

443番ポートを経由するようにし、WebGatewayのURLはhttps://webgateway、アプリケーションからFHIRサーバへの呼び出しはこのURLにリダイレクトする必要があります。(ウェブゲートウェイは、Dockerコンテナによって作成されたネットワークに与えられたマスクです)

Angularからサーバーへのすべての呼び出しはURLhttps://localhost/smart/fhir/r5で行われ、NGINXはそのlocalhostをwebgatewayにリダイレクトする役割を果たします。smart-ui/nginx.confを開くと、以下のような設定になっています。

 

この設定では、Webアプリケーションは443番ポートをリッスンし、URLに/を含むすべての呼び出しはAngularアプリケーションによって管理され、/smart/を含む呼び出しはすべてhttps://webgatewayにリダイレクトされます。 CORSによる頭痛の種を回避するproxy_set_headerには注意が必要です。Web Gatewayが他のサーバーからの呼び出しを拒否しないようにするには、Host ヘッダーの値を変更して、Web Gatewayのアドレスで設定する必要があります。

InterSystems IRIS

次に IRIS を Auth0 で動作するように設定する必要がありますが、そのためには IRIS を OAuth2 クライアントとして設定する必要があります。これを行うには、スーパーユーザ/SYS認証情報で管理ポータルにアクセスし、[System Administration (システム管理)] > [Security (セキュリティ)] > [OAuth 2.0 (OAuth 2.0)] > [Client (クライアント)] オプションにアクセスし、[Create Server Description (サーバ記述の作成)] をクリックし、発行者エンドポイントに Auth0 へのアプリケーション作成時に取得したドメイン値 (https://[MY_DOMAIN]/) を入力します。注意してください!URLは"/"で終わっていなければなりません。最後にSSL/TLSコンフィギュレーションを選択し、Discover and Saveをクリックします。

IRIS client

IRISインスタンスは自動的にAuth0から必要な情報を取得します

Issuer endpoint

先ほど設定したサーバにクライアントを追加するだけです。Client Configuration を押すと、アプリケーションとクライアントの名前を定義する新しい画面にアクセスできます。このクライアント名は、後で FHIR サーバを設定する際に使用します。

FHIRサーバ

プロジェクトの設定を完了する最後のステップは、接続に使用するOAuth2クライアントをFHIRサーバに伝えることです。コンフィギュレーションにアクセスするには、管理ポータルを開き、Health > FHIR > FHIR Configuration > Server Configurationを選択して、画面に表示されているエンドポイントを開きます。最後にOAuth Client Nameフィールドにクライアント・コンフィギュレーションを作成した名前を追加します。

FHIR OAuth Configuration

まとめ

さて、プロジェクトの設定は完了しました。次回は、Angularアプリケーションが各アクターとどのように相互運用するかを見ていきましょう。

ご清聴ありがとうございました!

0
0 74
記事 Toshihiko Minamoto · 6月 12, 2024 4m read

はじめに

先日、@Patrick Jamieson が開催した素晴らしいハンズオンに参加してきました。そこでは、SMART On FHIR が定義したプロトコルに従って Angular アプリケーションを IRIS FHIR サーバーとともに構成したセッションでした。非常に深い興味を得たため、独自に Andular アプリケーションを開発し、そこから学んだことを活用してコミュニティに共有することにしました。

SMART On FHIR

SMART On FHIR について Google ではどのように説明しているのか見てみましょう。

SMART On FHIR は電子健康記録(EHR)システムの情報にアプリケーションがアクセスできるようにするためのデータ規格です。 アプリケーション開発者は、その規格を採用した EHR システムに接続する単一のアプリケーションを作成できます。

SMART On FHIR では、以下の主な概念を処理します。

  • OAuth2 または OpenID による代理認証と承認。
  • 定義されたコンテキストにおける FHIR リソースの操作。
  • HTTPS 通信。

プロジェクトのアーキテクチャ

この演習では、Docker と Auth0 サービスの両方で以下の要素を構成しました。

  • フロントエンドとして機能する Angular で開発されたアプリケーション。このアプリケーションは SMART On FHIR の原則に従って開発されています。
  • Angular で開発されたアプリケーションを公開する NGINX Web サーバーおよびリバースプロキシ。
  • Auth0 が提供する OAuth2 による認証および承認サービス。
  • FHIR サーバーをデプロイし、Docker イメージですでに提供されている Apache サーバーを含む Web ゲートウェイを通じて接続する InterSystems IRIS。

Auth0

ユーザーの認証と承認をこの目的でデプロイされた別の IRIS サーバーに委任することもできますが、ここでは、Auth0 が提供するサービスを使用することにします。

Auth0 とは?

Auth0 は、プラットフォームの認証と承認を処理するメカニズム全体を提供するサービスです。

Auth0 には、あらゆるプロジェクトに簡単に統合できる多様な言語に特化したライブラリもあるため、SMART On FHIR に基づく開発において必ず考慮できるオプションです。

アプリケーションでの Auth0 の使用

OAuth2 の使用は SMART On FHIR を使用するための必要要件であるため、認証、承認、およびアプリケーションアクセスの通常のプロセスに OAuth2 サーバーを含める必要があります。 以下の図は、Auth0 サービスを使ってシステムに送信される情報が辿るパスを示しています。

では、プロセスを分析しましょう。

  • ログインリクエスト:
    1. ログインリクエスト: ユーザーがインターネットブラウザを使用してアプリケーションにアクセスし、ログインをリクエストします。
    2. ログインリクエスト: Angular アプリケーションがそのリクエストを Auth0 サービスに転送します。
    3. ログインページ: Auth0 がユーザーのインターネットブラウザを開発者が作成したページにリダイレクトします。
  • Auth0 での認証:
    1. ユーザー認証情報: ユーザーが、Auth0 に登録されたメールアドレスとパスワードを入力します。
    2. 認証と承認: Auth0 がデータを検証し、ユーザーに割り当てられたコンテキストを含む Access_token を生成します。
    3. Access_token のレスポンスとリダイレクト: Auth0 が生成されたトークンを含むレスポンスをプロジェクト構成に指定された URL にリダイレクトします。
    4. 患者の画面: Angulaar アプリケーションが、個人情報を登録するページをユーザーに表示します。
  • FHIR リソースレコード:
    1. 患者の保存: ユーザーが個人情報をフォームに入力し、Angular アプリケーションがフォームを FHIR Patient リソースのフォーマットで JSON オブジェクトに変換します。
    2. POST リクエスト: Angular アプリケーションが IRIS にデプロイされている FHIR サーバーに、認証トークンとしての access_token をリクエストヘッダーに含めて HTTP POST 呼び出しを送信します。
    3. POST レスポンス: Web ゲートウェイを通じて POST リクエストを受け取ると、IRIS はトークンの有効性とリクエストのコンテキストをチェックします。 すべてが正しければ、受信したリソースを検証して FHIR サーバーに登録し、新しいリソースの作成を示す HTTP 201 を返します。 また、ヘッダーに、新しいリソースに割り当てられた識別子が含められます。
    4. 処理成功: Angular アプリケーションが、主な機能を示す画面にユーザーをリダイレクトします。

ログインが完了すると、プロジェクトに含まれる Auth0 ライブラリが、FHIR サーバーに対して発行するすべてのリクエストを傍受し、Auth0 から受け取るアクセストークンを含めます。

今後の予定

次の記事では、関りのある各システムを構成し、最終的に Angular アプリケーションに接続する方法を説明します。 記事の公開を待ちきれない方は、この記事にリンクされた OpenExchange プロジェクトに関連付する GitHub で README.md をお読みください。Auth0 と InterSystems IRIS の両方を構成する方法が詳しく説明されています。

Awfully Good: Stay Tuned (1992) with John Ritter

0
0 127
お知らせ Mihoko Iijima · 3月 26, 2024

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

(2024/5/30:6月の日時、ウェビナー内容を更新しました)

InterSystems IRIS、InterSystems IRIS for Healthの新バージョン2024.1がリリースされました。

様々な機能の追加や実験的機能としての追加が行われましたが、その中から以下3種類の内容についてウェビナーを開催します!📣

✅4月23日(火)13時半~14時:IRIS 2024.1の管理用Webサーバ(PWS)廃止に備えて

YouTube公開しました👉https://youtu.be/bVwWZt1oNws?list=PLzSN_5VbNaxCeC_ibw2l-xneMCwCVf-Or

✅5月30日(木)13時半~14時:ベクトル検索機能のご紹介

YouTube公開しました👉https://youtu.be/v0G7K2et_Yk?list=PLzSN_5VbNaxB39_H2QMMEG_EsNEFc0ASz

✅6月25日(火)13時半~14時:FHIR新機能のご紹介~2024.1~

オンデマンド配信はこちら👉https://event.on24.com/wcc/r/4597704/ADA161B6446E6BA01623C875CF596FD0
(資料PDFもオンデマンド配信画面よりダウンロードいただけます)
 

2
0 208
記事 Toshihiko Minamoto · 5月 28, 2024 6m read

前回の記事では特定の HIS のデータベースに格納されたリソースを取得する方法を確認したので、今回は、HIS に、システムで受け取る FHIR リソースを起点とする新しいレコードを追加する方法を説明します。

FHIR の CRUD 操作

FHIR の主な機能の 1 つに、Rest API による CRUD 操作のサポートがあります。つまり、FHIR と連携するすべてのシステムには、GET、POST、PUT、および DELETE タイプの HTTP 呼び出しがサポートされていなければなりません。 この記事では、FHIR アダプターをインストールした際に自動的に構成されたエンドポイントへの POST 呼び出しを処理する方法を見てみましょう。

FHIR のリソースストレージ呼び出しに関する仕様を確認すると、呼び出しに使用する URL は、以下のフォーマットを使用している必要があります。

http(s)://server_url/{endpoint}/{Resource}

この記事の例では、セキュリティで保護された呼び出しは行わないため、以下のような URL になります。

http://localhost:52774/Adapter/r4/Patient

ここで行いたいのは新しい患者を記録することであるため、呼び出しの本文に患者のデータを含めた POST 呼び出しを行う必要があります。 application/fhir+xml として問題なく XML 形式を使用することもできますが、この場合の呼び出しのフォーマットは application/fhir+json とします。

患者のリソースの保存

前回の記事ですでに Patient リソースの定義を確認したのでここでは繰り返しません。ここでは、整形済みのテスト患者がどのように見えるかを確認しましょう。 ここで見るのは以下の患者です。

{
    "resourceType": "Patient",
    "address": [
        {
            "city": "SALAMANCA",
            "line": [
                "CALLE LAMENTOS 2 1ºA"
            ],
            "postalCode": "45021"
        }
    ],
    "birthDate": "1988-01-23",
    "gender": "F",
    "identifier": [
        {
            "type": {
                "text": "NHC"
            },
            "value": "803987"
        },
        {
            "type": {
                "text": "DNI"
            },
            "value": "87654321F"
        }
    ],
    "name": [
        {
            "family": "SANZ LÓPEZ",
            "given": [
                "REBECA"
            ]
        }
    ],
    "telecom": [
        {
            "system": "phone",
            "value": "699850017"
        },
        {
            "system": "email",
            "value": "rebek1988@hotmail.com"
        }
    ]
}

ご覧のように、Postman からサーバーのエンドポイントに送信する Patient タイプの Resource です。

200 を受け取り、患者が HIS に登録されたので、Patient テーブルを確認しましょう。

ここに、POST リクエストに対するレスポンスで受け取った識別子で HIS に正しく記録された Rebecca があります。 では、本番環境にアクセスし、FHIR メッセージが IRIS 内で通過したパスを確認しましょう。

IRIS での Patient リソースの操作

ここまでで、FHIR リソースをサーバーのエンドポイントに送信する方法を見てきました。では、受け取った FHIR リソースをどのように解釈し、特定の HIS に挿入するために変換できるかを確認しましょう。

まず、本番環境の構成をもう一度確認しましょう。

メッセージは InteropService から届き、ProcessFHIRBP に転送されます。そこで、FromAdapterToHIS が呼び出され、対応する操作が実行されます。 では、受信したメッセージのトレースを確認しましょう。

ここでは、受信したメッセージの詳細を確認できます。ご覧のように、Patient エンドポイントに HTTP POST リクエストが届いており、QuickStreamId に値があることがわかります。メッセージは Stream に格納されていることが示されています。

BO はこのメッセージをどのように処理するのでしょうか?

elseif (requestData.Request.RequestPath [ "Patient")
  {
    if (requestData.Request.RequestMethod = "POST")
    {
      If requestData.QuickStreamId '= "" {
        Set quickStreamIn = ##class(HS.SDA3.QuickStream).%OpenId(requestData.QuickStreamId,, .tSC)
    <span class="hljs-keyword">set</span> dynamicPatient = <span class="hljs-keyword">##class</span>(<span class="hljs-built_in">%DynamicAbstractObject</span>).<span class="hljs-built_in">%FromJSON</span>(quickStreamIn)

    <span class="hljs-keyword">set</span> sc = <span class="hljs-built_in">..InsertPatient</span>(dynamicPatient, .response)
  }      
}
<span class="hljs-keyword">elseif</span> (requestData.Request.RequestMethod = <span class="hljs-string">"GET"</span>)
{
  <span class="hljs-keyword">set</span> patientId = <span class="hljs-built_in">$Piece</span>(requestData.Request.RequestPath,<span class="hljs-string">"/"</span>,<span class="hljs-number">2</span>)
  <span class="hljs-keyword">set</span> sc = <span class="hljs-built_in">..GetPatient</span>(patientId, .response)
}

}

非常に単純です。受信したリクエストから得られる情報をもって、メッセージを適切なメソッドにリダイレクトできます。Patient リソースからの特定のリクエストであることとメソッドが POST であることを確認できるため、メッセージを格納している Stream を取得してそれを %DynamicObject に変換します。以下では、InsertPatient メソッドからこれを処理します。そのメソッドのコードを見てみましょう。

Method InsertPatient(dynamicPatient As%DynamicAbstractObject, Output patient As Adapter.Message.FHIRResponse) As%Status
{
  Set tSC = $$$OKkill pResp
  set pResp=$$$NULLOREFset sqlInsert="INSERT INTO his.patient (name, lastname, phone, address, city, email, nhc, postal_code, birth_date, dni, gender) values (?,?,?,?,?,?,?,?,?,?,?)"//perform the Insertset tSC = ..Adapter.ExecuteUpdate(.nrows, sqlInsert, dynamicPatient.%Get("name").%Get(0).%Get("given").%Get(0), dynamicPatient.%Get("name").%Get(0).%Get("family"), dynamicPatient.%Get("telecom").%Get(0).value, 
    dynamicPatient.%Get("address").%Get(0).%Get("line").%Get(0), dynamicPatient.%Get("address").%Get(0).%Get("city"), dynamicPatient.%Get("telecom").%Get(1).value, dynamicPatient.%Get("identifier").%Get(1).value, 
    dynamicPatient.%Get("address").%Get(0).%Get("postalCode"), dynamicPatient.%Get("birthDate"), dynamicPatient.%Get("identifier").%Get(2).value, dynamicPatient.%Get("gender"))

set sql="SELECT id, name, lastname, phone, address, city, email, nhc, postal_code, birth_date, dni, gender FROM his.patient WHERE nhc = ?"//perform the Selectset tSC = ..Adapter.ExecuteQuery(.resultSet, sql, dynamicPatient.%Get("identifier").%Get(1).value)

If resultSet.Next() { set personResult = {"id":(resultSet.GetData(1)), "name": (resultSet.GetData(2)), "lastname": (resultSet.GetData(3)), "phone": (resultSet.GetData(4)), "address": (resultSet.GetData(5)), "city": (resultSet.GetData(6)), "email": (resultSet.GetData(7)), "nhc": (resultSet.GetData(8)), "postalCode": (resultSet.GetData(9)), "birthDate": (resultSet.GetData(10)), "dni": (resultSet.GetData(11)), "gender": (resultSet.GetData(12)), "type": ("Patient")} } else { set personResult = {} }

//create the response messagedo patient.Resource.Insert(personResult.%ToJSON())

<span class="hljs-keyword">Return</span> tSC

}

ご覧のように、最初に行うのは、HIS の Patient テーブルへの挿入です(誰かがその患者が存在しないことを確認済みであると仮定しましょう)。挿入が完了したら、この患者に対して生成された識別子を取得してリクエストを送信したクライアントアプリケーションにそれを返すために、同じテーブルで SELECT を実行します。 レスポンスメッセージを完成させるために、最も関連性があると思われるフィールドを取得できます。

取得した患者データとともに、クライアントに返すことのできる Patient タイプリソースを生成するために必要な変換を実行する BP に戻ります。

変換については、前の記事をご覧ください。

リソースが生成されたら、レスポンスに含めてクライアントアプリケーションに戻す Stream に変換します。

ご覧のように、非常に簡単です。患者リソースからデータを取得し、対応するテーブルに挿入するだけです。 最後に、登録されたオブジェクトを、GET リクエストで行ったのと同じ方法で返します。

次の記事では、Bundle またはリソースセットを処理する方法を説明します。 お読みいただきありがとうございました!

0
0 122
記事 Toshihiko Minamoto · 5月 23, 2024 11m read

HealthShare、HealthConnect、および InterSystems IRIS ユーザーが使用できる FHIR アダプターツールに関する連載記事を再開しましょう。

前回の記事では、ワークショップをセットアップした小さなアプリケーションを紹介し、FHIR アダプターをインストールした後に IRIS インスタンスにデプロイされたアーキテクチャを説明しました。 この記事では、最も一般的な CRUD(作成、読み取り、更新、削除)操作の 1 つである読み取り操作を実行する方法の例を確認します。ここではリソースの取得によって行います。

リソースとは?

FHIR のリソースはある種の臨床情報です。この情報は、患者(Patient)、臨床検査へのリクエスト(ServiceRequest)、または診断(Condition)などです。 各リソースはそれを構成するデータのタイプのほか、データの制約や他のリソースタイプとの関係を定義します。 リソースごとに、それが格納する情報の拡張が可能であるため、FHIR ポリシーの範囲外のニーズに 80% 対応できます(ユーザーの 80% が使用する要件に対応)。

この記事の例では、最も一般的なリソースである Patient を使用します。 その定義を確認しましょう。

{
  "resourceType" : "Patient",
  // from Resource: id, meta, implicitRules, and language
  // from DomainResource: text, contained, extension, and modifierExtension
  "identifier" : [{ Identifier }], // An identifier for this patient
  "active" : <boolean>, // Whether this patient's record is in active use
  "name" : [{ HumanName }], // A name associated with the patient
  "telecom" : [{ ContactPoint }], // A contact detail for the individual
  "gender" : "<code>", // male | female | other | unknown
  "birthDate" : "<date>", // The date of birth for the individual
  // deceased[x]: Indicates if the individual is deceased or not. One of these 2:
  "deceasedBoolean" : <boolean>,
  "deceasedDateTime" : "<dateTime>",
  "address" : [{ Address }], // An address for the individual
  "maritalStatus" : { CodeableConcept }, // Marital (civil) status of a patient
  // multipleBirth[x]: Whether patient is part of a multiple birth. One of these 2:
  "multipleBirthBoolean" : <boolean>,
  "multipleBirthInteger" : <integer>,
  "photo" : [{ Attachment }], // Image of the patient
  "contact" : [{ // A contact party (e.g. guardian, partner, friend) for the patient
    "relationship" : [{ CodeableConcept }], // The kind of relationship
    "name" : { HumanName }, // I A name associated with the contact person
    "telecom" : [{ ContactPoint }], // I A contact detail for the person
    "address" : { Address }, // I Address for the contact person
    "gender" : "<code>", // male | female | other | unknown
    "organization" : { Reference(Organization) }, // I Organization that is associated with the contact
    "period" : { Period } // The period during which this contact person or organization is valid to be contacted relating to this patient
  }],
  "communication" : [{ // A language which may be used to communicate with the patient about his or her health
    "language" : { CodeableConcept }, // R!  The language which can be used to communicate with the patient about his or her health
    "preferred" : <boolean> // Language preference indicator
  }],
  "generalPractitioner" : [{ Reference(Organization|Practitioner|
   PractitionerRole) }], // Patient's nominated primary care provider
  "managingOrganization" : { Reference(Organization) }, // Organization that is the custodian of the patient record
  "link" : [{ // Link to a Patient or RelatedPerson resource that concerns the same actual individual
    "other" : { Reference(Patient|RelatedPerson) }, // R!  The other patient or related person resource that the link refers to
    "type" : "<code>" // R!  replaced-by | replaces | refer | seealso
  }]
}

ご覧のように、実質的に患者のすべての管理情報のニーズに対応しています。

HIS から患者の取得

前回の記事を覚えていれば、HIS システムのデータベースをシミュレーションする PostgreSQL データベースをデプロイしました。特定の HIS にあるサンプルテーブルを確認してみましょう。

多くはありませんが、ここでの例には十分です。 patient テーブルをもう少し詳しく見てみましょう。

ここに、3 つの患者の例があります。ご覧のように、それぞれに一意の識別子(ID)のほか、医療組織に関連性のある一連の管理データがあります。 最初の目標は、1 人の患者の FHIR リソースを取得することです。

患者のクエリ

サーバーから患者データをリクエストするにはどうすればよいでしょうか? FHIR が作成した実装仕様によると、サーバーのアドレス、リソース名、および識別子を使って REST 経由で URL に GET を実行する必要があり、 以下のように呼び出す必要があります。

http://SERVER_PATH/Patient/{id}

この例では、Juan López Hurtado という患者を検索します。この患者の ID は 1 であるため、呼び出す URL は以下のようになります。

http://localhost:52774/Adapter/r4/Patient/1

テストするには、クライアントとして Postman を使用します。 サーバーのレスポンスを確認しましょう。

{
    "resourceType": "Patient",
    "address": [
        {
            "city": "TERUEL",
            "line": [
                "CALLE SUSPIROS 39 2ºA"
            ],
            "postalCode": "98345"
        }
    ],
    "birthDate": "1966-11-23",
    "gender": "M",
    "id": "1",
    "identifier": [
        {
            "type": {
                "text": "ID"
            },
            "value": "1"
        },
        {
            "type": {
                "text": "NHC"
            },
            "value": "588392"
        },
        {
            "type": {
                "text": "DNI"
            },
            "value": "12345678X"
        }
    ],
    "name": [
        {
            "family": "LÓPEZ HURTADO",
            "given": [
                "JUAN"
            ]
        }
    ],
    "telecom": [
        {
            "system": "phone",
            "value": "844324239"
        },
        {
            "system": "email",
            "value": "juanitomaravilla@terra.es"
        }
    ]
}

次に、本番環境内でリクエストが通過した経路を詳しく見てみましょう。

ルートは以下のようになっています。

  1. BS InteropService にリクエストが到着。
  2. BS の宛先として構成し、受信した呼び出しの患者識別子がクエリされる BP に転送。
  3. BO FromAdapterToHIS から HIS データベースにクエリ。
  4. 患者データを BP に転送し、それを FHIR Patient リソースに変換。
  5. レスポンスを BS に転送。

BP ProcessFHIRBP で受信するメッセージのタイプを見てみましょう。

クライアントからどの種類のオペレーションをリクエストされたかを特定するための鍵となる 3 つの属性を見てみましょう。

  • Request.RequestMethod: どの種のオペレーションを実行するかを示します。 この例では、患者の検索は GET になります。
  • Request.RequestPath: この属性には、サーバーに届いたリクエストのパスが含まれ、操作するリソースを示します。この場合、取得するための具体的な識別子が含まれます。
  • Quick.StreamId: FHIR Adapter は Stream に届いたすべての FHIR メッセージを変換し、この属性に保存される識別子が割り当てられます。 この例では、GET を実行しており、FHIR オブジェクトを送信していないため、これは必要ありません。

処理を行う GLP を詳しく分析して、メッセージの流れをさらに見ていきましょう。

ProcessFHIRBP:

本番環境に、ビジネスサービスから受け取る FHIR メッセージングを管理する BPL を実装しました。 どのように実装されているか見てみましょう。

ステップごとに実行する操作を見てみましょう。

FHIR オブジェクトの管理:

HIS データベースへの接続とデータベースクエリを処理する BO FromAdapterToHIS を呼び出します。

Method ManageFHIR(requestData As HS.FHIRServer.Interop.Request, response As Adapter.Message.FHIRResponse) As%Status
{
  set sc = $$$OKset response = ##class(Adapter.Message.FHIRResponse).%New()

if (requestData.Request.RequestPath = "Bundle") { If requestData.QuickStreamId '= "" { Set quickStreamIn = ##class(HS.SDA3.QuickStream).%OpenId(requestData.QuickStreamId,, .tSC)

    <span class="hljs-keyword">set</span> dynamicBundle = <span class="hljs-keyword">##class</span>(<span class="hljs-built_in">%DynamicAbstractObject</span>).<span class="hljs-built_in">%FromJSON</span>(quickStreamIn)

    <span class="hljs-keyword">set</span> sc = <span class="hljs-built_in">..GetBundle</span>(dynamicBundle, .response)
  }

} elseif (requestData.Request.RequestPath [ "Patient") { if (requestData.Request.RequestMethod = "POST") { If requestData.QuickStreamId '= "" { Set quickStreamIn = ##class(HS.SDA3.QuickStream).%OpenId(requestData.QuickStreamId,, .tSC)

    <span class="hljs-keyword">set</span> dynamicPatient = <span class="hljs-keyword">##class</span>(<span class="hljs-built_in">%DynamicAbstractObject</span>).<span class="hljs-built_in">%FromJSON</span>(quickStreamIn)

    <span class="hljs-keyword">set</span> sc = <span class="hljs-built_in">..InsertPatient</span>(dynamicPatient, .response)
  }      
}
<span class="hljs-keyword">elseif</span> (requestData.Request.RequestMethod = <span class="hljs-string">"GET"</span>)
{
  <span class="hljs-keyword">set</span> patientId = <span class="hljs-built_in">$Piece</span>(requestData.Request.RequestPath,<span class="hljs-string">"/"</span>,<span class="hljs-number">2</span>)
  <span class="hljs-keyword">set</span> sc = <span class="hljs-built_in">..GetPatient</span>(patientId, .response)
}

} Return sc }

BO は受信した HS.FHIRServer.Interop.Request タイプのメッセージを確認します。この場合は、GET を設定して、Partient リソースに対応するパスに、以下の GetPatient メソッドが呼び出されることを示して確認します。

Method GetPatient(patientId As%String, Output patient As Adapter.Message.FHIRResponse) As%Status
{
  Set tSC = $$$OKset sql="SELECT id, name, lastname, phone, address, city, email, nhc, postal_code, birth_date, dni, gender FROM his.patient WHERE id = ?"//perform the Selectset tSC = ..Adapter.ExecuteQuery(.resultSet, sql, patientId)

If resultSet.Next() { set personResult = {"id":(resultSet.GetData(1)), "name": (resultSet.GetData(2)), "lastname": (resultSet.GetData(3)), "phone": (resultSet.GetData(4)), "address": (resultSet.GetData(5)), "city": (resultSet.GetData(6)), "email": (resultSet.GetData(7)), "nhc": (resultSet.GetData(8)), "postalCode": (resultSet.GetData(9)), "birthDate": (resultSet.GetData(10)), "dni": (resultSet.GetData(11)), "gender": (resultSet.GetData(12)), "type": ("Patient")}

} else { set personResult = {} }

//create the response messagedo patient.Resource.Insert(personResult.%ToJSON())

<span class="hljs-keyword">Return</span> tSC

}

ご覧のように、このメソッドは HIS のデータベースにクエリを発行し、すべての患者情報を取得してから後で String に変換されて Adapter.Message.FHIRResponse タイプの変数に格納される DynamicObject を生成します。 後でトレースでレスポンスを表示できるように、Resource プロパティを String リストとして定義しました。 直接 DynamicObjects として定義し、後続の変換を省略することもできます。

Bundle かどうかの確認:

BO からのレスポンスによって、Bundle タイプであるか(今後公開される記事で説明します)単なる Resource であるかをチェックします。

DynamicObject の作成:

BO レスポンスを DynamicObject に変換し、それを一時コンテキスト変数(context.temporalDO)に割り当てます。 変換に使用される関数は以下のとおりです。

##class(%DynamicAbstractObject).%FromJSON(context.FHIRObject.Resource.GetAt(1))

FHIR の変換:

DynamicObject タイプの一時変数を使用して、クラス HS.FHIR.DTL.vR4.Model.Resource.Patient のオブジェクトへの変換を行います。 他のタイプのリソースを探す場合は、タイプごとに特定の変換を定義する必要があります。 では、変換を確認しましょう。

この変換によって、BS InteropService が解釈するオブジェクトが得られます。 結果を context.PatientResponse 変数に格納します。

Stream へのリソースの割り当て:

FHIR の変換で取得した変数 context.PatientResponse を Stream に変換します。

QuickStream への変換:

response 変数に、クライアントに戻す必要のあるすべてのデータを割り当てます。

set qs=##class(HS.SDA3.QuickStream).%New()
 set response.QuickStreamId = qs.%Id()
 set copyStatus = qs.CopyFrom(context.JSONPayloadStream)
 set response.Response.ResponseFormatCode="JSON"set response.Response.Status=200set response.ContentType="application/fhir+json"set response.CharSet = "utf8"

この場合、200 レスポンスを常に返します。 本番環境では、検索されたリソースが正しく取得されたことを確認し、取得されていない場合は、レスポンスのステータスを 200 から「見つかりません」に対応する 404 に変更します。 このコード箇所で見られるように、オブジェクト HS.FHIR.DTL.vR4.Model.Resource.Patient
は Stream に変換されて、 HS.SDA3.QuickStream として格納されます。そのオブジェクトの識別子を QuickStreamID 属性に追加されるため、その後 InteropService サービスによって結果を JSON として正しく戻せるようになります。

まとめ:

この記事で行ったことをまとめましょう。

  1. GET タイプのリクエストを送信して、定義された ID を持つ Patient リソースを検索しいました。
  2. BS InteropService は構成済みの BP にリクエストを転送しました。
  3. BP は、HIS データベースを操作する BO を呼び出しました。
  4. 構成済みの BO は、HIS データベースから患者データを取得しました。
  5. BP は結果を、デフォルトの InteropService が作成された BS によって理解可能なオブジェクトに変換しました。
  6. BS はレスポンスを受け取り、クライアントに転送しました。

ご覧のように、操作は比較的単純で、より多くのタイプのリソースをサーバーに追加する場合、BO に取得される新しいリソースに対応するデータベースのテーブルにクエリを追加し、BO の結果を対応する HS.FHIR.DTL.vR4.Model.Resource.* タイプのオブジェクトに変換する処理を BP に含めます。

次の記事では、Patient タイプの新しい FHIR リソースを HIS データベースに追加する方法を説明します。

お読みいただきありがとうございました!

0
0 141
記事 Toshihiko Minamoto · 5月 21, 2024 4m read

さて、FHIR アダプターの使用例に戻り、この記事では、IRIS インスタンスでの構成方法とインストールの結果を確認したいと思います。

プロジェクトの構成手順は公式ドキュメントで指示されているものと同じなので、直接こちらで確認できます。 では作業に移りましょう!

インストール

この記事に関連するプロジェクトでわかるように、IRIS インスタンスを Docker でデプロイしています。そのため最初の構成の主な部分は Dockerfile で行います。 Docker 構成については詳しく確認しないため、気にする必要はありません。

FHIR アダプターをインストールする手順は、たったこれだけです。

  1. 相互運用性機能を備えた IRIS インスタンスに ADAPTER というネームスペースを作成します。
  2. IRIS ターミナルで、そのネームスペースにアクセスして以下のコマンドを実行します。
set status = ##class(HS.FHIRServer.Installer).InteropAdapterConfig("/Adapter/r4")

ここでは、REST リクエストを受信する IRIS エンドポイントの URL を /Adapter/r4 と定義しました。

インストール結果

FHIR アダプターのインストールが完了したら、IRIS インスタンスで何が起きたかを確認できます。 これを行うには、まず Web アプリケーションメニュー(システム管理 -> セキュリティ -> アプリケーション -> Web アプリケーション)を確認します。

ご覧のように、新しい Web アプリケーションがリストに追加されており、ADAPTER ネームスペースに対応しているのがわかります。 では、これにアクセスしてその構成をさらに詳しく見てみましょう。

作成された Web アプリケーションでは REST 呼び出しの受信が有効になっており、これらの呼び出しを管理するクラスは HS.FHIRServer.HC.FHIRInteropAdapter となっています。 また、パスワード認証と認証なしの呼び出しの両方が有効になっているのもわかります。 この例では何も変更しいませんが、JWT 認証がすべての本番環境で有効になっていると興味深いでしょう。

本番のネームスペースで何か起きたか見てみましょう。

インストールによって、ビジネスサービス InteropService とビジネスオペレーション InteropOperation という 2 つの新しいコンポーネントが作成されてデプロイされました。 この例では、受信した FHIR メッセージを転送する InteropService のみを使用します。これはクラス HS.FHIRServer.Interop.Request であり、受信した情報の抽出で使用するものです。 InteropService が JSON レスポンスを返すために受信する必要のあるレスポンスのタイプは HS.FHIRServer.Interop.Response です。

「HIS」の構成

前回の記事で、理論上の HIS で相互運用性をシミュレーションすると述べました。このために、Docker には一連のテストテーブルを含む PostgreSQL インスタンスをデプロイしています。 この外部データベースにクエリを発行するために Java ゲートウェイを含めて構成したため、必要な JDBC 接続を確立できます。 また、PostgreSQL との接続に使用する JAVA ライブラリも含めました。

では、この接続を管理する本番コンポーネントを見てみましょう。

Docker にデプロイした Java 仮想マシンを指すように構成された Java ゲートウェイがあります。

ビジネスオペレーション FromAdapterToHIS によって、PostgreSQL へのクエリが処理されるため、その構成を確認しましょう。

ご覧のように、Adapter クラスとして EnsLib.SQL.OutboundAdapter を使用しているため、「HIS」のデータベースに直接接続することができます。 DSN 値は、Docker にデプロイされた PostgreSQL インスタンスへの接続文字列になります。

まとめると...

この記事で行ったことをもう一度確認しましょう。

  1. ネームスペースに FHIR アダプターをインストールし、FHIR メッセージの送信先となるエンドポイントがあることを確認しました。
  2. 本番ネームスペースにデフォルトで作成されたコンポーネント(InteropService と InteropOperation)を確認しました。
  3. 「HIS」データベースとやり取りするのに必要なコンポーネントを作成しました。

この手順により、JSON 形式で FHIR メッセージを受信し始める準備がすべて整いました。 次の記事では、受信したメッセージを処理するビジネスプロセスを作成し、PostgreSQL データベースの照会と書き込みに必要な様々な機能を実装します。

お読みいただきありがとうございました!

0
0 138
記事 Toshihiko Minamoto · 5月 16, 2024 3m read

FHIR がシステム間の相互運用性と互換性に関するあらゆる問題に対する万能薬であり、ソリューションであることはご存知のことでしょう。 これは、FHIR リソースを手に掲げてそれに興じる戦士の画像です。

ですが、戦士ではない私たちのために、少しだけ紹介したいと思います。

FHIR とは?

早速定義を述べると、FHIR(Fast Healthcare Interoperability Resource; 高速ヘルスケア相互運用性リソース)とは、ヘルスケア産業において医療データを様々なシステム間で電子的にやり取りできるようにするために、HL7(Health Level 7) 規格化組織が作成した相互運用性の規格です。

FHIR の基盤テクノロジー

REST API や JSON 形式による HTTP 呼び出しの組み合わせを主としています(使用方法に応じて XML やその他の通信も可能)。

FHIR の操作方法

一般に、GET (サーバーからデータを取得)、PUT (データの更新)、POST (データの保存)、および DELETE (削除)などの HTTP 呼び出しを使用して通信する FHIR サーバーを使用するのが最も簡単です。 .

FHIR はサーバーとクライアント間でデータの送受信に使用されるリソースの概念を処理します。 これらのリソースはシステム間の 80% の相互通信のニーズに対応することを目指しています。 以下は、デフォルトで使用できるリソースの画像です。

ご覧のように、各リソースにはリソースの成熟度を示す数字か文字が備わっています(N は標準を表します)。 FHIR の公式ドキュメントには多数の例が記載されています。

Resource の発展形が Bundle です。これは大まかに言うと、同一の JSON 内にパッケージされたリソースのセットで、サーバーにクエリしたり、バッチやトランザクションで CRUD 操作を実行したりするために使用されます。

さて、FHIR が素晴らしいことはわかりますが、FHIR が定義する基準に従って動作するように設計されていないレガシーシステムでは、これをどのように応用できるのでしょうか?

FHIR アダプター

InterSystems はお客様に FHIR アダプター機能を提供しています。これを使用することで、既存のシステム上にビジネスレイヤーをセットアップし、FHIR ファサードとして知られるものを作成することができます。 以降の記事では、FHIR オブジェクトの操作方法と、PostgreSQL データベースを使用する HIS(健康情報サービス)システムがどのようなものかを示す簡単なシミュレーションの操作方法を説明します。

説明を理解しやすくするために、今後使用するサンプルを自動的にセットアップする OpenExchange アプリケーションを提供しています。

ワークショップの展開

今後の記事では、以下のポイントについて説明します。

  1. IRIS インスタンスにおける FHIR アダプターのアーキテクチャ
  2. 患者タイプリソースを HIS に登録する
  3. REST API 呼び出しを使って ID で患者をクエリする
  4. 患者と医療センターデータの Bundle を HIS に登録する

ご興味があれば、 コミュニティで近日公開される記事にご期待ください!

0
0 124
記事 Toshihiko Minamoto · 3月 25, 2024 10m read

バージョン 2023.3(InterSystems IRIS for Health)の新機能は、FHIR プロファイル基準の検証を実行する機能です。

(*)

この記事では、この機能の基本的な概要を説明します。

FHIR が重要な場合は、この新機能を絶対にお試しになることをお勧めします。このままお読みください。

 

背景情報

FHIR 規格は、$validate という演算を定義します。 この演算は、リソースを検証する API を提供することを意図しています。

FHIR Validation に関する概要を理解するには、こちらの FHIR ドキュメントをご覧ください。

また、Global Summit 2023 での私の「Performing Advanced FHIR Validation」セッションもご覧ください。最初の方で、様々な種類の検証に関する情報を提供しています。

この検証の一部は、特定のプロファイルに対する検証です。 プロファイリングについてはこちらをご覧ください。

簡単な例として、Patient Resource の基本的な FHIR 定義では、識別子の基数を '0..*' として定義します。つまり、Patient には識別子が何もなく(ゼロ)、それでも有効であるということです。 しかし、US Core Patient Profile は、'1..*' の帰趨を定義しています。つまり、Patient に識別子がない場合、有効ではないということになります。

別の例では、上記の US Core Patient の例に従うと、race や birthsex などの拡張が使用されることがあります。

FHIR Profiling についての詳細は、Global Summit 2022 で @Patrick Jamieson が講演した 「Using FHIR Shorthand」セッションをご覧ください。Pat が FSH(FHIR の略)の使用について説明していますが、Profiling の一般的なトピックの説明から始まっています。

以前のバージョンでは、FHIR Server はこの種(プロファイルベース)の検証をサポートしていませんでしたが、最新バージョン(2023.3)からはサポートされています。

使用方法

ドキュメントには、プロファイルベースの検証に $validate を呼び出す方法についてのセクションが含まれています。

$validate 演算を呼び出す基本的な方法には 2 つあります。

クエリ URL でのプロファイリング

1 つ目は、Request Body の Resource と URL パラメーターとしてのプロファイルを含めた POST 送信です。

たとえば、Postman では:

または curl を使用(プロファイル URL パラメーターの値のスラッシュのエンコーディングに注意してください。Postman によって処理されます):

 curl --location 'http://fhirserver/endpoint/Patient/$validate?profile=http%3A%2F%2Fhl7.org%2Ffhir%2Fus%2Fcore%2FStructureDefinition%2Fus-core-patient' --header 'Content-Type: application/fhir+json' --header 'Accept: application/fhir+json' --header 'Authorization: Basic U3VwZXJVc2VyOnN5cw==' --data "@data.json"

上記で参照される data.json には、例としてこの有効な US Core Patient が含まれています。

{
  "resourceType" : "Patient",
  "id" : "example",
  "meta" : {
    "profile" : ["http://hl7.org/fhir/us/core/StructureDefinition/us-core-patient|7.0.0-ballot"]
  },
  "text" : {
    "status" : "generated",
    "div" : "<div xmlns=\"http://www.w3.org/1999/xhtml\"><p style=\"border: 1px #661aff solid; background-color: #e6e6ff; padding: 10px;\"></div>"
  },
  "extension" : [{
    "extension" : [{
      "url" : "ombCategory",
      "valueCoding" : {
        "system" : "urn:oid:2.16.840.1.113883.6.238",
        "code" : "2106-3",
        "display" : "White"
      }
    },
    {
      "url" : "ombCategory",
      "valueCoding" : {
        "system" : "urn:oid:2.16.840.1.113883.6.238",
        "code" : "1002-5",
        "display" : "American Indian or Alaska Native"
      }
    },
    {
      "url" : "ombCategory",
      "valueCoding" : {
        "system" : "urn:oid:2.16.840.1.113883.6.238",
        "code" : "2028-9",
        "display" : "Asian"
      }
    },
    {
      "url" : "detailed",
      "valueCoding" : {
        "system" : "urn:oid:2.16.840.1.113883.6.238",
        "code" : "1586-7",
        "display" : "Shoshone"
      }
    },
    {
      "url" : "detailed",
      "valueCoding" : {
        "system" : "urn:oid:2.16.840.1.113883.6.238",
        "code" : "2036-2",
        "display" : "Filipino"
      }
    },
    {
      "url" : "text",
      "valueString" : "Mixed"
    }],
    "url" : "http://hl7.org/fhir/us/core/StructureDefinition/us-core-race"
  },
  {
    "extension" : [{
      "url" : "ombCategory",
      "valueCoding" : {
        "system" : "urn:oid:2.16.840.1.113883.6.238",
        "code" : "2135-2",
        "display" : "Hispanic or Latino"
      }
    },
    {
      "url" : "detailed",
      "valueCoding" : {
        "system" : "urn:oid:2.16.840.1.113883.6.238",
        "code" : "2184-0",
        "display" : "Dominican"
      }
    },
    {
      "url" : "detailed",
      "valueCoding" : {
        "system" : "urn:oid:2.16.840.1.113883.6.238",
        "code" : "2148-5",
        "display" : "Mexican"
      }
    },
    {
      "url" : "text",
      "valueString" : "Hispanic or Latino"
    }],
    "url" : "http://hl7.org/fhir/us/core/StructureDefinition/us-core-ethnicity"
  },
  {
    "url" : "http://hl7.org/fhir/us/core/StructureDefinition/us-core-birthsex",
    "valueCode" : "F"
  }
  ],
  "identifier" : [{
    "use" : "usual",
    "type" : {
      "coding" : [{
        "system" : "http://terminology.hl7.org/CodeSystem/v2-0203",
        "code" : "MR",
        "display" : "Medical Record Number"
      }],
      "text" : "Medical Record Number"
    },
    "system" : "http://hospital.smarthealthit.org",
    "value" : "1032702"
  }],
  "active" : true,
  "name" : [{
    "use" : "old",
    "family" : "Shaw",
    "given" : ["Amy",
    "V."],
    "period" : {
      "start" : "2016-12-06",
      "end" : "2020-07-22"
    }
  },
  {
    "family" : "Baxter",
    "given" : ["Amy",
    "V."],
    "suffix" : ["PharmD"],
    "period" : {
      "start" : "2020-07-22"
    }
  }],
  "telecom" : [{
    "system" : "phone",
    "value" : "555-555-5555",
    "use" : "home"
  },
  {
    "system" : "email",
    "value" : "amy.shaw@example.com"
  }],
  "gender" : "female",
  "birthDate" : "1987-02-20",
  "address" : [{
    "use" : "old",
    "line" : ["49 MEADOW ST"],
    "city" : "MOUNDS",
    "state" : "OK",
    "postalCode" : "74047",
    "country" : "US",
    "period" : {
      "start" : "2016-12-06",
      "end" : "2020-07-22"
    }
  },
  {
    "line" : ["183 MOUNTAIN VIEW ST"],
    "city" : "MOUNDS",
    "state" : "OK",
    "postalCode" : "74048",
    "country" : "US",
    "period" : {
      "start" : "2020-07-22"
    }
  }]
}

この演算のリソースは OperationOutcome Resource です。

Resource が有効(上記のとおり)である場合、この種のレスポンスが得られます。

{
    "resourceType": "OperationOutcome",
    "issue": [
        {
            "severity": "information",
            "code": "informational",
            "details": {
                "text": "All OK"
            }
        }
    ]
}

ただし、例えば上記の Resource から識別子を省略すると、この OperationOutcome が得られます。

{
    "resourceType": "OperationOutcome",
    "issue": [
        {
            "severity": "error",
            "code": "invariant",
            "details": {
                "text": "generated-us-core-patient-1: Constraint violation: identifier.count() >= 1 and identifier.all(system.exists() and value.exists())"
            },
            "diagnostics": "Caused by: [[expression: identifier.count() >= 1, result: false, location: Patient]]",
            "expression": [
                "Patient"
            ]
        }
    ]
}

クエリ本文でのプロファイリング

データを $validate に送信するもう 1 つの方法は、Parameters 配列内のリソースをプロファイルやその他のオプションとともに指定して POST 送信することです。

Postman では、これは以下のようになります。

curl を使用した場合:

curl --location 'http://fhirserver/endpoint/Patient/$validate' --header 'Content-Type: application/fhir+json' --header 'Accept: application/fhir+json' --header 'Authorization: Basic U3VwZXJVc2VyOnN5cw==' --data "@data.json"

URL にはプロファイルは含まれませんが、ボディのペイロード(または上記の例の data.json)は以下のようになります。

{
    "resourceType": "Parameters",
    "parameter": [
        {
            "name": "mode",
            "valueString": "profile"
        },
        {
            "name": "profile",
            "valueUri": "http://hl7.org/fhir/us/core/StructureDefinition/us-core-patient"
        },
        {
            "name": "resource",
            "resource": {
                "resourceType": "Patient"
                
               
            }
        }
    ]
}

実際の Patient Resource は前の例と同じであるため除外しました。

ただし、ここで異なるのは、mode パラメーター要素と profile パラメーター要素であり、リソースは「resource」という独自のパラメーター要素内に含まれています。

ID が URL のどこに含まれるかなど(たとえば、更新または削除を検証するため)、mode のその他のオプションについては、上記で参照したドキュメントをご覧ください。

便宜上、上記のサンプルリクエストなどの Postman コレクションを含む単純な Open Exchange パッケージを作成しました。

コードを使用

標準 REST API 経由で $validate 演算を呼び出す代わりに、ユースケースが適切であれば、内部的にクラスメソッドを呼び出すこともできます。

既存の HS.FHIRServer.Util.ResourceValidator:ValidateResource() メソッド(こちらのドキュメントでも説明)と同様に、ValidateAgainstProfile() という新しいメソッドも追加されており、それを利用できます。

 

範囲

現在(v2023.3)では、この種の検証(プロファイル基準の検証)は $validate 演算の一部としてのみ行われ、Resource の作成や更新時には行われないことに注意しておくことが重要です。 そこでは、より「基本的な」検証が行われます。 必要であれば、より「高度な」プロファイル基準の検証を使って、POST または PUT される前に Resouce を実行することができます。

別のオプションも、今後のバージョンで提供される可能性があります。

セットアップに関する注意事項

一般に、FHIR Server がほとんどの Profile Validator セットアップを処理します。

確認が必要なのは、サポートされている Java 11 JDK がインストールされていることです(現在、Oracle のものか OpenJDK のもの)。

詳細は、Profile Validation Server の構成に関するドキュメントをご覧ください。

基本的に、Validator JAR を実行するために、外部言語(Java)サーバーが実行中であることが確認されています(JAR ファイルはインストールフォルダの dev/fhir/java にあります。ちなみに、logs フォルダを覗くと、以下のような警告が表示されます:

CodeSystem-account-status.json : Expected: JsonArray but found: OBJECT for element: identifier

気にする必要はありません。 Validator はデフォルトで多数のプロファイルを読み込むものであり、その一部にはフォーマットエラーがあります)。

つまり、外部言語サーバーのリストを見ると、以下のようなものを確認できます。

Validator がプロファイルに対して検証する必要がある場合、初めてプロファイルをロードする必要があることに注意してください。そのため、パフォーマンスを向上させるために、HS.FHIRServer.Installer:InitalizeProfileValidator() メソッドを呼び出すことができます。

do##class(HS.FHIRServer.Installer).InitializeProfileValidator()

これについても上記で参照したドキュメントには、Validator の構成に関して説明されています。

実際、この呼び出しをインスタンスの %ZSTART 起動ルーチンに含めることもできます。

また、これについても関連するクラスリファレンスで説明されています。

このメソッドは、検証操作中にプロファイルを読み込むことによるパフォーマンスへの影響がないように、インスタンスまたは外部言語サーバーの再起動後に呼び出すことが推奨されています。

今後の予定

今後のバージョンでは、Validator 内と Validator 周りにより多くの機能を提供する予定です。

ただし、例えば現時点でも、外部用語サーバーを使った検証(LOINC コードなど)を実行する場合、別のアプローチを使用することができます。1 つは、前述の Global Summit セッションで説明と実践が行われている方法で、同僚の @Dmitry Zasypkin のサンプル(Open Exchange で提供)に基づくものです。

謝辞

この新機能を調べながらこの記事を準備するにあたって貴重な情報を提供してい頂いた @Kimberly Dunn にお礼申し上げます。

(*)Microsoft Bing の DALL-E 3 を使用して上記の画像を作成してくれた画像クリエーターに感謝しています。

0
1 207
お知らせ Mihoko Iijima · 1月 15, 2024

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

InterSystems FHIR とデジタルヘルスの相互運用性コンテスト のテクノロジーボーナス詳細が決定しましたのでお知らせします。

  • InterSystems FHIR の使用 - 3
  • InterSystems FHIR SQL Builder の使用 - 3
  • デジタルヘルスの Interoperability(相互運用性) - 4
  • LLM AI または LangChain の利用: Chat GPT、Bard、その他 - 3
  • Embedded Python - 2
  • Questionnaireの利用 - 2
  • IRIS For Health Instruqt Interoperability アンケートのへの回答 - 1
  • Docker コンテナの利用 - 2 
  • IPM Package によるデプロイ - 2
  • オンラインデモ - 2
  • InterSystems Community Idea の実装 - 4
  • InterSystems FHIR server のBugを見つける - 2
  • InterSystems Interoperability のBugを見つける - 2
  • コミュニティ(USコミュニティ)に記事を投稿する(最初の記事)- 2
  • コミュニティ(USコミュニティ)に2つ目の記事を投稿する - 1
  • 初めて参加した方 - 3
  • YouTubeにビデオを公開 - 3

詳細は以下の通りです。<--break->

0
0 115
記事 Kosaku Ikeda · 10月 2, 2023 8m read

皆さまこんにちは。
IRIS for Healthを用いてFHIRの開発に携わっている者です。

FHIRリポジトリの導入を検討している方々に向けて、足がかり的な記事になればと思い投稿致します。

<アジェンダ>
■IISでの環境構築
■POSTMANを利用しないリソースへのデータアクセス
■Patientリソースの作成について
■FHIRリポジトリを使ってみての感想

■おまけEmbedded Pythonを使って、サンプルファイルからFHIRリソースへアクセスする方法

3
1 598
記事 Toshihiko Minamoto · 10月 26, 2023 4m read

問題

あわただしい臨床環境では迅速な意思決定が重要であるため、文書保管とシステムへのアクセスが合理化されていなければいくつもの障害を生み出します。 文書の保管ソリューションは存在しますが(FHIR など)、それらの文書内で特定の患者データに有意にアクセスして効果的に検索するのは、重大な課題となる可能性があります。

動機

AI により、文書の検索が非常に強力になりました。 ChromaLangchain のようなオープンソースツールを使用して、ベクトル埋め込みを保存して使用し、生成 AI API 全体でクエリを実行することで、ドキュメント上での質疑応答がかつてないほど簡単になっています。 より献身的に取り組む組織は、既存のドキュメントにインデックスを作成し、エンタープライズ用に微調整されたバージョンの GPT を構築しています。 GPT の現状に関する Andrej Karpathy の講演では、このトピックに関する素晴らしい概要が提供されています。

このプロジェクトは、医療関係者が文書を操作するあらゆるタッチポイントにおいて発生する摩擦を緩和する試みです。 医療関係者が情報を保管し、必要な情報を難なく検索できるように、入力と処理から保管と検索まで、IRIS FHIR と AI を活用しました。

ソリューション

医療関係者が音声メモを記録できるフルスタックのウェブアプリを構築しました。 これらのメモは、Open AI を使って文字起こしされ、要約されてから FHIR サーバーに保管されます。 保管されたドキュメントは、インデックス作成されてから、セマンティック検索で使用できるようになります。  

デモ動画

主な機能

  1. ウェブアプリ - 患者、観察、遭遇に関する診療情報を表示します。 これは Vue.js で構築されています。
  2. 音声データの文字起こし - Open AI Whisper API を使って、録音を正確なテキストに文字起こしします。
  3. テキストの要約 - 文字起こしされた内容を必要なフォーマットで要約してタイトルが付けられます。 症状、診断などの具体的なセクションなどです。 これは、text-da-vinci-003 を使った Open AI テキスト補完 API で行われます。
  4. ドキュメントの保管 - 要約されたドキュメントは、DocumentReference アーティファクトを使って FHIR に保管されます。
  5. セマンティックドキュメント検索 - 保管されたドキュメントはインデックス作成されて、チャンクとして Chroma に保管されます。 これは、Langchain を使用して検索スペースを制限してセマンティック検索に GPT トークンを控えめに使用するために使用されます。 現時点では、使用できるドキュメント数が少ないため、検索時にドキュメントを読み込んでいますが、 非同期的にバックグラウンドでインデックス作成するように変更することが可能です。
  6. ドキュメントのエクスポート - 最後に、ドキュメントを Google Docs に、その他のデータを Google Sheets にエクスポートするオプションがあります。 ユーザーは他の医療関係者や患者とのコラボレーションとやり取りを簡単に行えるように、OAuth を使って特定のアカウントにログインし、ドキュメントをエクスポートすることができます。

試してみましょう

次の GitHub リンクからプロジェクトリポジトリをクローンします: https://github.com/ikram-shah/iris-fhir-transcribe-summarize-export。 提供された指示に従って、プロジェクトをローカルマシン上にセットアップしてください。 期待される動作が得られない場合は、お知らせください。

ご意見とフィードバック

現在使用できる高度言語モデルと大量のデータを合わせることで、ヘルスケア分野の特に文書管理の領域に革命を起こす大きな可能性があります。 以下に、ご意見やフィードバックをお寄せください。 このプロジェクトの背後にある技術的な情報について、さらに多くの記事を投稿する予定です。

このプロジェクトに期待できると思われる場合は、Grand Prix コンテストでこのアプリに投票してください!

0
0 184
記事 Mihoko Iijima · 3月 28, 2021 4m read

皆さんこんにちは!

この記事でご紹介する「開発環境テンプレート」は、最近 医療 IT で注目を集めている 医療情報交換標準規格  FHIRを体験できるコンテナです。

一式は、こちら(https://github.com/Intersystems-jp/IRIS-FHIR-Oximeter-Template)で公開しています。

コンテナビルド時、InterSystems IRIS for Health コミュニティエディションを使用した FHIR R4 リソースリポジトリの用意と、REST 用エンドポイントが用意されます。

作成されるエンドポイントに対して、REST クライアントから直接 FHIR R4 リソースリポジトリへアクセスすることもできますし(使用例はこちらビデオの解説はこちら)、Patient リソースと Observation リソースの操作体験が行えるサンプル Web アプリケーション(使用例はこちらビデオの解説はこちら)もコンテナに含まれていますので、お好みの方法で操作を体験できます。

この開発環境テンプレートでは、さらに! FHIR  サーバーサイドアプリケーション(=プロダクション)のサンプルも用意しています(図例はこちら)。

プロダクションは、新生児につけたパルスオキシメーターの測定値が定期的に送信されてくることを仮定して作られています。

2
1 1704
記事 Mihoko Iijima · 6月 12, 2023 2m read

FHIRドキュメント(診療情報提供書や退院時サマリ―など)をFHIRリポジトリにPOSTする場合、

エンドポイント/Bundle

上記URLでPOSTできます。(以下の例では、IRIS for Healthに用意したFHIRリポジトリを使用しています。)

GET要求で確認してみます。

登録できたことを確認できました。

FHIRリポジトリに登録したFHIRドキュメントですが、文書番号を指定してGETできると便利なのですが、現時点(バージョン2023.1)のIRIS for HealthのFHIRリポジトリでは、FHIR標準仕様にあるBundle の SearchParameter :composition について未対応のため、Composition.identifier を指定した Bundleリソースに対する GET要求が行えません。

そこで回避策として、Bundle登録時 Composition.identifier.value に設定している文書番号を Bundle.identifier.value にも設定しPOSTします。こうすることで、Bundle の Search Parameter:identifier に文書番号を指定でき、対象となるBundleリソースをGETできます。

文書例:(長いので途中までの抜粋です)

0
0 360
お知らせ Mihoko Iijima · 6月 12, 2023

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

InterSystems グランプリコンテスト2023 では、InterSystems IRIS data platform を使用する機能であればどんな内容でもご応募いただけます。

以下の機能を含めた場合、ボーナスポイントを獲得できます。

詳細は以下の通りです。

  • LLM AI や LangChain の使用:Chat GPT、Bard など - 6ポイント
  • InterSystems FHIR SQL Builder- 5ポイント
  • InterSystems FHIR - 3ポイント
  • IntegratedML - 4ポイント
  • Native API - 3ポイント
  • Embedded Python - 4ポイント
  • Interoperability - 3ポイント
  • Production EXtension(PEX) - 2ポイント
  • Adaptive Analytics (AtScale) のキューブの利用 - 3ポイント
  • Tableau, PowerBI, Logi の利用 - 3ポイント
  • InterSystems IRIS BI - 3ポイント
  • Docker container の利用 - 2ポイント 
  • ZPM Package によるデプロイ - 2ポイント
  • オンラインデモ - 2ポイント
  • ユニットテスト - 2ポイント
  • InterSystems Community Idea に投稿された内容の実装 - 4ポイント
  • コミュニティ(USコミュニティ)に記事を投稿する(最初の記事) - 2ポイント
  • コミュニティ(USコミュニティ)に2つ目の記事を投稿する - 1ポイント
  • Code Qualityをパスする - 1ポイント
  • はじめてチャレンジされた方 - 3ポイント
  • YouTubeにビデオを公開- 3ポイント
0
0 107
記事 Mihoko Iijima · 6月 11, 2023 2m read

IRIS for HealthのFHIRリポジトリには、「条件付き削除結果の最大数」がデフォルトで3件に設定されています。

そのため、条件指定のDELETE要求で4件以上が対象となる場合、以下のエラーが発生します。

例えば、あるcodeで条件指定したリソースが5件あるとします。

これをDELETE要求に変えて実行すると、以下のようにHTTPステータス412が戻り、「Conditional delete search found more than maximum allowed number of 3 results」のエラーが発生します。

HTTP応答を確認すると、ConditionalDeleteOverflowのエラーが発生しています。

これは、条件付き削除の最大値が3件で設定されているため、発生しています。

ということで、FHIR Configuration画面を開き、設定を確認します。

管理ポータル > [Health] > ネームスペース選択 > [FHIR Configuration] > [Server Configuration]

対象のエンドポイントを選択すると以下の設定画面が表示されます。

Max Conditional Delete Results の項目に 3 と設定されています。

0
0 171
記事 Mihoko Iijima · 6月 9, 2023 2m read

FHIRリソースをリポジトリから削除するには、対象リソースに対してDELETE要求を使用すればよいのですが、例えば「テスト的に登録していたリソースばかりなので、リポジトリのデータを一括で全消去したい!」という場合の方法をご紹介します。

実行前に、エンドポイントのURLを確認します。

管理ポータル > [Health] > ネームスペース選択 > [FHIR Configuration] > [Server Configuration] で確認できます。

データの全消去を行うには、IRIS for HealthのFHIRサーバ機能で提供されているAPIを使用します。実行のため IRISのターミナルを開く、またはIRISにログインします。

ご参考:HS.FHIRServer.Storage.Json.RepoManagerクラスにあるDeleteService()メソッドを使用して削除します。

WindowsにIRISをインストールされている場合は、タスクバー上のIRISランチャー  をクリックし、ターミナルを選択します。

Windows以外でお試しいただいてる場合は、iris session コマンドでIRISにログインしてください。

※ iris session インスタンス名 (インスタンス名=インストール時に指定した名称)

iris session irishealth
0
1 264
記事 Mihoko Iijima · 6月 8, 2023 3m read

FHIR関連トレーニングの中で複数の方よりいただいたご質問をご紹介していきます。

IRIS for HealthのFHIRリポジトリでは、リソースPOST時のデフォルトの動作としてリポジトリ内でユニークな論理ID(id)を自動的に付与します。

例えば、以下のようなPatientリソースをPOSTした場合

0
0 267
記事 Toshihiko Minamoto · 4月 18, 2023 14m read

今回は、「IRIS for Health Contest」に応募するために、どのような技術を使ってアプリケーションを開発していたのか、その詳細を紹介したいと思います。

  • OpenAPI仕様からのREST API生成
  • APIとWebページを保護する役割ベースのアクセス(RBAC)
  • InterSystems FHIR サーバー

内容

アプリケーション概要

まず、それらの技術に支えられたアプリケーションを簡単に紹介します。

このアプリケーションは、妊娠中の女性が簡単に症状を報告できるように設計されています。このアプリケーションはレスポンシブであるため、モバイルデバイスを使用して症状を簡単に報告することができます。このような症状は、FHIR Observation リソースInterSystems FHIR サーバーを使って記録されます。.

患者と医師は、通常のリレーショナル・テーブルを使用し、患者医師 のFHIRリソースのIDを参照して連携しています。そのため、医師は患者がどのような症状を訴えているのかを確認することもでき、万が一の事態に迅速に対応することができます。

アプリケーションは、IRIS リソース役割を使用して患者/医師を識別し、アクセス権限を制御します。

FHIRリソースは、アプリケーションのフロントエンドで利用可能なREST APIによってアクセスされます。IRIS Interoperability Credentialsに格納されたAPI KEYを使用して、FHIRサーバーへのHTTPS接続が確立されます。

アプリケーションのWebリソースは、IRIS Web Gatewayで扱われます。

一般的なアプリケーションのアーキテクチャ

OpenAPI仕様からのREST API生成

IRISプラットフォームでは、手動またはOpenAPI仕様を介してRESTインターフェースを定義することができます。

OpenAPIを使用することは、デザインファーストのアプローチ、容易な変更追跡、容易な文書化、強力なモデル、設計、モッキング、テストなどのための多くのツールなど、多くの利点があります。

そこで、IRIS REST Servicesを使って、OpenAPI仕様からコードを生成する方法に焦点を当てます。

まず、OpenAPIを使ってAPIを設計する必要があります。今回は、VS Codeの拡張機能であるOpenAPI (Swagger) Editorを使用しました。これは、エンドポイントやその他のOpenAPIリソースをVS Codeで直接作成するのに役立ちます。

VS Code用OpenAPI拡張子

OpenAPI仕様でAPIを設計したら、それをJSONファイルに保存する必要があります。ここでは、このファイルにAPIを保存しています。

これで、IRIS REST Services を使用して API 用のコードを生成する準備が整いました。これには3つのオプションがあります。

この記事では、最後の1つである %REST.API クラスを使用することにします。それでは、IRIS端末を開いて、以下のコードを実行してください。

Set applicationName = "dc.apps.pregsymptracker.restapi"
Set swagger = "/irisrun/repo/src/openapi/pregnancy-symptoms-tracker.json"
ZW ##class(%REST.API).CreateApplication(applicationName, swagger, , .newApplication, .internalError)
ZW newApplication
ZW internalError

OpenApi仕様のJSONファイルの場所は、swaggerパラメータで設定されます。

applicationName パラメータは、IRIS REST Servicesが生成されたコードを格納するパッケージ名です。

REST APIクラスを生成する

3つのクラスが生成されます。

  • spec.cls: OpenAPI仕様のための単なるコンテナです。このクラスは編集しないでください。

  • impl.cls: メソッドの実装を含むメインクラスです。このクラスは、APIロジックを開発するために、自分で編集することを意図しています。ヒント: OpenAPIのメソッドの名前は、必ずIRIS拡張属性 operationId を使って、 ここで のように定義します。この属性を使用しない場合、IRIS はランダムな名前のメソッドを作成します。

  • disp.cls: ディスパッチクラスは、IRIS で REST API を公開するために Web アプリケーションをバインドするクラスです。ヒント: このクラスを表示するには、生成されたアイテムを表示していることを確認します。このクラスを編集することもできますが、あまりお勧めできませんが、IRIS に任せてください。

REST API ディスパッチクラス

最後の2つのパラメータ、 newApplicationinternalError は出力パラメータで、それぞれ API が作成または更新されたかどうか、そして OpenAPI のパースやクラスの生成時に発生した可能性のあるエラーを返すものです。この情報をチェックするために書き出すだけです。

OpenAPI の仕様を更新した場合、コードを更新するために CreateApplication メソッドを再度実行する必要があります。 impl クラスに実装した以前のロジックコードはそのまま残し、IRIS REST Service が修正を行った箇所にはコメントを追加します。

APIとWebページを保護する役割ベースのアクセス(RBAC)

前述したように、このアプリケーションには、患者と医師の2種類のユーザーが存在します。そこで、この2種類のユーザー間でアプリケーションのリソースに対するアクセスルールを設計するために、リソースと役割を使用しました。

ユーザーは役割を与えられ、役割にはリソースへの権限があり、リソースは例えばREST APIのようなシステムリソースにアクセスするために必要であるべきです。

REST APIの安全性確保

IRIS REST Serviceでは、OpenAPIのIRIS拡張子である x-ISC_RequiredResource 属性によって、サービスにアクセスするために必要な権限を指定することができました。この属性は、API全体、または特定のエンドポイントに対して、次のように指定することができます:

    "paths": {
        "/symptom": {
            "post": {
                "operationId": "PostSymptom",
                "x-ISC_RequiredResource": ["AppSymptoms:write"],
                "description": "患者さんが自分の症状を報告するために使用する",
        …
        "/doctor/patients": {
            "get": {
                "operationId": "GetDoctorPatientsList",
                "x-ISC_RequiredResource": ["AppAccessDoctorPatients:read"],
                "description": "現在ログインしている医師の患者を取得する",
        …

OpenAPI仕様でAPIクラスを生成した後 - 前に説明したように , IRIS REST Serviceがx-ISC_RequiredResource制約をdispクラスでどのように実装しているかを見ることができます:

ClassMethod PostSymptom() As %Status
{
    Try {
        Set authorized=0
        Do {
            If '$system.Security.Check("AppSymptoms","write") Quit
            Set authorized=1
        } While 0
        If 'authorized Do ##class(%REST.Impl).%ReportRESTError(..#HTTP403FORBIDDEN,$$$ERROR($$$RESTResource)) Quit
        …
    } Catch (ex) {
        Do ##class(%REST.Impl).%ReportRESTError(..#HTTP500INTERNALSERVERERROR,ex.AsStatus(),$parameter("dc.apps.pregsymptracker.restapi.impl","ExposeServerExceptions"))
    }
    Quit $$$OK
}

RBACを使ったAPIの保護方法については、このページをご覧ください。

Webページの安全性確保

このアプリケーションでは、Web アプリケーションを実装するために CSP ページを使用しました。この技術は、現在の SPA に比べて古いと考えられていますが、それでもまだ利点があります。

例えば、ユーザーがページにアクセスするために、特定の役割を持つことを要求することができます。つまり、REST API のエンドポイントを保護することをまとめると、先に述べたように、アプリケーションに追加のセキュリティ・レイヤーを定義することができるのです。

ユーザがシステムにログインするとき、そのユーザに役割が割り当てられている場合、IRISはそのユーザに役割を割り当てます。このような役割は、CSP コンテキストで $ROLE コンテキスト変数を通してアクセスすることができ、ユーザに割り当てられた特定の役割を要求するために使用することができます。

<!-- patient.csp -->
<script language="cache" method="OnPreHTTP" arguments="" returntype="%Boolean">
Do ##class(dc.apps.pregsymptracker.util.Util).AssertRole("AppPatient")
Return 1
</script>
<!-- doctor.csp -->
<script language="cache" method="OnPreHTTP" arguments="" returntype="%Boolean">
Do ##class(dc.apps.pregsymptracker.util.Util).AssertRole("AppDoctor")
Return 1
</script>
ClassMethod AssertRole(pRole As %String)
{
    If ('$Find($ROLES, pRole)){
        Set %response.Redirect = "NoPrivilegesPage.csp"
    }
}

もし、現在のユーザーが patient.csp ページを評価するときに AppPatient 役割を持っていない場合、IRIS Web サーバはそのユーザーを NoPrivilegesPage.csp ページにリダイレクトし、ユーザーにセキュリティ問題を通知するメッセージを表示します。doctor.cpsページも同様ですが、今度は AppDoctor` 役割が必要です。

この例では、AppPatientAppDoctorの2つの役割を持つことができます。つまり、そのユーザーは患者であると同時に医師でもあり、両方のページにアクセスすることができるのです。

リソースと役割の作成

IRISポータルでリソース, 役割 を作成し、ユーザー に割り当てることができます - これは簡単なことです。しかし、ここではプログラムでそれらを作成する方法を紹介したいと思います:

ClassMethod CreateResources()
{
    Do ..Log("アプリケーションリソースを作成する...")
    Set ns = $NAMESPACE
    Try {
        ZN "%SYS"
        Do $CLASSMETHOD("Security.Resources", "Delete", "AppSymptoms")
        Do $CLASSMETHOD("Security.Resources", "Delete", "AppAccessDoctorPatients")
        $$$TOE(st, $CLASSMETHOD("Security.Resources", "Create", "AppSymptoms", "患者の症状", "RWU", ""))
        $$$TOE(st, $CLASSMETHOD("Security.Resources", "Create", "AppAccessDoctorPatients", "患者のアクセス権", "RWU", ""))
    } Catch(e) {
        ZN ns
        Throw e
    }
    ZN ns
}

ClassMethod CreateRoles()
{
    Do ..Log("アプリケーション役割を作成する...")
    Set ns = $NAMESPACE
    Try {
        ZN "%SYS"
        Do $CLASSMETHOD("Security.Roles", "Delete", "AppPatient")
        Do $CLASSMETHOD("Security.Roles", "Delete", "AppDoctor")
        $$$TOE(st, $CLASSMETHOD("Security.Roles", "Create", "AppPatient", "アプリケーション での患者の役割", "AppSymptoms:RWU", ""))
        $$$TOE(st, $CLASSMETHOD("Security.Roles", "Create", "AppDoctor", "アプリケーション での医師の役割", "AppSymptoms:RWU,AppAccessDoctorPatients:RWU", ""))
    } Catch(e) {
        ZN ns
        Throw e
    }
    ZN ns
}

ClassMethod CreateUsers()
{
    Do ##class(dc.apps.pregsymptracker.util.Setup).Log("サンプルユーザーを作成する...")

    //ある患者
    &SQL(drop user MarySmith)
    &SQL(create user MarySmith identified by 'marysmith')
    &SQL(grant %DB_IRISAPP, %DB_IRISAPPSECONDARY, AppPatient to MarySmith)
    &SQL(grant select on schema dc_apps_pregsymptracker_data to MarySmith)

    //他患者
    &SQL(drop user SuzieMartinez)
    &SQL(create user SuzieMartinez identified by 'suziemartinez')
    &SQL(grant %DB_IRISAPP, %DB_IRISAPPSECONDARY, AppPatient to SuzieMartinez)
    &SQL(grant select on schema dc_apps_pregsymptracker_data to SuzieMartinez)

    //ある医師
    &SQL(drop user PeterMorgan)
    &SQL(create user PeterMorgan identified by 'petermorgan')
    &SQL(grant %DB_IRISAPP, %DB_IRISAPPSECONDARY, AppDoctor to PeterMorgan)
    &SQL(grant select on schema dc_apps_pregsymptracker_data to PeterMorgan)

    // 患者である医師
    &SQL(drop user AnneJackson)
    &SQL(create user AnneJackson identified by 'annejackson')
    &SQL(grant %DB_IRISAPP, %DB_IRISAPPSECONDARY, AppDoctor, AppPatient to AnneJackson)
    &SQL(grant select on schema dc_apps_pregsymptracker_data to AnneJackson)
}

InterSystems FHIR サーバー

InterSystems FHIR サーバー は、IRIS for Health と同じように、FHIR リソースへのアクセスをクラウド上で提供するサービスです。

FHIR ServerではOAuth2が可能で、SMART on FHIR JavaScript Library などのライブラリを使ってアプリケーションから直接FHIRリソースにアクセスできますが、このアプリケーションでは、FHIR Serverをメインデータリポジトリとして使用しながら、IRISにローカルに保存されているメタデータで制御するハイブリッドアプローチを選択しました。

そこで、バックエンドがFHIR ServerでFHIRトランザクションを実行するために使用するFHIRクライアントを作成しました。このクライアントは、サーバーが生成したAPI KEYを使用して、FHIR ServerへのHTTPSコールを実行するために、%Net.HttpRequestを使用して実装されています。

これはHTTPクライアントのコードで、 `` を使って基本的なHTTP動詞を実装しています。

Class dc.apps.pregsymptracker.restapi.HTTPClient Extends %RegisteredObject
{

Property Request As %Net.HttpRequest;

Property Server As %String;

Property Port As %String;

Property UseHTTPS As %Boolean;

Property SSLConfig As %String;

Property APIKeyCred As %String;

Method CreateRequest()
{
    Set ..Request = ##class(%Net.HttpRequest).%New()
    Set ..Request.Server = ..Server
    Set ..Request.Port = ..Port
    Set ..Request.Https = ..UseHTTPS
    If (..UseHTTPS) {
        Do ..Request.SSLConfigurationSet(..SSLConfig)
    }
}

Method SetHeaders(headers As %DynamicObject)
{
    Set headersIt = headers.%GetIterator()
    While (headersIt.%GetNext(.headerName, .headerValue)) {
        Do ..Request.SetHeader(headerName, headerValue)
    }
}

Method GetApiKeyFromEnsCredentials() As %String
{
    Set apiKeyCred = ..APIKeyCred
    $$$TOE(st, ##class(Ens.Config.Credentials).GetCredentialsObj(.apiKeyCredObj, "", "Ens.Config.Credentials", apiKeyCred))
    Return apiKeyCredObj.Password
}

Method HTTPGet(pPath As %String) As %Net.HttpResponse
{
    Do ..CreateRequest()
    $$$TOE(st, ..Request.Get(pPath))
    Set response = ..Request.HttpResponse
    Return response
}

Method HTTPPost(pPath As %String, pBody As %DynamicObject) As %Net.HttpResponse
{
    Do ..CreateRequest()
    Do ..Request.EntityBody.Clear()
    Do ..Request.EntityBody.Write(pBody.%ToJSON())
    $$$TOE(st, ..Request.Post(pPath))
    Set response = ..Request.HttpResponse
    Return response
}

Method HTTPPut(pPath As %String, pBody As %DynamicObject) As %Net.HttpResponse
{
    Do ..CreateRequest()
    Do ..Request.EntityBody.Clear()
    Do ..Request.EntityBody.Write(pBody.%ToJSON())
    $$$TOE(st, ..Request.Put(pPath))
    Set response = ..Request.HttpResponse
    Return response
}

Method HTTPDelete(pPath As %String) As %Net.HttpResponse
{
    Do ..CreateRequest()
    $$$TOE(st, ..Request.Delete(pPath))
    Set response = ..Request.HttpResponse
    Return response
}

}

そしてこれがFHIRクライアントのコードで、HTTPクライアントを拡張し、CreateRequestメソッドをオーバーライドしてHTTPコールにFHIRサーバーのAPIキーを自動的に付加しています。

Class dc.apps.pregsymptracker.restapi.FHIRaaSClient Extends dc.apps.pregsymptracker.restapi.HTTPClient
{

Method CreateRequest()
{
    Do ##super()
    Do ..SetHeaders({
        "x-api-key" : (..GetApiKeyFromEnsCredentials())
    })
}

}
0
0 149
お知らせ Maki Hashizawa · 1月 18, 2023

 

インタ―システムズでは、医療ITソリューション・サービスを提供される方々向けに、医療DXの推進やデータ活用を支援するシステムの要件、求められる姿について考察するオンラインセミナーをシリーズで開催しております。ソリューション開発編の第2段として、今回は「相互運用性/FHIR®の実装」をテーマに、下記の通り、開催する運びとなりました。 是非、ご参加いただきたくご案内致します。

【開催概要】

日時:2023年2月9日(木)13:00 - 14:30 (予定)

参加:無料(事前登録制)

対象:医療情報ステムベンダー、医療機器メーカー、医療向けサービスプロバイダーの事業企画・開発の皆様

主催:インタ―システムズジャパン株式会社

お申込み・詳細はこちらから

【プログラム】

13:00~13:05 開会挨拶

インターシステムズジャパン株式会社
カントリーマネージャー 林 雅音

13:05~13:45「高度な医療DXを実現するための情報基盤とは」

宮崎大学医学部
名誉教授 荒木 賢二 様

13:50 - 14:25「HL7® FHIR® × InterSystems IRIS for Health」

インターシステムズジャパン株式会社
古薗 知子

13:25 - 14:30 閉会挨拶

※ プログラムは、変更の場合がございます。最新の情報はWebサイトでご確認ください。

詳細・お申込みはこちらをご覧ください。

0
0 149
記事 Mihoko Iijima · 10月 23, 2022 24m read

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

IRIS の FHIR リポジトリは、HL7 FHIR 標準プロファイルに対する検証をサポートしていますが、カスタムプロファイルに対する検証は、まだサポートできていません(将来のリリースバージョンで対応予定です)。

カスタムプロファイルの Search Parameter の追加はサポートしています!詳しくは、「動画:FHIR プロファイル」をご参照ください。

この記事では、IRIS の FHIR リポジトリに対して、カスタムプロファイルの検証を行う方法についてご紹介します。

方法としては、HL7 FHIR が提供している FHIR Validator で提供しているJARファイル(validator_cli.jar)を利用します。

利用のためには、FHIR リソースの検証のタイミングで、JARファイルの検証を実行するようにFHIRサーバサイドの動作をカスタマイズする必要があります。

ということで、大まかな準備は以下の通りです。

1) Java用外部サーバ(External Language Servers)の開始

IRISから FHIR Validator で提供しているJARファイル(validator_cli.jar)を利用するため、Java用外部サーバを開始します。

2) 検証ロジックを加工する

0
1 1497
お知らせ Maki Hashizawa · 10月 18, 2022

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

2022年7月に開催された国際モダンホスピタルショウ、インタ―システムズブースに設けたミニシアターで行ったインタ―システムズFHIRサポートの新しい機能を紹介したプレゼンテーション動画ごご紹介致します。

よろしければ、ご覧ください。

「FHIRリソースデータを分析に。~FHIR SQL Builderのご紹介~

0
0 140
お知らせ Mihoko Iijima · 10月 11, 2022

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

次のコンテストの詳細が決定しましたのでお知らせします📣

今回は、FHIRの知識を共有するためのコンテストを企画しています。

🏆 InterSystems IRIS for Health コンテスト: FHIR for Women's Health 🏆

InterSystems FHIR または、InterSystems Healthcare Interoperability を使用したアプリケーションを作成してご応募ください。

期間: 2022年11月14日~12月4日

賞金: $13,500!

>> 応募はこちらから! <<

0
0 181
お知らせ Toshihiko Minamoto · 8月 5, 2022

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

コミュニティウェビナーの再開をお知らせします!
​​​​​

今回は、@Ron.Sweeney1582による「Scaling InterSystems FHIR Server on Amazon Web Services with ECP」というウェビナーに皆さんをご招待します。

このウェビナーでは、Amazon Web Services 上の InterSystems FHIR Server を Enterprise Cache Protocol (ECP) を使ってスケールアウトする技術的な詳細、デモ、ベンチマークを紹介します。

日時: 8月18日(木)午前8時(東部標準時)、午後9時(日本標準時)
👨‍🏫 スピーカー: @sween, Integration Required社 フルスタックアーキテクト


0
0 308