2024年12月21日 星期六

CDS Hooks - 程式設計 - CDS Service端

如上篇所言,這兒是用暴力法,把MLM上的判斷邏輯,用人工方式直接轉成C#程式碼。
還記得有一個CreateEmptyCard,那個是只有MLM的宣告,卻沒有收到任何資料來源時可回應給EHR的部份。
我們這邊用了兩個MLM,要有資料來源得上Sandbox,要有確定的個案對象才好測試。所以,這邊仍暫時保留之。

===== Responses =====
還記得Call Service時,會叫用Responses.GetResponseContent(),當時,只展示了空的Card,現在不一樣了。

判斷要用什麼CDS服務是透過Id,若沒有當然是給空的。
則就是針對個別,回應正確的Card。
目前先把FHIR Resoure部份先保留,因為這塊我想要完整描述。他會用到我自己開發的FHIR SDK。這邊就先假設,已經從Resource中取回想要的值。
接著就是分別呼叫對應的CardService。

====== BMI  ======

25:就是拿傳進來的值去做邏輯判斷。
26~35:提供外部連接用。
36~44:準備建議按鈕。 篇所言,這兒是用暴力法,把MLM上的判斷邏輯,用人工方式直接轉成C#程式碼。
還記得有一個CreateEmptyCard,那個是只有MLM的宣告,卻沒有收到任何資料來源時可回應給EHR的部份。
我們這邊用了兩個MLM,要有資料來源得上Sandbox,要有確定的個案對象才好測試。所以,這邊仍暫時保留之。

===== Responses =====
還記得Call Service時,會叫用Responses.GetResponseContent(),當時,只展示了空的Card,現在不一樣了。

判斷要用什麼CDS服務是透過Id,若沒有當然是給空的。
則就是針對個別,回應正確的Card。
目前先把FHIR Resoure部份先保留,因為這塊我想要完整描述。他會用到我自己開發的FHIR SDK。這邊就先假設,已經從Resource中取回想要的值。
接著就是分別呼叫對應的CardService。

====== BMI ======

25:就是拿傳進來的值去做邏輯判斷。
26~35:提供外部連接用。
36~44:準備建議按鈕。 在此僅是產生一個按鈕,準備Feeback階段時可接收。但Action區塊沒有設定,沒有準備FHIR Resource,所以就沒有的後續作業問題。
45~57:產生Card。

至於BMIEvalue的部份,就依照MLM的邏輯判斷來處理。

===== HeartRate =====
這塊就簡單帶過。

HeartRateEvalue的部份。






2024年12月20日 星期五

CDS Hooks - 程式設計 - 實做抉擇

討論到現在,前端服務架構已逐漸成形。 現在的問題是要收來自EHR端的POST資料,更重要是FHIR Resource與FHIR Server的相關資訊。然後翠取出CDS Serevice所需的資料內容,送給他處理,並且等待結果轉化成Card類別,回覆給EHR端。

現在要面臨深思的事,這個平台到底是要處理一般化,還是要特殊化。

特殊化很單純,目前這個專案就是處理兩個CDS,BMI與Hear Rate。而且他們要的資料都很明確就是要Observation然後各自對應LOINC碼,把Value值抓出來丟給CDS。兩隻CDS收到資料後,開始進行邏輯處理(這個對資訊人員來說,就是最困難的部份)。處理好後,再把結果組合成Card後,送回給EHR。這個叫暴力實做法。

而一般化,就是說這個平台只要匯入MLM的話,就自動產生的一個CDS 服務,這是我的理想。而這個目標也是可行的。Arden Sytax已經開始支援FHIR,只是應用上還不很明確。當資料源(Data:)確定資料,那邏輯(Logic:)的部份就是Parser程式的問題。再明確一點,就是有一個MLM的編輯器,把文件寫好後,就可以產生CDS Hook要的設定檔。

可惜,這些年來我的工作一直跟FHIR無緣,只能利用下班時間研究,能量還是有限。再者也沒什麼深厚背景,可以搞新創,搞基金。總之一切隨緣。

==========

雖然說是暴力實做法,但是,跟FHIR Server互動這塊,還是會提供程式碼參考。雖然,目前挑的這兩個案例,只會用到Observation,但實務上,不會這麼簡單。(哈~要找到漂亮複雜的CDS,那就超出我能力範圍)。只是Access Token的部份,我還是會保留。畢竟我也不是專搞慈善事業的。



2024年12月19日 星期四

CDS Hooks - 程式開發 - Call Service

當EHR叫用cds-services得知目前CDS Server支援了哪些CDS項目。接著就依據Id名稱,正式叫用服務。但,這時候已經把兩邊搞的天翻地覆了。

EHR要依據CDS Hooks端的要求,把所有資料準備好,接著用POST方式叫用服務。

