2021年6月1日 星期二

HL7 FHIR 模組說明 - Level 4 Medications - Immunization

 官方文件:

簡述:

用來描述個案接種疫苗之相關資訊,偏重於事件描述。

欄位討論:

  • status [0..1]: code
  • statusReason [0..1]: CodeableConcept
    • 延續前項,沒有完成的原因。
    • 參考:Immunization Status Reason Codes (Example)
      • http://terminology.hl7.org/CodeSystem/v3-ActReason
        • {IMMUNE | MEDPREC | OSTOCK | OATOBJ} --> {已免疫 | 因病患違反施打要求 | 缺貨 | 病患反對}
      • http://snomed.info/sct
        • concept is-a 310376006 (Immunization consent not given)
  • vaccineCode [1..1]: CodeableConcept
  • patient [1..1]: Reference(Patient)
    • 施打之對象。
  • encounter [0..1]: Reference(Encounter)
    • 就診紀錄。
  • occurrence[x] [1..1]: {dateTime | string}
    • 施打日期。
  • recorded [0..1]: dateTime
    • 第一次施打時間。若本次是第一次施打(相同的vaccineCode時),那時間就該與occurrence相同。
  • primarySource [0..1]: boolean
    • 代表這份Resource的紀錄是來自第一時間施打者所寫。而非由其他系統所產生的紀錄。
    • 主要是代表這份文檔的可靠度(reliability)。
  • reportOrigin [0..1]: CodeableConcept
    • 若不是第一時間施打者之紀錄,那本紀錄來自哪裡。
    • 參考:Immunization Origin Codes (Example)
      • http://terminology.hl7.org/CodeSystem/immunization-origin
        • {provider | record | recall | school} --> {來自其他提供者 | 來是病患書面報告 | 來自病患本身、父母或監護人之回憶 | 來自學校紀錄}
  • location [0..1]: Reference(Locatioin)
    • 施打地點。
  • manufacturer [0..1]: Reference(Organization)
    • 疫苗製造商。
  • lotNumber [0..1]: string
    • 疫苗批量編號。
  • expirationDate [0..1]: date
    • 疫苗到期日。
  • site [0..1]: CodeableConcept
  • route [0..1]: CodeableConcept
    • 以什麼途徑方法進入人的身體。
    • 參考:Immunization Route Codes (Example)
      • http://terminology.hl7.org/CodeSystem/v3-RouteOfAdministration
    • 例如:
      • IDINJ --> 皮內注射
      • IM --> 肌內注射
      • NASINHLC --> 鼻吸入
      • IVINJ --> 靜脈注射
      • PO --> 口服
      • SQ --> 皮下注射
      • TRNSDERM --> 經皮
  • doseQuantity [0..1]: SimpleQuantity
    • 疫苗注射量。
    • 注意單位代碼。
  • performer [0..*]: BackboneElement
    • 進行本次施打疫苗事件的執行者。
    • 注意一個施打事件可能由很多人共同執行。
    • 欄位討論:
  • note [0..*]: Annotation
    • 註記。
  • reasonCode [0..*]: CodeableConcept
  • reasonReference [0..*]: Reference(Condition | Observation | DiagnosticReport)
    • 為何要施打此疫苗詳細原因之參考資訊。
  • isSubpotent [0..1]: boolean
    • 劑量的效力。應該是指本次施打並無得到完整效能。
  • subpotentReason [0..*]: CodeableConcept
    • 未達全效的原因。
    • 參考:Immunization Subpotent Reason (Example)
      • http://terminology.hl7.org/CodeSystem/immunization-subpotent-reason
    • 例如:
      • partial --> 並沒給予足夠劑量。
      • coldchainbreak --> 疫苗有經歷冷鏈損壞。
      • recall --> 此疫苗是被製造商招回的。
  • education [0..*]: BackboneElement
    • 要給施打此疫苗病患之教育訓練教材。
    • 欄位討論:
      • documentType [0..1]: string
        • 教材代碼。
      • reference [0..1]: uri
        • 教材的參考網址。
      • publicationDate [0..1]: dateTime
        • 教材出版日期。
      • presentationDate [0..1]: dateTime
        • 向病患展示教材的日期。
  • programEligibility [0..*]: CodeableConcept
    • 病患接種此疫苗的資格,或者說他是有資格取得贊助費用。
    • 參考:Immunization Program Eligibility (Example)
      • http://terminology.hl7.org/CodeSystem/immunization-program-eligibility
    • 例如:
      • ineligible --> 沒有資格獲取贊助費用。
      • uninsured --> 可獲贊助費用,因為病患無保險。
  • fundingSource
    • 贊助施打疫苗的費用來源。
    • 參考:Immunization Funding Source (Example)
      • http://terminology.hl7.org/CodeSystem/immunization-funding-source
    • 例如:
      • private --> 來自私人採購贊助。
      • public --> 來自政府採購贊助。
  • reaction [0..*]: BackboneElement
    • 詳細紀錄施打後的各種副作用反應。
    • 欄位討論:
      • date [0..1]: dateTime
        • 副作用開始時間日期。
      • detail [0..1]: Reference(Observation)
        • 詳細描述情況。
      • reported [0..1]: boolean
        • 用來註記是否為自行回報。
  • protocalApplied [0..*]: BackboneElement
    • 來自提供者的建議(協議)。
    • 太過專業,不方便闡述。

