Peter, GitHub
Active open source contributor
Speaker
COSCUP、MOPCON......
An engineer
DevOps
Back-end
System Architecture Researching
Web Application Security
PHP, Python and JavaScript
Industrial Technology Research Institute
Smart Grid Technology (2017~2021)
Institute for Information Industry
Database, Data platform architecture (2021~)
Fast Healthcare Interoperability Resources
FHIR,縮寫讀音同「Fire」
此標準在2011年由HL7(Health Level Seven)發表
FHIR整合前幾代國際醫療資料交換標準優點
強化資料互通性
不僅支援更多格式,還更遵從HTTP協定
支援行動裝置和資源受限系統以及緊跟行動化趨勢
實作指引
Implementation guide(IG)
不同國家可以參考HL7 FHIR實作指引
發展出符合自己國家需要的核心實作指引
可視為互通規格書,Specification
操作規範書
Profile,StructureDefinition
可以視為實作規格規範,資料結構定義,資料表綱要
實作是由一系列Resource(資源物件)組成
使用者可輕鬆複製、微調這些Resource
解決醫療實務上和管理上問題
Resource就像是資料庫的資料表中的資料
或是想像成一個可組織、用來記錄資料的Excel工作表
可以運行Python 3.8以上的Python程式語言環境
以Ubuntu 22.04上進行示範
安裝fhir-data-generator套件
相容於部分臺灣核心實作指引的Resource
產生Resource的資料欄位已經物件導向化
僅需呼叫Object定義方法即可產生Resource區塊
內建支援簡易HTTP client進行發送請求(Beta版本)
未來會參與聯測進行更進一步測試資料互通性
套件有完整Released log
使用pytest進行完整單元測試
$ sudo apt-get update
$ sudo apt-get install -y python3-pip
$ pip3 install -U fhir-data-generator
# Upgrade the existed fhir-data-generator
$ pip3 install -U --upgrade fhir-data-generator
$ python3
Python 3.10.12 (main, Jul 29 2024, 16:56:48) [GCC 11.4.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> from fhir_data_generator import Patient
>>>
從範例資料學習如何建立Patient Resource
參考Patient resource範例與說明
以TW Core IG 0.2.3版本做為參考
import json
import uuid
from fhir_data_generator import Patient
patient = Patient(str(uuid.uuid4()))
patient.set_profile_url('https://fhir.server/path/to/profile/path')
identifier1 = {
'use': 'official',
'system': 'http://www.boca.gov.tw',
'type': {
'coding': [
{
'system': 'http://www.boca.gov.tw',
'code': 'PPN',
'display': 'Passport number',
},
],
},
'value': '262344368',
}
identifier2 = {
'use': 'official',
'system': 'http://terminology.hl7.org/CodeSystem/v2-0203',
'type': {
'coding': [
{
'system': 'http://terminology.hl7.org/CodeSystem/v2-0203',
'code': 'MR',
'display': 'Medical record number',
},
]
},
'value': '123456789',
}
managing_organization = 'Organization/MITW.ForIdentifier'
name = {
'use': 'official',
'text': '李小明',
'family': '李',
'given': ['小明'],
}
gender = 'male'
birth_date = '2023-12-23'
addresses = [
{
'use': 'home',
'text': '105台北市松山區民生東路四段133號',
},
{
'country': 'TW',
},
]
scenario = 1
telecom = {
'use': 'home',
'system': 'phone',
'value': '0905285349',
}
patient.set_identifier(identifier1)
patient.set_identifier(identifier2)
patient.set_active(True)
patient.set_managing_organization(managing_organization)
patient.set_name(name)
patient.set_gender(gender)
patient.set_birth_date(birth_date)
patient.set_address(addresses[0])
patient.set_address(addresses[1])
patient.set_telecom(telecom)
# Retrieving the Patient resource dict
patient_json_dict = patient.create(1)
print(patient_json_dict)
# Retrieve the Patient resource JSON string
print(json.dumps(patient_json_dict))
執行patient_example1.py
從範例資料學習如何建立Patient Resource
參考Patient resource範例與說明
以TW Core IG 0.2.3版本做為參考
import json
import uuid
from fhir_data_generator import Patient
Patient = Patient(str(uuid.uuid4()))
patient.set_profile_url('https://fhir.server/path/to/profile/path')
identifier1 = {
'use': 'official',
'system': 'http://www.boca.gov.tw',
'type': {
'coding': [
{
'system': 'http://www.boca.gov.tw',
'code': 'PPN',
'display': 'Passport number',
},
],
},
'value': '262344368',
}
identifier2 = {
'use': 'official',
'system': 'http://terminology.hl7.org/CodeSystem/v2-0203',
'type': {
'coding': [
{
'system': 'http://terminology.hl7.org/CodeSystem/v2-0203',
'code': 'MR',
'display': 'Medical record number',
},
]
},
'value': '123456789',
}
patient.set_identifier(identifier1)
patient.set_identifier(identifier2)
patient.set_active(True)
managing_organization = 'Organization/MITW.ForIdentifier'
patient.set_managing_organization(managing_organization)
names = [
{
'use': 'official',
'family': 'Li',
'given': [
'Peter'
],
'text': 'Peter Li',
},
]
patient.set_name(names[0])
gender = 'male'
patient.set_gender(gender)
birth_date = '2023-12-23'
patient.set_birth_date(birth_date)
addresses = [
{
'use': 'home',
'text': '105台北市松山區民生東路四段133號',
},
{
'country': 'TW',
},
]
patient.set_address(addresses[0])
patient.set_address(addresses[1])
telecom = {
'use': 'home',
'system': 'phone',
'value': '0905285349',
}
patient.set_telecom(telecom)
communications = [
{
'language': {
'coding': [
{
'system': 'http://terminology.hl7.org/CodeSystem/v3-ietf3066',
'code': 'en-US',
},
],
'text': 'English (US)',
},
},
]
patient.set_communication(communications[0])
scenario = 2
# Retrieving the Patient resource dict
patient_json_dict = patient.create(scenario)
print(patient_json_dict)
# Retrieve the Patient resource JSON string
print(json.dumps(patient_json_dict))
執行patient_example2.py
從範例資料學習如何建立Observation Resource
以TW Core IG 0.2.3版本做為參考
import json
import uuid
from fhir_data_generator import Observation
observation = Observation(str(uuid.uuid4()))
profile_urls = ['https://fhir.server/path/to/profile/path']
observation.set_profile_urls(profile_urls)
status = 'final'
observation.set_status(status)
category_coding = [{
'system': 'http://terminology.hl7.org/CodeSystem/observation-category',
'code': 'vital-signs',
'display': 'Vital Signs',
}]
observation.set_category_coding(category_coding)
code_coding = [{
'system': 'https://twcore.mohw.gov.tw/ig/twcore/CodeSystem/loinc-tw',
'code': '39156-5',
'display': 'Body mass index (BMI) [Ratio]',
}]
observation.set_code_coding(code_coding)
code_text = 'Body mass index (BMI) [Ratio]'
observation.set_code_text(code_text)
subject= {
'reference': 'Patient/pat-example',
}
observation.set_subject(subject)
effective_datetime = '2023-12-23'
observation.set_effective_datetime(effective_datetime)
performer = [{
'reference': 'Practitioner/pra-dr-example',
}]
observation.set_performer(performer)
value_quantity = {
'value': 18.3,
'unit': 'kg/m2',
'system': 'http://unitsofmeasure.org',
'code': 'kg/m2',
}
observation.set_value_quantity(value_quantity)
# Retrieving the Observation resource dict
observation_json_dict = observation.create()
print(observation_json_dict)
# Retrieve the Observation resource JSON string
print(json.dumps(observation_json_dict))
執行observation_bmi_example.py
以前述執行python3 patient_example1.py所產生的Resource為例
{"resourceType": "Patient", "meta": {"profile": ["https://twcore.mohw.gov.tw/ig/twcore/StructureDefinition-TWPatient.json"]}, "identifier": [{"use": "official", "system": "http://www.boca.gov.tw", "type": {"coding": [{"system": "http://www.boca.gov.tw", "code": "PPN", "display": "Passport number"}]}, "value": "262344368"}, {"use": "official", "system": "http://terminology.hl7.org/CodeSystem/v2-0203", "type": {"coding": [{"system": "http://terminology.hl7.org/CodeSystem/v2-0203", "code": "MR", "display": "Medical record number"}]}, "value": "123456789"}], "active": true, "managingOrganization": {"reference": "Organization/MITW.ForIdentifier"}, "name": [{"use": "official", "text": "\u674e\u5c0f\u660e", "family": "\u674e", "given": ["\u5c0f\u660e"]}], "gender": "male", "birthDate": "2023-12-23", "address": [{"use": "home", "text": "105\u53f0\u5317\u5e02\u677e\u5c71\u5340\u6c11\u751f\u6771\u8def\u56db\u6bb5133\u865f"}, {"country": "TW"}], "telecom": [{"use": "home", "system": "phone", "value": "0905285349"}]}
驗證結果說明
dom-6 Guideline A resource should have narrative for robust management
Swagger UI與查看該FHIR server收錄的Meta profile
選用該FHIR server裡面收錄的TW Core Patient profile
複製patient_example1.py檔至patient_example3.py
修改patient_example3.py,修改地方如下所示
# 第二第三行間加入
import requests
# 第7行修改如下
patient.set_profile_url('https://twcore.mohw.gov.tw/ig/twcore/StructureDefinition/Patient-twcore')
# 最下面依序加入這幾行
headers = {'Content-Type': 'application/fhir+json'}
response = requests.post(
'https://twcore.hapi.fhir.tw/fhir/Patient',
headers=headers,
json=patient_json_dict
)
print(response.status_code)
print(response.json())
選用該FHIR server裡面收錄的TW Core Patient profile
執行patient_example3.py
Resource Organization/MITW.ForIdentifier not found
代表指定參考的Organization找不到
因此需要做修改
選用該FHIR server裡面收錄的TW Core Patient profile
將patient_example3.py複製成patient_example4.py
修改策略有兩個方法
刪除managingOrganization部分
找到該驗證的FHIR server中存在的managingOrganization
找到此組織並進行修改連結
managing_organization = 'Organization/org-hosp-example'
修改完成後接著執行patient_example4.py
在下載與執行JAR檔前,還需要先建立可以執行JAVA環境
需要先安裝OpenJDK
依據HL7 Confluence可以得知,JDK版本可以是11或17
JDK Version
The validator is tested to run on all currently support LTS versions of Java (at the time of writing this documentation, JDK 11 and 17)
以Ubuntu 22.04,則可以使用下列指令進行安裝
sudo apt-get update
sudo apt-get install openjdk-11-jdk -y
下載與解壓縮所需要的JAR檔、IG實作指引與profile檔
以TWCore IG 0.2.2為例
下載與解壓縮所需要的JAR檔、IG實作指引與profile檔
以TWCore IG 0.2.2為例
# 建立fhir_validate_example目錄
$ mkdir fhir_validate_example && cd fhir_validate_example
# 下載validator_cli.jar檔案
$ wget -O validator_cli.jar https://github.com/hapifhir/org.hl7.fhir.core/releases/latest/download/validator_cli.jar
# 安裝unzip指令,可以解壓縮實作指引、文件定義與範例等壓縮檔
$ sudo apt-get update
$ sudo apt-get install unzip -y
# 下載TW Core 0.2.2實作指引之壓縮檔
$ wget -O full-ig.zip https://twcore.mohw.gov.tw/ig/twcore/full-ig.zip
$ rm -rf full-ig && mkdir full-ig && unzip full-ig.zip -d full-ig
# 下載範例檔(此壓縮檔含有各類型Resource JSON與JSON profile等檔案)版本: TW Core 0.2.2
$ wget -O examples.json.zip https://twcore.mohw.gov.tw/ig/twcore/examples.json.zip
$ rm -rf examples.json && mkdir examples.json && unzip examples.json.zip -d examples.json
$ ls
examples.json examples.json.zip full-ig full-ig.zip validator_cli.jar
使用validator_cli.jar方式如下
$ java -jar validator_cli.jar -help
SLF4J: No SLF4J providers were found.
SLF4J: Defaulting to no-operation (NOP) logger implementation
SLF4J: See https://www.slf4j.org/codes.html#noProviders for further details.
SLF4J: Class path contains SLF4J bindings targeting slf4j-api versions 1.7.x or earlier.
SLF4J: Ignoring binding found at [jar:file:/home/peter/fhir_validate_example/validator_cli.jar!/org/slf4j/impl/StaticLoggerBinder.class]
SLF4J: See https://www.slf4j.org/codes.html#ignoredBindings for an explanation.
FHIR Validation tool Version 6.3.18 (Git# 5c3953cfdb3b). Built 2024-07-17T06:14:31.637Z (15 days old)
Java: 11.0.24 from /usr/lib/jvm/java-11-openjdk-amd64 on amd64 (64bit). 1482MB available
This is the help text for default usage of the validator. Help for other modes
of operation is available by using the parameter '-help [mode]' for one of the
......
使用validator_cli.jar方法
java -jar validator_cli.jar [source] -version [ver] -ig [package|file|folder|url] -profile [url]
使用validator_cli.jar方法
java -jar validator_cli.jar [source] -version [ver] -ig [package|file|folder|url] -profile [url]
$ java -jar validator_cli.jar ./examples.json/Patient-pat-example.json \
-version 4.0 \
-ig tw.gov.mohw.twcore
......
Java: 11.0.24 from /usr/lib/jvm/java-11-openjdk-amd64 on amd64 (64bit). 1482MB available
Paths: Current = /home/peter/fhir_validate_example, Package Cache = /home/peter/.fhir/packages
Params: ./examples.json/Patient-pat-example.json -version 4.0 -ig tw.gov.mohw.twcore
Locale: United States/US
Jurisdiction: United States of America
Loading
Load FHIR v4.0 from hl7.fhir.r4.core#4.0.1Installing hl7.fhir.r4.core#4.0.1 to the package cache
Fetching:
......
Installing tw.gov.mohw.twcore#0.2.2 done.
Installing hl7.terminology.r4#5.5.0 to the package cache
Fetching:
Load tw.gov.mohw.twcore#0.2.2 - 221 resources (00:00.774)
Package Summary: [hl7.fhir.r4.core#4.0.1, hl7.fhir.xver-extensions#0.1.0, hl7.fhir.uv.extensions.r5#5.1.0, hl7.terminology#6.0.2, hl7.terminology.r5#6.0.2, hl7.fhir.uv.extensions#5.2.0-ballot, hl7.terminology.r4#5.5.0, hl7.fhir.uv.extensions.r4#5.1.0, hl7.terminology.r4#5.0.0, fhir.dicom#2022.4.20221006, hl7.fhir.uv.ips#1.1.0, tw.gov.mohw.twcore#0.2.2]
Terminology Cache at /tmp/default-tx-cache
Get set... go (00:00.713)
Cached new session. Cache size = 1
Validating
Validate ./examples.json/Patient-pat-example.json
Validate Patient against http://hl7.org/fhir/StructureDefinition/Patient|4.0.1..........20..........40..........60.........
使用validator_cli.jar方法
java -jar validator_cli.jar [source] -version [ver] -ig [package|file|folder|url] -profile [url]
Done. Times: Loading: 00:28.521, validation: 00:32.136. Memory = 1Gb
Success: 0 errors, 0 warnings, 1 notes
Information: All OK
Done. Times: Loading: 00:28.521, validation: 00:32.136. Max Memory = 2Gb
可以從前面的執行驗證指令知道
在執行的時候,會去找指定IG的package cache進行下載
並將package cache目錄下載至家目錄底下.fhir/packages目錄下
再執行第二次之後,則不會再進行下載
$ java -jar validator_cli.jar ~/patient_example5.json \
-version 4.0 \
-ig tw.gov.mohw.twcore
......
Success: 0 errors, 3 warnings, 0 notes
Warning @ Patient.identifier[0].type (line 1, col228): None of the codings provided are in the value set 'IdentifierType' (http://hl7.org/fhir/ValueSet/identifier-type|4.0.1), and a coding should come from this value set unless it has no suitable code (note that the validator cannot judge what is suitable) (codes = http://www.boca.gov.tw#PPN)
Warning @ Patient.identifier[0].type.coding[0].system (line 1, col228): A definition for CodeSystem 'http://www.boca.gov.tw' could not be found, so the code cannot be validated
Warning @ Patient (line 1, col948): Constraint failed: dom-6: 'A resource should have narrative for robust management' (defined in http://hl7.org/fhir/StructureDefinition/DomainResource) (Best Practice Recommendation)
Done. Times: Loading: 00:26.666, validation: 00:02.462. Max Memory = 2Gb
peter@server1:~/fhir_validate_example$
Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
at org.hl7.fhir.utilities.json.JsonTrackingParser$Lexer.next(JsonTrackingParser.java:268)
at org.hl7.fhir.utilities.json.JsonTrackingParser$Lexer.consume(JsonTrackingParser.java:34
這是執行JAR檔常見的錯誤
原因是JVM裡面所指定給它的記憶體用光了
若要解決這問題,加入-Xmx2G指定JVM記憶體使用量
$ java -Xmx2G -jar validator_cli.jar ./examples.json/Patient-pat-example.json \
-version 4.0 \
-ig tw.gov.mohw.twcore
JAVA執行環境要自己建立
要自己下載很多檔案?如IG、範例以及各種檔案......
有沒有更好的方式?
用Docker image吧!
https://github.com/peter279k/docker_fhir_validator
完全相容validator_cli.jar執行的環境
與validator_cli.jar所釋出的版本同步
Docker image連結
使用peter279k/docker_fhir_validator_11
安裝Docker
把上述的Docker image下載回來
$ sudo snap install docker --classic
$ sudo docker pull peter279k/docker_fhir_validator_11
Using default tag: latest
latest: Pulling from peter279k/docker_fhir_validator_11
3713021b0277: Pull complete
11774ed96e66: Pull complete
d81f84b7fc25: Pull complete
Digest: sha256:7579743b548100cdee657a34cab725cfc619b45b503d4bdb46d910c6bdd184cc
Status: Downloaded newer image for peter279k/docker_fhir_validator_11:latest
docker.io/peter279k/docker_fhir_validator_11:latest
# Download IG package cache folder on the FHIR CI Build
$ wget -O package.tgz https://build.fhir.org/ig/cctwFHIRterm/MOHW_TWCoreIG_Build/package.tgz
# Or Download IG package cache folder on the Taiwan MOHW
$ wget -O package.tgz https://twcore.mohw.gov.tw/ig/twcore/package.tgz
# Create directory named IG name and version
$ mkdir tw.gov.mohw.twcore
# Extract the archived file to specific directory
$ tar -xvzf package.tgz -C tw.gov.mohw.twcore
# Download example JSON file
$ wget -O examples.json.zip https://build.fhir.org/ig/cctwFHIRterm/MOHW_TWCoreIG_Build/examples.json.zip
$ rm -rf examples.json && mkdir examples.json && unzip examples.json.zip -d examples.json
# Validate it!
docker run \
-v $PWD/tw.gov.mohw.twcore:/root/.fhir/packages/tw.gov.mohw.twcore \
-v $PWD/examples.json:/root/examples.json \
peter279k/docker_fhir_validator_11:latest -c "cd /root/ && java -Dfile.encoding=UTF-8 -jar validator_cli.jar ./examples.json/Patient-pat-example.json -version 4.0 -ig tw.gov.mohw.twcore"
使用方式
下載所需要的package cache
執行docker run時將其掛載(volume)進去
懶得在自己下載TW Core IG進行掛載
可以考慮選擇peter279k/tw_core_ig_validator
以peter279k/docker_fhir_validator_11之latest版本建置
以peter279k/docker_fhir_validator_17之latest版本建置
收錄TWCore IG的版本
目前包含0.2.2與0.2.3
未來有新的版本,會自動收錄並發布新的Image
若要執行JDK版本11且是TW Core IG 0.2.2
docker pull peter279k/tw_core_ig_validator_11:0.2.2
若要執行JDK版本17且是TW Core IG 0.2.2
docker pull peter279k/tw_core_ig_validator_17:0.2.2
將patient_example5.py所輸出的JSON內容
輸出成patient_example5.json並執行驗證
docker run \
-v /path/to/patient_example5.json:/root/patient_example5.json \
peter279k/tw_core_ig_validator_11:0.2.2 -c "cd /root/ && java -Dfile.encoding=UTF-8 -jar validator_cli.jar ./patient_example5.json -version 4.0 -ig tw.gov.mohw.twcore"
......
Validate Patient against http://hl7.org/fhir/StructureDefinition/Patient|4.0.1..........20..........40..........60..........80.........|
00:02.445
Done. Times: Loading: 01:56.949, validation: 00:02.447. Memory = 638Mb
Success: 0 errors, 3 warnings, 0 notes
Warning @ Patient.identifier[0].type (line 1, col228): None of the codings provided are in the value set 'IdentifierType' (http://hl7.org/fhir/ValueSet/identifier-type|4.0.1), and a coding should come from this value set unless it has no suitable code (note that the validator cannot judge what is suitable) (codes = http://www.boca.gov.tw#PPN)
Warning @ Patient.identifier[0].type.coding[0].system (line 1, col228): A definition for CodeSystem 'http://www.boca.gov.tw' could not be found, so the code cannot be validated
Warning @ Patient (line 1, col948): Constraint failed: dom-6: 'A resource should have narrative for robust management' (defined in http://hl7.org/fhir/StructureDefinition/DomainResource) (Best Practice Recommendation)
Done. Times: Loading: 01:56.949, validation: 00:02.447. Max Memory = 1Gb
https://github.com/peter279k/fhir-data-generator/tree/master/examples
patient_example1.py
patient_example2.py
patient_example3.py
patient_example4.py
patient_example5.py
patient_example5.json
observation_bmi_example.py
發展及推行支援標準化之系統
以利於系之整合應用,以及系統複製、擴散、商品化應用
開發好的服務或系統,透過聯測松的方式進行互通性之測試
https://github.com/peter279k/fhir-data-generator
https://twcore.hapi.fhir.tw
https://github.com/peter279k/docker_fhir_validator
https://github.com/peter279k/tw_core_ig_validator
符合各式情境的前端使用者介面(各位的最後一哩路)
透過走馬看花的方式了解FHIR醫學資訊標準與基本名詞解釋
降低產生FHIR Resources之門檻
透過peter279k/fhir-data-generator進行便利的產生Resources
增加離線驗證的便利性
https://github.com/peter279k/docker_fhir_validator
https://github.com/peter279k/tw_core_ig_validator