2015年12月18日 星期五

Dynamic Hotstring實例

之前在「自己寫武功祕笈:Radiologist的第一個Autohotkey」提到一點dynamic hotstring的使用,這篇再介紹幾個實用範例。

Prerequisite

  • Regular expression:雖然看起來像火星文但真得很重要(自行覆頌三遍),可參「Regular Expression入門
  • AutoHotkey_L:一般而言用Unicode 32-bit
  • Dynamic hotstring的library:AutoHotkey的論壇上可以找到幾種版本,我用的是比較多選項的這個版本
    • 下載Hotstring.ahk存到AutoHotkey主程式資料夾內的Lib資料夾,或者ahk檔資料夾內的Lib資料夾(詳見說明
    • ahk檔開頭加上#include <Hotstring>
  • 自訂的hotstring是以函數方式執行,所以要放在auto-execute section內,簡單來說就是在第一個return之前的範圍

 範例1:日期

  • 輸入:8個數字,再加上一個分隔字元,例如20151218/
    輸出:2015/12/18


 範例2:檢查部位

  • 輸入:不定部位的字母代號,加上without/with contrast enhancement數字代號,以及一個結尾符號,例如b1=
    輸出:CT of the brain without contrast enhancement shows:

範例3:lines and tubes for CXR

  • 輸入:數個字母代號,加上結尾符號,例如tgv=
    輸出:Placement of endotracheal tube, nasoenteric tube, central venous catheter(s).

2015年12月11日 星期五

醫病溝通

根本就是平行世界。大部分時候只是醫生覺得病人懂了自己講的,病人也覺得懂了醫生講的,其實是各自腦補

今天第一次參加這種面對面溝通,雖然主要是針對一線的醫師,但也會做到procedure的敝科也無法置身事外。簡而言之就是常見的劇本:病人因為碰到一連串的事件不幸掛了,家屬不能接受,列出某些不滿意的事項(通常都是小缺失),質疑如果沒有這些小事件,是不是就不會有今天的結果。當然,「人好好的進醫院,怎麼會變這樣」的經典台詞也出現。幾個簡單心得如下:
  • 大部分人「不理性」, 更何況是剛遭遇那麼重大的事件。同樣的質疑點一提再提,不知道是不接受還是聽不進去,或是瞬間就忘了,一直鬼打牆似的對話重播。大概就是問了A,回答A,有可能還沒回答完又突然想到質疑B,回答B後換C,C回答後又回到A,講半天完全沒進度沒共識。
  • 大部分人無法被「告知」、無法「理解」、更不用說「記住」專業的知識。以前說什麼要「告知同意」,但病人/家屬絕對不可能理解100%,甚至可能是「-100%」,也就是完全誤解。再加上記憶力是有限的而且不可靠,事後醫生說他講過,但家屬覺得沒講過,各說各話,沒錄音根本沒證據,只能說還好簽同意書已經是routine。
  • 承上點,除了沒有專業的知識,有些完全錯誤的知識反而根深諦固,例如沒看過急性中風,質疑為什麼30分鐘前人是好的,見面時就發作,「哪有那麼巧的」;醫院冷氣那麼冷,害人身體變虛,害人感染;「再觀察」就是沒在治療,「保守治療」就是沒有盡力治療。不勝枚舉,只能說還好這些觀念在法庭上沒有什麼威脅…
  • 大部分人無法注意到「醫療上」會影響病人的因素,只能把注意力放在「醫療外」的枝微末節,但覺得是這些細節影響了預後。這部分大概是最難想像、最難掌握的,護理師不經意的一個動作(沒有蓋被子)、某位醫師(包括大P或菜鳥)隨口的病情評估(這一定好起來/好不起來),反而記得一清二楚,連那個人長得胖瘦高矮都記著,總之就是各種服務不周到。有些人希望醫生講越多越詳細越好,做個手術可能會死可能會植物人是基本的,各種替代治療不管對病人是好是壞都要知道;有些人反而不敢聽那麼多,聽越多越怕,覺得不吉利;反正怎樣都能怪。
  • 大部分人沒有benefit/risk的概念,不知道在不同狀況下會有不同的考慮,沒有標準答案,也不是SOP。可能遇到的說詞是:為什麼某個(侵入性)治療要「拖」緊急時才做,不能提早做,不能「預防」嗎?侵入性治療一定兼有benefit/risk,沒有適應症甚至有禁忌症的狀況下,risk1 > benefit1,整體效益可能benefit1 - risk1 - cost < 0;但在危急狀況下,不做治療的risk嚴重許多,不治療效益是 - BigRISK,治療的效益是benefit2 - risk2 - cost,所以有可能要治療。注意benefit1不一定等於benefit2,risk1也不一定等於risk2;而且,在危急狀況當下,很可能不治療或治療的效益都是負的,只能「兩害相權取其輕」。隨著各專科專業化,有時候連不同科醫生間也會吵起來,互相思考不周,只看到人家某種治療的benefit,卻沒去了解相關的risk,或者反之。
行醫生涯,很難不會越來越保守,尤其是還很菜的時候… 大家常說的一句話是「還沒踢到鐵板,只是做得不夠多」。在踢到鐵板前,前輩們會叮嚀先穿好鐵鞋,雖然鐵鞋會造成某種程度的不便(例如別人覺得你效率低落),但為了防止踢到鐵板,確實是智慧的傳承,是一種自己人才知道的,benefit/risk之間巧妙的平衡。

2015年9月7日 星期一

Triangulation of mammography

所謂的breast lesion的triangulation,是說MLO或CC其中一張看到lesion,但另一個view不確定在哪,則再照ML。如果(相對breast中軸)的距離,ML比MLO高,則lesion在medial side,反之則在lateral side。可參考這篇paper或是這張小小示意圖

以數學表示之:

  • 以nipple為原點之極座標系,假設lesion在(r, θ),θ = 0表示正上方,θ = π/2表示lateral,θ = -π/2表示medial。如果直角座標系則是(r sinθ, r cosθ)
  • 於是lesion在ML時高度為r cosθ,在CC時為r sinθ。事實上,對於某φ角度(原點及方向同θ)之造影,lesion高度為r cos(θ-φ)。
  • 對cos(θ-φ)作圖,θ from -π to π表示lesion從medial到lateral,φ from 0 to π/2表示從ML到CC,Z軸表示lesion高度,如圖
  • 直接看contour plot,medial lesion也就是t from -π to 0的部分,在p from 0 to π/2也就是ML到CC,顏色變深也就是值變小;lateral lesion也就是t from 0 to π則相反。大致上正確。
  • 仔細想發現不對呀,就cos(θ-φ)而言,for any θ from -π to π,在φ from 0 to π/2並不一定是嚴格遞增或遞減,例如一個lesion在θ = π/8處,則ML排到CC的高度應該像這張圖
  • 因此結論是:原始敘述並不完全正確,而且lesion在各個view間的關係並不在「直線」上,而是在cos曲線上。

2015年8月16日 星期日

新天鵝堡拼圖



四月底去德國時,在新天鵝堡買了2000片的拼圖,前幾個月進度緩慢,反而這幾個禮拜準備考試,念書累了拼一下,終於在今天完成!!

以前很少拼圖,那麼多片也是第一次(小時候看舅舅拼1500就拼很久了),在拼之前還特別google看別人怎麼拼。雖然不是老手,但拼完總是有些心得:

  • 找一塊空地/空桌規劃為拼圖區,要做好長期抗戰的準備。不能只預留拼圖的完成大小,因為零散的一塊塊拼圖會佔更多空間。
  • 找一塊夠大的紙板(例如攤平的紙箱)當作底,素色面朝上,拼到一半要拍照留念比較美觀。
  • 找一些小紙盒,或是有凹槽的保麗龍(買家電時在紙箱內的),分類用。
  • 拼圖分類:
    • 找邊:最重要的邊緣先分出來!!
    • 依顏色區分,例如最醒目的紅色,建築的米白、天藍、雪白、黑色
    • 左上的樹是失焦的部分,對應的是糊糊的拼圖片
    • 斑駁色,包括兩邊下方的藍黑斑駁色、右邊超多樹枝區、背景細密樹林、不是很純白的白色(遠方雪山、左下積雪等)
  • 剛開始先拼建築,也就是紅色和米色的部分
    • 有些屋頂的雪可能會被歸到雪白類
    • 被樹枝覆蓋,或是和背景相接處,在分類時可能也歸在不同的地方。倒也不用特地去找。
  • 接下來是失焦的樹,但模糊的拼圖片看起來都很像,拼不順利。拼到一半先換兩邊下方的陰暗樹林。
  • 右邊樹枝是最耗眼力的部分,有鑑於東湊西湊太費時(一堆樹枝、雪塊、葉子都差不多),於是出動Radiologist大絕,直接在原圖找絕對位置,然後放到紙板上大概的位置!當然還是有些小技巧
    • 對原圖時最重要的是方向要對,例如雪會在樹枝之上、陰影在樹枝之下、雪塊的上半是較完整的圓弧、根據背景的顏色可以猜在上方還是下方
    • 無法猜方向就只能四個方向都找,找的時候先盯著拼圖片,記住一些特徵,例如樹枝交叉的角度、雪塊的形狀、一塊特別形狀的陰影之類的。
    • 因為和原圖比還是有色差,有時候先在紙板上已定位好的拼圖片比較,猜測大致的位置
    • 原圖是相對比較小的,最好有個比例尺可以時時參考,例如已知拼好的某一雪塊的長度大概是拼圖片的大小,這樣對於手上這片的目標物大小比較有概念。
    • 拼到七、八成以上,就不一定要對原圖,常常在半成品上比對一下就能找到位置,通常是老婆的工作,我繼續比對原圖
  • 有了右邊樹枝的經驗,左邊的樹就容易多了,建築下方及左方的部分也是用類似的方法完成。
  • 背景的細密樹林、遠山、天空、左下雪地則由老婆完成!
  • 找時間再去雷諾瓦裱框
結論:相輔相成的兩個技巧就是「找原圖絕對座標法」以及「鄰近片拼湊法」,優缺點大致剛好相反:
  • 前者耗眼力,但一旦找到就可當作已拼上,一次找一片,不需要額外的空間放置散落的拼圖片。因為原圖和拼圖有色差、比例的問題,有時候找起來沒那麼容易。
  • 後者在拼圖片數目太多時嚴重影響效率,而且需要額外的空間,通常要再依色澤、明暗度 分成幾個subgroup。優點是不需要分辨上下左右,拼起來就是了。拼圖片的大小寬窄、特殊片(全凸、全凹、三凸、三凹)也提供線索。
另外也找到新天鵝堡的3D拼圖,發現小時候好像拼過,真是有緣!

2015年8月9日 星期日

Structure of AutoHotkey Script

開始上工打報告,除了看說明檔學AHK的語法、函數,有些程式撰寫的概念是在說明檔學不到的,身為業餘工程師(?)分享一些用血淚(?)堆出的心得~

單一檔案


  • 大概是老師輩比較常用的,攜帶方便,一個ahk檔和一個AutoHotkey.exe主檔就可以到處帶著走,不管電腦有沒有安裝AutoHotkey,或是電腦內AutoHotkey版本不一樣,只要把ahk檔拖曳到主檔就好了。
  • 老師輩的AHK大部分是以字母順序排序,而且hotstring以全部大寫設定
    • 優點:管理方便,搜尋快速(人眼搜尋就很快了)
    • 缺點:
      • 只有hotstring字母按順序,送出string沒什麼順序,明明是相似的內容(例如left、right)但彼此距離很遠。
      • 重複的string可能分給不同的hotstring而不自知。
  • CWY老師的script雖然是字母排列,但是兼顧系統分類,例如:
    • 「J」開頭通常是joint →  JGH 是glenohumeral joint
    • 「B」開頭是bone的某個部分 →  BFI 是femoral intertrochanteric region
    • 「Q」開頭指的是某個方位 →  QP 是posterior aspect。

多個檔案

  • 最近幾屆的學長姐開始區分不同用途的script,通常有一個打plain film,有一個打CT/MR,根據group可能再多一個打特殊檢查例如mammography。
  • 優缺點大致和單一檔案的情形相反:
    • 優點:
      • 各script所用的hotstring可以重複,同樣是「C0」,可以設定為Chest X-ray的normal report,也可以設定為Chest CT的normal template。
      • script內的hotstring較少,效能較好(影響不大),比較不會因為電腦lag出現使string延遲送出
    • 缺點:
      • 需要切換script,當然,通常打報告時會集中打同一種類的檢查,再打另一種類的檢查,並不如想像中要一直切換(除了值班時急診報告?)
      • 管理不易,有些通用hotstring要在每一個script都寫一次,例如 L 是left,R 是right,不論是哪一種報告的script都需要

樹狀結構

  • 學弟妹接觸AHK較多,開始會用樹狀結構,把某些hotstring寫在main.ahk,再各自有CT.ahk、CXR.ahk之類的,然後include main.ahk,大致也是我用的方法但底下會再細談
  • 優點和上一個類似,新增的優點是有main.ahk可以寫通用的hotstring
  • 缺點就是複雜,如果加上一堆hotkey、function、subroutine,因為AHK先天不嚴格的語言結構,有時候很難找到出錯的地方,debug不易。但如果每個script都是純粹的hotstring/string pairs,樹狀結構其實是最好的。

Some Tips

  • 我的script架構是樹狀,基本上就像其他程式語言的library一樣,分工合作!
  • 因為hotstring的數量不會太影響效能,所以原則上是能縮寫就縮寫,從word、phrase、sentence到paragraph,只要用縮寫就是會比較快!(當然,要記憶的hotstring較多)
  • 基於歷史因素,因為resident時打最多的是急診CT,main.ahk就包括general term以及CT/MR會用到的片語/句子/範本
    • 在script中以用途/部位分類:
      • history/title:哪幾個部位的CT、有沒有打顯影劑,事實上這部位是以dynamic hotstring去送出字串。
      • 方位:上下左右內外深淺,及搭配「aspect of」
      • 一般字詞:thickening, wall thickening, fat stranding, stenosis, narrowing之類的都有設定hotstring
      • 輔助詞:把finding串接成句子/不完整句的一些輔助詞,例如there is, is suspected, is noted, suggestive of, probably, showing, causing, nature to be determined之類的
      • 各部位:brain, neck, chest, body, MSK, intervention
    • 在各個部分,剛開始以字母排序但後來就隨意了,反正有Hotstring Helper可以查詢,不需要用Ctrl + F找
    • 通常hotstring以「1」結尾代表名詞複數,例如::nd::nodule,則:*:nd1::nodules,加星號表示不用ending character。但在形容詞/動詞則是詞性變化,例如::enl::enlarged, :*:enl1::enlargement;::sig::significant, :*:sig1::significantly。
    • 用數字也可以代表程度,例如brain atrophy、leukoaraiosis的罐頭敘述
    • 基本上hotstring以2個或3個字母為主,因為排列組合後其實很夠用,最最最常用的才是1個字母,不常用的或是template可用到4個字母。為了避免重複,以子音決定所用的hotstring。
    • 其他一些dynamic hotstring也會在main.ahk設定,為了避免dynamic hotstring和一般的hotstring相衝突,dynamic hotstring常以特殊字元結尾當作trigger(例如 =, /)
  • Plain film的ahk以CXR, KUB, MSK plain film為主,然後在最後一行include main.ahk
    • main.ahk裡的auto-execute section無法被執行(函數的定義還會在),所以需要用到的dynamic hotstring需要在plain film重新寫入。
    • 如果有重複的function、subroutine名稱會出錯,考慮加上namespace的概念,例如main_func和plain_func以區分。
    • hotstring是先搶先贏制,所以plain film中的hotstring會優先於最後一行include進來的main.ahk。例如::ll::left lung,則main.ahk的::ll::on the left side就沒作用
    • Hotkey無法重複定義,但如果用dynamic hotkey則可以啟動、停止、覆蓋舊的hotkey
    • 在確認報告(F3)時,會check報告內容(plain film報告不分段)再送出
      • 句首字母大寫
      • 兩個以上的點「..」變成一個點「.」:打報告時以「.」來觸發hotstring(雖然沒有證據證明,但我覺得按空白鍵觸發比較容易在string還沒全部送出前就穿插在句子中間)
      • 「.,」變成「,」:需要補充句子(例如要加上more on the right side.)則以「,」觸發hotstring
      • 如果有三個字母/數字就接著句點,表示hotstring打錯或是沒觸發,出現提醒。
    • 打plain film時,active的視窗是PACS還是可以按F3送出報告。
    • 因為plain film有時候會爆量打不完,所以hotstring要盡量用1-2個字母,就像嘸蝦米輸入法一樣,一碼/兩碼都有對應的字(雖然很多要死背)。
  • 另外還有mammography的ahk
  • 一旦發現有字詞沒有hotstring一定要馬上新增,不能偷懶!
  • 少用到的字母如Z, X, Y, Q等都可以用來當hotstring,例如前面提到的Q當作某個aspect(記法:Quadrant)、Z當作和某個檢查/臨床correlation(記法:coRRelation)的敘述