2021年5月30日 星期日

HL7 FHIR 模組說明 - Level 4 Medications - Medication

 官方文件: 

  • http://www.hl7.org/fhir/medication.html (R4)
  • http://hl7.org/fhir/2021May/medication.html (R5)

簡述:

淺顯易懂,就是放藥品資訊的地方。注意,他沒有服藥相關資訊,就是單純的代表一種藥的編碼,廠商、樣式、成分、包裝,批量等資訊。

欄位討論:

  • code [0..1]: CodeableConcept
  • status [0..1]: code
  • manufacturer [0..1]: Reference(Organization)
    • 製造生產商。
  • form [0..1]: CodeableConcept
  • amount [0..1]: Ratio
    • 每一份包裝的數量。
    • 注意,他的資料型態是Ratio,就會有分子與分母。若為每一份,所以分母為1。
  • Ingredient [0..*]: BackboneElement
    • 藥品成分清單。
    • 欄位討論:
      • item[x] [1..1]: {CodeableConcept | Reference(Substance | Medication)}
        • 成分代碼。
        • 像複方藥,成分也可能是藥。
      • IsActive [0..1]: boolean
        • 是否可用。
      • Strength [0..1]: Ratio
        • 強度。此成分所佔的比率。
  • batch [0..1]: BackboneElement
    • 批量相關資訊。
    • 欄位討論:
      • lotNumber [0..1]: string
        • 批量序號。
      • expirationDate [0..1]: dateTime
        • 到期日

2021年5月27日 星期四

HL7 FHIR 模組說明 - Level 4 Medications - MedicationRequest - Dosage

延續前一篇提到MedicationRequest.dosageInstruction的資料型態是Dosage。他有點複雜,需要專頁來說明。其實,他並不適合放在這,Dosage在R4,他是被很尷尬的獨立成一篇。


到了R5,重新架構了資料型態,將Dosage歸入Special Purpose Types中(R4是隱晦在文件中),感覺就舒服多了。
言歸正傳,這邊討論的是R4版本。其實與R5就欄位內容是一樣的,只是R4是繼承BackboneElement,而R5是繼承BackboneType(實際上就是Element)。至於兩者有何差異,不在本篇討論範圍。(迫不及待想知道,那就參考R5的Type Framework)。
====================================

簡述:

關於藥物服用的指引。