CDS Hooks端收到資料後,就得開始找出真正提供CDS服務者。這個過程有點複雜,因為使用的Hooks不同,FHIR Resource會出現在不同的地方。另外,會有Reference Datatype的問題,不過這個可以在一開始Prefetch時,把查詢的URL先搞定。

這篇只說明呼叫時的運作,還沒有到CDS Service。

程式

===== Call Service ====
根據CDS Hooks的規範書可知,選定服務後在/cds-services/{service.id} 。

30: 根據傳進來的service.id來取得他的Hook內容。
32: 需要一個負責回應Card內容的類別Responses,呼叫啟始設定函數InitHook()。
33: 再呼叫GetResponseContent()。注意,這個函數要處理很多事情,包含去呼叫對應的CDS,然後產生適當的Card出來。
40~44: 這是要符合CDS Hooks規範要求。

===== Hooks =====
這個類別上次就看過,在這邊是已知Service.Id之下,來找出對應的Hook內容。

===== Responses.InitHook() =====
這裡的重點不是函數本身,而他ParseRequestModel();

在EHR送過來的資料中,有三個非常重要的東西其型態卻是object。分別為context,
prefectch與fhirAuthorization。避免複雜fhirAuthorization部份不實做。
利用ParseRequestModel()來拆解內容,並給後續步驟使用。
還有一個因素是FHIR Resource都有可能在Context與Prefectch中。前者是草稿中,後者是已結案的。

===== Responses.GetResponseContent() =====
目前這個函數的內容是暫時的,因為真正提供CDS服務的類別還沒完成,所以Card的內容都不會有。

這邊使用到一個CardService,他是用來與CDS溝通,並產生Card類別提供給EHR端。目前先用他的一個產生空白Card的函數。
這邊有個CardModel,這是依據CDS Hooks規範要求所設計。

===== CardModel =====
他衍生了很多類別,這邊就不多說。會有專篇來討論Card這個複雜的傢伙。

===== CardService =====
這個類別以後會很複雜,目前就單純先給個CreateEmptyCard的還是來做驗證之用。

另外,我也沒有使用Sandbox進行測試,所以Body資料是空的,只能一步一步寫,一步一步解說。

測試

===== BMICalculation =====

===== HeartRateMonitoring =====


CDS Hooks - 程式開發 - Discovery

整個遊戲的一開端,就是EHR端要先知道CDS Hooks端提供了哪些CDS服務。這個階段稱之為Discovery。不過,有些平台例如EPIC,他就會省略這一段。

程式

===== Discovery =====

根據CDS Hooks的規範書可知,CDS Hooks端要提供一個endpoint 叫cds-services。

