Manipulating FHIR Resource: client-py API
จัดการ FHIR Resource ด้วย Python Programming API: client-py
client-py
หลังจากที่ทดลอง operation ต่างๆ กับ FHIR resource ผ่าน RESTful APIs กันแล้ว ในตอนนี้ จะทำการอ่านข้อมูลของ Resource จาก FHIR server ผ่าน Programming APIs โดยใช้ Python
Open Source FHIR implementations ที่เป็น Python คือ client-py
Installation
client-py ใน pip package ยังเป็นเวอร์ชั่น 3.2.0 หากต้องการเวอร์ชั่น 4.0.0 ต้องติดตั้งจาก GitHub โดยตรง โดยใช้ pip3
หรือ python3 -m pip
python3 -m pip install git+https://github.com/smart-on-fhir/client-py.git
ตรวจสอบ package ที่ติดตั้งโดยใช้
python3 -m pip list | grep fhirclient
หรือ
python -m pip list | findstr fhirclient
(Windows)
Code
ในการติดต่อกับ FHIR server จะใช้ class FHIRServer
ที่อยู่ใน namespace fhirclient.server
from fhirclient.server import FHIRServer
และ class Patient
อยู่ใน namespace fhirclient.models
ที่เป็น Python implementation ของ Resource models ต่างๆ ตาม FHIR specifications
from fhirclient.models.patient import Patient
สร้าง server object โดยใช้ constructor ของ class FHIRServer
ตามนิยาม
ในตอนนี้ยังไม่ได้สร้าง client object, parameter client
จึงใส่ค่าเป็น None
ไว้ก่อน parameter base_uri
ใส่ค่าเป็น URL ของ FHIR Server ที่ต้องการใช้งาน
server = FHIRServer( None, "http://hapi.fhir.org/baseR4" )
อ่าน Patient resource จาก FHIR server โดยใช้ method read
ใน FHIRAbstractResource
ซึ่งเป็น base class ของ Patient resource
parameter rem_id
คือ id ของ resource บน server ที่ต้องการ read ในที่นี้คือ id ของ Patient resource ที่ต้องการ
p = Patient.read( "921009", server )
เนื่องจาก models ต่างๆ ใน fhirclient.models
เขียนขึ้นตาม FHIR specifications ดังนั้น attributes ต่างๆ รวมทั้ง Data types ของ Patient class ก็จะเป็นไปตาม elements ของ Patient resource
ทำให้เข้าถึง elements ต่างๆ ของ resource ได้โดยผ่าน attributes ของ class
print( f"NAME: {p.name[0].text}" )
print( f"BIRTHDATE: {p.birthDate.date.isoformat()}" )
- เนื่องจากนิยามของ element
name
ใน Patient resource มี Cardinality เป็น0..*
(มีได้มากกว่า 1) ใน Python implementation จึงเป็น Sequence - นอกจากนี้ element
name
ยังมี data type เป็นแบบHumanName
ซึ่งเป็น Complex data type เมื่อ output ออกมาทาง console จะเป็น object ของ class นั้นใน Python แต่ข้อดีของ FHIR specifications คือ มีการกำหนดให้แต่ละ resource มี Narrative/Text section ที่เป็น human-readable summary (https://medium.com/thai-fhir-sig/resource-part-3-ce17f1d6b108) ใน resourceHumanName
มี elementtext
ซึ่งมี data type เป็น string จึงสามารถ output ออกมาทาง console ได้โดยตรง - element
birthDate
มี data type ตาม FHIR specifications เป็นdate
ซึ่งเป็น Primitive data type แต่ใน Python implementation นี้birthDate
จะมี data type เป็น classFHIRDate
ใน namespacefhirclient.models.fhirdate
แทน - ใน class
FHIRDate
จะมี attributedate
อีกทีหนึ่งซึ่งมี data type เป็นdate
class ของ Python ใน moduledatetime
ทำให้สามารถเรียกใช้ methodisoformat()
ของ classdate
ซึ่งจะ return วันที่เป็น string ตามรูปแบบ ISO กลับมา
ในครั้งก่อนนี้ ใช้ clinFHIR (http://clinfhir.com) ช่วยสร้าง Patient resource, นอกจาก Patient resource แล้ว clinFHIR ยังสร้างตัวอย่าง resource ต่างๆ เพื่อการศึกษาและทดลองใช้งาน FHIR ทางคลินิกให้อีกด้วย
สร้าง Problem list ของผู้ป่วย จาก Condition resources
Import class ที่ต้องการใช้งานเพิ่มเติมได้แก่ Condition
from fhirclient.models.condition import Condition
ทำการค้นหา Condition resource ที่มี subject=921009 โดยใช้ class method where()
ที่อยู่ใน base class FHIRAbstractResource
ซึ่งจะ return ค่ากลับมาเป็น FHIRSearch
object
srch = Condition.where( { “subject”: “921009” } )
เรียกใช้งาน method perform_resources()
ของ FHIRSearch
ซึ่งจะทำการค้นหา resource ที่ตรงกับ search parameter แล้ว return ค่ากลับมาเป็น list ของ resource นั้น
conditions = srch.perform_resources( server )
สามารถเขียน code แบบ method chaining ได้ ให้ code อยู่บรรทัดเดียวกัน
conditions = Condition.where( { “subject”: “921009” } ).perform_resources( server )
ถ้า list conditions
ไม่ empty แสดงว่ามี Condition resource ที่มี subject=921009 แสดงผลการค้นหาแต่ละ Condition resource ที่ได้ ในที่นี้เลือกแสดงเฉพาะ condition และ severity
if not conditions:
print( "PROBLEM LIST: None" )
else:
print( "PROBLEM LIST:" )
i = 1
for cond in conditions:
print( f"{i:>3d}. {cond.code.text:<40s} Severity: {cond.severity.text:<12s}" )
i += 1
Full code listing:
Output:
----------------------------------------
Patient Information
----------------------------------------
NAME: Edward Melonseed
BIRTHDATE: 1988-03-25
PROBLEM LIST:
1. high cholesterol Severity: Moderate
2. GERD Severity: Moderate
3. onychomycosis Severity: severe
4. asthma Severity: mild to moderate
5. angina Severity: Moderate
6. hypertension Severity: Mild
7. diabetes Severity: moderate
8. neuropathic pain Severity: moderate
9. depression Severity: Moderate
10. rheumatoid arthritis - left elbow Severity: Diagnosis
11. rheumatoid arthritis - both hands Severity: Moderate
Official FHIR Implementation
- JAVA: https://github.com/jamesagnew/hapi-fhir โดย James Agnew / University Health Network (Canada) HAPI FHIR เริ่มโครงการตั้งแต่ปี 2001 มีความสมบูรณ์ที่สุดในเรื่อง implementation และเอกสารประกอบ (documentation) ศึกษารายละเอียดเพิ่มเติมได้ที่ https://hapifhir.io/
- DotNET https://github.com/FirelyTeam/fhir-net-api โดย Firely (Netherlands) เป็น implementation ที่มีความสมบูรณ์เช่นเดียวกับ HAPI FHIR เอกสารประกอบเป็นลักษณะแบบ tutorial ดูได้ที่ http://docs.simplifier.net/fhirnetapi/ หากต้องการรายละเอียดเพิ่มเติมต้องติดต่อผู้พัฒนา
- Python https://github.com/smart-on-fhir/client-py เอกสารประกอบดูได้ที่ http://docs.smarthealthit.org/client-py/ เอกสารมีรายการ models และ class methods/attributes ครบถ้วน แต่ยังขาดรายละเอียดคำอธิบายค่อนข้างมาก ต้องเปิด FHIR specifications ควบคู่กันไปในการทำความเข้าใจ
- Swift https://github.com/smart-on-fhir/Swift-FHIR เอกสารประกอบดูได้ที่ https://github.com/smart-on-fhir/Swift-SMART/wiki และ http://docs.smarthealthit.org/Swift-SMART/
- Implementation อื่นๆ ดูเพิ่มเติมได้ที่ https://confluence.hl7.org/display/FHIR/Open+Source+Implementations