欄位討論:

  • sequency [0..1]: integer
    • MedicationRequest.dosageInstruction是[0..*],表示一張MequestionRequest所要求的一種藥,可以有多筆用藥說明。
    • 這個欄位就是用來當序號的。
  • text [0..1]: string
    • 非結構描述用藥資訊。
  • additionalInstruction [0..*]: CodeableConcept
  • patientInstruction [0..1]: string
    • 針對此病患提供額外服藥指引。
  • timing [0..1]: Timing
    • 服藥資訊與時間有關者。
    • Timing這個資料型態在R4比Dosage更尷尬。他是被放在General-Purpose DataType中,卻是唯一繼承於BackboneElement者。
    • 到了R5,就與Dosage一樣,繼承於BackboneType。但是,仍放在General-Purpose DataType。
    • 為什麼?因為BackboneElement已經不繼承於DataType而是直接繼承於Element。
    • 這個資料型態有點複雜,可參考之前的文章HL7 FHIR 資料型態篇 - Complex Types - 時間類
  • asNeeded[x] [0..1] {Boolean | CodeableConcept}
  • site [0..1]: CodeableConcept
  • route [0..1]: CodeableConcept
    • 使用什麼途徑將藥進入身體(在什麼地方,就看site)。
    • 參考:SNOMED CT Route Codes (Example)
      • Code System http://snomed.info/sct
        • Concept is-a 284009009 (Route of administration values)
    • 例如:
  • method [0..1]: CodeableConcept
    • 以什麼方法技術來使用藥進行服藥。 
    • 參考:SNOMED CT Administration Method Codes (Example)
      • Code System http://snomed.info/sct
        • Concept is-a 422096002 (Dosing instruction fragment)
    • 例如:
      • 419747000 Chew
      • 421521009 Swallow
      • 421538008 Instill
      • 422145002 Inject
      • 421682005 Dissolve
  • doseAndRate [0..*]: Element
    • 服藥資訊與數量/速率有關者。
    • 注意他的資料型態是Element。而非常見的BackboneElement。
    • 欄位討論:
      • type [0..1]: CodeableConcept
        • 數量/速率的值是怎麼來的。
        • 參考:DoseAndRateType (Example)
          • Code System http://terminology.hl7.org/CodeSystem/dose-rate-type
            • Concept is calculated
            • Concept is ordered
      • dose[x] [0..1]: { Range | SimpleQuantity }
        • 每一劑的使用數量(可數)。
        • 是範圍值,還是特定值。
        • 每一個值要提供單位。常用之Code System為http://unitsofmeasure.org
      • rate[x] [0..1]: {Ratio | Range | SimpleQuantity}
        • 每一劑使用之速率(不可數)
        • 例如掉點滴。
  • maxDosePerPeriod [0..1]: Ratio
    • 每單位時間內的最大劑量
  • maxDosePerAdministrtion [0..1]: SimpleQuantity
    • 每次服藥之最大劑量。
  • maxDosePerLifetime [0..1]: SimpleQuantity
    • 病患此身最大使用劑量。

2021年5月25日 星期二

HL7 FHIR 模組說明 - Level 4 Medications - MedicationRequest

官方文件:http://hl7.org/fhir/medicationrequest.html

簡述:

這個其實不能被視為等同開立處方籤,因為我們對處方籤的概念是一張單子上,會列出很多筆藥。依據欄位內容定義,Medication[1..1]僅能描述一種藥,所以,他是醫師開立一項藥品的請求單。

他會經由EMR系統啟動一系列的流程,進而產生其他的本系列有關之Resource。

