2016年3月12日 星期六

Hotstring優化:追求極致速度

AutoHotkey的最大優點就是簡易的語法,方便設定hotstringhotkey。不過畢竟最後是CPU在跑,寫一行程式碼,不一定比三行程式碼還快,要讓程式跑得快,還是要以電腦的角度去思考。例如以最簡單的 ::btw::by the way 為例,trigger之後AutoHotkey會模擬鍵盤傳給Windows的code,Windows再送到active的文字編輯器,文字編輯器被接收到一個鍵會觸發/更新一些內建數值(例如目前是第幾個字元、總共幾個字元、儲存上個狀態以便Ctrl+Z可以復原等等),然後更新文字輸入區的畫面,讓使用者知道程式沒當掉依然有反應。在AutoHotkey的範圍內可做到幾點優化:
  • SetBatchLines -1
    • 預設設定下,AutoHotkey每執行一行程式碼,會短暫休息,再執行下一行,以避免讓CPU太操。但既然用AutoHotkey就是要效率,給他催下去!
  • SendMode, Input
    • 預設的Send是SendEvent模式,但SendInput在大部分的狀況下是Z>B,包括
      • 送字速度快
      • 因為有buffer,如果程式正在send字串時使用者也按下鍵盤,使用者按的鍵會在字串送完時接上,而不會中斷(最多buffer 5000個字元)
  • SetKeyDelay, -1, -1
    • 這個設定也是類似SetBatchLines,為了模擬正常人類按鍵,按下去會有一定duration,兩個按鍵間一定有一些delay,通常是遊戲才會偵測有沒有cheat
    • 雖然這個設定影響的是SendEvent,但有非常少數情況下AutoHotkey會自動從SendInput轉換成SendEvent或SendPlay,所以還是可以設定
  • 複製貼上法
    • 對於較大量的字串,例如某個procedure note的範本,用send會非常慢。比較直覺的方式是用剪貼簿當作媒介來複製、貼上

    • 註解掉的兩行是為了保留原本的剪貼簿內容,但在連續輸入的情況下不太需要
    • 有一說要搭配ClipWait,但日常小量字串應該都能順利運作,所以沒有使用
    • 實測比較SendInput和sendByClipboard,發現大概以7~10個字元為分界,更多的字元後者較快,較少的字元前者較快。
    • sendByClipboard的缺點:
      • 組合鍵(用到Ctrl, Alt, Shift, Win等)無法用(不過通常也不會很大量)
      • 單行定義的Hotstring會依據首字是否大寫/全部大寫,送出相對應的字串(首字大寫/全部大寫),sendByClipboard只能用笨方法來模擬。(注意後兩個搭配c選項)

  • 直接送字法
    • 利用剪貼簿畢竟多了一道程序,可以直接設定輸入框裡要顯示的文字。
    • Standard edit control可以搭配Edit library,測試會比剪貼簿方法還快,但缺點是全部文字整個更新,畫面可能會閃一下,或者捲軸的位置不一樣:

    • Scintilla control是SciTE、NotePad++所使用的,可以搭配Scintilla wrapper以及自己寫的RemoteScintilla,速度和standard edit差不多,優點是很多強大的功能
      • 在自己的gui建立及操作Scintilla control要用Scintilla wrapper,但如果要access或modify其他process中的Scintilla control,則要用RemoteScintilla,利用_RemoteBuf library搭配Scintilla Documentation裡列出的messages(AutoHotkey的ControlGetText和ControlSetText只針對standard edit)。
      • 利用SCI_ADDTEXT,可以在游標處插入字串,而且游標會跳到加入字串的最後面,和Hotstring或是複製貼上的動作是一致的。

    2016年3月5日 星期六

    Automatic Lung CAD

    Low dose chest CT漸漸成為趨勢,幾乎是chest X-ray般的輻射劑量,卻提供超多細節,以及chest radiologist的工作量 T_____T

    本院chest CT檢查量就像物價一樣漲個不停,打起來最爽快的莫過於cancer follow up,爽點包括:
    • 已經有診斷、有治療,定期追蹤看有沒有復發、轉移,大部 分都是post-op changes, non-specific changes,以及一些雜魚tiny stable nodules。
    • 有前人打的報告,copy & paste再做些修改。
    • 之後會繼續來追蹤,有nodule沒看到,下次總會有機會再看到。
    • Multiple bilateral lung metastases最為#無痛,而且可以#秒殺,因為就已經是一堆nodules了啊!
    相反地,low dose chest CT可怕之處在於:
    • 通常是較健康的人(例如健檢),只有非常少、非常小的nodule
    • 因為是健康的人,氣吸很飽,肺變得很大,守備範圍加大…
    • 這個檢查要看細切影像(1mm),動輒兩三百張,非常耗神耗眼…
    • 萬一沒找到lesion,下次回診時可能已經真的有cancer了,雖然不一定有相關性,但被告的機率感覺比較高,#怕怕der
    • 因為low dose,soft tissue看不清楚,liver到底有沒有tumor只能瞎猜

    當LDCT成為事實,CAD就是義務!


    目前部內的架構是:
    • 做完CT → 細切傳至部內RAID(Osirix, iMac)
                 ↘ 粗切傳至醫院資訊室PACS

    為了自動化CAD,幻想中的流程是
    CT → 某台強大電腦運算CAD  ← user query
    • 可惜本人image processing很弱,只看paper無法自己拼成可用的程式
    • 也是有別人寫好的現成的matlab code,但效果沒有很好…

    於是規劃了複雜的流程
    CT → RAID → Workstation (CAD) → Orthanc server   ← user query

    細節如下
    • 做CT,series name需要改為「LungCARE」,傳至部內RAID
    • Osirix設定auto-routing,有「LungCARE」的series會自動傳至#S牌工作站
    • 工作站設定「LungCARE」的study自動apply為MM Oncology,而且會在背景先做CAD
    • AutoHotkey程式,每天早上三點(所謂三更半夜四下無人)會執行
      • 登入
      • 篩選「昨天」的「LungCARE」
      • 打開study
      • Show lung CAD results
      • Accept all candidates(本來是要醫師自己到場accept或reject每一個candidate)
      • Complete and archive:result會存成一個新的series
    • 工作站設定result的series再自動re-routing到自己架的server(Orthanc

    主要的考量包括:
    • S牌工作站
      • 可以找GGN,accuracy還算OK
      • 軟體介面是AutoHotkey可以access到的
      • 向工程師要到某種帳號,可以做進階設定
      • CAD可以pre-processing,不用現場等,前提是一定要命名為LungCARE
    • 其他工作站:
      • G牌:本部最舊的,很久沒更新;軟體只能一次處理一個case,無法批次處理;用linux系統,不熟…
      • P牌:CAD很弱...
      • T牌:介面無法用AutoHotkey抓,不能找GGN或是4mm以下的nodule
    • RAID轉運站
      • 每一台CT都會傳到RAID,而且Osirix可以設定auto-routing,就不再麻煩放射師要另外傳到工作站
      • 缺點是主機老舊,硬碟容量小,其實就是一個外接硬碟而已,還要常常手動更換,和「RAID」完全沾不上邊…
    • Orthanc server
      • 支援web介面查詢、瀏覽series、基本影像操作(亮度/對比)
      • 支援REST API,可以用http request配合json查詢、抓影像

    使用者端(chest radiologist們)則用另一個AutoHotkey程式,將下列動作綁在一個hotkey:
    • 抓RIS目前報告的病歷號
    • 用http request去查自架server是否有符合的result,有的話…
    • 在已開啟/新開啟的firefox或chrome打開連結,直接連到web viewer的頁面

    目前要再做一個server,針對非LDCT,可以丟一個病歷號過去,然後:
    • 從RAID拉影像(用dcm4che)
    • 修改series name為「LungCARE」(用ExifTool,或是出動Python)
    • 將dicom傳到工作站,等CAD
    • 登入工作站,accept candidates,export result
    • 回傳通知CAD已完成
    雖然很複雜,但目前能力只能做到這樣,希望以後有更好的流程~