區塊鏈在醫療領域的應用(Rock Stars of Blockchain Healthcare)

這本關於區塊鏈的書:區塊鏈社會,引起了我對於區塊鏈這個技術的好奇心,因為“區塊鏈”這三個字太特別了,其中有一章談論區塊鍊在醫療資料處理的應用,稍微開了點腦洞,畢竟醫療資料開始移往移動設備,這樣的技術對於資料的同步和儲存應該有一定的重要地位。

區塊鏈社會:解碼區塊鏈全球應用與投資案例

然後最近在研究HL7相關的資料時,碰巧看到了2017 HIMSS會議中,有一個關於Blockchain在醫療上的應用,便記錄起來。
screenshot.png

screenshot.png

閱讀參考:
Rock Stars of Blockchain Healthcare
Blockchain:Internet問世以來最具破壞力的發明

 

健康資訊交換第七層協定(Health Level Seven):醫療資訊系統的框架

醫療資訊系統目前最重要的資料交換協定為HL7(Health Level Seven),1987年Health Level Seven Internation組織正式成立開始作為推廣HL7框架的非營利組織,這套協定的影響力便越來越大,往前追溯HL7最早在1970年代在UCSF裡開始發展,這邊有HL7早期的歷史,HL7為何要叫做Health Level Seven呢?,其實是呼應在International Organization for Standardization(ISO)裡面Open Systems Interconnection中的第七層應用層
screenshot.png

簡單來說,HL7清楚定義了醫療資訊如何整合、傳遞、包裝,讓不同醫療組織間的資訊傳遞能更順暢。HL7 standards主要有七大類:Primary Standards、Foundational Standards、Clinical and Administrative Domains、EHR profiles、Implementation Guides、Rules and References、Education and Awareness。每個類別下面都分別有很詳細的規範。

目前在HL7官方網站有登錄約316個以HL 7 協定所開發的大型專案,其中已有9個專案試圖將基因資料整合進去。

本身HL7官方有提供一套認證機制,來確立能理解HL7裡頭的協定,並提供產業應用的能力,稱作Clinical Document Architecture(CDA) specialist、HL7 Version2、HL7 Version3的認證。其認證可以藉由網路考試的方式來取得,但價錢都不便宜。

今年五月在西班牙有HL7 Conference
screenshot.png

閱讀參考:
OpenFoundry 關於健康資料交換第七層協定的說明
Introduction to HL7 Standards
一個具備HL7 CDA R2簡化界接介面的電子病歷系統之設計與實作
HL7中國委員會
台灣健康資訊交換協定委員會

理解Bioconductor系列(二):AnnotationDbi,決定annotation database的基本結構

AnnotationDbi主要是設計用來對應資料庫的不同物件,讓各式資料庫在R有一個統一的使用指令,也就是一個標準的package資料庫介面用來開發各種SQLite-base annotaion database。所有的“.db”結尾的library其實就是使用AnnotationDbi來,而從資料庫的命名就可以知道此資料庫是使用哪一類的資料(OrgDb,ChipDb,TxDb,hgu133plus..)。

其中,AnnotationDbi內部有提供一系列開發者比較詳細的方法和資料庫的scheme使用方式,方便用來處理不同生物體或是資料。