欄位討論:

  • 他繼承於DomainResource。(大部分的Resource都會繼承於DomainResource,但有些不是,例如Bundle,Binary...。)

  • status [1..1]: code
    • 限定:Medicationrequest status (Required) --> http://hl7.org/fhir/ValueSet/medicationrequest-status#{active | on-hold | cancelled | completed | entered-in-error | stopped | draft | unknown}
    • 從CDS Hooks的角度來說,開立一張訂單,要經過查核後才能確認。此時,收到MedicationRequest的狀態就會是draft。active是指此Request可能還有些步驟未完成。Completed表示所有步驟接已完成。
  • intent [1..1]: code
    • 限定:Medication request intent (Required) --> http://hl7.org/fhir/ValueSet/medicationrequest-intent#{proposal | plan | order | original-order | reflex-order | filler-order | instance-order | option}
    • 這份Request的意圖。一般而言,都是放order。
  • category [0..*]: CodeableConcept
    • 此Resource用於何處。
    • 參考:Medication request category codes (Example)  --> http://terminology.hl7.org/CodeSystem/medicationrequest-category。
    • 門診、住院、社區照護、出院。
  • priority [0..*]: code
    • 此Resource的優先序。
    • 限定:Request priority (Required) --> http://hl7.org/fhir/ValueSet/request-priority#{routine | urgent | asap | stat}
    • {常規 | 緊急 | 愈快愈好 | 立刻} 低-->高
  • doNotPerform [0..1]: boolean
    • 若為true,反而是告知此MedicationRequest不要執行。
  • reported[x] [0..1]: {boolean | Reference(Patient | Practitioner | PractitionRole | RelatedPerson | Organization)}
    • 設定此MedicationRequest是報告,而非主要紀錄。
    • 主要紀錄是當時情境。報告是事後情境,那就會有一份引發此報告的來源。 
  • medication[x] [1..1]: {CodeableConcept | Reference(Medication)}
    • 這份MedicationRequest所指稱的藥品資料。
    • 因為是Choice資料型態,所以要注意抓回來的是哪一種資料型態。
    • 這個是依紀錄不同,千萬別以為同一台FHIR Server都會給固定資料型態。
    • 無論哪種,最終目標還要抓到code。
    • 但要注意,這個code是哪種sytem。
    • 國外會用RxNorm。
  • subject [1..1]: Reference(Patient | Group)
    • 這份MedicationRequest為誰|那哪些人而申請的。
    • Group類似Bundle的功能,用來打包其他Resource。但是有很大差異。Group只能打包固定六種類的東西(person | animal | practitioner | device | medication | substance)。可接受固定的Resource(Patient | Practitioner | PractitionerRole | Device | Medication | Substance | Group)
  • encounter [0..1]: Reference(Encounter)
    • encounter在國外的定義是很複雜。只要有醫病交流之情境,就可以產生一份Encounter,所以Encounter會有Location。很多個Encounter會衍生自同一個Appointment。
    • 此處就是紀錄這份MedicationRequest是發生在哪一次的Encounter。
  • supportingInformation [0..*]: Reference(Any)
    • 其他有關開立處方之支持性資源。
  • authoredOn [0..1]: dateTime
    • 此MedicationRequest開立日期。
  • requester [0..1]: Reference(Practitioner | PractitionerRole | Organization | Patient | RelatedPerson | Device)
    • 提出此處方需求之來源。
  • performer [0..1]: Reference(Practitioner | PractitionerRole | Organization | Patient | Device | RelatedPerson | CareTeam)
    • 執行處方的人。
    • 也就是會拿藥去餵subject的人。
  • performerType [0..1]: CodeableConcept
    • 適合來執行此處方的角色要求。
    • 參考:Procedure Performer Role Codes (Example) -->  http://hl7.org/fhir/ValueSet/performer-role
    • CodeSystem
      • http://snomed.info/sct | 223366009(Healthcare professional)
  • recorder [0..1]: Reference(Practitioner | PractitionerRole)
    • 真正開立此MedicationRequest的人。
    • 注意不要與requester混淆,這個是想要處方的人,所以才會有Patient。
    • 而此處是有資格開立處方的人,當然只能是有醫師資格的人。
  • reasonCode [0..*]: CodeableConcept
    • 定義開立或不開立此藥的原因或指示。
    • 參考:Procedure Performer Role Codes (Example) --> http://hl7.org/fhir/ValueSet/condition-code
    • CodeSystem
      • http://snomed.info/sct | 404684003 (Clinical finding)
      • http://snomed.info/sct | #160245001 (No current problems or disability)
  • reasonReference [0..*]: Reference(Condition | Observation)
    • 用來支持證明需要開立這份MedicationRequest的Condition或Observation。
    • 一般而言,這個Condition的category會是encounter-diagnosis。
  • basedOn [0..*]: Reference(CarePlan | MedicationRequest | ServiceRequest | ImmunizationRecommendation)
    • 是基於哪一個流程中所開立的MedicationRequestion。也就是,為了滿足哪一個流程而開立。
  • dosageInstruction [0..*]: Dosage
    • 如何服用此藥物的指示。
    • Dodage資料型態有點複雜,得專頁說明。

P.S. 實在無法把所有欄位都描述說明。有些沒碰到過,還真不知道是幹嘛用的。我也不是/不能搞翻譯,就我所知盡量分享了。

2021年5月17日 星期一

HL7 FHIR 模組說明 - Level 4 Medications Module

本系列要討論的是FHIR Level 4 Medications 相關的Resource。

本系列的Resource主要用於:

  • 處方籤相關流程,如開立、配藥、給藥、服藥等紀錄。
  • 紀錄防疫,評估接種疫苗時間點等。
  • 藥品資訊與用藥知識。
