顯示具有 autohotkey 標籤的文章。 顯示所有文章
顯示具有 autohotkey 標籤的文章。 顯示所有文章

2016年10月11日 星期二

AutoHotkey: traditional & expression

在 AutoHotkey 的官方說明檔講到變數Variables時,就開始提到 traditional & expression。Traditional 指的是 AutoHotkey 的傳統,寫什麼就是什麼,剛開始會覺得方便,但偶爾就會遇到一些陷阱,在文末會提到。

字串

a = test1
b := "test2"

  • Traditional 就是寫什麼是什麼(但忽略開頭的空白)
  • Expression 的話就是要有一對雙引號 " 夾住字串,相當於要從雙引號中取出字串


a = add
b = test%a%
c := "test" . a

  • Traditional 字串串接變數要用兩個 % 把變數的值先取出
  • Expression 的話可以用一個點 . 或一個空白鍵相隔,就是字串串接

a = c
bc = test
d := b%a%
  • 前兩個 traditional 很直覺,但第三行是什麼? %a% 是對 a 取值,所以是 c 這個字,右邊就是 bc,因為是 expression 所以要對 bc 取值,所以 d 的值也是 test

    流程控制

    if a > 2
        c = 1
    else if a = b
        c = 2
    • Traditional 模式,運算元左邊視為變數,運算元右邊視為普通文字,所以第一行會取出 a 的值,如果比 2 大則為 true。第三行右邊的 b 就只是一個 b,a 的值如果就是 b 這個字的話會是 true

    if (a>b)
        c = 1
    else if StrLen(a)
        c = 2

    Command & Function

    MsgBox,,,test,
    MsgBox,,,% "test" var1 var2
    MsgBox,test
    MsgBox % var
    MsgBox % var%a%
    • 以 MsgBox 這個典型的 command 來說,最左邊是 command 的名稱,右邊以逗點分隔參數,參數區預設為 traditional 模式,所以可以空著不寫,AutoHotkey 會幫你填入最常用的預設值
    • 如果某一個參數之後就全部空著,那麼連逗號都不必寫,全部空掉也可以
    • 第二行的第三個參數先一個%再接一個空格(或tab),表示這個參數變成 expression 模式,可以自由串接變數
    • 第三、四、五行僅限於部分 command,只用第一個參數代表省略其他的參數,一樣也區分 traditional 或 expression 模式

    SubStr( var, 1, 2)
    SubStr( var%a%, 1, 2)
    SubStr( "test", 2)
    SubStr( "test", 2, )
    • Function 是以 function 名稱加上一對小括號,參數也是以逗號分隔但只限expression模式。
    • 空的參數應該要以 "" 表示,或者就不要有逗號,第三行是錯誤示範

      常見陷阱


      • 因為 AutoHotkey 不用宣告變數類別,所以數字類的值有可能是字串,也可能是數字(整數、小數等)
      • a 是 01 的字串
      • b 牽涉到數學運算,所以變成數字 1
      • c 牽涉到字串串接,所以又變為 01 字串
      • 在 AutoHotkey_L 版本可以用到object類的陣列,如果key是像數字的字串,會自動被轉成數字,所以 r[a] 事實上變成 r[1] 而不是 r["01"] 也不是 r["1"],除非指定 r["" a] 才是 r["01"]


        • if 之後如果有兩行以下則要用大括號 { } 包起來,但如果 if 是traditional模式,事實上第一行被視為 a 的值是不是 2 { 這個字串,也就是 { 被誤解了。所以原本的 } 就會被 AutoHotkey 解讀為多出來的,而這個 if 影響的只有 c=1 不包括 d=1 (因為根本沒有大括號包起來)
        • 第二個 if 是 expression 模式,而且很有效率順便給 a 變數一個值。可是 := 這個運算元的優先順序是很低的,a 的值會變成 (c+1) && (d>0) 整串的結果,而不是 c+1


        2016年10月2日 星期日

        MammoSR

        前幾個月上了一堂課突然獲得資格:打國民健康署的乳房篩檢報告。這在外面的醫院幾乎是必備技能/資格,但在本院根本是賽缺中的賽缺。原因如下:
        • 在院內的報告系統(RIS)打好報告,還要在國健署專用的紙本報告(附表7的第二頁、附表12)上勾選你看到了什麼、結果是什麼,然後蓋章。同一件事情分成兩次做已經很蠢,更蠢的是把電子化的資料要化為紙本資料
        • 最蠢的是,其實國健署的系統也是電子化的啊,所以每個禮拜會有專員來把紙本的資料再key到那個系統內。無以倫比的官府效率!
        • 多做這些麻煩的事,報酬卻和一般的乳房攝影報告一樣。不同工卻同酬,而且是比外院低很多的酬,非常不公平。
        • 更慘的是,乳房攝影報告通常是胸腔影像團隊負責的,一個報告量最大、報告完成度最低、平均pay最低、離職率最高的團隊,還要接受這麼鳥的業務,落入惡性循環。(這不就是台灣的縮影嗎)
        很不幸的接到了賽缺,只好想辦法讓這業務稍微不賽一點。目前的流程是「院內系統打報告→勾選表格→蓋章→交卷」,變成「AHK程式打報告→報告貼到院內系統、生出一個勾選好的網頁表單→列印→印出來的表單塞回檢查單」。詳述如下:


        • 主程式MammoSR
          • Open study
            • 從RIS的舊片清單讀舊片資料,包括日期(直接輸出到報告內文)、單號(經由Impax Context Server在Impax開啟影像)
            • 舊片清單沒有資料的話,把Comparison欄位設定為No
          • 除了breast density其他欄位為combobox,可選取預設的幾個文字選項,也可以自行輸入(修改)
          • 有意義的finding,也就是屬於BI-RADS 0, 3-6的finding,要以程式內的按鈕輸入,並在那個finding的suggestion選取相對應的處置,否則都視為一般finding。
          • 提供B1, B2按鈕,為BI-RADS 1, 2的預設報告內容,這兩個應該是最常用的
          • 不管按鈕按了什麼,輸出的報告內容可以在文字框自由修改
          • Save
            • 報告貼到RIS
            • xml檔儲存本次報告
            • 以xml檔的資料以及範本output.html,生成一個勾選好的表單html
            • 將html檔以chrome開啟,檢查是否有錯誤。html也能手動勾選後儲存變更。
          • Send:將本報告的html傳送到print server儲存
          • Print All:打了一組報告後,可以傳送列印指令,print server將列印該放射科醫師已儲存未列印的html,以傳送時間排序
          • 自動抓RIS上的資訊,包括放射師、病人姓名、檢查單號等。如果單號改變會自動存檔後reset GUI,如果有之前的存檔會自動匯入
        • output.html
          • 第一頁是每個檢查都會填寫的,就是基本的判讀結果;第二頁是BI-RADS 0, 3-6才需要勾選的finding細節,如果BI-RADS 1, 2的話第二頁是隱藏的
          • 文字輸入部分是span,以紅色底線標示表示可以手動修改(紅色底線不會印出來);其他都是checkbox input勾選符合的選項
          • 有任何變動的話,會在最底下出現Save按鈕,按Save後才能儲存變更(javascript無法儲存檔案,其實還是間接用AutoHotkey去完成的)
        • MammoSRprint
          • 將xml轉成html,主要靠output.html裡各個欄位的name屬性去修改值
          • 第二頁有些病人資料(生日、身份證字號)是靠院內portal系統去抓的
        • MammoSRprintClient
          • 將html傳送到server,或者傳送print all的指令
          • 所使用的是Socket library,用的是TCP,雖然不是最detailed的library,沒辦法做很多細部設定,但就跟ahk一樣很簡單上手
        • MammoSRprintServer
          • 接收html儲存到相對應的資料夾(放射科醫師姓名),html會加入一段開啟時列印的javascript
          • 接收到print指令,以chrome打開html來列印

        待改進部分:
        • 雖然叫MammoSR但還不是很嚴謹的structure report,主要是太嚴謹的話用起來不方便,小程式還是以工作便利性優先
        • 設計表單時是以chrome的呈現結果為準,可惜網路上已經很難找到支援WinXP的portable chrome(版本49以下),目前用的是之前存在隨身碟的版本37
        • 在server端的列印還是以類似按鍵精靈的方式去點列印鍵,最佳解應該是可以在背景以command line方式執行批次列印(還沒嘗試chrome的--kiosk-printing)

        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已完成
          雖然很複雜,但目前能力只能做到這樣,希望以後有更好的流程~

          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年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)的敘述

          2015年7月9日 星期四

          新工作

          七月一日新工作,其實也只是原地升級,從一種勞力工作轉換成另一種勞力工作,特別是手指肌、動眼肌、轉頭肌。大概是姿勢不當加上沒有適當的工作環境(桌、椅的高度),才第二週就開始兩邊肩膀硬硬der

          打報告比想像中更routine,趁剛開始這三個月要準備考試只分配到適量的工作,有一半的時間都是開著autohotkey相關程式進行研發。有些細節真的是實際做事的時候才會體會,住院醫師時不會知道VS很需要某些功能,更不用說是工程師了… 趁著空擋多做了一些東西,也大修自己的打報告AHK。比較可惜的是autohotkey畢竟不是正常的程式語言,實在難以管理,很多功能也很難理想的分享給大家使用@@

          已開發

          • 滑鼠鍵盤
            • 滑鼠到最右邊螢幕的右邊界,可以接到最左邊螢幕的左邊界(循環式螢幕)
            • 滑鼠在IMPAX上滾輪,自動activate IMPAX;在IMPAX按CapsLock,自動activate RIS。這樣滑鼠可保持在IMPAX。
            • Ctrl + Alt + Tab:選取病歷號後按快速鍵,自動輸入到IMPAX查詢框
            • Alt + Win + Tab:選取病歷號後按快速鍵,在Sleipnir查詢就診記錄
            • Alt + Win + Ctrl:選取病歷號後按快速鍵,執行上述兩動作
            • Ctrl + Win + Tab:選取病歷號或單號後按快速鍵,在RIS搜尋
            • `:刪除一個字(而非一個字元)
            • Alt + Backspace:刪除一句
            • Ctrl + Y:刪除一整行
            • 快速鍵自動登入RIS, IMPAX和Portal(以Sleipnir開啟),以及執行自己的打報告AHK
            • 如果有多個AHK針對不同modality,可按Win + 1, Win + 2等切換(最多10個)
          • RIS:打報告程式,寫得很爛,只好寫更多外掛補東補西
            • 報告搜尋列表
              • Ctrl + N:搜尋條件設定為「總院、急診、CT」(結果常常忘了打大夜MRI)
              • Ctrl + R:重設搜尋條件,報告狀態改為「未發送」
              • Ctrl + F:輸入框鍵入VS縮寫,可選取該報告醫師
              • Ctrl + G:輸入框鍵入R縮寫,可選取報告撰打醫師
              • Ctrl + H:輸入框鍵入R縮寫,可選取執行醫師
              • Ctrl + Enter:送出查詢
            • 報告撰打介面
              • 臨床資訊抓portal的,但斷行字元轉換不正確,變成沒有斷行 = =。每跳下一個報告,自動把\n取代成\r\n,就有斷行了。
              • Ctrl + K:查詢臨床資訊,例如急診主訴、癌症staging,選取文字後按快速鍵可自動加到報告框,選取文字有斷行則轉換為分號。可分次使用。
              • Ctrl + I:(滑鼠在IMPAX某個series的frame內)輸出滑鼠所在影像的SE和IM
              • Ctrl + D:擷取indication文字並貼上
              • 自動編號/標號:WORD-like的處理方式,按Enter後新行會延續上一行的編號/標號,編號可自動更新。
              • 發送報告前自動檢查:
                • 句點後存在且只有一個空格
                • 將兩個以上的句點/空格變成一個(所以報告裡不能用…)
                • 句點後的第一個字母為大寫(所以報告裡不能用縮寫點例如bil.)
              • 臨床報告視窗按Esc可關閉(是的,連這個基本功能都沒有)
              • 即時查詢自己的打報告AHK(總是會忘記加了哪些東西)
          • IMPAX
            • F1:跳到查詢介面的病歷號查詢框
            • `:跳到報告文字介面
            • Tab:顯示/隱藏Series列表
            • 滑鼠拖曳時原本只有往上或往下可捲動影像,加入左右拖曳也能捲動影像(手不夠長?試著橫向拖曳)

          To Do

          • 定時提醒起來活動。
          • 當日已打報告及績效分析。
          • RIS砍掉重練最快,有夠慢。
          • 希望能要到IMPAX的API,自行寫RIS?

          2014年8月16日 星期六

          Autohotkey: 基本面

          前言

          • 講了幾篇後,朋友試寫script一直遇到問題,我才發現最基本的東西沒講 orz
          • 其實最穩的方式還是讀autohotkey的說明檔,尤其autohotkey_L有簡體中文版本的說明,英文苦手可以考慮。
          • 以下列舉一些要點,但如果沒有詳細看說明檔還是可能會遇到問題,總之見招拆招!

          環境設定

          • 之前這篇有提到過,目前所用的免安裝版主程式是Autohotkey_L Unicode 32bit,編輯器是SciTE4AutoHotkeySciTE的資料夾應該要放在Autohotkey內。如果都是安裝版,要先安裝autohotkey再裝SciTE,SciTE會自動裝到適當的地方。
          • 副檔名ahk的檔案本質上就是純文字檔,滑鼠點兩下可能會發生幾種事情:
            • 如果有安裝autohotkey、SciTE,可以直接執行這個script,或者直接打開SciTE編輯ahk檔案。
            • 如果用免安裝版,剛下載下來時電腦並不認得ahk檔,要選擇開啟ahk檔的程式(autohotkey、SciTE或者任何一種文字編輯程式)。
            • 如果是像我一樣裝在隨身碟裡到處跑,通常的流程是打開SciTE,然後直接把ahk檔拖曳到SciTE裡開啟,debug或執行都可以直接用SciTE完成(所以才說SciTE資料夾和autohotkey.exe要放一起)。
          • 在沒有裝autohotkey的電腦要能直接執行script,就要把ahk檔「編譯」(compile)成exe檔,其實本質上就是把autohotkey主程式和純文字script綁在一起。
            • 在SciTE裡按Ctrl + F7可以compile(其實是用ahk2exe.exe來完成的),產生的exe檔和ahk檔在同一資料夾。
            • Compile有時候會出現錯誤,常見的原因包括原本的exe還在執行中(要先關閉),或是電腦中執行的程式衝到,後者就不容易解決了…
            • 理論上exe檔並沒有什麼加密的功能,原始的程式碼其實還是能復原,ahk2exe.exe加入參數能讓compile時加入密碼,保密性會比較好一些。
            • EXE檔可以附加客製化的圖示(ico檔,128*128 pixels以下),通常可以用icon編輯軟體,搭配這個網站,然後用這個把icon加進exe檔。

          Script結構

          • 通常最開頭會用#include來引用前人的智慧結晶,例如同個資料夾func.ahk裡面有一些函數定義,#include func.ahk就相當於func.ahk裡面的內容複製貼上到#include這一行。
            • 也較好的方法是在ahk檔同一層或者主程式Autohotkey.exe同一層新增資料夾Lib,然後把func.ahk放進去,這樣的話可以用語法#include <func>
          • 其他#開頭的指令也都會優先處理,常用的有
            • #NoTrayIcon:程式執行時不會在螢幕右下角那區出現小圖示,所以TrayTip這個指令也會無效。
            • #Persistent:如果script沒有hotkey、hotstring、GUI,程式執行完就會自動結束,加了這指令,程式不會直接結束變成idle狀態。
            • #SingleInstance:如果程式執行中,又再滑鼠點兩下同一個exe檔,會出現message box問是否取代原本執行中的程式,有這個指令則可以讓message box不出現,參數force、ignore、off分別對應「新的取代舊的」、「繼續執行舊的,不執行新的」、「新的執行新的,舊的執行舊的」。
          • Hotkey、hotstring、function定義的block可以放在script裡任何地方皆有作用,但放的地方不對可能讓其他非hotkey/hotstring的script沒有執行到(下面會說明),建議把同類型的放在一起,而且都放在script底端的位置。
            • SciTE中,在某個label或function名稱按滑鼠中鍵或Shift + Enter,可以直接跳到label或function定義的地方;或者在空白處按,會出現查詢框。
          • 想像script中把hotkey、hotstring、function定義的block都拿掉後,留下的script(auto-execution section)會從最上面開始執行,直到遇到return、exit或是hotkey/hotstring
            • 如果#include裡的檔案有空閒的return(不是hotkey、hotstring、function內的),那自己的script就等於不會執行到。
            • 如果是先用gosub跳到subroutine,subroutine的return會回到剛才gosub的那行,script不會停下來。

          Threads

          • 理論上同一個process中可以有一個以上的thread(執行緒),每個執行緒可以各自執行自己的任務,但也有相對應的缺點。
          • Autohotkey_L只有單一執行緒,在auto-execution section執行中跳出message box、input box,程式就相當於被暫停,或者執行中遇到一個耗費時間的loop(甚至根本是無窮迴圈),那程式就沒辦法做其他事。
          • 事實上Autohotkey_L會模擬多執行緒,有一些block會以新的thread來執行,包括hotkey/hotstring、GUI events、SetTimer引發的subroutine、menu引發的subroutine。所以說如果程式卡在loop或是message box,hotkey還是能被trigger,SetTimer反覆執行的subroutine還是繼續。
          • 有些外掛可以更模擬多執行緒,例如WorkerThread(事實上是藉由重覆執行exe檔)。只有Autohotkey_H才能使用真正的執行緒。

          語法速成

          var = abc
            • abc這個字串儲存到var變數。
          var = %var2%
            • var2這個變數代表的值取出,然後儲存到var變數。
          if a = 2
          {
              …
          }
            • 比對變數a的值是否等於2,大括號不能和if在同一行。
          MsgBox test
            • 跳出message box,內容是test。
          InputBox,OutputVar,%title%
            • 出現input box,標題為變數title的值,注意OutputVar這個參數是一個變數的名稱,通常不用%,除非要用的變數的名稱是存在某一個變數。
          • Non-expression:
          var := "abc"
            • abc這個字串儲存到var變數,要用運算元 := 而且字串前後要加雙引號。
          var := var2
            • var2這個變數代表的值取出,然後儲存到var變數。
          if (a = b) {
              …
          }
            • 比對變數a的值是否等於變數b的值,整個條件式要有小括號圍起來才視為expression,大括號可以和if在同一行。
          MsgBox % test
            • %後面加空格,會視為expression。
          MouseClick, L, % x, % y, 1
            • %後面加空格,作用的範圍只有那一個參數。
          • Autohotkey官方版的array純粹是單純的變數,只不過變數名稱最後一個字元是數字,autohotkey_L支援object(物件)的array,使用起來比較有效率。主要有幾個重點:
            • 一般的array以 [ ] 括起來,例如arr := [ 5, 4, "3" , "abc" ],index從1開始遞增,所以arr[2]的值是4,而arr[4] := "bcd"會蓋過本來的"abc"。
            • Associative array有點像dictionary,指定一個key對應一個value,例如 arr := { 1: "a", k: v },以大括號括起來,key和value間以冒號隔開,key的部分是non-expression,預設視為字串,value的部分是expression,arr["k"]儲存的是變數v的值。

          2014年8月13日 星期三

          Autohotkey: Hotkey

          前言

          • 從名稱可以知道Autohotkey的強項就是hot key,所謂熱鍵、快速鍵。控制滑鼠、視窗也是autohotkey的常用功能,用簡單的語法就能組合完成複雜的動作。
          • 百般task皆可由一個hot key引發,hot key可以是一個按鍵、多個按鍵、一串特定按鍵,可以是某個滑鼠鍵、多個滑鼠鍵,或是鍵盤搭配滑鼠鍵。可以指定在某些視窗才有快速鍵,或是某些視窗沒有快速鍵。

          Hotkey

          • 之前的post提過Send可以模擬按出某個鍵(鍵盤、滑鼠),hotkey就是以這些鍵當作trigger。
          • Hotkey的第一行定義trigger的按鍵,send指令需要的大括號 { } 在hotkey要省略,然後後面加兩個冒號 :: 
          • 如果指令只有一行(包括以小括號包圍的段落文字),則可以寫在冒號右邊;如果是多行則最後要用return表示hotkey的結尾,開頭到結尾間可以有其他return,只要一遇到return這個hotkey就會結束。
          • Hotkey定義之後原本的功能會被覆蓋,例如LButton::,會讓autohotkey抓住滑鼠左鍵,但不做任何事,原本的滑鼠左鍵功能就消失了(請勿輕易嘗試XD)。
          • Hotkey之前可以有修飾符,調整hotkey的行為
            • *:例如^c::的hotkey只有ctrl + c才會trigger,多按一個鍵shift + ctrl + c則不會,但*^c::則只要ctrl + c有按到,多按shift或其他按鍵都還能trigger。
            • ~:原本hotkey的功能保留,不會被覆蓋
            • $:如果是^c::send ^c會出現無限迴圈,因為send出去的按鍵又trigger自己,$則避免出現迴圈。
            • UP:一般hotkey的trigger是在「按下」的階段發生(某些功能鍵除外),如果希望hotkey是在按鍵「放開」時發生,則在後面加一個up (不分大小寫)
              • ^c up::會在c放開時才執行。
              • 雖然只指定了^c up::,原本的^c還是會被覆蓋,所以如果要保留原本功能則用~^c up::或是另外再設定^c::send ^c(這時不需要加$)。
          • 組合鍵:只能組合兩個,舉例如下
            • a & b:::先按住a不要放掉,再按b可以觸發,有點像是按ctrl + c之類快速鍵的順序
            • 前面的按鍵a功能會被覆蓋,只按a不會做任何事,彌補的方法一樣是加一個~或是設定a::send a(兩者的行為不一樣,比較建議後者)
          • Suspend指令可以暫時停止所有的hotkey及hotstring(除了造成suspend的那個hotkey或hotstring),再一次suspend指令則會回復
          • Context-sensitive hotkey:以#IfWinActive包圍的hotkey,只有在指定的視窗會有作用
          • Hotkey本身就是一個label(不含兩個冒號::),可以用gosubgosub直接執行一個hotkey。例如$^c::可以用gosub $^c來執行,不用去按ctrl + c。

          KeyWait

          • KeyWait可以設定微調hotkey,功能是等待某個按鍵放開或按下。
          • KeyWait, a 會等待按鍵a被放開
          • KeyWait, LButton, D 會等待滑鼠左鍵按下
          • KeyWait, Ctrl, T3 會等待Ctrl鍵放開,但只會等待3秒鐘,如果超過時間沒放開,ErrorLevel這個變數會是1;如果時間內放開,ErrorLevel會是0而且繼續執行script,不會等到3秒鐘。

          GetKeyState

          • KeyWait一樣,GetKeyState也是輔助hotkey的小函數。有兩種形式的用法。
          GetKeyState, OutputVar, KeyName [, Mode] 
          • 針對KeyName是按下還是放開,將OutputVar設定成 D U Mode中可以設定用哪一種方式判斷按鍵的狀態
            • Logical state:預設值,windows所認為的這個按鍵的狀態
            • Physical state:使用者是否按著這個按鍵,可能會和logical state不相同。如果script有mouse hook或keyboard hook,就能完全監測滑鼠/鍵盤,physical state可以當成等於logical state。
            • Toggle state:像是Caps Lock或Num Lock,如果用toggle state則是傳回目前的燈號,燈號亮的時候傳回 D ,反之傳回 U 。
          KeyIsDown := GetKeyState("KeyName" [, "Mode"])
          • 用法類似,唯一的不同是剛才傳回 D 的地方現在會傳回 1 ,傳回 U 變成傳回 0

          Double Click/Keyboard Event

          • 前面的hotkey都是按一下就會trigger,如果想要的hotkey是滑鼠左鍵「按兩下」,或是Esc鍵「按兩下」,可以加一行判斷式:
          if (A_PriorHotkey = A_ThisHotkeky && A_TimeSincePriorHotkey < 500)
          • 白話翻譯就是「上一個trigger的hotkey和現在trigger的hotkey是同一個」而且「從上次trigger到現在的時間差小於500毫秒」,所以只要同一個鍵按兩下,時間差小於500毫秒,就會通過判斷式,如果不成立,就return回去。當然,500毫秒可以改成其他時間。
          • 如果hotkey需要按三次以上,建議可以用RapidHotkey()

          Dynamic Hotkey

          • 之前的hotkey都是直接寫好在code裡,程式執行後就一直存在,如果要在程式執行時改變hotkey,就要用Hotkey指令。
          Hotkey, KeyName [, Label, Options]
          Hotkey, IfWinActive/Exist [, WinTitle, WinText]
          • KeyName是按鍵組合,就是上面提到的那些,Label則是要執行的區塊名稱(所以這部分還是要先寫在code裡)。
          • 多個hotkey可以共用同一個label,在區塊中可以用A_ThisHotkey變數區分是誰trigger的。
          • 按鍵組合一樣,但修飾符不一樣,或者在不同IfWinActive條件下的同樣按鍵組合,視為不同的hotkey。如果設定了重覆的hotkey,新的功能會覆蓋舊的功能。

          2014年8月8日 星期五

          Regular Expression入門

          前言

          • Regular expression一般翻譯做「正規表達式」之類的,但其實翻譯不重要,因為看了翻譯還是不知道他的用途。
          • 在字串裡搜尋字串是大家很常用的功能,例如在硬碟內找某個檔案,或者是在文章內找某個字。
          • 但更常用的是搜尋「某個pattern」,例如想要找「連續7個數字」或是「三個字母接一個特殊字元,後面又有1或2個數字」,就需要用到regular expression!
          • 很多程式語言(或者script)都會有regular expression,使用上大同小異,花點時間學習這些火星文,一生受用無窮。
          • 以下以autohotkey環境來講解,其實大部分也是翻譯自autohotkey的官方文件
          • 測試regular expression的工具

          RegExMatch

          • 在開頭先簡介autohotkey內所用的函數RegExMatch,用法是
          FoundPos := RegExMatch(Haystack, NeedleRegEx [, UnquotedOutputVar = "", StartingPosition = 1])
            • 一定要有的參數:Haystack是被搜尋的文字,Needle則是所搜尋的pattern,也就是底下要學的東西。
            • 選擇性參數:match後的結果會儲存在OutputVar變數裡,StartingPosition可以指定從Haystack的第幾個字元開始搜尋。
            • 這個函數會傳回第一個找到pattern的字元位置,如果沒找到的話是 0 。
            • 相較於autohotkey很多函數/變數是大小寫不區分,regular expression預設是區分大小寫的。

          Regular Expression

          • 一般字元
            • 大部分的字元都可以直接用在regular expression內,搜尋起來就是和傳統的搜尋文字一樣,例如 RegExMatch("abcde","bcd") 會傳回 2 。
          • 特殊字元
            • 在regular expression裡有特殊意義,要用 \ 去escape,才會是原本的字元:\ . * ? + [ { | ( ) ^ $ 
            • 例如要找中括號,不能用 RegExMatch("()[]{}","[") ,而是要用 RegExMatch("()[]{}","\[") 
          • Symbols
            • .:一個點表示除了斷行以外的任何一個字元。
            • \d:表示任何一個數字,也就是0到9。如果要表達「一個非數字」,則用\D (大寫)。
            • \w:表示任何一個文字,包括數字、大小寫的a到z,還有底線 _ 。如果要表達「一個非文字」,則用\W (大寫)。
            • \s:表示某種空白字元,包括空白、tab (\t),斷行 (\r\n)等。如果要表達「一個非空白」,則用\S (大寫)。
            • [...]:一對中括號內為候選字,正面表列
              • [abc]:找某一個字元,可以是a,也可以是b或是c。
              • [a-z]:找某一個字元,可以是a到z。同理可以用在[A-Z][0-9],或是組合用[b-s4-7]
              • 候選字中某些特殊字元可以不用escape,例如 * ? + 都不用加 \ ,當然如果怕搞混加上去也沒關係。
              • [^...]:最前面標一個^表示是黑名單,找一個字元且這個字元不在黑名單中。
          • 數量詞
            • 前面的Symbol都是指單一字元,數量詞一定接在某個symbol右邊,也就是說數量詞作用在左邊那一個symbol。
            • *:表示0個或是0個以上。
            • ?:表示0個或是1個。
            • +:表示1個或是1個以上。
            • {min,max}:表示min個以上、max個以下。例如a{2,3}表示連在一起的兩個或三個a。
          • Syntax
            • \b:表示一個「文字邊界」,例如 cat\b 不會match到 catfish ,因為cat是fish連在一起的。\B(大寫)則表示「非文字邊界」。
            • ^ $:把^放在整個pattern的最前面表示「開頭」,把$放在整個pattern的最後面表示「結尾」,例如 ^bcd abc$ 都無法match到 abcd
            • |:表是「或」,例如 (Sun|Mon|Tues|Wednes|Thurs|Fri|Satur)day 可以match到 SundayMonday 或 ... 或 Saturday
            • ( ):小括號一方面可以讓pattern比較容易閱讀,一方面被括起來的部分會成為一個submatch。
          • Options
            • 在pattern的左邊,以一個右括號)隔開option和pattern,各個options可以連起來寫,或是用空白、tab分開。
            • i:表示case insensitive,例如 i)abc 可以match到 ABC
            • m:表示multiline模式,影響的是^$,在多行文字時本來表示「全部文字」的頭尾,會變成「一行文字」的頭尾。
            • s:讓一個點.表示「所有」字元,包括斷行。
            • U:ungreedy
              • 預設情況下如果是不定數量的數量詞* + ? { },regular expression會符合「盡量多」的字元,所以 1\d+1 會match到全部的 1000010000101,稱作greedy
              • 如果在數量詞後加一個問號?,則變成ungreedy1\d+?1 只會match到 100001。
              • 如果有U設定,則預設為ungreedy,加問號變greedy。
          • Submatch (subpattern)
            • 剛才提到小括號可以形成submatch,例如 RegExMatch("zzabcdefzz","ab(.*)e(f)",match) match變數會儲存 abcdefmatch1變數會儲存 cdmatch2變數會儲存 f
            • 如果小括號只是為了語法,而不是為了submatch,可以用(?:  )表示這個括號不是submatch,例如 RegExMatch("zzabcdefzz","ab(?:.*)e(f)",match) match變數會儲存 abcdefmatch1變數會儲存 f
            • (<?P<...>   ):Named subpattern,例如 RegExMatch("20140102","(?P<Year>\d{4})(?P<Month>\d{2})(?P<Day>\d{2})",match) 執行後,match20140101,而matchYear變數是2014matchMonth變數是01matchDay變數是02
          • Assertion
            • 雖然是用小括號,但不是submatch也不包含在match裡,僅僅是當成一個條件。
            • (?=   ):positive look ahead,例如 a(?=b) 會match一個a,這個a要接著b。
            • (?!   ):negative look ahead,例如 a(?!b) 會match一個a,這個a後面不能接著b。
            • (?<=  ):positive look behind,例如 (?<=a)b 會match一個b,這b左邊接著a。
            • (?<!  ):negative look behind,例如 (?<!a)b 會match一個b,這b左邊不能接著a。

          Further Reading

          2014年7月9日 星期三

          自己寫武功祕笈:Radiologist的第一個Autohotkey

          開發環境

          主程式

          • 官方版autohotkey
          • Autohotkey_L:根據官方版加入更多功能,例如unicode支援、64位元支援、物件導向,而且有提供簡體中文的說明檔
          • 以上都有提供portable版本,免安裝,解壓縮後就可以直接用

          Script File

          •  只有主程式沒用,還需要script才能做事,script的副檔名是ahk,但本質上就是文字檔,可以用任何文字編輯軟體打開撰打
          • 同樣是文字檔會有不同的編碼方式,原PO儲存時都使用UTF-8 (with BOM),對於中文字或是其實特殊文字比較不會變亂碼

          編輯器

          • 工欲善其事,必先利其器,好的編輯器可以讓寫程式更有效率,包括偵測錯誤、函數提示、顏色標示
          • 原PO使用的是SciTE4Autohotkey,一樣有分安裝版和portable版

          寫程式

          前言

          • 所有程式都能做很簡單或是很複雜的事,autohotkey也是,尤其autohotkey特別針對日常使用電腦需要用到的功能,寫起來非常有效率,用最少的程式碼做最多的事
          • 本篇主要介紹血汗國家(地區?)的放射科醫師,靠著autohotkey在夾縫中求生存的一段故事

          模擬鍵盤、滑鼠

          • 基本上打報告的所有動作,包括鍵盤上任何按鍵、滑鼠上任何按鍵和動作,都是可以模擬出來的,所以寫程式的第一步是思考、設計,「我要我的程式做什麼事情」,而且要step by step,分析每一個步驟
          send
          • 官方詳細說明
          • 送出一個按鍵,例如:send blabla
          • 英文字母、數字、特殊符號可以直接送出,例如:send abc123&*?
            • 例外的是 ` ,要在字元前加一個`,也就是 send ``
            • ! # + ^ { } ,這些字元有特殊用途,要用大括號包圍起來,表示送出原本的字元而不是特殊用途,例如 send {!}{#}
          • 功能鍵(會自動和右邊一個按鍵變組合鍵)
            •  ^ 表示ctrl,例如 send ^c 就是按 ctrl + c
            •  ! 表示alt,例如 send !{F4} 就是按 alt + F4
            •  + 表示shift,例如 send ^+{esc} 就是按 ctrl + shift + esc
            •  # 表示視窗鍵(ctrl和alt中間那個),例如 send #e 就是按 win + e
          • 特殊字元
            • { } 包圍起來,族繁不及備載,可參考說明檔,大部分都很直覺,常用如下
            • {enter} {space} {tab}
            • {backspace} 或 {bs}、{delete} 或 {del}
            • {up} {down} {left} {right} {home} {end} {pgup} {pgdn}
            • {F1} ~ {F12}
            • 在數字盤的按鍵都是這個形式:{Numpad___}
          • 滑鼠按鍵
            • {LButton} {RButton} {MButton}
            • {WheelUp} {WheelDown}:滾輪
          • 重複同一個按鍵:send {space 10}會送出10個空白鍵

          Hotstring & Hotkey & Settings


          ::cct::CT of the chest without and with contrast enhancement is read and compared with prior study dated . This CT study shows:{left 22}
          •  送出了這段文字,通常會將游標移到前面填入日期,所以在後面加上{left 22},將游標往左移動22次
          •  或者可以用^{left 5},因為 ctrl + left 會往左移動一個「字」而不是「字元」,但使用後的效果不如前一個方法精準
          SendMode Input
          • 將send mode改成input模式,比較不會發生打報告打太快時,autohotkey送出的模擬按鍵和自己實際按的按鍵交錯送出
          ^!x::suspend
          • 打報告時還是常需要google查資料(&上facebook?),這時可以用suspend指令將這個script的所有hotstring和hotkey停用,繼續打報告時再按同一個快速鍵(也只有這個快速鍵不會被停用)回復
          ^!r::reload
          • 如果script在執行中,修改程式碼後要重新執行,可以直接用reload指令
          ^!e::
          inputbox,addahk
          if addahk!=
              fileappend,% addahk,% A_ScriptFullPath
          reload
          return

          • 跳出一個輸入框,輸入的文字(例如新的hotstring)會加到原本的script最底下,然後reload整個script,就能使用剛加入的hotstring
          ^!q::exitapp
          • exitapp指令可以離開整個script
          ~+enter::
          ~+NumpadEnter::
          send -{space}

          return
          •  bullet是項目符號,每個人用的都不一樣,原PO是用「- 」,設定快速鍵後按 ctrl + enter 可以跳到下一行並輸出項目符號

          Dynamic Hotstring

          • 進階版的hotstring,見AHK論壇
          • 原始的hotstring是一對一的關係,打出一些特定的字跳出一些特定的字,dynamic  hotstring則是多對多的,打出某些pattern的字跳出某些pattern的字
          • 常見在一些列舉項目,例如left/right/bilateral、head/neck/chest/abdomen/pelvis,或是需要輸入某些數字,例如SE3 IM20,都適合用dynamic hotstring,舉一個例子…
          #include hotstring.ahk

          hotstring("([.\W])?(\d+)\.\.(\d+)(\W)","specifyImage",3)
          return

          specifyImage:
          if $.value(1)="."
              send % "(SE" $.value(2) " IM" $.value(3) ")" $.value(4)
          else
              send % $.value(1) "SE" $.value(2) " IM" $.value(3) $.value(4)
          return

          • 下載Hotstring.ahk後放到自己的script的資料夾;自己的script(通常在最前面)要有一行#include hotstring.ahk載入函數
          • hotstring("([.\W])?(\d+)..(\d+)(\W)","specifyImage",3)要放在「第一個return」之前,因為return之後的程式碼不會被直接執行
            • ([.\W])?(\d+)..(\d+)(\W)表示要trigger的pattern
            • specifyImage表示trigger後要執行的段落標籤
            • 3表示pattern是用regular expression
          • 總之最後的效果是
            • 輸入 .3..20 ,輸出 (SE3 IM20) 
            • 輸入 3..20 ,輸出 SE3 IM20 

            2013年11月23日 星期六

            Hotstring Helper

             Tool for Radiology Resident !!

            Background

            • 當resident開始用起VS們的ahk...
              • 看shoulder plain film,一直要打down-sloping and low-lying of the acromion真是累
              • 打開游醫師的cwy.ahk,搜尋看看有沒有對應的hotstring
              • 找到了!以後只要打「shd」就會是down-sloping and low-lying of the acromion
              • 這樣實在太浪費時間了!!

            Hotstring Helper使用說明

            • 把要查詢的ahk(可以多個)全部複製到Hotstring Helper.exe的資料夾 
            • 執行Hotstring Helper.exe
            • 開啟RIS (目前限制在RIS裡才查詢)
            • 打報告打一半想查某個字(eg. acromion)相關的hotstring,則打「;acromion」,也就是一個分號,再接著查詢的單字
            • 如上圖只要當作注音輸入法使用,輸入0~9後就會把剛才的「;acromion」取代成候選句
              • 輸入0是第10個候選句,不是第一個!
            • 其他小技巧及注意事項
              • 如果按空白鍵則自動選擇第一個候選句
              • 至少輸入三個字母以上才會查詢,就上面的例子至少要輸入「;acr」才會出現選單
              • 如果有一頁以上的結果,可用滑鼠滾輪捲動
              • 只要輸入字母以外的按鍵(eg. ESC),或是滑鼠按鍵,就會停止查詢,選單消失
                •  問號(?)和星號(*)為例外,問號表示「任一字元」,星號表示「零或多個字元」
                • 例如「gr?y」會搜尋grey或gray
              • 或者可以先key一串字(片語、句子),選取後按Alt+F搜尋



            2013年6月9日 星期日

            Facebook備份

            話說前幾天試用Facebook備份,其實不用從email收確認信,從facebook備份頁再輸入一次密碼就能下載了。但下載下來覺得裡面像渣一樣…

            • 總體來說,檔名一堆亂碼,非英文數字的字元整個是悲劇,例如 ??瘞湔?蝞?Photos 或是 蝚砌??蝵居 根本不知道是尛。
            • 下載下來是一個zip檔,裡面先是一個資料夾,名稱是自己的facebook首頁連結去掉facebook網域,例如我的是scsnake.chen。解壓縮後點開index.html就可以看到備份的成果,以下就zip檔內的資料夾、檔案簡介…
            • html
              • album開頭的一些html檔
                • 各個facebook相簿摘要,該是縮圖的部分都不會有圖,只剩下文字資訊(例如照片底下的好友回應)。
              • events.html
                • 加入過的活動,檔題還保有超連結,算是資訊比較完整的。
              • friends.html
                • 好友清單,內容走極簡風,就只是純文字的好友列表。
              • message.html
                • 跟所有人的訊息都收集在同一頁裡,以對話者分類,所以除了第一個人外都要用搜尋名字才知道在網頁中哪個範圍。
                • 最上面是最早的日期,但也只到2012年9月,往下到備份的時間點。
              • notes.html
                • 網誌內容加回應,一樣是純文字版,有超連結的文字會留著。
              • profiles.html
                • 個資大全
              • video.html
                • 分享過的影片,很意外地可以直接點影片收看,最令人滿意的備份。
            • photo
              • 只是自己的大頭照一張。
            • photos
              • 相簿、照片應該是完整的,除了檔名幾乎滅團,以及因為亂碼的因素無法從壓縮檔中解壓縮出來。
            • videos
              • 上傳到facebook的影片檔。

            因為想要備份完整的訊息,只好出動土法煉鋼:
            • 先到facebook的收件匣
            • 持續的讓滑鼠往上滾,先前的訊息會一點一滴地讀取進來
              • Autohotkey/按鍵精靈是我們的好朋友,10000則訊息其實不用1小時就捲到頂了。
              • 請選擇比較穩的瀏覽器例如Chrome,因為10000則訊息會用到快900MB多的記憶體。
            • 全部loading完別想全選+複製,就算是Chrome還是當掉了…
              • 在IE或Chrome按F12會出現主控台,IE點「指令碼」/ Chrome點「Console」,輸入  document.getElementById('webMessengerRecentMessages').innerText ,會出現純文字版的所有訊息,複製之。
            • 10000則訊息大約400KB,大家每天洩露給facebook或google的資訊其實檔案不大,儲存起來完全不費功夫呀!

            2012年12月17日 星期一

            Search Lab


            Download
            • Last update: 20121217
            • 用途:
              • 快速查詢病人lab data及個人資料
            • 在 login.ini 內設定portal帳號、密碼
            • 於院內網開啟程式
              • 輸入病歷號後按enter,查詢病人資料(查詢時程式會有點lag)
              • 左鍵點病人姓名,會在螢幕右下角顯示身份證字號
              • 左鍵點病人年齡,會在螢幕右下角顯示生日
              • 左鍵點 lab data,會在螢幕右下角顯示data日期
              • 「Preg」為Urinary pregnancy test
              • 左鍵點 BW(體重),會在螢幕右下角顯示體重登錄日期、體重數值x1.3、 體重數值x1.5
            • 按「Restart」則重新開啟程式
            • 在其他地方選取病歷號後快按兩次Ctrl+C,則自動貼上病歷號到程式內並查詢。
            • Bug report: (please send to scsnake@gmail.com)
            • Future feature:
              • 一次輸入多個病歷號
              • 開啟第四代報告系統的按鈕

            2012年12月16日 星期日

            Angioroom Scheduler


            Download
            • Last update: 20121217
            • 用途:
              • 快速查詢病人lab data及個人資料
              • 將查詢資料轉換成excel檔表格
            • 在 login.ini 內設定portal帳號、密碼
            • 於院內網開啟程式
              • 輸入病歷號後按enter,查詢病人資料(查詢時程式會有點lag)
              • 左鍵點病人姓名,會在螢幕右下角顯示身份證字號
              • 左鍵點病人年齡,會在螢幕右下角顯示生日
              • 左鍵點 lab data,會在螢幕右下角顯示data日期
            • 按「Convert to Excel」可以將查詢到的資料轉換成excel表格
              • 如果有安裝excel,會開新檔案
              • 如果沒有安裝excel但能開啟excel檔,則以angioSchedule.xls為範本修改,要再另存新檔
            • 按「Restart」則重新開啟程式
            • 在其他地方選取病歷號後快按兩次Ctrl+C,則自動貼上病歷號到程式內並查詢。
            • Bug report: (please send to scsnake@gmail.com)
              • 20121217:lab data日期無法顯示的問題
            • Future feature:
              • 一次輸入多個病歷號
              • 開啟第四代報告系統的按鈕

            Bone age report system

            Download
            • Last update: 20121216
            • login.ini 內設定portal帳號、密碼
            • 開啟RIS,開啟撰打報告畫面
            • 於院內網開啟程式
              • 自動讀取RIS目前病人病歷號、性別、年齡
              • 人工判讀bone age後輸入(eg. 輸入「12.5」代表「 12歲5月」)
              • 如果是計算ossified centers數量則勾選「ossified centers」
              • 按Enter/CopyPaste按鈕:將報告貼到RIS並暫存
            • Bug report: (please send to scsnake@gmail.com)
            • Future feature:
              • 找尋上次bone age報告,計算間隔時間

            2012年12月15日 星期六

            cleanLab

            Download

            • Last update: 20121215
            • 將出院病摘之檢驗報告減少行數
            • 刪除條件:
              •  刪除空白行
              •  檢驗數值全為0、NORMAL、符號(檢體有問題)、空白者刪除
            •  Bug report: (please send to scsnake@gmail.com)




            2012年11月27日 星期二

            Autohotkey hotstring簡介

            前言

            • 參考Autohotkey說明文件
            • ahk的指令一般是不分大小寫,忽視額外/行末的空白鍵,除非特別說明。


            簡介、 簡單範例

            ::btw::by the way
            • btw是hotstring,兩邊各夾著::,打完hotstring再按ending character(例如空白鍵、標點符號),btw就會替換成by the way
            ::btw::
            Msgbox You typed "btw".
            return
            • hotstring可以搭配ahk的指令,本例為輸入btw後跳出訊息框顯示You typed "btw".


            Ending Characters

            • 除非另外設定(見底下"*"設定),輸入ending character才會觸發hotstring,預設的ending character包含-()[]{}:;'"/\,.?!`n `t,其中`n為斷行(按Enter),`t為tab,`n`t之間有一個空白(空白鍵)。
            #Hotstring EndChars -()[]{}:;'"/\,.?!`n `t
            • Ending characters可更改,但會作用到整個script,不像底下介紹的設定是作用到其後的hotstring。


            常用設定

            #Hotstring c r *0
            • hotstring設定影響到所有其後的hotstring,上面的指令將設定cr兩個選項。
            • *0表示將*這個設定關掉(加一個零在後面)。
            :cr:j@::john@somedomain.com
            • 另一種方式是寫在前兩個冒號之間,這樣的設定只會影響當前的hotstring,後面的hotstring不會影響。
            * (星號)
            • 不需要輸入ending characters便能觸發hotstring。
            ? (問號)
            • hotstring可以在一個單字內部被觸發。
            b0
            • 預設情況hotstring觸發時,會先送出backspace將原hotstring刪除,再輸出替代的字串,b0設定則不送出backspace,保留原hotstring。
            • 例如:*b0:<td>::</td>{left 5},在輸入時(不需要ending character因為有星號*設定),自動輸出以及五個左方向鍵,最後游標停在<td>和</td>之間
            c
            • hotstring為區分大小寫,:c:Btw:::c:btw::是不一樣的hotstring。
            c1
            • 預設情況輸入的hotstring為首字大寫(eg. Btw)時,送出的字串也是首字大寫(eg. By the way);輸入的hotstring全部大寫(eg. BTW),則送出的字串也全部大寫(eg. BY THE WAY);其他的輸入方式,則照原字串輸出。c1設定則不管輸入的大小寫,都照原字串輸出。
            o
            • 預設情況輸入ending character會觸發hotstring,且保留ending character。o設定仍要輸入ending character,但ending character會被刪除。
            • 適用於名詞複數、所有格、動詞過去式的情況。以:o:nd::nodule為例,nd s會輸出nodules
            r
            • 預設情況輸出字串中{enter}是Enter、^c是ctrl+c(詳見Send)。r設定(raw)則忽視特殊字元,字串中是{enter}就輸出{enter}。


            Long Replacements

            ::text1::
            (
            line1, blabla
            line2, blabla
            )
            • 如上面格式時,可以輸出一大段文字。預設使用r設定,視括號內為純文字,除非以r0設定蓋過。


            Context-sensitive Hotstrings

            #IfWinActive 放射線資訊管理系統
            ::scc::suggest clinical correlation
            #IfWinActive
            ::scc::squamous cell carcinoma
            • #IfWinActive所夾住的程式碼,表示在某個視窗active時才會作用,scc會輸出suggest clinical correlation,在其他視窗則是squamous cell carcinoma。也可用#IfWinExist


            AutoCorrect

            • 官網所提供的自動拼字校正ahk,收集4700個常見的英文拼字錯誤。按Win+h可加入新的拼字校正。


            其他

            ::test::
            SendInput %var%
            return
            • 如果要輸出一個變數的值,則要用SendInput指令輸出var的值。
            ::btw::by the way   `
            ::btw:: by the way
            • 在行末加一個accent/backtick ( ` ),則`之前的空白也包含在輸出的字串。此例btw將輸出by the way  
            • 第二行則會輸出 by the way(注意最前面的空白)
            #Hotstring NoMouse
            • 預設情況下滑鼠左右鍵的點擊會重設hotstring,因為滑鼠動作通常表示使用者要改變輸入位置。可用上述設定使滑鼠動作不動設hotstring。
            A_EndChar
              • 內建變數A_EndChar會儲存最後一個ending character,可判斷A_EndChar達到不同的輸出方式。
              ::`t`n``::
              • 在ahk中有些escape character,如果作為hotstring也需要以`來escape,除了逗點 ( , )、百分比符號 ( % )、冒號 ( : )。
              ::texts::
              SendPlay %var%
              return
              • hotstring最多40個字元。在SendInput模式下最多輸出5000個字元,在其他模式最多16383個字元。利用上述SendPlay輸出變數值,則沒有上限。另外參考SendMode,一般建議設定SendMode Input
              ::hs::string1
              ::hs::string2
              • 如果同時有兩個以上的hotstring被觸發,會優先觸發在script中出現的第一個。在此例中hs會觸發string1。

              • Backspace並不會重設hotstring,所以打成btx後按backspace再打w仍是觸發btw;但方向鍵、上一頁、下一頁、Home、End會重設hotstring。
              • 可參考Input以達到更進階用途。


              實用範例

              :*?:``::+^{left}{bs}
              • 在輸入單字途中(?設定)可觸發,不需要ending character(*設定)。
              • hotstring為鍵盤最左上角的`(以`來escape,`` = `),可觸發shift (選取) + ctrl+左方向鍵 (跳到一個單字之前) + backspace (刪除)
              • 總結來說類似backspace,但backspace刪除一個字元,而上述hotstring刪除一個單字。