Nextflow|input channels 含有重複辨識碼會引發資料串擾

先前曾介紹如何透過辨識碼來避免不同樣本的分析資料在平行運算時彼此串擾。

當 workflow 涉及 output 合流的狀況時,要把所有資料整合在同一個 input channel 並且共享唯一的辨識碼。

1
val(id), val(data_1), val(data_2)

分開寫的話很可能會發生串擾。首先 process 釋出資料的順序取決於完成時間,沒辦法保證來自不同 channels 的 data_1 和 data_2 同屬一個樣本。其次,前面的辨識碼會被後面的辨識碼覆蓋,導致辨識碼與資料不相符。

1
2
val(id), val(data_1)
val(id), val(data_2)

整合 output channels 的設計其實很常見,例如合併多組分析的統計表,我剛寫 Nextflow 時也常踩這個坑,所以覺得值得寫一篇短文說明問題的起因。

為了模擬 processes 資料釋出不同步的情形,我建立了內容一致但排列順序不同的 ch_1ch_2,代表上游分析其它 processes 的 output channels。我刻意讓資料的數值與辨識碼相符,方便後續觀察資料串擾。

1
2
ch_1 = channel.of(["id_1", 1], ["id_2", 2], ["id_3", 3])
ch_2 = channel.of(["id_1", 1], ["id_3", 3], ["id_2", 2])

然後再用 print_data 來印出兩個 channels 的資料,

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
process print_data {
input:
tuple val(id), val(data1)
tuple val(id), val(data2)

output:
stdout

"""
echo "Inputs of ${id} are ${data1} & ${data2}"
"""
}
workflow {
print_data(ch_1, ch_2).view()
}

執行 process 會發現 id_3 和 id_2 的資料彼此混淆了,這是因為不同 channels 的內容順序不同,再次加上二個 $id 覆蓋了第一個 $id 的資料。

1
2
3
Inputs of id_1 are 1 & 1
Inputs of id_3 are 2 & 3
Inputs of id_2 are 3 & 2

正確的作法是讓輸入資料共享唯一的辨識碼,並且在執行 process 前先使用 join 依照辨識碼合併 channels。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
process print_data {
input:
tuple val(id), val(data1), val(data2)

output:
stdout

"""
echo "Inputs of ${id} are ${data1} & ${data2}"
"""
}
workflow {
ch_input = ch_1.join(ch_2, by: 0)
print_data(ch_input).view()
}

這樣就能保證樣本和資料彼此對應了。

1
2
3
Inputs of id_1 are 1 & 1
Inputs of id_2 are 2 & 2
Inputs of id_3 are 3 & 3