Resource 主要分成兩大類:Medications與Immunizations。

Medications 系列簡單地說就是:
開藥-->配藥-->服藥 
(MedicationRequest-->MedicationDispense-->MedicationAdministration)
藥資訊-->藥更多資訊
(Medication--> MedicationKnowledge)
在吃什麼藥
(MedicationStatement)

Immunizations系列簡單地說就是:
打疫苗前-->打了什麼疫苗-->打疫苗後
(ImmunizationRecommendation-->Immunization-->ImmunizationEvaluation)

說實在,要介紹Resource的內容,真的是吃力不討好。講多了像翻譯,講少了還不如自己去看。

所以,這系列僅會針對重要的欄位進行說明。一些背景知識,就不再多加說明。網路上搜尋,中文的資料也越來越多了。(我寫的東西,已經不在搜尋的前幾條中,這是好現象吧。)



2021年2月8日 星期一

CDS Hooks 實作驗證

實作這塊,有點不好意思,程式碼還是不方便公布。簽了保密,還是保守點。除非老闆說可以。所以,這邊只好用別人的東西來展示。

CDS Services

CDS Hooks在Github上的資料也不少,網址:CDS Hooks (github.com)
進到docs裡的wiki頁面,可以找到一些對外公開的CDS Services。注意是在Example CDS Services。CDS Services for testing的東西都不能用。
裡面有很多不同Cards的實作。

CDS Hooks Sandbox

這就是所謂的CDS Client,可以是EMR。反正就是會讓使用者去叫用CDS Services介面的東西。

FHIR Server

原則上EMR應該會配有FHIR Server。但我們測試是用Sandbox,不會有FHIR Server,我們得找一個。
我是用Sandbox建議的FHIR Server:https://launch.smarthealthit.org/v/r4/fhir 。選哪個都無所謂,但建議還是以R4為準。
首先你要確認你所選擇的FHIR Server有支援,你在Prefetch Template所叫用的FHIR Resource。否則,你怎麼死的都不知道。
用Postman當然是最好的工具,問題是要打什麼指令呢?
  1. Get {based url}/{Resource} : 看看回來什麼東西。注意如果有Bundle回來,但筆數為0,表示這台Server有支援此Resource,只是現在沒有資料。
  2. Get {based url}/metadata:這個會回傳CapabilityStatement。在rest/resource,就會列出所有支援的Resource。其實,這個CapabilityStatement還有其他非常重要的資訊。就舉個最重要的吧。他們會把OAuth資訊放在這。這超出本系列的範圍了,但這真的很重要。

Patient ID

如果,有仔細閱讀此系列文章的話,應該知道Hooks的意義,以及Patient ID的重要性。你得要先確保,你的Prefetch Template所叫用的FHIR Resource,真的有這個Patient。否則你可能會不知道錯在哪兒。還有一個大前提,你要引用的Resrource得要與Patient(Subject)有關才可以用。
怎麼確認?還是用Postman。假設我要引用MedicationRequest。我們就用這個ID吧:2744ab6f-91dd-4e4f-8208-fe52ee2c27d1


那要怎麼知道,這個Patient有多少份MedicationRequest呢?MedicationRequest不是對應於處方箋唷,他只對應於一項藥品。所以,encounter就很重要,抱歉R4才支援。就當是作業吧。

進行驗證程序

假設您已經開啟CDS Hook Sandbox。畫面可能已經會有東西了,我們先把他清除掉。
開啟視窗後,把每一項都刪除吧。
沒有服務了,但左邊還有之前的病患資料。

設定FHIR Server

將系統建議的FHIR Server版次改為R4即可。記得要按Next。

設定Patient

上一步驟按Next就會開啟Change Patient的畫面。當然,也可從右上的選單中選擇。將我們找好的Patient ID貼上去。記得按Save。
到這邊總算完成了基礎設定的工作。原則上,變動機率不大啦。除非你想換另一台FHIR Server。一換FHIR Server,那Patient當然也要換。

加入CDS Services