每個以annotationdbi為資料框架的package中,會將annotation對應的資料以AnnDbBimap物件的方式將各種對應關係存放起來,而每個AnnDbiBimap物件有點類似environment物件,所以可以用ls,[[,mget,get這些函數。

#可以檢視reactome.db package中,有多少個獨立放置對應關係的AnnDbBimap物件
ls("package:reactome.db")
#看此物件中的資料之欄位名稱
columns(reactome.db)



#顯示reactome.db中可以用來抓取資料的key種類
keytypes(reactome.db)

screenshot.png

#直接讀取特定key種類的值
keys(reactome.db,keytypes="ENTREZID")

screenshot.png

#最後使用keys來query此annotation database
AnnotationDbi::select(reactome.db, keys = c("2547"), columns = c("PATHID","PATHNAME"), keytypes="ENTREZID")

screenshot.png

這些基本指令是有依賴annotationdbi所開發annotation package會具有的共通性指令,可以趁機去看裡面有什麼自己有興趣的資料!

閱讀參考:
How to use bimaps from the “.db’ annotation package
AnnotationDbi: Introduction To Bioconductor Annotation Packages

理解Bioconductor系列(一):Bioconductor中的Annotation資源

最近對於所謂的“Annotation”這個辭彙在生物資訊裡的意思越來越有感覺,而且深深覺得其對於整個生資分析中所佔有極重要的角色,經驗高低可能就決定在此,很多基本的分析流程都是可以很快速學會的,但是對於自己資料做好的annotation卻是沒有固定模式可學的。

那什麼是annotation的定義呢?(這邊是在探討比較廣義層面的)

下面是annotation在wiki裡面的定義,簡單而精準:

An annotation is a metadata attached to text, image, or other data. Often, annotations make reference to a specific part of the original data.

好的annotation其實就是善用全世界科學家花費時間和金錢做實驗得出的寶貴資料,將其應用在自己的分析專案中,怎麼善用全世界上千個資料庫的資訊,就必須要有廣泛的知識,且另一方面,進行annotation的過程,本身就有一些“目的”導向,通常你就要很清楚自己想要了解的方向,比如你拿到了一個Gene list,你好奇的是這群基因的序列關係、功能上的關係、藥物反應、多少比例是文獻中跟癌症幹細胞相關的標記、多少是跟生長因素相關的、分別牽涉到什麼生物路徑的,根據不同的好奇方向,其實就要去找不同的資料庫來佐證,且怎麼呈現又是另一門需要花費心思的事情。

從bioconductor上面的package總數,有一半以上都是跟annotation功能相關的

screenshot.png

Bioconductor的計劃其中很重要的便是讓R變成在做生物資訊annotation的專業工具,所以開發出很多的annotation package來達成這個目的,且有一套良好的規範,分別讓想要將資料庫包成package,或是如何好的query資料,都能更加的統一性,其中AnnotationDbi就是其中一個package,將各種可以用來註釋的資料包成package,不用再使用web request的方式,這結構便是由AnnotationDbi packages所決定的,而這其中分成很多種類:

  1. Organism level: e.g org.Mm.eg.db
  2. Platform level: e.g. hgu133plus2.db
  3. Homology level: e.g. hom.Dmi.inp.db
  4. Transcriptom level:e.g.TxDb.Hsapiens.UCSC.hg19.knownGene,EnsDb.Hsapiens.v75
  5. System-biology level: GO.db

screenshot.png

這結構很好的把所有在bioconductor中的annotation資源分成五大類,並能根據這五大類來找尋自己所需要用的annotation 資源,而不會被搞糊塗。

Python多線程使用Queue和Thread來加速用Ensembl REST API查找variant資訊

現在主要生物醫學資料庫如ensembl, nubi都有開放API接口,可以直接用程式去提出一堆的請求,不用像傳統的網頁查找那樣,省掉很多麻煩,只要稍微瞭解一下http原理,各種程式語言如R的httr中文教學)或 是Python的requests,使用起來都算方便,

這裡遇到一個小問題,應該說想要更好的解決它:如何加速查找速度,假如我有上千個想要查找的資料?
舉例來說,當你想要找一大串4000個基因變異、相關基因功能,雖然不需要在網頁上點選4000次(可能花好幾天吧),幾行程式碼就可以解決,但當要丟4000次請求,來取得資料時,假設1次請求,要花5秒種取得資料,那麼4000次,還是要花6個小時,那要怎麼改善這個問題呢?因為我們很貪心的想要花更少時間(假如網路頻寬很大的話)

一種最直覺的方式,便是把要查找的variant列表,切成多份,然後同時跑,最後再把資料整合起來。

另外,因抱持者想要探索看看新方法,便嘗試使用Python中的QueueThread,用多線程的方式來解決這個問題。

我基本思路是將我要查找的Rsid(Variant的資訊),用iterator的方式來吐出每次要query的id,而Queue object可以把我處理好跟我所開啟thread間資訊同步的問題。

這邊是最後使用的代碼

#這邊是我想要查找的基因變異variant的ID
test = RSID.iteritems()

#我希望開的線程數量
concurrent = 10

#因為資料是以json檔傳回,最後我都要塞回這個test_list中
test_list = {}

#使用queue的重點,是要解決共享變數不能被thread同時讀取的問題,他可以有效解決thread間在取用共享變數的問題
que = queue.Queue()
for i in range(concurrent):
    que.put(next(test)[1])

def doWork(*args):
    tmp = args[0]
    while tmp.qsize() > 0:
        rsid = tmp.get()
        test_list[rsid]=rsid
        #這邊是ensembl Rest API的接口
        server = "http://grch37.rest.ensembl.org"
        url_1 = "/variation/human/"
        url_2 = "?pops=1"
        ext = url_1+rsid+url_2
        r = requests.get(server+ext, headers={ "Content-Type" : "application/json"})

        if not r.ok:
            r.raise_for_status()
            sys.exit()
        decoded = r.json()
        test_list[rsid] = decoded

print("\t[Info] Queue size={0}".format(que.qsize()))

# 這邊是線程開啟和運行的地方
for i in range(concurrent):
    thread_name='Thd'+i
    t = threading.Thread(target=doWork, name=thread_name, args=(que,))
    t.daemon = True
    t.start() 

td = datetime.datetime.now() - st
print("\t[Info] Spending time={0}!".format(td))

P.S:後記,這種方式其實頗危險的,假如所使用的服務管理者,會特別管理高頻要資源的IP那麼就要注意,可能從此ip就被封了,所以最好可以掛載proxy在進行query,另一方面,時間允許下,就用單線慢慢抓吧!甚至必須去測試對方有沒有限制每秒能query的數量,就要去調適最佳化的參數!

閱讀參考:

Python Queue 模塊
what is the fastest way to send 100,000 HTTP requests in Python?
using iterators and generators in multi-threaded applications
iterables/iterators/generators
How many threads is too many?
Python模塊學習 – threading 多線程控制和處理

生物資訊入門書推薦:The Biostar Handbook (測序資料分析為主)

screenshot.png
這本書The Biostar Handbook最近總是在Biostar論壇裡看到他的廣告,其實作者stván Albert很早就開始預告這本書的寫作計畫了,整個書的landing page很早就出來了,但最近才開始賣這本書,身為資訊焦慮患者,就敗了一本來研究一下。

 

Stvan Albert本身為Pennsylvania State University 生物資訊教授, Biostars: Bioinformatics Questions and Answers(就是Biostar論壇)就是他在維護和管理的,另外,Galaxy platform是他其中一個參與的專案,所以算是教學經驗豐富,本身做了許多有趣的生資項目。

整本書算是很入門的測序資料分析分享,可以看到部分章節不太完整,開頭談了一點生物資訊的入門起手觀念,目前三大主流測序機器pacficbio/illumina/miniON,帶一點unix指令教學,分別介紹基本的alignment 資料結構、vcf的資料結構、常用的分析方式和網站(GO analysis/BLASK),基本上一個主題提三個例子,大多點到為主,Variant calling和RNAseq為兩大分析主題簡介,為起手的介紹。

整本書我個人喜歡的地方是他解說文章寫得很親民,不太會文鄒鄒的,且通常會附許多很經典的網路文章,來幫助他把一些“網友”的觀點原汁的加到他的書裡面(蠻好奇引用部落格文章的趨勢,會不會慢慢成主流),可以點選超連結,再進一步閱讀(買電子書的好處),所以買這本電子書,可以想成他幫你整理網路上很多經典文章的連結於其中,節省你上網大海撈針的時間,直接看這些經典文章,從如何做好專案資料整理到統計的p value該如何處理等,相對於很硬派的教科書,這本書應該是本“小書”,蠻適合作為定序資料分析的入門書。

R使用aggregate來處理註釋過後的基因列表

問題其實很簡單,在使用panther database來幫手上的基因找尋他們的功能,通常一個基因都會對應到5-6個功能,而最後希望能用一張表格來輕鬆瞭解自己找到的基因功能,處理前的資料如下:screenshot.png

希望處理後,檔案可以看起來如下面這幫

screenshot.png

實際上,這個問題使用aggregate就可以解決,輕鬆一行代碼的事情,裡面總共有三種寫法,供參考使用

#method 01
up.result.protein.function %>% aggregate(CLASS_TERM ~ ENTREZ, data=.,c)

#method 02</pre>
up.result.protein.function %>% aggregate(CLASS_TERM ~ ENTREZ, data=.,toString

#method 03
up.result.protein.function %>% aggregate(CLASS_TERM ~ ENTREZ, data=.,paste,collapse=",")
 

這問題也可以使用dplyr中的summarise來解決!

閱讀參考:
Aggregating by unique identifier and concatenating related values into a string

匯入多個csv檔:使用grid.expand搭配reduce和map

有時我們會需要讀入多個不同編碼或是代號儲存的,最麻煩的是如何產生這些檔案路徑的各種組合,此時便可以使用expand.grid函數,這函數可以產生各種組合的data.frame,然後使用do.call或是reduce,來將這些組合合併成路徑,另外,cross_n函數等,跟傳統expand.grid的功能是差不多,有興趣可以查一下他的函數介紹。

#method 1: with all dplyr tool
expand.grid(c("DNA_","RNA_"),c("sample-1","sample-2","sample-3"),c(".csv") %>% as.list %>% reduce(paste) %>% map(read_csv) %>% reduce(rbind)

#method 2: with do.call
expand.grid(c("DNA_","RNA_"),c("sample-1","sample-2","sample-3"),c(".csv")  %>% do.call(paste) %>% map(read_csv) %>% reduce(rbind)

其實這問題的解決方法有蠻多的,下面的討論串分別是用不同的概念和想法去實現的,而使用reduce和map這兩個的方式算是比較簡單,且可以輕易的串在分析流程的方式。
 

相關閱讀參考:
R – concatenate row-wise across specific columns of dataframe
concatenating rows of a data frame
How do I concatenate a vector of strings/character in R?
Finding all possible combinations of a three strings

進階R網路爬蟲:利用rvest來爬取需要帳號密碼登入的藥物基因體資料庫

rvest是由Hadley Wickham所開發的R的package,其結合httr和xml2,提供更簡潔方便的來抓取網頁的html, xml資料。單純使用httr其實就可以很方便地使用http的方式來抓取網站資源,但還需要再另外使用其他處理回傳資料的軟件包,所以rvest就解決這個問題,可以直接指定css或是xpath來抓取特定的xml/html nodes。

關於如何選定css或是xpath,可以使用Hadley Wickham推薦的selectorgadget,可以很方面的在網頁上選取想要抓取的部分。

這邊想要分享更進階的應用,使用rvest來爬取需要先登入帳號密碼的網站。

問題
主要是想用rvest來爬取藥物基因體學PharmGKB的資料庫,但此資料庫需要先登入

(此資料庫是可以申請License授權資料的,這邊只是想做一個練習!)


%e8%9e%a2%e5%b9%95%e5%bf%ab%e7%85%a7-2017-01-18-%e4%b8%8b%e5%8d%8811-44-20

那要怎麼解決這個問題呢?

可以利用rvest裡面的html_session, html_form, submit_form, jump_to這幾個函數來解決!

# create a session
# 首先,第一個使用的url為有填寫登入帳號密碼的頁面
url.address       <-"https://www.pharmgkb.org/sign-in-start.do"  

## 使用html_session建立一個session(session其實是用package所建立的,可以保持你在此網站互動的足跡,想更深入可以稍微瞭解一下http協定和這篇文章)
pgsession <-html_session(url.address)
## 抓取填寫帳密欄位的表格(這邊的2是要根據每個人所登入的網頁不同調整,這邊帳密表格剛好在第2個)
pgform    <-html_form(pgsession)[[2]]       ## pull form from session

## 填寫帳密
filled_form <- set_values(pgform,
                          `userId` = "****@gmail.com",
                          `password` = "*****")

## 送出帳密到這個session中,取得進一步爬取資料的授權
submit_form(pgsession,filled_form)

## 接者要跳轉入自己真正有興趣的網頁
rs.url.address <- paste0("https://www.pharmgkb.org/view/variant-annotations.do?variantId=",rsID)

# 使用jump_to函數在此session中送出url request(模擬個人瀏覽網頁的狀況)
web.page <- jump_to(pgsession, rs.url.address) %>%
                    read_html

參考閱讀:
關於http協定和session
1. how programming language implement “session"
stackover討論串
1. scrape password-protected website in R
2. automating the login to the uk data service website in R with Rcurl or httr
3. scraping password protected forum in r
4. Using rvest or httr to log in the non-standard forms on a webpage
rvest資料
1.rvest package on Github
2.rvest documentation on CRAN
3.rvest tutorial

使用purrr package學functional programming的觀念(五):一行同時讀取多個檔案,彙整成單一個data.frame且新增欄位

這邊嘗試要解決一個很棘手的問題,手上有一個下面這樣的資料清單,而每個資料夾下面有多個有固定編號的檔案。

screenshot.png

而每筆資料大概長的如下面這樣:

screenshot.png

而每個檔名是那筆資料的編號和資訊,最後希望可以把單個檔案讀取進來後,合併在一起,且根據每個檔案的檔名,新增4個欄位和其型態,最後理想上希望變成下面的樣子:

screenshot.png

根據這個問題的話,可以使用read_delim, pmap_chr, map, pmap, reduce這四個函數來使用,要完成這個小工作的話,能簡單可以分成幾個概念:
第一個是要彙整多個檔案路徑、第二個讀取多個檔案路徑的函數、第三個則是根據不同資料的檔名,來為其所讀取的data.frame新增欄位、第四個則是將所有放在list中的data.frame合併。

當概念解離清楚之後,便可以針對每一步挑選適用的函數來處理,比如
第一個
小步驟想要彙整多個檔案路徑,這步要準備的便是把所有路徑以list的方式來儲存,然後用paste0函數來將每個路徑合起來,使用pmap_chr來完成這件事。
pmap_chr函數可以用函數來處理list中的每個element,接者在使用map搭配read_delim來完成第二個小步驟,如下面這個代碼

#將所有的變數,使用list來儲存
list(as.list(rep(Pathway.path, pathway.number)),as.list(rep("/",pathway.number)),as.list(list.pathway.json)) %>%
#將這些變數導入到pmap_chr函數,因為pmap_chr是當list內的element為chr時所用的,這一部是為了把每個檔案的路徑組合起來
pmap_chr(paste0) %>%
#接者在使用map函數來針對上面處理完的一串路徑list,使用read_delim函數,分別讀取,並且在用list來吐出
map(read_delim,delim="\t")

第三個則是根據不同的資料檔名,來為其所讀取的data.frame新增欄位
此時我們已取得一個list,裡面的element都是一個檔案讀入的data.frame,而我們希望再把data.frame合併前,將每個data.frame使用其檔案名稱來增添其資料欄位,如下面的代碼:

#這邊的.代表從剛剛上面的代碼pipe進來的位置,後面三個則是我們希望增加的欄位,和每個欄位的名稱
list(.,pharmGKB_ID,pathwayName,Pharmacokinetics,Pharmacodynamics) %>%
#同樣的這邊可以使用pmap,此時不同使用pmap_chr,因為我們list中,一組是data.frame的格式
pmap(function(x,pharmGKB_ID,pathwayName,pharmacokinetics,pharmacodynamics){
                x %>%
mutate(`PharmGKB ID`=pharmGKB_ID,
       `PathwayName`=pathwayName,
        Pharmacokinetics=pharmacokinetics,
        Pharmacodynamics=pharmacodynamics )
                 })
#這邊比較值得一提的是pmap裡面可以使用函數作為參數,而這個函數可以直接在裡面定義,有點套用lambda的寫法,來做這件事情,這邊是為了把欄位的名稱確立

第四個則是將所有放在list中的data.frame合併,這邊使用reduce來解決這件事情,reduce可以將放入的list,把每個element用某個函數處理,一個接一個。

CleanPathway <-list(as.list(rep(Pathway.path, pathway.number)),                 as.list(rep("/", pathway.number)),as.list(list.pathway.json)) %>%
pmap_chr(paste0) %>%
map(read_delim,delim="\t") %>%
list(.,pharmGKB_ID,pathwayName,Pharmacokinetics,Pharmacodynamics) %>%
pmap(function(x,pharmGKB_ID,pathwayName,pharmacokinetics,pharmacodynamics){
                x %>% mutate(`PharmGKB ID`=pharmGKB_ID,
                             `PathwayName`=pathwayName,
                              Pharmacokinetics=pharmacokinetics,
                              Pharmacodynamics=pharmacodynamics )
                 }) %>%
                reduce(rbind)

這四個步驟便可以完成這件事情,這過程很重要的便是搞清楚map, pmap, reduce,他們要怎麼接受參數和處理,可以因此更清楚在R裡面list和data.frame的特性。不過在處理的過程也會使用到stringr的函數,來處理字串的問題。

閱讀參考:

How can I read in multiple files
Reading and combining many tidy data files into R