Reference-free Quantification Code Review

linnil1
9 min readSep 4, 2020

--

這次 code review 背景是 學長這篇 Effect of de novo transcriptome assembly on transcript quantification

如果不了解原始論文在做什麼的,請先去看前篇

這篇是我第一個 code review 所以會從 0 開始講(應該)(結果沒有)

這個 paper 的 pipeline 長這樣,總共有 3x2x2x3x3=108 種組合,所以code 有可能會很混亂,但也因為如此,如果寫的整齊,是一個很好的範例。

The pipeline overview of QuantEval
一張圖說完整個實驗

說明

原始的 code:

我重新魔改的 code(本文使用):

首頁

首先要看說明 README 也就是進這個 github repo 第一個地方

非常重要,通常會寫怎麼跑 怎麼安裝 怎麼設定

一定要寫,務必要寫,而且要寫的精簡

系統工具安裝

我很推薦 docker,docker 講簡單點是個虛擬環境(容器)的執行器,你可以下載環境(Image),然後執行他,執行時你的環境(container) 是跟外界隔離的,所以:

  1. 資料不會髒掉,即使髒掉在重開新的環境就好ㄌ
  2. 你可以隨時使用不同的版本的環境
  3. 環境別人都包好了,所以通常直接使用就可以了,直接省去安裝步驟
  4. 你也可以包環境,避免妳自己也重現不出來自己的 code

Example: docker run -it --rm -v $PWD:/app docker.io/library/alpine ls /app 解釋一下,

  • -it是 interactive
  • --rm 是 執行完後刪除環境
  • 那執行什麼呢 ls /app
  • /app 是你把現在的資料夾(PWD) mount 進去環境裡面的位置,稱之 volume 所以是 -v ,也只有 mount 進去的才能被改到,存在環境(container)的其他地方重開就不見了
  • ls 是在 docker.io/library/alpine 這個環境裡面的 script 這樣,假設library/alpine這個環境你沒有,他會自動幫你下載

Python 部分

通常 Python 會把需要的套件都會放在一個叫 requirements.txt 的檔案裡,然後你就安裝 pip3 install -r requirments.txt

然後我蠻推薦 ipython 的 (Jupyter notebook 是 ipython 再把它弄成 web 介面這樣),ipython 我覺得最好用的功能是

  • 有 python 功能,要操作複雜的字串處理就很簡單
  • 執行 shell command 也很方便

根本就可以取代 shell script ㄌ,等等我們就會看到效果

Pipeline 部分

首先要做到的是 code 跟 meta 資料 分離,

meta 資料

我把東西放在 metadata/ 裡面,比如說模擬的參數,還有一些設定

最主要的設定在 metadata/meta.yml,yaml 是個很適合人類閱讀與編輯的類似 json格式

比如說,下面的 yaml 檔,我設定了有那些 species 與 species 的 reference 的 檔案在哪裡

metadata/meta.yaml#L1

又或者你設定該工具的 docker 版本(images 那排),與執行時的參數( trimmomatic 那行),這樣的話,檢查跟維護就很輕鬆

metadata/meta.yaml#L43

Pipeline code

首先我們用 argparser 把剩下的參數讀進來,比如說 threads memory

所以操作起來變成這樣: ipython3 pipeline.ipy --method=all -t 32 可以讓使用者輕鬆修改他想用的資源但不會動到 code (尤其是資料夾路徑)

最後一行我們就把 meta 資料讀進來

pipeline.ipy#L11

然後我們看看 ipython 的威力,用 assemble 這個操作為例(下圖)

  1. 用 python 的 function 包起來,然後用 docstring(就是那幾行註解),去說明這個做了什麼,input 什麼 output 什麼
  2. 可以在裡面 import 其他 python code,執行你想要的事情(from xx import xx 那裏), 比如說這裡就是一個簡單的 code 把 contig < 500bp 的 contig 去掉
  3. 因為我們對 每個 species(e.g. yeast) 每個 dataset(e.g. simulation low, simulation high, …) 做 我們想要的 assemble 方式(e.g trinity) 所以用三個 for 迴圈
  4. 跟 shell code 只差一點,加個 ! 就可以執行,重點是可以塞 python 變數(e.g. !mkdir -p {xx_folder} )
  5. 執行 docker,前面有定義 dk 是執行 docker 的 alias,把那段全部展開就是像這樣 docker run -it --rm -v $PWD:/app -w /app docker.io/trinityrnaseq/trinityrnaseq:2.11.0 Trinity --max_memory 300G --CPU 32 ...
pipeline.ipy#L205

就這樣 剩下的都差不多

總之這樣寫就全部都統一了,不會有東一個 .sh檔 西一個 .py 檔 而且變數名稱還可能不同

Connected-component 部分

先呼叫上篇的 pipeline 圖,其中最看不懂的可能是 for each segment 跟 for each sequence 這裡,我們就從 code 分析

先對每一個 local alignment 做 Threshold

scripts/quanteval_utils.py#L88

再把每個 pair 丟進去 Match 這個 class,extend 完後 計算 Identity(其實就是 accuracy 跟 recovery)

scripts/quanteval_utils.py#L139

Extend 做了什麼,其實就是把 Sequence Align 到的地方 給一個 identity

scripts/Match.py#L73

所以以上的 code 大概可以視覺化成這樣

Mean 的部分寫在 scripts/Match.py#L87

最後 每個 sequence 的 recovery & coverage 如果 > 90 (整份 code 單位都是 %,單位要一致,才不會後面 debug 很辛苦) 就可以當作一個 edge ,然後我用 scipy 的 connected-component 直接拿到答案(原作者是自己寫)

scripts/quanteval_utils.py#L195

其他

Dataframe

接下來的操作就是 pandas dataframe 的操作了

就像這樣

DataFrame 操作示意圖

可以自己去看 code ,我盡量把 code 寫的簡單易懂ㄌ

命名

除了 function 的名字,檔案的命名也很重要,不然你還要翻 code 才會知道那個檔案再幹嘛

Readme.md 那張圖

example

大家都是速食主義的,大家想看到的就是 code 能馬上動,

  1. 提供 example,本 repo 放在 example/
  2. 或者是是截圖成功的樣子,別人至少會認為你的東西能跑
  3. 包成一份環境,或者是包成一個 bin 檔之類的

結論

這份 code 我重寫了一個禮拜,看起來應該都沒有寫錯 但是

  • 拜託寫註解
  • code style 要統一
  • function 的命名要合理

不然不會有人想看ㄉ 大家都很忙

最後

按 claps 好ㄇ

也可以順便按我的 code 跟學長的 code 一個 Star

--

--

linnil1
linnil1

Written by linnil1

目前做生物資訊與演算法,過去做過 Machine Vision(Deep learning),維護伺服器(k8s, docker),部分IOT(rpi, arduino)

No responses yet