這邊要注意一下,依據CDS Hooks規範,第一階段是Discovery,但並非所有的系統環境有支援。像EPIC就沒有,作法就會有不同。
CDS Hooks Sandbox有支援,所以你的CDS Server有幾隻CDS Services他都會全部抓回來。EPIC則是需要自己輸入CDS Services。
輸入CDS Service的Endpoint。還記得前面所建議的CDS Server嗎?
當你按下Save按鈕時,就是驗證奇蹟的時候。

結果

所有細節就不多說了。等待有緣人吧。

2021年2月1日 星期一

CDS Hooks - 規範 - 5

 終於來到最無聊的最後階段「Feedback」。

前言

在CDS Response Object中,有提到Suggestion,其實他應是由CDS Client端產生一個按鈕,並以POST方式帶Feedback物件回給CDS Server。這邊就得要注意,CDS Client的使用者,到底是按哪一個suggestion按鈕。還要注意,CDS Services有很多個,根據規範書的內容每一個CDS Service都要有自己的Feedback。

POST {baseUrl}/cds-services/{serviceId}/feedback

Feedback Object


card

當初CDS Response物件中Card.uuid的內容值。

outcome

CDS Client對此card的態度。兩個選項accepted或者overridden。

acceptedSuggestions

如果outcome是選擇accepted,那就得回傳到底是接收哪個(些)suggestion(無論是單選還是多選)。其結構很簡單,就是當初suggesion的uuid。


overrideReason

如果outcom是選擇overridden的話,可以提供理由。其結構為OverrideResaon物件:

 

 outcomTimestamp

最後給這個回應押一個時間戳記。這是必要欄位。


這邊高度依賴CDS Client的支援程度而定。不過,身為CDS Service必須位自己提供的建議作後續支援服務的機制。因為這個過程可能不是只有一個來回,有可能是數個CDS Service的組合方能完成一個臨床實務上的決策循環。 

2021年1月31日 星期日

CDS Hooks - 規範 - 4

今天討論「CDS Response」

CDS Response

CDS Service --> CDS Client

Response的前置作業

這個過程其實沒有這麼簡單。當CDS Client決定要引用CDS Server哪個Service時,就得遵守規定,把FHIR相關資源準備好後,叫用Service時,用POST帶上。如果用Postman測試時,在BODY的部分可選擇x-www-form-urlencoded(可減少設定)。
CDS Server從Endpoint接受到資料後,要開始解析。整個作業流程應該要分成四個重要階段。
  1. 檢核Post 資料正確性。也就是說,傳回來的Hook跟當初規定的是否一樣。
  2. 要解析fhirAuthorization。你要設計好流程,到底還要再跟FHIR Server要什麼東西。因為Access Token一般都是有時間限制(當然,還會有個Refresh Token的機制)。另外一點就是,他會有Scope的問題,就是Resource.Interactions。
  3. 要解析prefetch的內容。這塊要小心。一般而言,若Read,原則上你要什麼Resource就會回給你什麼Resource。若你是用Search,那就會是Bundle,要再進一步解析entry才是你想要的Resource。
  4. 取你CDS真正要的資料進行運算處理,然後得到結果。這個結果才是用來組出Response Object的資料。
這段講得輕鬆,但FHIR技術關鍵就在這兒。
Web的技術關鍵是OAuth與CORS。

Response Object

回傳一個物件包含兩個欄位cards與systemActions,兩個皆是陣列。
systemActions在1.0版沒有。所以,最簡單的範例:這個Card,是由CDS Client決定要如何呈現在他們的系統中。在EPIC他們稱之為Best Practice Advisory,會將Card的內容轉成HTML Web介面。
{ "cards": [] }

Card Object


這個是有點複雜,還會衍生出幾個物件出來。我就簡單描述,會做的應該一點就懂。

uuid

這個是可選欄位。若你有處理到feedback階段的話,那這個就很重要。在C#有個GUID物件,很簡單處理。

summary

這個是必要欄位。將你的結果簡單描述。字串長度要小於140個字元(我實作時有踢到這個鐵板) 。

detail

結果的詳細說明。若是Debug階段,一些訊息就放在這(別像我,以為summary是必要就放在那兒,結果是Bug的Bug)。

indicator

說明這個結果的重要程度。目前支援有info、warning與critical。理想上,應該是不同程度畫面要有所區別,但是要看CDS Client要不要實作。

source

這是用來宣告版權的,為必要欄位。其結構為:(不多加解釋,coding結構就是FHIR的資料型態)