(這不是C# DotNet教學,細節就不多提)

這個Endpoint內容很直覺。就設計一個Hooks類別提供所有Hooks清單。

===== Hooks =====


Hooks類別,主要目的是去讀取HookSettings.json檔案。這個檔案就是描述著會有哪些CDS Hooks服務。

讀進來後,就可以提供GetHooksList函數了。


其中ServiceModel就是依照CDS Hooks規範之要求所設計的。

===== ServicesModel, HookItem  =====



這兩個類別應該不需要多做解釋。那個UsageRequirements抱歉,我也還沒搞清楚實際用意為何。

===== HookSettings.json =====

 回到這個設定檔。


透露一下,這個設定檔是產生自另一個介面,其內容都是來自MLM(當然,您不需要如此)。唯一要注意的是Prefetch這段。這是要求EHR端,要使用這個CDS服務時,需要準備什麼樣的FHIR Resource。這塊自動化的程度,仍有待思考。

==========

測試



2024年12月15日 星期日

CDS Hooks - 程式開發 - 簡易說明

開發CDS Hooks,其實不難,難的是你要提供什麼服務。

在此架構中,EHR是需求端,CDS Hooks是服務(回應)端。之間只有資料層面的交換,並沒有UI(網頁)內容呈現。(若有,那請走Smart on FHIR架構) 

本次系統開發採用C# DotNet 9,用Web API專案範本。(若Smart on FHIR就需MVC或Blazor) 

依據CDS Hooks規範,需要提供下列服務(Endpoint)

  1. Discovery:讓EHR端知道CDS端提供了哪些CDS項目。 CDS端要告知每一項服務會走什麼Hook(這個會決定Context內容),其id編碼是什麼(如Patient Id, Encounter Id)。然後可以順便告知,要使用這項服務的話,需先準備哪些FHIR Resource。上述內容CDS端會回傳services這個json檔。
  2. CDS Service:有了上述服務清單,EHR端的使用者就要決定採用哪一項服務。EHR決定要呼叫那個服務時,就得先準備好幾項東西,例如Fhir Server在哪(若還要再撈其他資料,例如遇到Reference型態),fhirAuthorization相關資訊(若需要的話),還有Conttext所要求的Id內容,另外,當初在Discovery時,CDS端告知需要事先準備的FHIR Resource。CDS端收到資料後,經過處理,然後回傳card這個json檔。EHR端要負責解析呈現這個card json檔內容。
  3. Feeback::上一階段回傳的card內容,其實包含了很多按鈕宣告。而CDS端則需要接收EHR使用者到底按了那個按鈕的訊息,然後進行下一個步驟。例如刪除Resource或者新增Resource。
雖然,表面說來很容易,但為了系統彈性等因素,相關配套物件設計就不能少。例如:
  1.  Prefetch的宣告:重點就是如何宣告一個Resource的查詢URL,而能夠效率最佳化。(不用一來一往,重複存取)
  2. Hooks的選用:目前這塊也不是很穩定。向CDS Hooks Sandbox他也只支援patient-view與order-select。這塊會影響到Perfetch能產生多複雜的查詢語法。
  3. Authorization設計:CDS Hooks與Smart on FHIR架構差距此為重要一點。CDS Hooks是請EHR端準備好Access Token相關資料,請一併送過來。而Smart on FHIR則是需要一段一段交握中取回。
  4. Card的設計:這個是最困難的部份,因為要配合CDS端的設計,畢竟Card能夠處理的是有限的。CDS設計了太複雜的回應結果,是很難用Card來完整呈現。再來,Card是有EHR負責Render,所以,呈現的結果可能不會是CDS端所想要的。
  5. Feeback設計:EHR端的回饋,其實是由CDS端決定的。也就是把按鈕設計在Card中。問題就是,能設計到多複雜,要細分到什麼程度?後續的處理模式刪除或新增,這個還得問問FHIR Server是否有開放支援。
總之,CDS Hooks並非像有些人口中所言,可以輕輕鬆鬆完成的事情。

CDS HOOKS - 選擇測試平台(CDS Hooks Sandbox)

原則上應該要有自己發展的EHR,然後搭配自己的FHIR Server來進行展示。可惜,自己工作不在FHIR上,無法專心開發相關系統。
但就CDS Hooks的開發者來說,就是開發一個單純提供資料處理服務,資料來源(FHIR Server)與展示平台(EHR)本來就是要來自外界。

目前CDS Hooks Sanbox 最好的測試平台是:https://sandbox.cds-hooks.org/
(用Chrome開啟會有問題)
一些設定功能可參考這篇
 
1.的部份,就是接著我們要開發的部份。
2.的部份,是我們選擇從那個FHIR Server調取哪一個病人的資料。
當然這個介面就是用來暫時替代EHR。

這系列強調的是實做,至於CDS Hooks的規範部份,請參考這系列文章




2024年12月14日 星期六

CDS HOOKS - 確認測試資料源

這個步驟在實際上線時,可有可無。若個案沒有所需資料,當然此項CDS HOOKS就不成立。但為了說明實做,總不能最後結果都是個案無資料。

目前各家可公開測試的FHIR Server都有些差異性,而且,查詢特定資料的方法也可以多樣性。所以,這篇的目的就是想先確認,哪一個FHIR Server可以提供穩定資料來源方便測試。

使用工具就是之前開發的FHIR Query Builder工具。有興趣可以參考這篇

預計檢視的FHIR Server有:(為降低實做複雜度,僅採用Open)

要實做CDS的項目有下列,而根據MLM的描述,要實做這些項目,所需要的資料分別註記於後。
  • BMI Calculation
    • bmi: numeric (input)
    • weight: numeric (option)
    • height: numeric (option)
    • bmi_category: text (output)
  • Blood Glucose Monitoring
    • blood_glucose: numeric (input)
    • recommendation: text (output)
  • Heart Rate Monitoring
    • heart_rate: numeric (input)
    • recommendation: text (output)
接著要問有沒有FHIR Profile可以參考呢?
=====補充說明=====
Blood Glucose的部份有一點麻煩。他是來自NHSN Reporting: Adverse Drug Events - Glycemic Control,其中code的部份,他要求綁定VSAC 2.16.840.1.113762.1.4.1190.38。要查他的碼,得要先註冊UMLS。然後查得這是一系列編碼。

以我能力是無法做出正確判斷。我的能力只能告知這些東西要怎麼取得,要怎麼看,最後的臨床知識,我就不能逞強。也就是說,這個CDS HOOKS我就暫時不處理了。
==========

接著就是要從FHIR Server查看看,是否有個案可以提供測試與展示。(不想篇幅過長,就展示結果)
=====BMI https://server.fire.ly/ ====
根據Profile,要找Observation
  1. code/Coding/system = http://loinc.org
  2. code/Coding/code = 39156-5
這個FHIR Server可以,高達122筆個案符合此條件。


=====Heart Rate  https://server.fire.ly/  =====
根據Profile,要找Observation
  1. code/Coding/system = http://loinc.org
  2. code/Coding/code = 8867-4
這個也不錯,有283個個案符合。