suggestions

這個整個card的核心,卻是Optional。他的內容是suggestion物件陣列。用來描述,CDS所提供的可採取行動之建議。其結構為:

其中action欄位是實際描述「當CDS Client接受這個Suggestion時要如何處理」。其結構為:


 處理的方式不外乎create、update與delete(怎麼沒有retrive?啊你前面在幹嘛?)。resource就是處理的對象。就是Resource啦。這裡要注意你要處理的Resource,當初的Scope都要宣告到。不過,還是得看CDS Client有沒有支援啦(坦白說,FHIR的真還在發展中,就是因為發展中,那還不趕快跟上)。貼個EPIC支援的給各位參考。(剪圖關係未能全部)


 Source: https://fhir.epic.com/

selectionBehavior

如果你有suggestion欄位,那這個欄位就是必要。他只有兩種選項at-most-one,單選。與any,多選。哈~還是要看CDS Client有沒有支援啦。

overrideReasons

當CDS Client不接受你任何suggestion時,你可以用這個欄位讓他選擇不接受的理由。他是coding的陣列。還是一樣,要看CDS Client要不要支援。

links

這是提供給CDS Client一些建議網站或者APP實用的。他是Link物件陣列。其結構為:


範例

官方範例提供參考

{ "cards": [ { "summary": "Example Card", "indicator": "info", "detail": "This is an example card.", "source": { "label": "Static CDS Service Example", "url": "https://example.com", "icon": "https://example.com/img/icon-100px.png" }, "links": [ { "label": "Google", "url": "https://google.com", "type": "absolute" }, { "label": "Github", "url": "https://github.com", "type": "absolute" }, { "label": "SMART Example App", "url": "https://smart.example.com/launch", "type": "smart", "appContext": "{\"session\":3456356,\"settings\":{\"module\":4235}}" } ] }, { "summary": "Another card", "indicator": "warning", "source": { "label": "Static CDS Service Example" } } ] }

在實作的過程這個階段很痛苦。因為每一個CDS Client的支援程度與方式不盡相同,甚至容錯能力也不同。

2021年1月28日 星期四

CDS Hooks - 規範 - 3

 複習一下,CDS的實作流程有四個階段的規範,「Discovery」、「Request CDS」、「CDS Response」與「Feedback」。今天討論Request CDS。

Request CDS

CDS Client 呼叫 --> CDS Server實作

 Endpoint: POST {baseURL}/cds-services/{service.id}

Request Object


註:
1. 由CDS Client負責組合物件。
2. CDS Server得解析物件。

 hooks

叫用這個service所規定的hooks標準。大部分都是patient-view。

hookInstance

這是由CDS Client產生的UUID碼,他必須需Globally unique。CDS Server端,每一個hookInstance都是單一事件,都得單獨處理。我這次實作比較像寫範例,所以這個值我沒有記錄下來。其實,回應訊息時也不會用到。

 fhirServer

這個是CDS Client告訴CDS Server我的FHIR Server在哪裡。他是一個完整路徑。(切到資源)

fhirAuthorization

這個有點複雜是OAuth 2.0內容。主要是給你Access Token,讓你可以直接向CDS Client的FHIR Server抓取資料。不過,都得要事先宣告Scope,其流程沒有那麼簡單。也不是CDS Client都會給你。

context

hooks是規範,只有描述需要哪些鍵值欄位。CDS Client就把這次POST資料實際鍵值內容放在這裡。如果Client採用Prefetch方式,已經這個內容不重要。但是,採fhirAuthorization的話,這個就很重要。每次來回的資料總得是同一個病人吧。 

prefetch

這的內容很重要。他就是CDS Server用prefetch template告知CDS Client要準備的FHIR內容。CDS Server端在解析的時候要小心。當初你可以同時要了好幾條不同的Resource。另外,你可能走Search 方式,那你收到的可能是Bundle回來的東西,解析時要小心。

 Request 範例


 這是CDS Client發出的資料(部分)

至於這個sandbox介面後續會介紹。網址先給各位了:https://sandbox.cds-hooks.org/

CDS Server端就根據自己所需要資料到prefetch裡的FHIR Resource去抓囉。

其實,如果CDS Client如果沒有給你fhirAuthorization的資訊,那就隱含告訴你,去他們的FHIR Server抓資料無須Access Token。

至於要怎麼解析,程式面的問題,應該會找適當時間來寫寫。如果沒有保密問題的話。

至於CDS要怎麼運用資料,那就超出本系列的範圍了。




CDS Hooks - 規範 - 2

 進入無聊的階段,卻是實作最重要的階段。

實作CDS的整個過程,可以粗分「Discovery」、「Request CDS」、「CDS Response」與「Feedback」四個階段。(先把OAuth的部分屏除)

Discovery

CDS Client呼叫 <--> CDS Server實作

 Endpoint: GET {baseURL}/cds-services

Response Object:


註:

  1.  想看完整有Swagger文件:Swagger Editor
  2. 都是JSON格式。
  3. 注意Type是Primitive type, Object還是Array。 

hook

這個欄位是宣告兩端要共同遵守的鍵值變數組合(Context)。最常見的就是patient-view,他要求雙方有userId(R)、patientId(R)與encounterId(O)。這些鍵值欄位會以「prefetch tokens」的形式應用於prefetch欄位(後敘)中。所謂prefetch tokens就是用{{ }}包覆鍵值變數。

title

這個欄位可有可無,純粹用來給人看,由CDS Client決定要不要去呈現他。

description 

這個欄位反而是必要欄位,用來描述這個Hook服務的主要任務是什麼。

id

這個欄位非常重要,而且要小心設計。這個會是URL的一部分,也就是呼叫這個服務的路徑。所以,他必須要唯一。{baseUrl}/cds-services/{id}。

prefetch

這個欄位雖為Optional,卻是非常重要的欄位。CDS Server端告知CDS Client端,若要使用此服務,請你要提供哪些FHIR Resource。這個欄位內容的表達方式,有一個專有名稱為「Prefetch Template」是否能看懂且會用,又要用得好,就是看你FHIR的功力了。後面會專節說明。 

Discovery 範例

為避免一頭霧水,提供規範書的範例參考。這由CDS Server端實作,為/cds-services的回應內容。
{ "services": [ { "hook": "patient-view", "title": "Static CDS Service Example", "description": "An example of a CDS Service that returns a static set of cards", "id": "static-patient-greeter", "prefetch": { "patientToGreet": "Patient/{{context.patientId}}" } }, { "hook": "medication-prescribe", "title": "Medication Echo CDS Service", "description": "An example of a CDS Service that simply echos the medication being prescribed", "id": "medication-echo", "prefetch": { "patient": "Patient/{{context.patientId}}", "medications": "MedicationRequest?patient={{context.patientId}}" } } ] }
提醒,這個id與prefetch必須配對好,Server端要記住。當Client用某Id過來時,要知道他可能會帶什麼prefetch,別接錯了。

Prefetch Template

這段可能是CDS Hook最關鍵的地方。講到這先補充一下FHIR的Interactions。

CDS Hooks的Prefetch Template他就是FHIR read與search的機制。(另外支援的機制在後面規範會提到)所以,懂FHIR愈多,就能寫個漂亮的Prefetch Template,CDS Server端能要來的資料就更精確。
在官方文件就提供了一個範例:
{ "prefetch": { "hemoglobin-a1c": "Observation?patient={{context.patientId}}&code=4548-4&_count=1&sort:desc=date" } }
我非臨床人員,就不便多作解釋。不過,我可以跟妳說上述稱之為search機制。
一般最常用的就是
{ "prefetch": { "patient": "Patient/{{context.patientId}}", "user": "{{context.userId}}" } }
這是read機制。那個被{{ }}圍起來的就是prefetch Token。能有哪些可用,就看你是引用哪個Hooks規範。

先偷偷展示,回應會是長什麼樣子?(這是由CDS Client負責產生的)
{ "prefetch": { "patient":{ "resourceType": "Patient", "gender": "male", "birthDate": "1974-12-25", "...": "<snipped for brevity>" }, "hemoglobin-a1c": { "resourceType": "Bundle", "type": "searchset", "entry": [{ "resource": { "resourceType": "Observation", "code": { "coding": [{ "system": "http://loinc.org", "code": "4548-4", "display": "Hemoglobin A1c" }] }, "...": "<snipped for brevity>" } }] } } }