-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathatom.xml
461 lines (244 loc) · 298 KB
/
atom.xml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
<title>Juse's Blog</title>
<subtitle>积跬步 至千里</subtitle>
<link href="https://biojuse.com/atom.xml" rel="self"/>
<link href="https://biojuse.com/"/>
<updated>2025-02-12T08:10:11.548Z</updated>
<id>https://biojuse.com/</id>
<author>
<name>Juse</name>
</author>
<generator uri="https://hexo.io/">Hexo</generator>
<entry>
<title>VCF 文件转坐标的方法汇总及注意事项</title>
<link href="https://biojuse.com/2025/02/12/VCF%20%E6%96%87%E4%BB%B6%E8%BD%AC%E5%9D%90%E6%A0%87%E7%9A%84%E6%96%B9%E6%B3%95%E6%B1%87%E6%80%BB%E5%8F%8A%E6%B3%A8%E6%84%8F%E4%BA%8B%E9%A1%B9/"/>
<id>https://biojuse.com/2025/02/12/VCF%20%E6%96%87%E4%BB%B6%E8%BD%AC%E5%9D%90%E6%A0%87%E7%9A%84%E6%96%B9%E6%B3%95%E6%B1%87%E6%80%BB%E5%8F%8A%E6%B3%A8%E6%84%8F%E4%BA%8B%E9%A1%B9/</id>
<published>2025-02-12T08:00:00.000Z</published>
<updated>2025-02-12T08:10:11.548Z</updated>
<content type="html"><![CDATA[<html><head></head><body><p>历史数据的整合分析往往涉及不同时期使用不同参考基因组版本产生的数据。例如,某些较早的研究可能基于 hg19/GRCh37 进行分析,而新的研究多采用 hg38/GRCh38。<strong>为了进行比较分析,需要将这些数据统一到同一个版本</strong>。</p><p>坐标转换是通过 chain file 来实现的,<strong>该文件记录了两个基因组版本之间的对应关系</strong>,包含了基因组重排、插入和删除等信息。转换工具会根据这些信息将原始坐标映射到目标版本的相应位置。</p><h2 id="正文"><a href="#正文" class="headerlink" title="正文"></a>正文</h2><p>本文将介绍如何使用两款主流工具 <strong><u>CrossMap</u></strong> 和 <strong><u>GATK LiftoverVcf</u></strong> 以及最近的一个新工具 <strong><u>BCFtools liftover</u></strong> 进行 VCF 文件的坐标转换。在说明之前,首先简要介绍三个软件的差别:</p><ul><li>CrossMap 除了 VCF 的坐标映射外,也支持很多其他文件格式的坐标转换。对于 VCF 文件而言,CrossMap 并不要求其具有完备的 Meta-information 和 Header line 部分,<strong>只需要突变数据行符合格式即可</strong>。</li><li>GATK LiftoverVcf 则主要支持对 VCF 文件的坐标进行转换。其<strong>要求 VCF 文件具有完整的 Meta-information 和 Header line 部分</strong>。相对 CrossMap 而言对 VCF 文件格式的要求更加严格。</li><li>BCFtools liftover 在前两者的基础上,<strong>对 InDel 的转换逻辑进行了完善,从而支持更准确的 InDel 坐标转换</strong>,并且相对而言功能更加完善齐全(例如多等位基因的支持、INFO 字段的更新等)& 效率更高。其对 Meta-information 的要求更加严格,需要包含原始坐标的 contig 长度信息。</li></ul><img src="https://oup.silverchair-cdn.com/oup/backfile/Content_public/Journal/bioinformatics/40/2/10.1093_bioinformatics_btae038/1/btae038f7.jpeg?Expires=1742369767&Signature=RZR7IoEOR8iKdVM4o5D1ApcX9A0-FZiEZVf2QwISN11~N5Y0x7Q2-9svah0KKKhFM6VlebYg1JzIUWw-rE3aYO~GThyM6dzbQsOR6I9FCPJeC7jN6SR79-7O2B2gV5PsEF4FZcqHHyVFvQ3pKU8-El~zoOG-nJlFV1im7VWo8n5aO9SdW-0SVuQ1RS-CwfxVgZ3hH4T~Ip39pGU1eXAC6hUN4~Yx7GZ91o-hjcTq1l46ixjDWWrYiukUWPUba0KHnkzu5wA51g9mtuIaPrEuC3uW7BPGuUQFl3TuLtYUd3psDTrvFVi4lBNmAWHKe~d1cfSBPPjFbOZpDP3JScHTkw__&Key-Pair-Id=APKAIE5G5CRDK6RD3PGA" width="800px"><center>各种坐标转换工具的内存使用和时间开销对比</center><p>VCF 文件格式详解:<a href="https://samtools.github.io/hts-specs/VCFv4.2.pdf">https://samtools.github.io/hts-specs/VCFv4.2.pdf</a></p><p>Meta-information & Header line 示例可见以下文件开头以 # 起始的行:</p><p><a href="https://github.com/vcflib/vcflib/blob/master/samples/sample.vcf">https://github.com/vcflib/vcflib/blob/master/samples/sample.vcf</a></p><h3 id="CrossMap"><a href="#CrossMap" class="headerlink" title="CrossMap"></a>CrossMap</h3><p>github 链接:<a href="https://github.com/liguowang/CrossMap">https://github.com/liguowang/CrossMap</a></p><p>官方文档链接:<a href="https://crossmap.readthedocs.io/en/latest/">https://crossmap.readthedocs.io/en/latest/</a></p><p>使用 pip 安装 CrossMap:</p><figure class="highlight shell"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">pip3 install git+https://github.com/liguowang/CrossMap.git # 从 github 上安装,相对而言可能更新一些</span><br><span class="line">或者</span><br><span class="line">pip3 install CrossMap # 从 PyPI 安装,按照版本发布情况安装</span><br></pre></td></tr></tbody></table></figure><p>需准备的输入文件:</p><ul><li><strong>指定了转换方向的 chain 文件</strong>,可以从 UCSC 网站下载(所有物种的下载信息详细可见 <a href="https://hgdownload.soe.ucsc.edu/downloads.html">UCSC download</a> 中的 LiftOver files)。以人类基因组为例,hg19 到 hg38 的 chain file 下载链接: <a href="https://hgdownload.soe.ucsc.edu/goldenPath/hg19/liftOver/hg19ToHg38.over.chain.gz">hg19ToHg38.over.chain.gz</a>。</li><li><strong>目标参考基因组文件</strong>,例如转坐标是 hg19 到 hg38 的话,则准备 hg38 的参考基因组文件。</li></ul><p>运行命令示例(链文件和参考基因组文件按需求更改为自己的路径):</p><figure class="highlight shell"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">CrossMap vcf [chain file] [input vcf] [target genome] [output vcf]</span><br></pre></td></tr></tbody></table></figure><p>各框注部分需填写的文件路径:</p><ul><li><code>[chain file]</code>:填入使用的链文件路径,例如 hg19ToHg38.over.chain.gz。</li><li><code>[target genome]</code>:填入转换的目标基因组文件,例如 hg38.fa。</li><li><code>[input vcf]</code>:填入需要进行转换的 VCF 文件路径</li><li><code>[output vcf]</code>:填入输出的转换后的 VCF 文件路径。</li></ul><p>可选参数如下:</p><ul><li><code>--chromid</code>:指定输出的染色体 id 格式,详细可见 <code>CrossMap vcf -h</code> 说明。</li><li><code>--no-comp-alleles</code>:指定该参数后,CrossMap 会取消对 ref & alt 的检查。默认不指定该参数时,如果转换后 ref 和 alt 一致则会被认为转换失败。</li><li><code>--compress</code>:指定该参数后,CrossMap 会调用 <code>gzip</code> 对输出的 VCF 文件进行压缩。</li></ul><p>未转换成功的变异信息可见 <code>[output vcf].unmap</code>。</p><h3 id="GATK-LiftoverVcf"><a href="#GATK-LiftoverVcf" class="headerlink" title="GATK LiftoverVcf"></a>GATK LiftoverVcf</h3><p>官方文档链接:<a href="https://gatk.broadinstitute.org/hc/en-us/articles/360036831351-LiftoverVcf-Picard">https://gatk.broadinstitute.org/hc/en-us/articles/360036831351-LiftoverVcf-Picard</a></p><p>使用 conda 安装 GATK:</p><figure class="highlight shell"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">conda install -c bioconda gatk4</span><br></pre></td></tr></tbody></table></figure><p>需准备的输入文件与 CrossMap 相同(可见上文),以下是一个运行示例:</p><figure class="highlight shell"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">gatk LiftoverVcf \</span><br><span class="line"> -I [input vcf] \</span><br><span class="line"> -O [output vcf] \</span><br><span class="line"> -CHAIN [chain file] \</span><br><span class="line"> -R [target genome] \</span><br><span class="line"> --REJECT [unmap vcf]</span><br></pre></td></tr></tbody></table></figure><p>各框注部分需填写的文件路径:</p><ul><li><code>[input vcf]</code>:填入需要进行转换的 VCF 文件路径</li><li><code>[output vcf]</code>:填入输出的转换后的 VCF 文件路径。</li><li><code>[unmap vcf]</code>:指定转换失败的变异输出文件。</li><li><code>[chain file]</code>:填入使用的<strong>链文件</strong>路径,例如 hg19ToHg38.over.chain.gz。</li><li><code>[target genome]</code>:填入转换的<strong>目标基因组文件</strong>,例如 hg38.fa。</li></ul><p>需注意 GATK 会识别文件尾缀以判断输出的文件类型,因此相关的 VCF 文件名应当以 <code>.vcf</code> 结尾。</p><p>一些可能比较常用的参数(详细信息请使用 <code>gatk LiftoverVcf -h</code> 查看):</p><ul><li><code>--ALLOW_MISSING_FIELDS_IN_HEADER</code>:允许 header 中缺失 INFO & FORMAT 字段的说明,但仍需其他的部分(例如 header line 等)。</li><li><code>--WRITE_ORIGINAL_ALLELES</code> & <code>--WRITE_ORIGINAL_POSITION</code>:输出原始的等位基因信息 & 输出原始的坐标信息。</li></ul><h3 id="BCFtools-liftover"><a href="#BCFtools-liftover" class="headerlink" title="BCFtools liftover"></a>BCFtools liftover</h3><p>该工具是 BCFtools 的插件,<strong>因此需要先安装 BCFtools 后再使用</strong>。</p><p>github 链接:<a href="https://github.com/freeseek/score?tab=readme-ov-file#liftover-vcfs">https://github.com/freeseek/score?tab=readme-ov-file#liftover-vcfs</a></p><p>安装方法:</p><figure class="highlight shell"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta prompt_"># </span><span class="language-bash">首先需要安装 bcftools,可以自行编译或者使用 conda 安装</span></span><br><span class="line">conda install -c bioconda bcftools</span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">自行选择一个合适的路径,开始下载插件文件 (Linux)</span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">插件也可以自行编译,有需求请在上方 github 链接中自行查阅</span></span><br><span class="line">wget https://software.broadinstitute.org/software/score/score_1.20-20240927.zip</span><br><span class="line">mkdir -p bcftools_plugin</span><br><span class="line">unzip -d bcftools_plugin score_1.20-20240927.zip</span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">将插件的路径设置为 BCFtools 插件的环境路径</span></span><br><span class="line">export BCFTOOLS_PLUGINS=$(pwd .)/bcftools_plugin</span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">或者保存到 .bashrc 文件中保证以后能直接调用</span></span><br><span class="line">echo "export BCFTOOLS_PLUGINS=$(pwd .)/bcftools_plugin" >> ~/.bashrc</span><br><span class="line">source ~/.bashrc</span><br></pre></td></tr></tbody></table></figure><p>查看是否安装成功:</p><figure class="highlight shell"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">bcftools +liftover -h</span><br></pre></td></tr></tbody></table></figure><p>需准备的输入文件与 CrossMap 相同,在此基础上还需要准备<strong>源基因组版本的基因组序列文件</strong>,以下是一个运行示例:</p><figure class="highlight shell"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">bcftools +liftover -Ou [input vcf] -- \</span><br><span class="line"> -s [source genome] \</span><br><span class="line"> -f [target genome] \</span><br><span class="line"> -c [chain file] \</span><br><span class="line"> --reject [unmap vcf] --write-reject | \</span><br><span class="line"> bcftools sort -Ou -o [output vcf]</span><br></pre></td></tr></tbody></table></figure><p>各框注部分需填写的文件路径:</p><ul><li><code>[input vcf]</code>:填入需要进行转换的 VCF 文件路径</li><li><code>[output vcf]</code>:填入输出的转换后的 VCF 文件路径。</li><li><code>[unmap vcf]</code>:指定转换失败的变异输出文件。</li><li><code>[chain file]</code>:填入使用的<strong>链文件</strong>路径,例如 hg19ToHg38.over.chain.gz。</li><li><code>[source genome]</code>:填入转换的<strong>源基因组文件</strong>,例如 hg19.fa。</li><li><code>[target genome]</code>:填入转换的<strong>目标基因组文件</strong>,例如 hg38.fa。</li></ul><p>更多可选项的说明详细可见 <code>bcftools +liftover -h</code>。以上命令行在输出后对 VCF 进行了排序并以未压缩格式输出(<code>-Ou</code>),可根据自身需求调整以上命令的工作流。</p><h2 id="后记"><a href="#后记" class="headerlink" title="后记"></a>后记</h2><p>关于三个工具,就我个人的使用经验而言(主要是一些 SNV),三者的结果相差并不大,所以目前使用较多的是更方便的 CrossMap(因为它不对 header 做要求)。如果在你的应用场景中涉及到较多的 InDel,可以考虑使用专门为 InDel 进行过优化的 BCFtools liftvcf 进行。以下是 BCFtools liftvcf 文章中的一个表格,展示了各个工具的功能和限制,可按照自己的需求进行挑选:</p><table><thead><tr><th align="left">Tool</th><th align="left">BCFtools liftvcf</th><th align="left">GATK LiftoverVcf</th><th align="left">CrossMap</th></tr></thead><tbody><tr><td align="left">Version tested</td><td align="left">2023-12-06</td><td align="left">3.1.1</td><td align="left">0.6.6</td></tr><tr><td align="left">GitHub username</td><td align="left">freeseek</td><td align="left">broadinstitute</td><td align="left">liguowang</td></tr><tr><td align="left">GitHub repository</td><td align="left">score</td><td align="left">picard</td><td align="left">CrossMap</td></tr><tr><td align="left">License</td><td align="left">MIT</td><td align="left">MIT</td><td align="left">GPLv3</td></tr><tr><td align="left"><strong>Main features</strong></td><td align="left"></td><td align="left"></td><td align="left"></td></tr><tr><td align="left">Can reverse-complements alleles</td><td align="left">Yes</td><td align="left">Yes</td><td align="left">Yes</td></tr><tr><td align="left">Handles multi-allelic records</td><td align="left">Yes</td><td align="left">No</td><td align="left">No</td></tr><tr><td align="left">Can swap SNV alleles</td><td align="left">Yes</td><td align="left">Bi-allelic only</td><td align="left">No</td></tr><tr><td align="left">Can swap indel alleles</td><td align="left">Yes</td><td align="left">No</td><td align="left">No</td></tr><tr><td align="left">Can add new reference allele</td><td align="left">Yes</td><td align="left">No</td><td align="left">No</td></tr><tr><td align="left">Can recover SNVs at chain gaps</td><td align="left">Yes</td><td align="left">No</td><td align="left">No</td></tr><tr><td align="left"><strong>File input/output options</strong></td><td align="left"></td><td align="left"></td><td align="left"></td></tr><tr><td align="left">Sort records after liftover</td><td align="left">No</td><td align="left">Yes</td><td align="left">No</td></tr><tr><td align="left">Left-aligns indels after liftover</td><td align="left">Yes</td><td align="left">Yes</td><td align="left">No</td></tr><tr><td align="left">Can record the original position</td><td align="left">Yes</td><td align="left">Yes</td><td align="left">No</td></tr><tr><td align="left">Flexible with contig names</td><td align="left">Yes</td><td align="left">No</td><td align="left">Yes</td></tr><tr><td align="left">Loads full reference in memory</td><td align="left">No</td><td align="left">Yes</td><td align="left">No</td></tr><tr><td align="left">Can input VCF as a file stream</td><td align="left">Yes</td><td align="left">No</td><td align="left">Yes</td></tr><tr><td align="left">Can output VCF as a file stream</td><td align="left">Yes</td><td align="left">No</td><td align="left">No</td></tr><tr><td align="left">Can input/output binary VCFs</td><td align="left">Yes</td><td align="left">No</td><td align="left">No</td></tr><tr><td align="left"><strong>Variants annotations updates</strong></td><td align="left"></td><td align="left"></td><td align="left"></td></tr><tr><td align="left">Updates INFO/END field</td><td align="left">Yes</td><td align="left">No</td><td align="left">No</td></tr><tr><td align="left">Updates Number=G/R fields</td><td align="left">Yes</td><td align="left">PL and AD</td><td align="left">No</td></tr><tr><td align="left">Updates AC-like fields</td><td align="left">Yes</td><td align="left">No</td><td align="left">No</td></tr><tr><td align="left">Updates AF-like fields</td><td align="left">Yes</td><td align="left">Yes</td><td align="left">No</td></tr><tr><td align="left">Updates GWAS-VCF fields</td><td align="left">Yes</td><td align="left">No</td><td align="left">No</td></tr></tbody></table><center>Source: https://academic.oup.com/view-large/438467641</center><p>但也正如该文章中结尾的部分所说,<strong>不管哪个工具能做得更好,liftover 终究是一个有损过程</strong>,无论什么情况下,重新比对进行 call variant 总会产生比 liftover 更好的结果。当然有些情况下我们也不可避免地只能选择 liftover 这一途径(比如说原始测序数据无法访问或需申请权限等)。</p><h2 id="相关文章链接"><a href="#相关文章链接" class="headerlink" title="相关文章链接"></a>相关文章链接</h2><ul><li>CrossMap:<a href="https://pubmed.ncbi.nlm.nih.gov/24351709/">CrossMap: a versatile tool for coordinate conversion between genome assemblies.</a></li><li>BCFtools liftover:<a href="https://pubmed.ncbi.nlm.nih.gov/38261650/">BCFtools/liftover: an accurate and comprehensive tool to convert genetic variants across genome assemblies</a></li></ul></body></html>]]></content>
<summary type="html">本文介绍了如何使用 CrossMap / GATK LiftoverVcf / BCFtools liftover 对 vcf 中的突变进行不同基因组版本之间的坐标转换。</summary>
<category term="学习" scheme="https://biojuse.com/categories/%E5%AD%A6%E4%B9%A0/"/>
<category term="杂项" scheme="https://biojuse.com/categories/%E5%AD%A6%E4%B9%A0/%E6%9D%82%E9%A1%B9/"/>
</entry>
<entry>
<title>bedtools merge 不合并相邻区间(仅合并重叠区间)</title>
<link href="https://biojuse.com/2024/12/28/bedtools%20merge%20%E4%B8%8D%E5%90%88%E5%B9%B6%E7%9B%B8%E9%82%BB%E5%8C%BA%E9%97%B4%EF%BC%88%E4%BB%85%E5%90%88%E5%B9%B6%E9%87%8D%E5%8F%A0%E5%8C%BA%E9%97%B4%EF%BC%89/"/>
<id>https://biojuse.com/2024/12/28/bedtools%20merge%20%E4%B8%8D%E5%90%88%E5%B9%B6%E7%9B%B8%E9%82%BB%E5%8C%BA%E9%97%B4%EF%BC%88%E4%BB%85%E5%90%88%E5%B9%B6%E9%87%8D%E5%8F%A0%E5%8C%BA%E9%97%B4%EF%BC%89/</id>
<published>2024-12-28T09:30:00.000Z</published>
<updated>2024-12-28T09:42:32.613Z</updated>
<content type="html"><![CDATA[<html><head></head><body><p>关于 bedtools merge 的详细参数设定可见:</p><p>bedtools merge documentation:</p><p><a href="https://bedtools.readthedocs.io/en/latest/content/tools/merge.html">https://bedtools.readthedocs.io/en/latest/content/tools/merge.html</a></p><img src="https://bedtools.readthedocs.io/en/latest/_images/merge-glyph.png" height="300px"><p>默认情况下,bedtools merge 会对所有重叠区间及相邻区间进行合并,例如:</p><figure class="highlight shell"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta prompt_"># </span><span class="language-bash">运行前</span></span><br><span class="line">chr11000010001</span><br><span class="line">chr11000110002</span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">运行后</span></span><br><span class="line">chr11000010002</span><br></pre></td></tr></tbody></table></figure><p>但在最近遇到的分析场景中,我仅想合并重叠的点并对它们的值求平均,并不想将它们与相邻的点合并起来,例如:</p><figure class="highlight shell"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">chr110000100010.1</span><br><span class="line">chr110000100010.2</span><br><span class="line">chr110001100020.3</span><br></pre></td></tr></tbody></table></figure><p>这里我仅想在 <code>chr1:10000-10001</code> 上进行合并且求平均,但此时使用 <code>bedtools merge -c 4 -o mean</code> 会输出以下结果:</p><figure class="highlight shell"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">chr1 10000 10002 0.2</span><br></pre></td></tr></tbody></table></figure><p>这并不符合我的预期工作情况,在查阅参数说明后,发现了以下关键参数:</p><ul><li><code>-d</code>:Maximum distance between features allowed for features to be merged. Default is 0. That is, overlapping and/or features are merged.</li></ul><p>这里的 <code>-d</code> 默认值为 0,说明中提到<strong>该值会将重叠的以及首尾相接的区间合并到一起</strong>,于是乎我尝试了将该参数改为 <strong>-1</strong>:</p><figure class="highlight shell"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta prompt_">$ </span><span class="language-bash">bedtools merge -i test.bed -d -1 -c 4 -o mean</span></span><br><span class="line">chr1 10000 10001 0.15</span><br><span class="line">chr1 10001 10002 0.3</span><br></pre></td></tr></tbody></table></figure><p>在设置为 -1 后,bedtools merge 仅对重叠区间进行合并,以下是一个测试:</p><figure class="highlight shell"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta prompt_"># </span><span class="language-bash">运行前</span></span><br><span class="line">chr110000100010.1</span><br><span class="line">chr110000100010.2</span><br><span class="line">chr110001100090.3</span><br><span class="line">chr110008100200.4</span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">运行后</span></span><br><span class="line">chr1 10000 10001 0.15</span><br><span class="line">chr1 10001 10020 0.35</span><br></pre></td></tr></tbody></table></figure></body></html>]]></content>
<summary type="html">本文介绍了如何通过设置恰当参数使 bedtools merge 仅对重叠区间进行合并(而不合并相邻区间)。</summary>
<category term="学习" scheme="https://biojuse.com/categories/%E5%AD%A6%E4%B9%A0/"/>
<category term="生信" scheme="https://biojuse.com/categories/%E5%AD%A6%E4%B9%A0/%E7%94%9F%E4%BF%A1/"/>
</entry>
<entry>
<title>基于 US-align 计算两个蛋白结构之间的 RMSD 和 TM-score</title>
<link href="https://biojuse.com/2024/12/18/%E5%9F%BA%E4%BA%8E%20US-align%20%E8%AE%A1%E7%AE%97%E4%B8%A4%E4%B8%AA%E8%9B%8B%E7%99%BD%E7%BB%93%E6%9E%84%E4%B9%8B%E9%97%B4%E7%9A%84%20RMSD%20%E5%92%8C%20TM-score/"/>
<id>https://biojuse.com/2024/12/18/%E5%9F%BA%E4%BA%8E%20US-align%20%E8%AE%A1%E7%AE%97%E4%B8%A4%E4%B8%AA%E8%9B%8B%E7%99%BD%E7%BB%93%E6%9E%84%E4%B9%8B%E9%97%B4%E7%9A%84%20RMSD%20%E5%92%8C%20TM-score/</id>
<published>2024-12-18T08:40:00.000Z</published>
<updated>2024-12-18T08:54:14.022Z</updated>
<content type="html"><![CDATA[<html><head></head><body><p>在蛋白质结构研究里,比较不同蛋白质结构之间的相似性是一个核心任务,尤其是在结构预测、同源建模和结构功能关系研究中。以下是一些常用到的衡量蛋白结构间相似性的指标:</p><ul><li><strong>RMSD(均方根偏差)</strong>:该值是衡量两种蛋白质三维结构之间原子位置差异的标准度量。较小的 RMSD 值意味着两个结构相似度较高,RMSD 值对大分子在全局对齐时的大小和形状变化非常敏感。</li><li><strong>TM-score</strong>:相较于 RMSD,TM-score 更加关注<strong>结构的全局相似性</strong>,且对于蛋白质的尺寸和形状变化具有更高的鲁棒性。TM-score 的值介于 0 到 1 之间,值越接近 1,表示两个结构越相似。</li></ul><p>本文将介绍如何使用 US-align 对两个蛋白结构进行 align(对齐)并计算其 RMSD 及 TM-score。</p><h2 id="US-align"><a href="#US-align" class="headerlink" title="US-align"></a>US-align</h2><p>US-align github page:</p><p><a href="https://github.com/pylelab/USalign">https://github.com/pylelab/USalign</a></p><p>该软件的研究团队也同样是 <a href="https://zhanggroup.org/TM-align/">TM-align</a> 的开发者。相比其他的计算工具,US-align 有以下优点:</p><ul><li>支持比对<strong>除蛋白质以外的生物大分子及其复合物</strong>(例如 DNA / RNA 等)。</li><li>通过改进的计算方法从而实现高效及准确的比对过程。</li></ul><p>下文介绍的为其本地部署的使用方式,如果你没有在本地大量运行的需求,也可以使用网页版:</p><p><a href="https://zhanggroup.org/US-align/">https://zhanggroup.org/US-align/</a></p><h3 id="安装"><a href="#安装" class="headerlink" title="安装"></a>安装</h3><p>推荐通过 conda 安装 US-align:</p><figure class="highlight shell"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">conda install -c bioconda usalign</span><br></pre></td></tr></tbody></table></figure><p>在安装后,可通过 <code>USalign -h</code> 查看是否能正常工作:</p><figure class="highlight shell"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta prompt_">$ </span><span class="language-bash">USalign -h</span></span><br><span class="line"></span><br><span class="line"> ********************************************************************</span><br><span class="line"> * US-align (Version 20240730) *</span><br><span class="line"> * Universal Structure Alignment of Proteins and Nucleic Acids *</span><br><span class="line"> * Reference: C Zhang, M Shine, AM Pyle, Y Zhang. (2022) Nat Methods*</span><br><span class="line"> * C Zhang, AM Pyle (2022) iScience. *</span><br><span class="line"> * Please email comments and suggestions to zhang@zhanggroup.org *</span><br><span class="line"> ********************************************************************</span><br><span class="line"></span><br><span class="line">Usage: USalign PDB1.pdb PDB2.pdb [Options]</span><br><span class="line"></span><br><span class="line">......</span><br></pre></td></tr></tbody></table></figure><h3 id="参数"><a href="#参数" class="headerlink" title="参数"></a>参数</h3><p>这里仅对其最重要的几个参数进行介绍,介绍完后将提供部分运行示例。</p><ul><li><p><code>-mm</code>:该参数为比对选项,其<strong>默认值为 0,对应两个单体结构(monomer)的比对</strong>。</p><ul><li>将 <code>-mm</code> <strong>设置为 1 时,对应两个寡聚体结构(oligomer)的比对</strong>。如果结构文件中涉及到多条链,使用该参数以正常工作(如果未设置,则默认取第一条链进行比对)。</li><li>其余 <code>-mm</code> 的设置对应的应用场景较特殊,例如 <code>-mm 2</code> 将单条链与寡聚体结构进行比对(适用于确定单个蛋白链在寡聚化的构象变化)、<code>-mm 6</code> 为半非连续比对(允许有限的重排)。</li></ul></li><li><p><code>-ter</code>:该参数指定比对的链数量,其默认值为 2,对应仅比对第一条链。</p><ul><li>当 <code>-mm</code> 设置为 1 或 2 时,<code>-ter</code> 仅可选择 0 或 1。其中 <strong>0 适用于比对不对称单元,1 适用于比对生物学单元</strong>(例如血红蛋白四聚体)。这一部分的概念介绍可见<a href="https://www.novopro.cn/articles/201904261180.html">此处</a>。</li><li><code>-ter</code> 设置为 3 时可选择性地仅比对第一条链的其中一部分(将该部分标记为 'TER' 以进行识别)。</li></ul></li></ul><p>此外,US-align 也提供了批量比对的功能以及其他调整比对行为的参数,详细请通过 <code>USalign -h</code> 查看。本文不再对此进行更多延申。</p><h3 id="运行示例"><a href="#运行示例" class="headerlink" title="运行示例"></a>运行示例</h3><p>本文以两个 PDB 上的结构 <a href="https://www.rcsb.org/structure/2PGH">2PGH</a> 和 <a href="https://www.rcsb.org/structure/3GOU">3GOU</a> 作为示例进行比对:</p><figure class="highlight shell"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta prompt_"># </span><span class="language-bash">数据下载</span></span><br><span class="line">wget https://files.rcsb.org/download/2PGH.cif</span><br><span class="line">wget https://files.rcsb.org/download/3GOU.cif</span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">比对</span></span><br><span class="line">USalign -mm 1 -ter 1 ./2PGH.cif ./3GOU.cif -o HEMOGLOBIN</span><br></pre></td></tr></tbody></table></figure><figure class="highlight plaintext"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br></pre></td><td class="code"><pre><span class="line"> ********************************************************************</span><br><span class="line"> * US-align (Version 20240730) *</span><br><span class="line"> * Universal Structure Alignment of Proteins and Nucleic Acids *</span><br><span class="line"> * Reference: C Zhang, M Shine, AM Pyle, Y Zhang. (2022) Nat Methods*</span><br><span class="line"> * C Zhang, AM Pyle (2022) iScience. *</span><br><span class="line"> * Please email comments and suggestions to zhang@zhanggroup.org *</span><br><span class="line"> ********************************************************************</span><br><span class="line"></span><br><span class="line">Name of Structure_1: ./2PGH.cif:A:B:C:D (to be superimposed onto Structure_2)</span><br><span class="line">Name of Structure_2: ./3GOU.cif:C:D:A:B</span><br><span class="line">Length of Structure_1: 574 residues</span><br><span class="line">Length of Structure_2: 574 residues</span><br><span class="line"></span><br><span class="line">Aligned length= 574, RMSD= 1.03, Seq_ID=n_identical/n_aligned= 0.815</span><br><span class="line">TM-score= 0.98690 (normalized by length of Structure_1: L=574, d0=8.41)</span><br><span class="line">TM-score= 0.98690 (normalized by length of Structure_2: L=574, d0=8.41)</span><br><span class="line">(You should use TM-score normalized by length of the reference structure)</span><br><span class="line"></span><br><span class="line">(":" denotes residue pairs of d < 5.0 Angstrom, "." denotes other aligned residues)</span><br><span class="line">VLSAADKANVKAAWGKVGGQAGAHGAEALERMFLGFPTTKTYFPHFNLSHGSDQVKAHGQKVADALTKAVGHLDDLPGALSALSDLHAHKLRVDPVNFKLLSHCLLVTLAAHHPDDFNPSVHASLDKFLANVSTVLTSKYR*VHLSAEEKEAVLGLWGKVNVDEVGGEALGRLLVVYPWTQRFFESFGDLSNADAVMGNPKVKAHGKKVLQSFSDGLKHLDNLKGTFAKLSELHCDQLHVDPENFRLLGNVIVVVLARRLGHDFNPDVQAAFQKVVAGVANALAHKYH*VLSAADKANVKAAWGKVGGQAGAHGAEALERMFLGFPTTKTYFPHFNLSHGSDQVKAHGQKVADALTKAVGHLDDLPGALSALSDLHAHKLRVDPVNFKLLSHCLLVTLAAHHPDDFNPSVHASLDKFLANVSTVLTSKYR*VHLSAEEKEAVLGLWGKVNVDEVGGEALGRLLVVYPWTQRFFESFGDLSNADAVMGNPKVKAHGKKVLQSFSDGLKHLDNLKGTFAKLSELHCDQLHVDPENFRLLGNVIVVVLARRLGHDFNPDVQAAFQKVVAGVANALAHKYH*</span><br><span class="line">::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::.*:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::.*:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::.*</span><br><span class="line">VLSPADKTNIKSTWDKIGGHAGDYGGEALDRTFQSFPTTKTYFPHFDLSPGSAQVKAHGKKVADALTTAVAHLDDLPGALSALSDLHAYKLRVDPVNFKLLSHCLLVTLACHHPTEFTPAVHASLDKFFAAVSTVLTSKYR*VHLTAEEKSLVSGLWGKVNVDEVGGEALGRLLIVYPWTQRFFDSFGDLSTPDAVMSNAKVKAHGKKVLNSFSDGLKNLDNLKGTFAKLSELHCDKLHVDPENFKLLGNVLVCVLAHHFGKEFTPQVQAAYQKVVAGVANALAHKYH*VLSPADKTNIKSTWDKIGGHAGDYGGEALDRTFQSFPTTKTYFPHFDLSPGSAQVKAHGKKVADALTTAVAHLDDLPGALSALSDLHAYKLRVDPVNFKLLSHCLLVTLACHHPTEFTPAVHASLDKFFAAVSTVLTSKYR*VHLTAEEKSLVSGLWGKVNVDEVGGEALGRLLIVYPWTQRFFDSFGDLSTPDAVMSNAKVKAHGKKVLNSFSDGLKNLDNLKGTFAKLSELHCDKLHVDPENFKLLGNVLVCVLAHHFGKEFTPQVQAAYQKVVAGVANALAHKYH*</span><br><span class="line"></span><br><span class="line">#Total CPU time is 1.05 seconds</span><br></pre></td></tr></tbody></table></figure><p>在其<strong>屏幕输出</strong>中,可以看到比对的详细情况(包括计算得到的 RMSD 以及 TM-score)。该过程里你可以将屏幕输出保存到一个文件中,以便后续查看,此外你也可以通过 <code>-outfmt 2</code> 参数,将其转化为更简洁的形式:</p><figure class="highlight shell"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta prompt_">$ </span><span class="language-bash">USalign -mm 1 -ter 1 ./2PGH.cif ./3GOU.ci2 -outfmt 2 -o HEMOGLOBIN</span></span><br><span class="line"><span class="meta prompt_">#</span><span class="language-bash">PDBchain1 PDBchain2 TM1 TM2 RMSD ID1 ID2 IDali L1 L2 Lali</span></span><br><span class="line">./2PGH.cif:A:B:C:D ./3GOU.cif:C:D:A:B 0.9869 0.9869 1.03 0.815 0.815 0.815 574 574 574</span><br></pre></td></tr></tbody></table></figure><p>在运行上述示例后,你可以在运行目录里看到以下新增文件:</p><ul><li><code>HEMOGLOBIN.cif</code>:Structure1 的晶体文件,此处各原子的坐标根据比对结果进行了修改。</li><li><code>HEMOGLOBIN_*.pml</code>:用于输入给 PyMol 进行比对结果可视化的文件。不同的 pml 文件对应不同的可视化方式。</li></ul><p>你可以运行以下命令安装 PyMol 并可视化比对结果:</p><figure class="highlight shell"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta prompt_"># </span><span class="language-bash">安装</span></span><br><span class="line">conda install schrodinger::pymol</span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">可视化</span></span><br><span class="line">pymol -c -d @HEMOGLOBIN_all_atm.pml -x 3000 -y 3000 -g HEMOGLOBIN_all_atm.png</span><br></pre></td></tr></tbody></table></figure><img src="/pic2/HEMOGLOBIN_all_atm.png" height="400px"><center>红色和蓝色分别对应两个比对的结构</center><p>如果你想要输出的图片更清晰,也可以手动对 pml 文件进行调节,按照 PyMol 的命令方式对其添加抗锯齿并增大分辨率,修改相关设置后的图片示例可见<a href="/pic2/HEMOGLOBIN_all_atm_high_quality.png">此处</a>。你也可以将两个结构加载到交互式 PyMol 应用程序中进行调节。</p><h2 id="参考材料"><a href="#参考材料" class="headerlink" title="参考材料"></a>参考材料</h2><ol><li><p>Zhang et al. 2022, Nat Methods: US-align: universal structure alignments of proteins, nucleic acids, and macromolecular complexes</p></li><li><p>不对称单元与晶胞,生物单元概念解析:<a href="https://www.novopro.cn/articles/201904261180.html">https://www.novopro.cn/articles/201904261180.html</a></p></li></ol></body></html>]]></content>
<summary type="html">本文介绍了如何使用 US-align 计算两个蛋白结构之间的相似性。除此之外,该软件同样可以进行蛋白质寡聚体(多个蛋白或蛋白与 DNA 复合物)结构之间的比较。</summary>
<category term="学习" scheme="https://biojuse.com/categories/%E5%AD%A6%E4%B9%A0/"/>
<category term="生信" scheme="https://biojuse.com/categories/%E5%AD%A6%E4%B9%A0/%E7%94%9F%E4%BF%A1/"/>
</entry>
<entry>
<title>使用 ESM 计算蛋白序列的突变影响分数</title>
<link href="https://biojuse.com/2024/11/16/%E4%BD%BF%E7%94%A8%20ESM%20%E8%AE%A1%E7%AE%97%E8%9B%8B%E7%99%BD%E5%BA%8F%E5%88%97%E7%9A%84%E7%AA%81%E5%8F%98%E5%BD%B1%E5%93%8D%E5%88%86%E6%95%B0/"/>
<id>https://biojuse.com/2024/11/16/%E4%BD%BF%E7%94%A8%20ESM%20%E8%AE%A1%E7%AE%97%E8%9B%8B%E7%99%BD%E5%BA%8F%E5%88%97%E7%9A%84%E7%AA%81%E5%8F%98%E5%BD%B1%E5%93%8D%E5%88%86%E6%95%B0/</id>
<published>2024-11-16T08:00:00.000Z</published>
<updated>2024-12-06T08:28:30.538Z</updated>
<content type="html"><![CDATA[<html><head></head><body><p><strong>ESM(Evolutionary Scale Modeling)</strong> 是由 Facebook AI Research 开发的蛋白质语言模型。其基于大规模的蛋白质序列数据进行训练,能够捕捉蛋白质序列中的复杂模式和进化信息,从而在多个生物学下游应用中表现出色。</p><p>预训练好的 ESM 可用于多个生物学下游应用,本文将就其突变影响分析方面的功能进行介绍。</p><h2 id="关于-ESM"><a href="#关于-ESM" class="headerlink" title="关于 ESM"></a>关于 ESM</h2><p>ESM 预测突变影响的方式是无监督的,也就是说 <strong>ESM 的训练过程中并未使用到与突变影响相关的标签进行有监督学习</strong>。其评估每个氨基酸错义突变影响程度的方式是掩蔽该位置上的氨基酸并<strong>计算两种氨基酸(参考氨基酸与突变氨基酸)在该位置出现的对数似然比</strong>:</p><img src="/pic2/esm_score.png" height="100px"><p>ESM 的预训练阶段使用了类似于 BERT 的掩码任务,因此 ESM 可以给出每个位点里各类氨基酸出现的概率,而参考氨基酸(Ref,即未突变时的氨基酸)和突变氨基酸(Alt)的概率差异即可作为一种 effect score。可以简单理解为,<strong>突变氨基酸出现的概率比参考氨基酸低越多,说明这类突变越有害</strong>。这种无监督的评估方式也被用于许多其他的深度学习工具,例如 EVE 和 GPN 等。</p><img src="/pic2/esm1.png" height="200px"><center>Reference: Brandes et al. 2023, Nat Genet</center><p>对于多氨基酸突变,ESM 采取的策略是简单的加性模型,即对每个位置计算出其对数似然比后,进行加和得到最终评分(Meier et al. 2021, bioRxiv)。其他研究者的 benchmark 测试表明,ESM 在诸多数据集上具有出色性能(Tabet et al. 2024, Genome Biol)。</p><h2 id="ESM-使用"><a href="#ESM-使用" class="headerlink" title="ESM 使用"></a>ESM 使用</h2><p>在使用下述任何一种方法前需提前安装好需要的 module:</p><figure class="highlight shell"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">pip install tqdm numpy pandas biopython torch fair-esm</span><br></pre></td></tr></tbody></table></figure><p>其他需要的 module 可在后续使用 script 报错时自行通过 pip 或 conda 补充安装。</p><h3 id="原始的-ESM-工作流程"><a href="#原始的-ESM-工作流程" class="headerlink" title="原始的 ESM 工作流程"></a>原始的 ESM 工作流程</h3><p>使用 <code>git clone</code> 下载其 github repository:</p><figure class="highlight shell"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">git clone https://github.com/facebookresearch/esm.git</span><br></pre></td></tr></tbody></table></figure><p>如果你的设备无法连接外网,你也可以尝试克隆 gitee 源:</p><figure class="highlight shell"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">git clone https://gitee.com/li42110/esm.git</span><br></pre></td></tr></tbody></table></figure><p>在 <code>git clone</code> 下载完成后,运行以下命令跳转到为 variant prediction 提供的示例文件夹中:</p><figure class="highlight shell"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">cd esm/examples/variant-prediction</span><br></pre></td></tr></tbody></table></figure><p>该文件夹下的 <code>predict.py</code> 即 ESM 团队提供的用于计算 effect score 的 script,其中示例命令如下:</p><figure class="highlight shell"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line">python predict.py \</span><br><span class="line"> --model-location esm1v_t33_650M_UR90S_1 esm1v_t33_650M_UR90S_2 esm1v_t33_650M_UR90S_3 esm1v_t33_650M_UR90S_4 esm1v_t33_650M_UR90S_5 \</span><br><span class="line"> --sequence HPETLVKVKDAEDQLGARVGYIELDLNSGKILESFRPEERFPMMSTFKVLLCGAVLSRVDAGQEQLGRRIHYSQNDLVEYSPVTEKHLTDGMTVRELCSAAITMSDNTAANLLLTTIGGPKELTAFLHNMGDHVTRLDRWEPELNEAIPNDERDTTMPAAMATTLRKLLTGELLTLASRQQLIDWMEADKVAGPLLRSALPAGWFIADKSGAGERGSRGIIAALGPDGKPSRIVVIYTTGSQATMDERNRQIAEIGASLIKHW \</span><br><span class="line"> --dms-input ./data/BLAT_ECOLX_Ranganathan2015.csv \</span><br><span class="line"> --mutation-col mutant \</span><br><span class="line"> --dms-output ./data/BLAT_ECOLX_Ranganathan2015_labeled.csv \</span><br><span class="line"> --offset-idx 24 \</span><br><span class="line"> --scoring-strategy wt-marginals</span><br></pre></td></tr></tbody></table></figure><ul><li><code>--model-location</code>:选择模型,此处选择的是 5 个 ESM-1v 模型(这些模型使用不同的随机种子生成训练数据集并进行训练),也可选择其他模型例如 ESM-1b (esm1b_t33_650M_UR50S) 或 ESM2 (esm2_t33_650M_UR50D) 等。</li><li><code>--sequence</code>:输入的蛋白序列,注意过长的序列可能会引发内存溢出或者其他意外状况(由于 ESM 的 token 最大数量限制),如果你输入的序列过长,请直接跳转后文 <strong><u>优化的 ESM 工作框架</u></strong> 部分。</li><li><code>--dms-input</code>:输入的表格,其中需包含 mutant 列(<code>--mutation-col</code> 中指定的列名),mutant 格式为 <code>[ref amino][idx][alt amino]</code>,例如示例文件中的 <code>H24C</code> 表示的为第 24 位上的 H 突变为 C。<strong>请在该表格的该列中填入所有你希望计算 effect score 的 mutant</strong>。</li><li><code>--mutation-col</code>:指定突变在输入表格中所在的列名,此处即 <code>mutant</code>。</li></ul><img src="/pic2/esm_mutant.png" height="200px"><center>红框标注即 mutant 列,后续的列并不是必需的</center><ul><li><code>--dms-output</code>:输出的表格,其中最后 n 列(n 的具体数字取决于你输入的模型数量)为各模型的评分。</li><li><code>--offset-idx</code>:突变位置的偏倚,例如在 ESM 示例中第一个 mutant 为 H24C,但 H 其实位于序列的开端,因此将此参数设置为 24 使其从 24 开始位置计数。如果你从 1 开始,则将该项设置为 1 即可。</li><li><code>--scoring-strategy</code>:计算 effect score 的策略,分为三种。<code>wt-marginals</code> 直接<strong>将 wt 序列(未突变序列)输入模型</strong>得到每个 token 的 embedding 并计算其出现各个氨基酸的概率;<code>masked-marginals</code> <strong>将 wt 序列中每个 token 逐个掩码</strong>并计算掩码位置上出现各个氨基酸的概率;<code>pseudo-ppl</code> <strong>将 mutant 序列中每个 token 逐个掩码并计算整条序列的伪困惑度</strong>作为其 effect score。</li></ul><p>关于 <code>--scoring-strategy</code> 参数,<code>masked-marginals</code> 的计算方式是最符合直觉和逻辑的,但由于 <code>masked-marginals</code> 计算中要对每个 token 都掩码计算一次,因此时间开销很高(特别是在序列很长的情况下)。相比之下,<code>wt-marginals</code> 虽然向模型暴露了原始序列信息,但仅需计算一次便可得到所有位置上各个氨基酸的出现概率。已有研究分析表明 <code>wt-marginals</code> 也具有很好的性能表现(虽然其会高估原始氨基酸的概率),建议此处选择 <code>wt-margins</code> 即可。</p><p>运行以上命令后,<strong>如果你缺乏这些模型的文件,脚本会自行开始下载并存储到特定位置</strong>(例如 Linux 为 home 目录下的 <code>.cache/torch/hub/checkpoints/</code>)。该步骤同样可能遇到网络问题,此时你可以选择自行从其他途径下载到指定路径中(例如通过 hugging face 的国内镜像)。如果要预测其他序列,请修改 <code>--sequence</code> 参数并自行准备 <code>--dms-input</code> 的输入文件。</p><img src="/pic2/esm_model.png" height="200px"><center>下载的 ESM model</center><h3 id="优化的-ESM-工作框架"><a href="#优化的-ESM-工作框架" class="headerlink" title="优化的 ESM 工作框架"></a>优化的 ESM 工作框架</h3><p>使用 ESM github repository 中的 script 虽然可以达成目的,但是它有以下一些缺点:</p><ul><li>不适用过长的蛋白序列。</li><li>定制化程度较高,迁移到自己的需求上时有一定的难度(如果数据量大),门槛相对更高。</li></ul><p>基于此,这里推荐一个由 <a href="https://www.nature.com/articles/s41588-023-01465-0">Brandes 等人</a>开发的流程,该流程经过了以下改进:</p><ul><li><strong>只需输入 fasta 文件</strong>即可批量计算这些序列中所有氨基酸位点上各个突变的 effect score。</li><li>对于过长的序列,该流程<strong>使用滑动窗口方法将长序列分解成具有 overlap 的多条序列</strong>,并对重叠位置上的 effect score 进行加权平均计算。</li><li>对于序列中的<strong>插入或缺失同样可以进行计算</strong>(衡量标准是整条序列的似然比差异)。</li></ul><p>使用 <code>git clone</code> 配置:</p><figure class="highlight shell"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">git clone https://github.com/ntranoslab/esm-variants.git</span><br><span class="line">cd esm-variants</span><br></pre></td></tr></tbody></table></figure><p>该文件夹下的 <code>esm_score_missense_mutations.py</code> 使用示例:</p><figure class="highlight shell"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">python esm_score_missense_mutations.py --input-fasta-file [fasta] --output-csv-file [output csv] --model-name esm1b_t33_650M_UR50S</span><br></pre></td></tr></tbody></table></figure><ul><li><code>[fasta]</code> 处填入你所需要分析的 fasta 序列文件路径,<code>[output csv]</code> 处填入输出的 csv 表格文件路径(含文件名)。</li><li>可通过 <code>--model-name</code> 指定使用的 ESM 模型,默认为 ESM-1b。</li></ul><p>以下是一个运行示例,展示如何使用,首先建立一个 <code>test.fa</code>,填入以下内容:</p><figure class="highlight plaintext"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">>seq1</span><br><span class="line">FISHWISHFQRCHIPSTHATARECRISP</span><br><span class="line">>seq2</span><br><span class="line">RAGEAGAINSTTHEMACHINE</span><br></pre></td></tr></tbody></table></figure><p>运行脚本,指定输出文件为 <code>test.csv</code>:</p><figure class="highlight shell"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">python esm_score_missense_mutations.py --input-fasta-file test.fa --output-csv-file test.csv</span><br></pre></td></tr></tbody></table></figure><p>运行结束后,<code>test.csv</code> 中的第一列为 fasta 文件中对应的序列 id,第二列为该序列所有可能的氨基酸突变,第三列为基于 ESM1b 计算得到的 ESM score:</p><img src="/pic2/esm_output.png" height="300px"><p>关于 InDel 的 score 计算此处不进行详细阐述,如感兴趣可参考其 github repository README:</p><p><a href="https://github.com/ntranoslab/esm-variants?tab=readme-ov-file#scoring-multi-residue-mutations">https://github.com/ntranoslab/esm-variants?tab=readme-ov-file#scoring-multi-residue-mutations</a></p><h2 id="参考材料"><a href="#参考材料" class="headerlink" title="参考材料"></a>参考材料</h2><ol><li>Meier et al. 2021, bioRxiv: Language models enable zero-shot prediction of the effects of mutations on protein function</li><li>Tabet et al. 2024, Genome Biol: Benchmarking computational variant effect predictors by their ability to infer human traits</li><li>Brandes et al. 2023, Nat Genet: Genome-wide prediction of disease variant effects with a deep protein language model</li><li>EVE (Nature 2021): Disease variant prediction with deep generative models of evolutionary data</li><li>GPN (PNAS 2023): DNA language models are powerful predictors of genome-wide variant effects</li></ol><h2 id="题外话"><a href="#题外话" class="headerlink" title="题外话"></a>题外话</h2><p>esm-variant repository 中有一个 issue 针对其函数命名提出了质疑:</p><p><a href="https://github.com/ntranoslab/esm-variants/issues/12">https://github.com/ntranoslab/esm-variants/issues/12</a></p><p>发起该 issue 的人是 <a href="https://github.com/sokrypton/ColabFold">ColabFold</a> 的创建者,大致内容是 esm-variant 算出来的 score 不应该称作 pll (pseudo-likelihood)。基于这一点,本文也避开了 pll 这一说法直接使用 score 一词进行说明。各位朋友如果要使用其他关于 score 的称呼请自行斟酌。</p></body></html>]]></content>
<summary type="html">本文介绍了如何使用 ESM 计算蛋白序列中各个氨基酸突变的影响分数,并提供了一些其他使用 ESM 的方法和思路。</summary>
<category term="学习" scheme="https://biojuse.com/categories/%E5%AD%A6%E4%B9%A0/"/>
<category term="生信" scheme="https://biojuse.com/categories/%E5%AD%A6%E4%B9%A0/%E7%94%9F%E4%BF%A1/"/>
</entry>
<entry>
<title>基于 JCVI 共线性分析确定一对一直系同源基因</title>
<link href="https://biojuse.com/2024/11/09/%E5%9F%BA%E4%BA%8E%20JCVI%20%E5%85%B1%E7%BA%BF%E6%80%A7%E5%88%86%E6%9E%90%E7%A1%AE%E5%AE%9A%E4%B8%80%E5%AF%B9%E4%B8%80%E7%9B%B4%E7%B3%BB%E5%90%8C%E6%BA%90%E5%9F%BA%E5%9B%A0/"/>
<id>https://biojuse.com/2024/11/09/%E5%9F%BA%E4%BA%8E%20JCVI%20%E5%85%B1%E7%BA%BF%E6%80%A7%E5%88%86%E6%9E%90%E7%A1%AE%E5%AE%9A%E4%B8%80%E5%AF%B9%E4%B8%80%E7%9B%B4%E7%B3%BB%E5%90%8C%E6%BA%90%E5%9F%BA%E5%9B%A0/</id>
<published>2024-11-09T09:30:00.000Z</published>
<updated>2024-11-11T02:54:35.905Z</updated>
<content type="html"><![CDATA[<html><head></head><body><p>前段时间因为课题需求,需要获取两个物种间的所有一对一直系同源基因对(One-to-One ortholog, 为避免文章内容冗余后面统称 OTO)。由于两个目标物种在 Ensembl 上都有,所以可以直接通过 BioMart 下载其基因的同源关系并提取出来。</p><p>但经过筛选和过滤后,发现 BioMart 中能确定的 OTO 数量极低,不太能满足分析需求。考虑到我所分析的目标基因类型在不同物种间具有高顺序保守性和序列保守性,因此想看看能不能通过 JCVI 的共线性结果来获取更多的 OTO 作为补充,发现效果还挺不错,固有此文。</p><h2 id="JCVI-介绍"><a href="#JCVI-介绍" class="headerlink" title="JCVI 介绍"></a>JCVI 介绍</h2><p>JCVI 是一个用于比较基因组学分析的多功能工具包,<strong>共线性分析只是它其中的一个子功能</strong>。</p><p>JCVI 的安装,最简单的方式是通过 <code>pip</code>:</p><figure class="highlight shell"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">pip install jcvi</span><br></pre></td></tr></tbody></table></figure><p>也可通过 <code>conda</code> 或 <code>mamba</code> 安装:</p><figure class="highlight shell"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">conda install bioconda::jcvi</span><br></pre></td></tr></tbody></table></figure><p>此外也需要安装用于比对的 LAST:</p><figure class="highlight shell"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">conda install bioconda::last</span><br></pre></td></tr></tbody></table></figure><p>关于 JCVI 的运行,更多细节可见:<a href="https://github.com/tanghaibao/jcvi/wiki/MCscan-%28Python-version%29">JCVI tutorial</a></p><p>请注意,JCVI 的 wiki 写的并不全面,<strong>很多参数需要灵活调整以适配自身需求</strong>。本文所用到的文件(如注释等)均来自 Ensembl 数据库,如果使用其他来源的文件,请灵活调整参数(或调整源文件格式)以达成相同目的。</p><h2 id="JCVI-寻找-OTO-示例"><a href="#JCVI-寻找-OTO-示例" class="headerlink" title="JCVI 寻找 OTO 示例"></a>JCVI 寻找 OTO 示例</h2><p>本文使用到的文件下载(人和黑猩猩 Ensembl V110):</p><figure class="highlight shell"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">wget ftp://ftp.ensembl.org/pub/release-110/fasta/pan_troglodytes/cds/Pan_troglodytes.Pan_tro_3.0.cds.all.fa.gz</span><br><span class="line">wget ftp://ftp.ensembl.org/pub/release-110/gff3/pan_troglodytes/Pan_troglodytes.Pan_tro_3.0.110.gff3.gz</span><br><span class="line">wget ftp://ftp.ensembl.org/pub/release-110/fasta/homo_sapiens/cds/Homo_sapiens.GRCh38.cds.all.fa.gz</span><br><span class="line">wget ftp://ftp.ensembl.org/pub/release-110/gff3/homo_sapiens/Homo_sapiens.GRCh38.110.gff3.gz</span><br></pre></td></tr></tbody></table></figure><p>下文中的命令请根据自身情况修改相关输入和输出文件名,同时检查是否需要修改参数。</p><p>①、首先使用 <code>jcvi.formats.gff</code> 将其 <code>gff</code> 文件中特定的注释类型转为 <code>bed</code> 文件格式:</p><figure class="highlight shell"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">python -m jcvi.formats.gff bed --type=mRNA --key=transcript_id --primary_only Pan_troglodytes.Pan_tro_3.0.110.gff3.gz -o chimpanzee.bed</span><br><span class="line">python -m jcvi.formats.gff bed --type=mRNA --key=transcript_id --primary_only Homo_sapiens.GRCh38.110.gff3.gz -o human.bed</span><br><span class="line">python -m jcvi.formats.bed uniq chimpanzee.bed</span><br><span class="line">python -m jcvi.formats.bed uniq human.bed</span><br><span class="line">mv chimpanzee.uniq.bed chimpanzee.bed</span><br><span class="line">mv human.uniq.bed human.bed</span><br></pre></td></tr></tbody></table></figure><p>参数说明:</p><ul><li><code>--type</code>:指定想要提取的注释类型,可以通过逗号分隔同时提取多种信息。这里指定提取蛋白编码基因的 mRNA 序列区间范围。</li><li><code>--key</code>:指定提取时使用的标志信息。由于 Ensembl CDS 文件中序列以 transcipt id 开头,因此此处使用 <code>transcript_id</code> 以和 CDS 文件对应。</li></ul><figure class="highlight plaintext"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"># Ensembl CDS 文件示例</span><br><span class="line">>ENST00000633790.1 cds scaffold:GRCh38:HSCHR7_2_CTG6:503684:504150:1 gene:ENSG00000282748.1 gene_biotype:TR_V_gene transcript_biotype:TR_V_gene gene_symbol:TRBV5-7 description:T cell receptor beta variable 5-7 (non-functional) [Source:HGNC Symbol;Acc:HGNC:12224]</span><br><span class="line">ATGGGCCCCGGGCTCCTCTGCTGGGTGCTGCTTTGTCCCCTAGGAGAAGGCCCAGTGGAC</span><br><span class="line">GCTGGAGTCACCCAAAGTCCCACACACCTGATCAAAACGAGAGGACAGCACGTGACTCTG</span><br><span class="line">AGATGCTCTCCTATCTCTGGGCACACCAGTGTGTCCTCGTACCAACAGGCCCTGGGTCAG</span><br><span class="line">GGGCCCCAGTTTATCTTTCAGTATTATGAGAAAGAAGAGAGAGGAAGAGGAAACTTCCCT</span><br><span class="line">GATCAATTCTCAGGTCACCAGTTCCCTAACTATAGCTCTGAGCTGAATGTGAACGCCTTG</span><br><span class="line">TTGCTAGGGGACTCGGCCCTCTATCTCTGTGCCAGCAGCTTGG</span><br></pre></td></tr></tbody></table></figure><ul><li><code>python -m jcvi.formats.bed uniq</code>:此步将提取的注释中存在重叠的部分删除,最终保留更长的那一个转录本。</li><li><code>--primary</code>:此步仅保留每个 transcript id 下最长的 mRNA。<strong>该步骤和 uniq 步骤的目的都是为了尽可能去除冗余性以提高后续的共线性得分</strong>。</li></ul><p>②、对于 CDS,使用 <code>jcvi.formats.fasta</code> 将其 ID 处理为不带版本尾缀的格式:</p><figure class="highlight shell"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">python -m jcvi.formats.fasta format --sep=. Pan_troglodytes.Pan_tro_3.0.cds.all.fa.gz chimpanzee.cds</span><br><span class="line">python -m jcvi.formats.fasta format --sep=. Homo_sapiens.GRCh38.cds.all.fa.gz human.cds</span><br></pre></td></tr></tbody></table></figure><figure class="highlight plaintext"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"># 处理前</span><br><span class="line">>ENSPTRT00000098376.1</span><br><span class="line"># 处理后</span><br><span class="line">>ENSPTRT00000098376</span><br></pre></td></tr></tbody></table></figure><p>进行该步骤的原因主要是 <code>--key</code> 提取的 bed 文件中 <code>transcript_id</code> 里并不携带 version,因此这里通过 <code>--sep=.</code> 去除 CDS ID 中的 version 尾缀使 bed 文件和 cds 文件能够相吻合(<strong>在 Ensembl 同一版本的注释信息中不会出现一个 transcript id 同时具有多个 version 的情况</strong>)。</p><p>③、进行成对共线性搜索:</p><figure class="highlight shell"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">python -m jcvi.compara.catalog ortholog human chimpanzee --cscore=.99 --no_strip_names</span><br></pre></td></tr></tbody></table></figure><p>该步骤通过 LAST 进行比对,并通过 <code>--cscore=.99</code> 过滤 hit 以保留 reciprocal best hit (RBH)。</p><p>请注意 <code>jcvi.compara.catalog ortholog</code> 后紧接两个需要进行分析的物种文件名,此处应与前文输出的文件前缀对应,例如 human 对应 <code>human.bed</code> 及 <code>human.cds</code>。分析后输出的 <code>.anchors</code> 中即包含保留下的高质量共线性块。</p><figure class="highlight plaintext"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"># anchors 文件内容</span><br><span class="line">###</span><br><span class="line">ENST00000616016 ENSPTRT00000090571 2030</span><br><span class="line">ENST00000338591 ENSPTRT00000103781 3000</span><br><span class="line">ENST00000428771 ENSPTRT00000073784 871</span><br><span class="line">ENST00000624697 ENSPTRT00000076196 742</span><br><span class="line">ENST00000453464 ENSPTRT00000098436 1010</span><br><span class="line">ENST00000379339 ENSPTRT00000106256 459</span><br></pre></td></tr></tbody></table></figure><p>④、筛选 OTO:</p><p><code>.anchors</code> 文件中绝大多数都为 one-to-one 的对应关系,但也<strong>依然存在少数为多对一或一对多</strong>,因此需要进行进一步的过滤,该步骤可以通过 Python 实现:</p><figure class="highlight python"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> pandas <span class="keyword">as</span> pd</span><br><span class="line"><span class="keyword">import</span> sys</span><br><span class="line"></span><br><span class="line">jcvi_result_df = pd.read_csv(sys.argv[<span class="number">1</span>], sep=<span class="string">"\t"</span>, comment=<span class="string">"#"</span>, header=<span class="literal">None</span>)</span><br><span class="line">jcvi_result_df.columns = [<span class="string">"spe1"</span>, <span class="string">"spe2"</span>, <span class="string">"score"</span>]</span><br><span class="line"></span><br><span class="line">spe1_counts = jcvi_result_df[<span class="string">"spe1"</span>].value_counts()</span><br><span class="line">spe1_only_once = spe1_counts[spe1_counts == <span class="number">1</span>].index.to_list()</span><br><span class="line"></span><br><span class="line">spe2_counts = jcvi_result_df[<span class="string">"spe2"</span>].value_counts()</span><br><span class="line">spe2_only_once = spe2_counts[spe2_counts == <span class="number">1</span>].index.to_list()</span><br><span class="line"></span><br><span class="line">jcvi_result_filter_df = jcvi_result_df.loc[</span><br><span class="line"> (jcvi_result_df[<span class="string">"spe1"</span>].isin(spe1_only_once)) &</span><br><span class="line"> (jcvi_result_df[<span class="string">"spe2"</span>].isin(spe2_only_once))</span><br><span class="line">]</span><br><span class="line"></span><br><span class="line">jcvi_result_filter_df[[<span class="string">"spe1"</span>, <span class="string">"spe2"</span>]].to_csv(<span class="string">f"<span class="subst">{sys.argv[<span class="number">1</span>]}</span>.one2one"</span>, sep=<span class="string">"\t"</span>, index=<span class="literal">False</span>, header=<span class="literal">False</span>)</span><br></pre></td></tr></tbody></table></figure><p>将上述代码保存到一个名为 <code>jcvi_filter.py</code> 的文件中,运行以下命令:</p><figure class="highlight shell"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">python jcvi_filter.py human.chimpanzee.anchors</span><br></pre></td></tr></tbody></table></figure><p>随后将生成一个名为 <code>human.chimpanzee.anchors.one2one</code> 的文件,其中每一行都为一个 human 和 chimpanzee 间的共线性一对一直系同源基因。</p><h2 id="其他需要注意的地方"><a href="#其他需要注意的地方" class="headerlink" title="其他需要注意的地方"></a>其他需要注意的地方</h2><p>由于 JCVI 除了考虑比对情况以外,也考虑了这些基因在基因组位置上的线性关系,因此使用 JCVI 有利于回收在两种物种基因组上<strong>位置顺序保守</strong>的直系同源基因对,但相对的也掩盖了一些在不同物种间位置不一致的直系同源关系。如果你并不关心基因位置信息,可以考虑直接使用 RBH 方法进行确定。</p></body></html>]]></content>
<summary type="html">本文介绍了一种使用 JCVI 分析结果确定一对一直系同源基因的方法,以期通过这种方式寻找到更多的 One-to-One ortholog。</summary>
<category term="学习" scheme="https://biojuse.com/categories/%E5%AD%A6%E4%B9%A0/"/>
<category term="生信" scheme="https://biojuse.com/categories/%E5%AD%A6%E4%B9%A0/%E7%94%9F%E4%BF%A1/"/>
</entry>
<entry>
<title>获取 vcf 文件中每个个体携带的突变数量</title>
<link href="https://biojuse.com/2024/10/10/%E8%8E%B7%E5%8F%96%20vcf%20%E6%96%87%E4%BB%B6%E4%B8%AD%E6%AF%8F%E4%B8%AA%E4%B8%AA%E4%BD%93%E6%90%BA%E5%B8%A6%E7%9A%84%E7%AA%81%E5%8F%98%E6%95%B0%E9%87%8F/"/>
<id>https://biojuse.com/2024/10/10/%E8%8E%B7%E5%8F%96%20vcf%20%E6%96%87%E4%BB%B6%E4%B8%AD%E6%AF%8F%E4%B8%AA%E4%B8%AA%E4%BD%93%E6%90%BA%E5%B8%A6%E7%9A%84%E7%AA%81%E5%8F%98%E6%95%B0%E9%87%8F/</id>
<published>2024-10-10T06:30:00.000Z</published>
<updated>2024-10-10T06:29:49.056Z</updated>
<content type="html"><![CDATA[<html><head></head><body><p>最近的工作涉及到处理大量种群数据,其中有个分析需要统计每个个体携带的突变数量,在网上搜寻了诸多方法后确定了一些比较高效的策略,固有此文记录。</p><blockquote><p>本文的部分流程参考源:</p><p><a href="https://www.biostars.org/p/336206/">BioStars "how to count variants par sample per chromosome in a vcf file?"</a></p></blockquote><h2 id="提取每个个体携带的突变数量"><a href="#提取每个个体携带的突变数量" class="headerlink" title="提取每个个体携带的突变数量"></a>提取每个个体携带的突变数量</h2><p>该流程主要通过 plink2 实现:</p><figure class="highlight shell"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">plink2 --vcf [vcf file] --out [plink output1]</span><br><span class="line">plink2 --pfile [plink output1] --sample-counts --out [plink output2]</span><br></pre></td></tr></tbody></table></figure><ul><li><code>[vcf file]</code>:此处填入 vcf 文件的路径。</li><li><code>[plink output1]</code>:此处填入 plink2 输出的文件前缀。</li><li><code>[plink output2]</code>:此处填入 plink2 输出的文件前缀。</li></ul><p>运行结束后,可以得到以 <code>.scount</code> 结尾的文件,其中各列的含义如下:</p><ol><li><strong>#IID</strong>:标识每个样本的编号。</li><li><strong>HOM_REF_CT</strong>:纯合参考基因型计数,个体纯合参考基因型的位点数量。</li><li><strong>HOM_ALT_SNP_CT</strong>:纯合变异基因型计数,个体纯合变异基因型的单核苷酸多态性(SNP)数量。</li><li><strong>HET_SNP_CT</strong>:杂合基因型计数,个体在该位点上是杂合基因型的SNP数量(一条染色体是参考基因型,另一条是变异基因型)。</li><li><strong>DIPLOID_TRANSITION_CT</strong>:二倍体转换变异的数量(转换:嘌呤与嘌呤或嘧啶与嘧啶之间的替换)。</li><li><strong>DIPLOID_TRANSVERSION_CT</strong>:二倍体颠换变异的数量(颠换:嘌呤与嘧啶之间的替换)。</li><li><strong>DIPLOID_NONSNP_NONSYMBOLIC_CT</strong>:二倍体非SNP非符号变异计数。包括一些插入、缺失(INDELs)等。</li><li><strong>DIPLOID_SINGLETON_CT</strong>:二倍体单例变异计数,表示在整个样本集中只出现在该个体中的变异数量。</li><li><strong>HAP_REF_INCL_FEMALE_Y_CT</strong>:单倍体参考基因型计数,即在单倍体区域(Y 染色体)的参考等位基因数量。</li><li><strong>HAP_ALT_INCL_FEMALE_Y_CT</strong>:单倍体变异基因型计数,在单倍体区域中出现的变异等位基因的数量。</li><li><strong>MISSING_INCL_FEMALE_Y_CT</strong>:缺失基因型计数,在样本中缺失的基因型数据计数。</li></ol><p>更多可输出列的详细信息可见:<a href="https://www.cog-genomics.org/plink/2.0/formats#scount">https://www.cog-genomics.org/plink/2.0/formats#scount</a></p><p>具体参数的用法可见:<a href="https://www.cog-genomics.org/plink/2.0/basic_stats#sample_counts">https://www.cog-genomics.org/plink/2.0/basic_stats#sample_counts</a></p><p>通过 <code>HOM_ALT_SNP_CT</code> <code>HET_SNP_CT</code> <code>DIPLOID_NONSNP_NONSYMBOLIC_CT</code> 计算每个个体携带的突变数量。</p><h2 id="提取每个突变对应的携带者信息"><a href="#提取每个突变对应的携带者信息" class="headerlink" title="提取每个突变对应的携带者信息"></a>提取每个突变对应的携带者信息</h2><figure class="highlight shell"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">bcftools norm -m -any [vcf file] | bcftools query -i 'GT="alt"' -f '%CHROM\t%POS\t%REF\t%ALT[\t%SAMPLE:%GT]\n' - > [output]</span><br></pre></td></tr></tbody></table></figure><ul><li><code>[vcf file]</code>:此处填入 vcf 文件的路径。</li><li> <code>[output]</code>:此处填入输出文件的路径。</li></ul><p>此处通过 <code>bcftools norm -m -any</code> 对多等位基因进行了拆分,可视自身需求去除该部分,此处 <code>GT="alt"</code> 将所有携带替代等位基因的个体提取出并打印。</p><p>输出结果示例:</p><figure class="highlight plaintext"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">chr1 228424930 G A 4922792:0/1 4884261:0/1 3988378:0/1 2479308:0/1 4414951:0/1 3862053:0/1</span><br></pre></td></tr></tbody></table></figure><p>前四列用于表示特定突变(分别指示染色体编号、位置、ref 和 alt),后续以制表符分隔记录该突变的携带者及基因型。</p></body></html>]]></content>
<summary type="html">这篇文章介绍了如何获取 vcf 中每个个体携带的突变数量(及每个突变对应的携带者 id)。</summary>
<category term="学习" scheme="https://biojuse.com/categories/%E5%AD%A6%E4%B9%A0/"/>
<category term="杂项" scheme="https://biojuse.com/categories/%E5%AD%A6%E4%B9%A0/%E6%9D%82%E9%A1%B9/"/>
</entry>
<entry>
<title>vscode 在远程服务器上通过 jupyter notebook 使用 R</title>
<link href="https://biojuse.com/2024/09/19/vscode%20%E5%9C%A8%E8%BF%9C%E7%A8%8B%E6%9C%8D%E5%8A%A1%E5%99%A8%E4%B8%8A%E9%80%9A%E8%BF%87%20jupyter%20notebook%20%E4%BD%BF%E7%94%A8%20R/"/>
<id>https://biojuse.com/2024/09/19/vscode%20%E5%9C%A8%E8%BF%9C%E7%A8%8B%E6%9C%8D%E5%8A%A1%E5%99%A8%E4%B8%8A%E9%80%9A%E8%BF%87%20jupyter%20notebook%20%E4%BD%BF%E7%94%A8%20R/</id>
<published>2024-09-19T09:00:00.000Z</published>
<updated>2024-09-20T02:18:17.541Z</updated>
<content type="html"><![CDATA[<html><head></head><body><p>最近一段时间的关键分析要用到 R,但是办公电脑的机械硬盘前段时间出了问题,现在用 Rstudio 会非常卡顿,加上相关分析对计算资源的要求也比较高,就想着是否有什么办法能在服务器上也弄一个类似于 Rstudio 的可视化界面出来作为辅助。</p><p>不过看了一圈发现 Rstudio 的 server 版本似乎局限性不少,而且还要用到 root 权限。考虑到平时运行 Python 进行分析时大多数时候都在 jupyter notebook 上进行,就想着是否能套用过来,于是就有了这篇文章。</p><h2 id="安装"><a href="#安装" class="headerlink" title="安装"></a>安装</h2><p>该文章的具体实现在 Linux + mamba 环境下完成,如果你没有 conda/mamba 环境,可以参考网上资料进行安装。</p><p>首先确认你的环境中有 R,如果没有可以通过以下命令安装:</p><figure class="highlight shell"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">mamba install conda-forge::r-base</span><br><span class="line">R # 确认可以进入 R 终端,使用 q() 退出</span><br></pre></td></tr></tbody></table></figure><p>通过 mamba 安装 <a href="https://github.com/IRkernel/IRkernel">IRkernel</a> 和 jupyter(使用 conda 也行,本文章以 mamba 为准):</p><figure class="highlight shell"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">mamba install r::r-irkernel</span><br><span class="line">mamba install anaconda::jupyter</span><br></pre></td></tr></tbody></table></figure><p>完成上述步骤后,进入 R 终端,输入 <code>IRkernel::installspec()</code>:</p><figure class="highlight plaintext"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">$ R</span><br><span class="line">> IRkernel::installspec()</span><br></pre></td></tr></tbody></table></figure><p>如果在 VScode 中尚未安装 jupyter 扩展,则点开侧栏的 <strong><u>拓展</u></strong> 页面并搜索 jupyter 安装:</p><img src="/pic2/vscode_jupyter1.png" height="400px"><h2 id="运行"><a href="#运行" class="headerlink" title="运行"></a>运行</h2><p>新建一个 jupyter notebook 文件,使用 vscode 打开它:</p><img src="/pic2/vscode_jupyter2.png" height="300px"><p>点击右上角的 <code>select kernel</code>,此时如果仅存在 Python 相关的 kernel,则先在服务器上运行 jupyter notebook:</p><figure class="highlight shell"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">jupyter notebook</span><br></pre></td></tr></tbody></table></figure><p>此时屏幕输出里会返回 server 的链接,例如:</p><figure class="highlight plaintext"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">http://localhost:8888/tree?token=11d321403f5a4d62d94d07ddae56e48017cf641c059573b0</span><br></pre></td></tr></tbody></table></figure><p>在 <code>select kernel</code> 里,点击 <code>Select Another Kernel</code>,此后选择 <code>Existing Jupyter Server</code>,在弹出的窗口里输入上面得到的 server 链接,并选择弹出的 R。图示:</p><img src="/pic2/vscode_jupyter3.png" height="500px"><p>此后即可在 jupyter notebook 中使用 R 进行分析:</p><img src="/pic2/vscode_jupyter4.png" height="400px"></body></html>]]></content>
<summary type="html">这篇文章介绍了 vscode 上如何在远程服务器中通过 jupyter notebook 使用 R(无需 root 权限),包括详细的图文步骤。</summary>
<category term="学习" scheme="https://biojuse.com/categories/%E5%AD%A6%E4%B9%A0/"/>
<category term="生信" scheme="https://biojuse.com/categories/%E5%AD%A6%E4%B9%A0/%E7%94%9F%E4%BF%A1/"/>
</entry>
<entry>
<title>簇突变的类型简介及识别方法(Clustered mutation classification)</title>
<link href="https://biojuse.com/2024/08/23/%E7%B0%87%E7%AA%81%E5%8F%98%E7%9A%84%E7%B1%BB%E5%9E%8B%E7%AE%80%E4%BB%8B%E5%8F%8A%E8%AF%86%E5%88%AB%E6%96%B9%E6%B3%95/"/>
<id>https://biojuse.com/2024/08/23/%E7%B0%87%E7%AA%81%E5%8F%98%E7%9A%84%E7%B1%BB%E5%9E%8B%E7%AE%80%E4%BB%8B%E5%8F%8A%E8%AF%86%E5%88%AB%E6%96%B9%E6%B3%95/</id>
<published>2024-08-23T12:30:00.000Z</published>
<updated>2024-08-23T12:29:12.593Z</updated>
<content type="html"><![CDATA[<html><head></head><body><p>基因组中,某些特殊的突变过程可能会导致一小段区域内连续的突变发生。这些突变在基因组中呈现成簇分布,因此被称作 <strong><u>clustered mutation</u><strong>(本文将称其为</strong>簇突变</strong>)。研究这些突变的分布及组成有助于我们揭示导致其发生的内源性和外源性过程。该文章将主要讲述簇突变的类别并列举一些会导致特定类别的生物学原因,同时介绍该领域中的某些生物信息学工具等。</p><h2 id="簇突变类型"><a href="#簇突变类型" class="headerlink" title="簇突变类型"></a>簇突变类型</h2><p>簇突变类型主要被分作六类,其中五类针对碱基水平的变化,一类针对插入及缺失(InDel):</p><ul><li><p><strong>DSB(Doublet Base Substitutions)</strong>:双碱基替换,表示这两个突变<strong>发生在相邻的碱基上</strong>。某些外源性过程例如紫外线损伤会导致双碱基替换的发生(CC>TT),此外 DNA 修复缺陷和聚合酶功能突变也会导致 DSB 发生。</p></li><li><p><strong>MBS (Multiple Base Substitutions)<strong>:多碱基替换,表示在</strong>很短的序列范围内发生多个碱基突变且这些突变彼此相邻</strong>。由于该簇突变的出现数量很有限,因此尚未得到全面研究。</p></li><li><p><strong>Omikli</strong>:源自希腊语,意为 <u>雾</u> 或 <u>薄雾</u>,也被称作 <strong>diffuse hypermutation(弥漫性超突变)</strong>,表现为 IMD(Inter-Mutation Distance,突变间距)小于预期的少数几个碱基突变(两到三个)。多种外源过程可导致 Omikli 事件,内源过程则有单链错配修复等。</p></li><li><p><strong>Kataegis</strong>:源自希腊语,意为 <u>暴雨</u>。其本质上是 <strong>Omikli 的更大规模事件</strong>。表现为 IMD 小于预期的多个碱基突变聚集在一起。当前认为大多数导致 Kataegis 的过程都归因于 <a href="https://en.wikipedia.org/wiki/APOBEC">AID/APOBEC 家族</a>(Omikli 也受部分影响),与双链断裂具有一定关系。</p></li><li><p><strong>Other:</strong>IMD 小于预期但是 <strong>VAF(Variant allele frequency,突变等位基因频率)不相等的一些碱基突变聚集在一起</strong>。而<strong>上述几种突变类型中,一个 clustered mutation group 里所包含的突变 VAF 都相同</strong>。</p><ul><li><blockquote><p>如果簇突变在同一个事件中发生(也可以当作在同一个细胞中发生),那么这些突变的细胞谱系树将完全相同,因此最后得到的 VAF 预期一致。不同则表明这些突变是在多次突变事件中独立发生的。<strong>Other 类型的突变可能表明其所处的基因组区域本身突变率高</strong>,所以严格意义上讲它并不算主流研究中关注的簇突变。</p></blockquote></li></ul></li><li><p><strong>indels</strong>:IMD 小于预期的插入或缺失事件。与微卫星不稳定性有关并常见于错配修复缺陷的细胞中。</p></li></ul><img src="/pic2/clustered_mutation.jpeg" height="500px"><center>Refer: https://osf.io/qpmzw/wiki/2.%20Workflow/</center><h2 id="簇突变的确定"><a href="#簇突变的确定" class="headerlink" title="簇突变的确定"></a>簇突变的确定</h2><p>一般而言,确定簇突变的步骤如下:</p><ol><li>计算一个 IMD 阈值。</li><li>对基因组上的突变进行判断,如果存在与其距离低于 IMD 阈值的突变,则认为其是簇突变。</li></ol><p>在一些比较久之前的文章中,IMD 的阈值是直接人为确定的。例如 <a href="https://www.cell.com/cell/fulltext/S0092-8674(17)30774-2">Supek 等人</a>采用了以下判断标准:</p><p>①、突变之间的距离 <= 500bp。</p><p>②、突变的类型必须相同(例如都为 C>T)且链对应(例如 C 都在正链上)。</p><p>这种划分方法虽然在一定程度上可靠,但是并不适用于所有应用场景,且不同研究采取的标准也不完全相同(例如阈值大小),导致不方便整合比较。</p><p>随着期刊对分析的可靠性要求越来越严格,现在已经有许多用于分析簇突变的生物信息学工具被开发出来,它们采用了更加严谨的策略并且保证了可再现性,例如突变特征分析领域的主流工具套件 SigProfiler 中也提供了用于分析簇突变的 <a href="https://osf.io/qpmzw/wiki/home/">SigProfilerClusters</a>。其运行过程大致如下:</p><p>①、根据突变的上下文(周边序列)等信息,对突变的位置进行打乱重排,以模拟随机情况下的突变分布情况。</p><p>②、根据真实数据与模拟数据的突变分布计算出每个样本的 IMD 阈值。</p><p>③、根据基因组各个窗口内的突变率对 IMD 阈值进行校正。</p><p>④、根据簇突变的 VAF 等信息对其进行分类。</p><p>该团队使用该工具对 PCAWG 项目的数据进行了分析,系统阐述了各癌症类型中的簇突变景观,并发现了 APOBEC3 Kataegis 对 Extrachromosomal DNA (ecDNA) 的作用(<a href="https://www.nature.com/articles/s41586-022-04398-6#Sec8">Bergstrom et al. 2022, Nature</a>)。</p><h2 id="参考资料"><a href="#参考资料" class="headerlink" title="参考资料"></a>参考资料</h2><ol><li>常见的 DSB 特征及生物学成因:<a href="https://cancer.sanger.ac.uk/signatures/dbs/">https://cancer.sanger.ac.uk/signatures/dbs/</a></li><li>Clustered Mutation Signatures Reveal that Error-Prone DNA Repair Targets Mutations to Active Genes, Cell 2017</li><li>Examining clustered somatic mutations with SigProfilerClusters, Bioinformatics 2022</li><li>Mapping clustered mutations in cancer reveals APOBEC3 mutagenesis of ecDNA, Nature 2022</li></ol></body></html>]]></content>
<summary type="html">这篇文章详细介绍了 clustered mutation(簇突变)的各个类型及其划分标准,并描述了用于确定簇突变的方法。</summary>
<category term="学习" scheme="https://biojuse.com/categories/%E5%AD%A6%E4%B9%A0/"/>
<category term="杂项" scheme="https://biojuse.com/categories/%E5%AD%A6%E4%B9%A0/%E6%9D%82%E9%A1%B9/"/>
</entry>
<entry>
<title>rsync 中排除文件的规则详解(rsync --exclude)</title>
<link href="https://biojuse.com/2024/08/15/rsync%20%E4%B8%AD%E6%8E%92%E9%99%A4%E6%96%87%E4%BB%B6%E7%9A%84%E8%A7%84%E5%88%99%E8%AF%A6%E8%A7%A3/"/>
<id>https://biojuse.com/2024/08/15/rsync%20%E4%B8%AD%E6%8E%92%E9%99%A4%E6%96%87%E4%BB%B6%E7%9A%84%E8%A7%84%E5%88%99%E8%AF%A6%E8%A7%A3/</id>
<published>2024-08-15T08:50:00.000Z</published>
<updated>2024-08-17T13:13:22.167Z</updated>
<content type="html"><![CDATA[<html><head></head><body><p>前段时间在备份服务器时,由于备份策略的变化,对 rsync 的 exclude patterns 进行了一些更加深入的探索。</p><p>这篇文章将介绍如何设计 rsync 的 exclude patterns 以排除特定目录或文件。</p><h2 id="命令介绍"><a href="#命令介绍" class="headerlink" title="命令介绍"></a>命令介绍</h2><p>rsync 是 Linux 和 Unix 中常用的文件复制和同步命令,相比 cp 命令而言更加高效和完善,其优点包括但不限于:</p><ul><li><strong>增量复制</strong>:rsync 只会复制那些自上次同步后更改的文件部分,极大地减少了数据传输量。例如 a 文件已经同步过一次并且没有发生变化,则 rsync 会跳过。同样,rsync 也会进行完整性检查以确定传输的数据无误。</li><li><strong>保留属性</strong>:rsync 可以保持文件的权限、时间戳、软硬链接、所有权等属性。</li><li><strong>灵活的过滤规则</strong>:支持使用包括和排除规则来选择同步的文件或目录。</li></ul><img src="https://tse3-mm.cn.bing.net/th/id/OIP-C.m0CLH5eqL6kvqiFjEVu6VQHaD4?rs=1&pid=ImgDetMain" height="200px"><h2 id="排除规则"><a href="#排除规则" class="headerlink" title="排除规则"></a>排除规则</h2><p>rsync 通过参数 <code>--exclude</code> 或 <code>--exclude-from</code> 指定排除的文件模式。其中 <code>--exclude-from</code> 用于指定包含排除模式的文件(包含多个排除规则)。</p><h3 id="排除指定文件"><a href="#排除指定文件" class="headerlink" title="排除指定文件"></a>排除指定文件</h3><p>输入文件名称(如 <code>123.txt</code>)即可排除所有命名为 <code>123.txt</code> 的文件。</p><h3 id="排除特定尾缀的文件"><a href="#排除特定尾缀的文件" class="headerlink" title="排除特定尾缀的文件"></a><strong>排除特定尾缀的文件</strong></h3><p>通过 <code>*.xxx</code> 排除包含特定尾缀的文件,例如:</p><ul><li><code>*.txt</code> 排除所有以 <code>.txt</code> 结尾的文件。</li><li><code>*vcf</code> 排除所有以 <code>vcf</code> 结尾的文件。注意这里<strong>并不推荐这样做</strong>,因为这<strong>也会排除掉所有以 vcf 结尾的目录</strong>,例如:<ul><li><code>source/dir1/dir_vcf/xxx</code>,这里 <code>dir_vcf</code> 及其中的所有文件也会被排除。</li></ul></li></ul><p>因此在根据尾缀排除文件时,最好添加尾缀前的 <code>.</code> 以避免其他文件夹的意外排除。</p><p>同理也可通过前缀进行文件排除,例如 <code>SRR*</code> 等,但同样地,这会排除符合该条件的所有目录。因此请<strong>谨慎使用</strong>。</p><h3 id="排除隐藏文件及文件夹"><a href="#排除隐藏文件及文件夹" class="headerlink" title="排除隐藏文件及文件夹"></a>排除隐藏文件及文件夹</h3><p>通过 <code>.*</code> <strong>排除所有隐藏文件及隐藏文件夹</strong>。</p><h3 id="排除特定文件夹"><a href="#排除特定文件夹" class="headerlink" title="排除特定文件夹"></a>排除特定文件夹</h3><p>直接使用文件夹名称,例如 <code>anaconda3</code> 等。但注意,<strong>如果有与该文件夹名同名的文件,那么该文件也会被排除</strong>,例如:</p><ul><li>使用 <code>juse</code> 时,<code>source/juse/</code>(目录)会被排除,此外 <code>source/other/juse</code>(文件名为 <code>juse</code>)也会被排除。</li></ul><p>因此如果你想排除特定文件夹但又担心具有同名文件,两个好的权衡方式是:</p><ul><li>添加该目录先前的信息,例如你已经知道其位于其他文件夹中:<code>dir1/dir2</code>(排除位于 dir1 下的 dir2)。</li><li>排除该目录中的所有文件,并保留空文件夹:<code>dir2/**</code>,该做法更加推荐,因为你也可以保留下 ‘哪些文件夹被排除’ 这个信息。</li></ul><p>这里使用两个星号是为了和之后的跨多目录匹配相一致,但其实只用一个 <code>*</code> 的效果是一样的。</p><h3 id="跨目录排除匹配的文件夹"><a href="#跨目录排除匹配的文件夹" class="headerlink" title="跨目录排除匹配的文件夹"></a>跨目录排除匹配的文件夹</h3><p>该方法的应用场景如下:</p><p>用户 <code>juse</code> 的目录里存在多个 <code>work</code> 文件夹,<code>juse</code> 想将它们全部排除掉,但是他认为仅使用 <code>work/**</code> 并不妥当,因为其他人的 <code>work</code> 文件夹中可能存在需要备份的文件,而根据单个目录路径进行排除也存在困难,因为 <code>juse</code> 目录中的 <code>work</code> 文件夹很多且位置不一。</p><ul><li><code>/juse/dir1/work/</code></li><li><code>/juse/work/</code></li><li><code>/juse/dir2/dir3/work/</code></li></ul><p>此时可以通过使用 <code>juse**/work</code> 排除 <code>juse</code> 目录下所有 <code>work</code> 子目录。请注意<strong>仅使用单个 <code>*</code> 时无法实现跨目录匹配</strong>:</p><ul><li><code>juse/*/work</code> 仅能识别到 <code>/juse/dir1/work/</code>,无法识别 <code>/juse/dir2/dir3/work/</code>。</li></ul><p>而使用 <code>juse/**/work</code> 则无法识别到 <code>juse</code> 目录下的 <code>work</code> 文件夹,可以通过去除第一个斜杠避免该问题。</p><p>相比之下 du 命令可以通过单个星号实现跨多个目录匹配,同时两个星号也不影响 du 的使用。</p><h2 id="rsync-使用建议"><a href="#rsync-使用建议" class="headerlink" title="rsync 使用建议"></a>rsync 使用建议</h2><p>首先需要明确一点,rsync <strong>以 source 目录作为根目录进行同步操作,因此并不会因为先前的绝对路径中存在排除模式就导致同步失败</strong>,例如:</p><figure class="highlight shell"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">rsync -av --exclude 'juse' /juse/dir1/ /pathto/destination/</span><br></pre></td></tr></tbody></table></figure><p>上述命令并不会导致 <code>/juse/dir1/</code> 中的文件全部无法同步,因为其并不会考虑源目录本身的路径信息。</p><p>此外,在使用 rsync 推荐使用以下一些参数:</p><ul><li><code>-av</code>:归档模式 + 输出更多信息,前者保证 rsync 递归复制目录并保留文件的各种属性,后者有助于监控同步过程。</li><li><code>-z</code>:在数据传输过程中进行压缩,在慢速网络中进行同步时建议启用。</li><li><code>--bwlimit</code>:限制带宽(传输速度),避免影响其他进程。</li><li><code>--delete</code> & <code>--delete-excluded</code>:前者删除目标文件夹中源文件夹里不存在的文件,后者删除目标文件夹中被排除模式匹配的文件,适合需要完全同步时使用。</li></ul><p>注意 rsync 可以通过 <code>--exclude-from</code> 使用多个排除模式。</p></body></html>]]></content>
<summary type="html">这篇文章详细介绍了如何设置 rsync 中的 exclude patterns,并说明了在实际应用过程中的一些可选参数。</summary>
<category term="学习" scheme="https://biojuse.com/categories/%E5%AD%A6%E4%B9%A0/"/>
<category term="杂项" scheme="https://biojuse.com/categories/%E5%AD%A6%E4%B9%A0/%E6%9D%82%E9%A1%B9/"/>
</entry>
<entry>
<title>Snakemake pipeline 搭建的进阶教程</title>
<link href="https://biojuse.com/2024/07/06/Snakemake%20pipeline%20%E6%90%AD%E5%BB%BA%E7%9A%84%E8%BF%9B%E9%98%B6%E6%95%99%E7%A8%8B/"/>
<id>https://biojuse.com/2024/07/06/Snakemake%20pipeline%20%E6%90%AD%E5%BB%BA%E7%9A%84%E8%BF%9B%E9%98%B6%E6%95%99%E7%A8%8B/</id>
<published>2024-07-06T13:05:00.000Z</published>
<updated>2024-07-09T04:51:15.393Z</updated>
<content type="html"><![CDATA[<html><head></head><body><h2 id="关于-Snakemake"><a href="#关于-Snakemake" class="headerlink" title="关于 Snakemake"></a>关于 Snakemake</h2><p>Snakemake 是一个工作流管理系统,可用于创建易于迁移和复现的数据分析流程(pipeline),因此被广泛应用于生物学分析中。虽然 Snakemake 算是一个独立的编程语言,但其本质是基于 Python 搭建的,因此如果你对 Python 有一定了解,那么上手 Snakemake 就会更容易很多。并且 Python 技能的掌握对于某些情况下 Pipeline 下游分析部分的拓展是有必要的。</p><img src="/pic2/snakemake1.png"><p>本文将结合多个近些年生物论文中公开的 Snakemake Pipeline,介绍如何搭建一个具有一定功能的 Pipeline。</p><p>Snakemake 安装:<a href="https://snakemake.readthedocs.io/en/stable/getting_started/installation.html">https://snakemake.readthedocs.io/en/stable/getting_started/installation.html</a></p><p>Snakemake Pipeline 示例教程:<a href="https://snakemake.readthedocs.io/en/stable/tutorial/basics.html">https://snakemake.readthedocs.io/en/stable/tutorial/basics.html</a></p><p>有利于提升阅读体验的一些条件:</p><ul><li>对于 Python 编程已经具备一定的了解,包括文件的一些基本读写操作和 lambda 表达式的应用。</li><li>具有初步的 Snakemake Pipeline 制作经验。</li></ul><p>阅读后有望获得的一些能力:</p><ul><li>知晓 Snakemake 中一些基本的语法和操作。</li><li>编写具有明确结构的 Snakemake Pipeline。</li></ul><h2 id="搭建-Pipeline"><a href="#搭建-Pipeline" class="headerlink" title="搭建 Pipeline"></a>搭建 Pipeline</h2><p>注意,该 Pipeline 的完整版本在以下 github repository 的 <a href="https://github.com/JuseTiZ/Blog-Snakemake-pipeline/tree/main/Tutorial-Pipeline">Tutorial-Pipeline</a> 可见,建议结合完整 Pipeline 阅读文章以避免不必要的混淆:</p><p><a href="https://github.com/JuseTiZ/Blog-Snakemake-pipeline">https://github.com/JuseTiZ/Blog-Snakemake-pipeline</a></p><p>该 Pipeline 的运行环境也可通过以上 repository 中的指引进行安装和配置。</p><h3 id="Pipeline-要求"><a href="#Pipeline-要求" class="headerlink" title="Pipeline 要求"></a>Pipeline 要求</h3><p><strong>目标:</strong>搭建一个可以根据 SRR accession number 自动下载数据、处理数据和进行表达定量的 Pipeline。</p><p><strong>流程:</strong></p><ol><li><code>prefetch</code> 下载数据,该步骤还需配置 <code>pigz</code>(多线程压缩)及 <code>fasterq-dump</code>(提取 fastq)。</li><li><code>trim_galore</code> 过滤数据</li><li><code>salmon</code> 进行定量</li></ol><p><strong>功能:</strong>①、Pipeline 可以识别来自不同样本的数据,并把同一样本的多个数据进行合并;②、Pipeline 可以分为单端和双端模式进行处理;③、可以自定义各个软件运行时使用的参数;④、下载数据时<strong>如果遇到网络错误应当可以自行重续下载</strong>。</p><p><strong>需要提前准备的:</strong>①、指定自行构建的 salmon 索引;②、已安装好的并放置于环境变量中的软件。</p><p>如果你想将软件的版本控制也考虑进 Pipeline 中,可见本文 <strong><u>Pipeline 拓展</u></strong> 部分。</p><p>你可以通过下述命令进行 hg38 salmon 索引的构建以在后文中使用,或者你可以在阅读本文后将该步骤嵌入 Pipeline 流程中(但并不建议,因为该步骤并不是每一次分析都需要复用,这种情况下最好作为参数指定):</p><figure class="highlight shell"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">mkdir hg38_salmon_index</span><br><span class="line">wget ftp://ftp.ebi.ac.uk/pub/databases/gencode/Gencode_human/release_44/gencode.v44.pc_transcripts.fa.gz</span><br><span class="line">wget ftp://ftp.ebi.ac.uk/pub/databases/gencode/Gencode_human/release_44/GRCh38.primary_assembly.genome.fa.gz</span><br><span class="line">grep "^>" <(gunzip -c GRCh38.primary_assembly.genome.fa.gz) | cut -d " " -f 1 > decoys.txt</span><br><span class="line">sed -i.bak -e 's/>//g' decoys.txt</span><br><span class="line">cat gencode.v44.pc_transcripts.fa.gz GRCh38.primary_assembly.genome.fa.gz > GRCh38.gentrome.fa.gz</span><br><span class="line">salmon index -t GRCh38.gentrome.fa.gz -d decoys.txt -p 12 -i hg38_salmon_index --gencode > hg38_salmon_index/salmon_index.log 2>&1</span><br></pre></td></tr></tbody></table></figure><h3 id="Pipeline-管理"><a href="#Pipeline-管理" class="headerlink" title="Pipeline 管理"></a>Pipeline 管理</h3><p>首先,一个清晰的文件夹结构对于 Pipeline 的管理和拓展是有帮助的,因此请 <code>cd</code> 到拟存储 Pipeline 的路径,并输入以下命令:</p><figure class="highlight shell"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line">cd [path]</span><br><span class="line">tutorial_path=$(pwd)</span><br><span class="line">mkdir rules</span><br><span class="line">mkdir config</span><br><span class="line">touch config/config.yaml</span><br><span class="line">mkdir envs</span><br><span class="line">mkdir logs</span><br><span class="line">touch Snakefile</span><br></pre></td></tr></tbody></table></figure><p>这些文件夹的用途将在后续搭建过程中一一介绍。</p><img src="/pic2/snakemake2.png" style="zoom:80%;"><h3 id="Pipeline-搭建"><a href="#Pipeline-搭建" class="headerlink" title="Pipeline 搭建"></a>Pipeline 搭建</h3><p>阅读时请留意每个代码块指定的文件,文件头中的 <code>#</code> 仅作文件名说明用,在实际文件中请将该标头去除。</p><h4 id="1、输出目标文件确定"><a href="#1、输出目标文件确定" class="headerlink" title="1、输出目标文件确定"></a>1、输出目标文件确定</h4><p>搭建一个 Pipeline 具有一定的前置条件,首先<strong>你需要对每一个步骤会产生什么样的文件有具体的了解</strong>,因此<strong>建议完全跑过一套流程以后再进行这一步骤</strong>。</p><p>按照上述目标,我们首先希望 Pipeline 能够做到以下事情:</p><p>①、下载 SRR id 对应的原始数据。</p><p>②、经过一系列处理以后,将这些数据在样本层级进行定量。</p><p>已知第一步我们会得到一些以 <code>.sra</code> 结尾的文件,而完成 ② 后我们会得到所有样本的 <code>quant.sf</code> 文件,这些将决定我们如何<strong>定义 Snakemake 的输出目标</strong>。</p><p>因此我们先创建一个包含我们定量所用 sra id 及其对应的样本名的文件,命名为 <code>group.txt</code>,以下分析将以一个人类海拉细胞示例数据集为例进行: </p><figure class="highlight txt"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"># group.txt</span><br><span class="line">SRR25601734HeLa_Rep1</span><br><span class="line">SRR25601735HeLa_Rep1</span><br><span class="line">SRR25601736HeLa_Rep2</span><br><span class="line">SRR25601737HeLa_Rep2</span><br></pre></td></tr></tbody></table></figure><p>假设每个 sra 文件我们打算放置于 <code>rawfastq/[srrid]</code> 中,样本的定量结果我们打算放置于 <code>results/[sample]</code> 中,那我们预期得到的文件应该有:</p><figure class="highlight txt"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">rawfastq/SRR25601734/SRR25601734.sra</span><br><span class="line">rawfastq/SRR25601735/SRR25601735.sra</span><br><span class="line">rawfastq/SRR25601736/SRR25601736.sra</span><br><span class="line">rawfastq/SRR25601737/SRR25601737.sra</span><br><span class="line">results/HeLa_Rep1/quant.sf</span><br><span class="line">results/HeLa_Rep2/quant.sf</span><br></pre></td></tr></tbody></table></figure><p>首先,我们需要一个方法指定 <code>group.txt</code> 能让 Snakemake 识别,请在 <code>config/config.yaml</code> 文件中添加以下内容:</p><figure class="highlight yaml"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="attr">inputfile:</span></span><br><span class="line"> <span class="attr">groupfile:</span> <span class="string">"group.txt"</span></span><br></pre></td></tr></tbody></table></figure><p>这是一个 yaml 数据格式的文件,我们将在 Snakefile 中读取它并确定相关参数。在<strong>之后每次 Pipeline 的复用中一般只需要调整该文件</strong>。</p><p>现在,请打开之前新建的 <code>Snakefile</code> 文件,输入以下内容:</p><figure class="highlight python"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line">configfile: <span class="string">"config/config.yaml"</span></span><br><span class="line"></span><br><span class="line">srrlist = <span class="built_in">set</span>([line.strip().split()[<span class="number">0</span>] <span class="keyword">for</span> line <span class="keyword">in</span> <span class="built_in">open</span>(config[<span class="string">"inputfile"</span>][<span class="string">"groupfile"</span>], <span class="string">'r'</span>)])</span><br><span class="line">samples = <span class="built_in">set</span>([line.strip().split()[<span class="number">1</span>] <span class="keyword">for</span> line <span class="keyword">in</span> <span class="built_in">open</span>(config[<span class="string">"inputfile"</span>][<span class="string">"groupfile"</span>], <span class="string">'r'</span>)])</span><br><span class="line"></span><br><span class="line">rule <span class="built_in">all</span>:</span><br><span class="line"> <span class="built_in">input</span>:</span><br><span class="line"> expand(<span class="string">"rawfastq/{srr}/{srr}.sra"</span>, srr=srrlist) + </span><br><span class="line"> expand(<span class="string">"results/{sample}/quant.sf"</span>, sample=samples)</span><br></pre></td></tr></tbody></table></figure><p>逐段解释:</p><ol><li><p>首先我们通过 <code>configfile</code> <strong>指定配置文件</strong>,该命令行会将 <code>config/config.yaml</code> 读取为字典并赋予给 <code>config</code> 变量。</p></li><li><p>此后我们通过 Python 语法读取了先前在 config.yaml 中指定的 <code>group.txt</code>,并分别将 SRR id 和 Sample 的集合传入给了 <code>srrlist</code> 和 <code>samples</code> 两个变量。</p></li><li><p>通过 <code>rule all</code> 语句,<strong>确定 Snakemake 最终检查的文件(用于判断该 workflow 是否运行完成)</strong>,其中:</p><ul><li><p><code>expand</code> 为 Snakemake 的特殊语法,本质是遍历并得到一个新列表,即 <code>expand("{x}", x=xlist)</code> 功能上等价于 <code>[f"{x}" for x in xlist]</code>。</p></li><li><p>此处使用 <code>srrlist</code> 和 <code>samples</code> 通过 <code>expand</code> 语法将先前预期得到的文件列表传递给了 Snakemake,以使其监控工作流的运行结果。</p></li></ul></li></ol><p>这里需要注意的是,虽然我们最终的目的仅是得到每个样本的 <code>quant.sf</code>,但是由于后续 Snakemake 的运行中,其是<strong>通过 <code>rule all</code> 中的 <code>input</code> 为不同 rule 的 input 分配通配符的</strong>,因此<strong>如果不在 input 中给定 srr 文件相关的信息,它无法判断后续我们每个 rule 运行的意图</strong>,具体可见后文介绍。</p><h4 id="2、工作流框架实现"><a href="#2、工作流框架实现" class="headerlink" title="2、工作流框架实现"></a>2、工作流框架实现</h4><p>到这里,我们已经为工作流指定了最终的目标文件,现在我们可以开始搭建得到这一系列文件所需要的框架,接下来的步骤将主要在 <code>rule</code> 文件夹下进行,并涉及到一些 <code>config.yaml</code> 中参数的补充。</p><p>由于我们想要开发的 Pipeline <strong>能够根据单端和双端数据进行调整</strong>,因此我们现在 <code>config.yaml</code> 文件中添加一个新的参数:</p><figure class="highlight yaml"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="attr">mode:</span> <span class="string">"paired"</span></span><br></pre></td></tr></tbody></table></figure><p>该 mode 参数也可改为 single,后续我们框架中每个 rule 的行为将根据该 mode 的指定发生变化。</p><figure class="highlight shell"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">cd $tutorial_path/rules</span><br><span class="line">touch common.smk # 该文件将用于编写 Python 函数以拓展后续 rule 的动态性</span><br></pre></td></tr></tbody></table></figure><p>根据先前拟定的 Pipeline 流程,我们首先创建一个下载规则文件:</p><figure class="highlight shell"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">touch 01_prefetch.smk</span><br></pre></td></tr></tbody></table></figure><p>下载部分中我们可能需要调整的参数:</p><ol><li>可以同时并行的下载任务数量。该点将通过运行 Snakemake 时指定 <code>--resources</code> 实现。</li><li>下载如果失败(因为网络原因)重试的次数。该点将通过在 <code>config.yaml</code> 中添加参数实现。</li></ol><p><code>config.yaml</code> 新添参数以让下载失败时重新运行,最多运行三次:</p><figure class="highlight yaml"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="attr">download:</span></span><br><span class="line"> <span class="attr">retry:</span> <span class="number">3</span></span><br></pre></td></tr></tbody></table></figure><p><code>01_prefetch.smk</code> 内容:</p><figure class="highlight python"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br></pre></td><td class="code"><pre><span class="line">rule download:</span><br><span class="line"> output:</span><br><span class="line"> srafile = <span class="string">"rawfastq/{srr}/{srr}.sra"</span></span><br><span class="line"> log:</span><br><span class="line"> <span class="string">"logs/{srr}_download_prefetch.log"</span></span><br><span class="line"> params:</span><br><span class="line"> srrid = <span class="string">"{srr}"</span></span><br><span class="line"> threads: <span class="number">1</span></span><br><span class="line"> retries: config[<span class="string">"download"</span>][<span class="string">"retry"</span>]</span><br><span class="line"> resources:</span><br><span class="line"> download_slots = <span class="number">1</span> </span><br><span class="line"> shell:</span><br><span class="line"> <span class="string">"""</span></span><br><span class="line"><span class="string"> if [ -e {output.srafile}.lock ]; then</span></span><br><span class="line"><span class="string"> rm {output.srafile}.lock</span></span><br><span class="line"><span class="string"> echo "{output.srafile} lock found but no output file! Deleting..." >> {log}</span></span><br><span class="line"><span class="string"> fi</span></span><br><span class="line"><span class="string"></span></span><br><span class="line"><span class="string"> prefetch --max-size 100000000 --progress --output-directory rawfastq {params.srrid} > {log} 2>&1</span></span><br><span class="line"><span class="string"> if [ -e {output.srafile} ]; then</span></span><br><span class="line"><span class="string"> echo "{output.srafile} download finished!" >> {log}</span></span><br><span class="line"><span class="string"> else</span></span><br><span class="line"><span class="string"> mv {output.srafile}* {output.srafile}</span></span><br><span class="line"><span class="string"> echo "{output.srafile} not find! May end with .sralite. Renaming..." >> {log}</span></span><br><span class="line"><span class="string"> fi</span></span><br><span class="line"><span class="string"> """</span></span><br></pre></td></tr></tbody></table></figure><p>逐段解释:</p><ol><li><code>output</code> 段用于<strong>定义该 rule 用于产生什么文件</strong>,Snakemake 会自行创建相应目录(如果不存在)。运行完该 rule 后 Snakemake 会检查是否有产生 <code>output</code> 中指定的输出文件,<strong>如果没有则判断其运行失败</strong>。上例中该段指定了一个输出文件 <code>srafile</code>,其中通配符 <code>{srr}</code> 的识别方式可见下文。</li><li><code>log</code> 段用于<strong>定义该 rule 的日志文件</strong>,可以在相应命令行中将屏幕输出记录在该文件中。<code>params</code> 段用于<strong>定义该 rule 使用的参数</strong>。<code>threads</code> 段用于<strong>定义该 rule 使用的线程数(核数)</strong>。</li><li><code>retries</code> 段用于<strong>定义该 rule 失败后重新运行的次数</strong>,如果不指定则该 rule 失败后即会停止 Pipeline 的运行(正在进行的任务不会中断)。可以在 snakemake 运行时通过 <code>--keep-going</code> 使工作流继续运行其他独立的任务。</li><li><code>resources</code> 段用于<strong>定义该 rule 所占用的资源</strong>,可以在 snakemake 运行时通过 <code>--resources</code> 指定资源总量。以该 rule 为例,每个下载任务在 rule 中指定会占用 1 个下载槽(download_slots),因此可以通过 <code>--resources download_slots=4</code> 分配四个下载槽,使下载任务最多同时进行四个。</li><li><code>shell</code> 段用于<strong>定义该 rule 执行的 shell 命令行</strong>,内容解释如下:<ul><li><code>{output.srafile}</code> 将替换为 output 段的 srafile 字段。首先,让其检查是否存在 <code>.lock</code> 文件(<code>prefetch</code> 在下载过程中会产生的文件,如果不移除则无法重续下载),这一步是<strong>为失败以后重试而准备的</strong>。此后通过 <code>prefetch</code> 下载,将日志输出到 <code>{log}</code> 中。下载结束后进行检查,将后缀统一为 <code>.sra</code>(部分 sra 文件以 <code>.sralite</code> 结尾)。</li></ul></li></ol><p>对于一个 rule 而言,最少仅需要 <code>output</code> 和指令(如 <code>shell</code>、<code>script</code>、<code>run</code>)部分,其他都是可选字段(增强 rule 的功能和可管理性)。</p><p>下载结束后就是我们还需要进行处理,即将 <code>sra</code> 文件提取为 fastq 文件(使用 <code>fasterq-dump</code>),考虑到这也属于原始数据的处理,因此新的规则可以继续添加在 <code>01_prefetch.smk</code> 中,首先我们确定一些要提前确定的参数:</p><ul><li><code>fasterq-dump</code> 和 <code>pigz</code> 使用的线程数。</li></ul><figure class="highlight yaml"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># config.yaml</span></span><br><span class="line"><span class="attr">download:</span></span><br><span class="line"> <span class="attr">retry:</span> <span class="number">3</span></span><br><span class="line"> <span class="attr">extract_threads:</span> <span class="number">6</span></span><br></pre></td></tr></tbody></table></figure><p>此外,这一步中单端时仅产生一个文件,双端时产生两个文件。因此规则需要根据 <code>config</code> 中指定的 <code>mode</code> 进行行为调整:</p><figure class="highlight python"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 01_prefetch.smk</span></span><br><span class="line">rule extract:</span><br><span class="line"> <span class="built_in">input</span>:</span><br><span class="line"> srafile = <span class="string">"rawfastq/{srr}/{srr}.sra"</span></span><br><span class="line"> output:</span><br><span class="line"> fastq_files = <span class="string">"rawfastq/{srr}.fastq.gz"</span> <span class="keyword">if</span> config[<span class="string">"mode"</span>] == <span class="string">"single"</span> <span class="keyword">else</span> [<span class="string">"rawfastq/{srr}_1.fastq.gz"</span>, <span class="string">"rawfastq/{srr}_2.fastq.gz"</span>],</span><br><span class="line"> log:</span><br><span class="line"> <span class="string">"logs/{srr}_extract.log"</span></span><br><span class="line"> params:</span><br><span class="line"> srrid = <span class="string">"{srr}"</span></span><br><span class="line"> threads: config[<span class="string">"download"</span>][<span class="string">"extract_threads"</span>]</span><br><span class="line"> shell:</span><br><span class="line"> <span class="string">"""</span></span><br><span class="line"><span class="string"> fasterq-dump {input.srafile} --progress --details --split-files -v --outdir rawfastq --threads {threads} > {log} 2>&1</span></span><br><span class="line"><span class="string"> pigz -p {threads} rawfastq/{params.srrid}*.fastq</span></span><br><span class="line"><span class="string"></span></span><br><span class="line"><span class="string"> if [ "{config[mode]}" == "single" ]; then</span></span><br><span class="line"><span class="string"> if [ -e rawfastq/{params.srrid}_1.fastq.gz ]; then</span></span><br><span class="line"><span class="string"> mv rawfastq/{params.srrid}_1.fastq.gz {output.fastq_files}</span></span><br><span class="line"><span class="string"> echo "Single extract finished! (Renamed _1.fastq.gz)" >> {log}</span></span><br><span class="line"><span class="string"> else</span></span><br><span class="line"><span class="string"> echo "Single extract finished!" >> {log}</span></span><br><span class="line"><span class="string"> fi</span></span><br><span class="line"><span class="string"> else</span></span><br><span class="line"><span class="string"> if [ -e rawfastq/{params.srrid}_1.fastq.gz ] && [ -e rawfastq/{params.srrid}_2.fastq.gz ]; then</span></span><br><span class="line"><span class="string"> echo "Paired extract finished!" >> {log}</span></span><br><span class="line"><span class="string"> else</span></span><br><span class="line"><span class="string"> echo "Paired extract failed: one or both FASTQ files missing!" >> {log}</span></span><br><span class="line"><span class="string"> exit 1</span></span><br><span class="line"><span class="string"> fi</span></span><br><span class="line"><span class="string"> fi</span></span><br><span class="line"><span class="string"> """</span></span><br></pre></td></tr></tbody></table></figure><p>逐段解释:</p><ol><li><code>input</code> 段<strong>指定该 rule 需要的输入文件</strong>,snakemake 将进行监测直到这些文件出现后再开始运行该 rule。<u>这里涉及到 snakemake 中最重要的一个概念</u>:<ul><li>Snakemake <strong>将依据各个 rule 的 input 和 output 确认它们彼此之间的依赖关系,构建一个工作流的有向无环图</strong>,此后按照图的拓扑顺序运行,确保某一规则在依赖的其他规则结束后才会执行。同样也是在这个过程中,Snakemake 会自动根据目标文件向各规则的 input 和 output 中进行通配符填补(即上述的 <code>{srr}</code>)。以本文拟构建的 Pipeline 为例(<code>snakemake --dag | dot -Tpng > dag.png</code>):</li></ul></li></ol><img src="/pic2/dag.png" style="zoom:80%;"><ol start="2"><li><p><code>output</code> 段新增了根据 mode 进行的输出文件调整。</p></li><li><p><code>shell</code> 段中,首先通过 <code>fasterq-dump</code> 进行提取,并使用 <code>pigz</code> 进行压缩。此后,如果使用单端模式,则将后缀统一为 <code>[SRR id].fastq.gz</code>;如果使用双端模式,则检查是否两端数据都存在。</p></li></ol><p>到此即产生我们所需要的原始数据,将这些 rule 整合进 <code>Snakefile</code> 中(声明 <code>smk</code> 文件):</p><figure class="highlight python"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># Snakefile</span></span><br><span class="line"><span class="comment"># download and extract SRA files</span></span><br><span class="line">include: <span class="string">"rules/01_prefetch.smk"</span></span><br></pre></td></tr></tbody></table></figure><p>此后 <code>trim_galore</code> 的流程构建也遵循相同的思路(设定参数 —— 编写规则 —— 整合):</p><figure class="highlight shell"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">touch 02_trimgalore.smk</span><br></pre></td></tr></tbody></table></figure><figure class="highlight yaml"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># config.yaml</span></span><br><span class="line"><span class="attr">trim:</span></span><br><span class="line"> <span class="attr">threads:</span> <span class="number">8</span></span><br><span class="line"> <span class="attr">param:</span> <span class="string">""</span></span><br></pre></td></tr></tbody></table></figure><figure class="highlight python"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 02_trimgalore.smk</span></span><br><span class="line">rule trim_galore:</span><br><span class="line"> <span class="built_in">input</span>:</span><br><span class="line"> fastq_files = <span class="string">"rawfastq/{srr}.fastq.gz"</span> <span class="keyword">if</span> config[<span class="string">"mode"</span>] == <span class="string">"single"</span> <span class="keyword">else</span> [<span class="string">"rawfastq/{srr}_1.fastq.gz"</span>, <span class="string">"rawfastq/{srr}_2.fastq.gz"</span>]</span><br><span class="line"> output:</span><br><span class="line"> trimmed_fastq = <span class="string">"trimgalore_result/{srr}_trimmed.fq.gz"</span> <span class="keyword">if</span> config[<span class="string">"mode"</span>] == <span class="string">"single"</span> <span class="keyword">else</span> [<span class="string">"trimgalore_result/{srr}_1_val_1.fq.gz"</span>, <span class="string">"trimgalore_result/{srr}_2_val_2.fq.gz"</span>]</span><br><span class="line"> params:</span><br><span class="line"> option = config[<span class="string">"trim"</span>][<span class="string">"param"</span>]</span><br><span class="line"> log:</span><br><span class="line"> <span class="string">"logs/{srr}_trimgalore.log"</span></span><br><span class="line"> threads: config[<span class="string">"trim"</span>][<span class="string">"threads"</span>]</span><br><span class="line"> shell:</span><br><span class="line"> <span class="string">"""</span></span><br><span class="line"><span class="string"> if [ "{config[mode]}" == "single" ]; then</span></span><br><span class="line"><span class="string"> trim_galore {params.option} --cores {threads} {input.fastq_files} -o trimgalore_result/ > {log} 2>&1</span></span><br><span class="line"><span class="string"> else</span></span><br><span class="line"><span class="string"> trim_galore --paired {params.option} --cores {threads} {input.fastq_files[0]} {input.fastq_files[1]} -o trimgalore_result/ > {log} 2>&1</span></span><br><span class="line"><span class="string"> fi</span></span><br><span class="line"><span class="string"> """</span></span><br></pre></td></tr></tbody></table></figure><figure class="highlight python"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># Snakefile</span></span><br><span class="line"><span class="comment"># Trim fastq</span></span><br><span class="line">include: <span class="string">"rules/02_trimgalore.smk"</span></span><br></pre></td></tr></tbody></table></figure><p>这里将监测先前 <code>extract</code> 规则输出的文件,如果 <code>extract</code> 规则运行完成则启动,并根据单端和双端模式自动调节输入的 fastq 文件和过滤后的 fastq 文件。可以设置的参数有两个,一个是每个 <code>trim_galore</code> 使用的线程数,另一个是 <code>trim_galore</code> 的额外参数。通过<strong>设置一个可以灵活调节的参数项可以让使用者依据自身的情况进行参数设定而不至于受 Pipeline 限制</strong>,例如自行设置最短长度和接头序列等。如果不需要则留空即可。</p><p><code>salmon</code> 的构造流程大致相同,但由于这里使用的通配符将变为样本名,因此这里需要进行一定变动:</p><figure class="highlight shell"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">touch 03_salmon.smk</span><br></pre></td></tr></tbody></table></figure><figure class="highlight yaml"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># config.yaml</span></span><br><span class="line"><span class="attr">salmon:</span></span><br><span class="line"> <span class="attr">threads:</span> <span class="number">16</span></span><br><span class="line"> <span class="attr">salmon_index:</span> <span class="string">"/path/to/hg38_salmon_index"</span></span><br><span class="line"> <span class="attr">param:</span> <span class="string">"--seqBias --gcBias --dumpEq"</span></span><br></pre></td></tr></tbody></table></figure><figure class="highlight python"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 03_salmon.smk</span></span><br><span class="line">rule salmon:</span><br><span class="line"> <span class="built_in">input</span>:</span><br><span class="line"> trimmed_fastq = <span class="keyword">lambda</span> wildcards: get_fastq_list(config[<span class="string">"mode"</span>], config[<span class="string">"inputfile"</span>][<span class="string">"groupfile"</span>], wildcards.sample)</span><br><span class="line"> output:</span><br><span class="line"> count_file = <span class="string">"results/{sample}/quant.sf"</span></span><br><span class="line"> params:</span><br><span class="line"> index = config[<span class="string">"salmon"</span>][<span class="string">"salmon_index"</span>],</span><br><span class="line"> samplename = <span class="string">"{sample}"</span>,</span><br><span class="line"> option = config[<span class="string">"salmon"</span>][<span class="string">"param"</span>],</span><br><span class="line"> fastqpath = <span class="keyword">lambda</span> wildcards: get_fastq_path(config[<span class="string">"mode"</span>], config[<span class="string">"inputfile"</span>][<span class="string">"groupfile"</span>], wildcards.sample)</span><br><span class="line"> log:</span><br><span class="line"> <span class="string">"logs/{sample}_salmon.log"</span></span><br><span class="line"> threads: config[<span class="string">"salmon"</span>][<span class="string">"threads"</span>]</span><br><span class="line"> shell:</span><br><span class="line"> <span class="string">"""</span></span><br><span class="line"><span class="string"> if [ "{config[mode]}" == "single" ]; then</span></span><br><span class="line"><span class="string"> salmon quant -i {params.index} -l A -r <(zcat {params.fastqpath}) -p {threads} {params.option} -o results/{params.samplename} > {log} 2>&1</span></span><br><span class="line"><span class="string"> else</span></span><br><span class="line"><span class="string"> salmon quant -i {params.index} -l A -1 <(zcat {params.fastqpath[0]}) -2 <(zcat {params.fastqpath[1]}) -p {threads} {params.option} -o results/{params.samplename} > {log} 2>&1</span></span><br><span class="line"><span class="string"> fi</span></span><br><span class="line"><span class="string"> """</span></span><br></pre></td></tr></tbody></table></figure><figure class="highlight python"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># Snakefile</span></span><br><span class="line"><span class="comment"># Salmon quant</span></span><br><span class="line">include: <span class="string">"rules/03_salmon.smk"</span></span><br></pre></td></tr></tbody></table></figure><p>可以看到这里使用的通配符变为了 <code>{sample}</code>,并且使用了两个自行构造的函数 <code>get_fastq_list</code> 及 <code>get_fastq_path</code>,分别用于获取每个样本中所有 fastq 文件的列表和路径。这两个函数的具体实现在 <code>common.smk</code> 中进行:</p><figure class="highlight python"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> csv</span><br><span class="line"></span><br><span class="line"><span class="keyword">def</span> <span class="title function_">get_fastq_list</span>(<span class="params">mode, filepath, group</span>):</span><br><span class="line"> <span class="string">'''</span></span><br><span class="line"><span class="string"> Get fastq list for each group.</span></span><br><span class="line"><span class="string"> '''</span></span><br><span class="line"> group_fastq = {}</span><br><span class="line"> <span class="keyword">with</span> <span class="built_in">open</span>(filepath, <span class="string">'r'</span>) <span class="keyword">as</span> f:</span><br><span class="line"> <span class="keyword">for</span> line <span class="keyword">in</span> f:</span><br><span class="line"> info = line.strip().split()</span><br><span class="line"> <span class="keyword">if</span> info[<span class="number">1</span>] <span class="keyword">not</span> <span class="keyword">in</span> group_fastq:</span><br><span class="line"> group_fastq[info[<span class="number">1</span>]] = [info[<span class="number">0</span>]]</span><br><span class="line"> <span class="keyword">else</span>:</span><br><span class="line"> group_fastq[info[<span class="number">1</span>]].append(info[<span class="number">0</span>])</span><br><span class="line"> </span><br><span class="line"> <span class="keyword">if</span> mode == <span class="string">"single"</span>:</span><br><span class="line"> fastq_path_list = [<span class="string">f'trimgalore_result/<span class="subst">{i}</span>_trimmed.fq.gz'</span> <span class="keyword">for</span> i <span class="keyword">in</span> group_fastq[group]]</span><br><span class="line"> <span class="keyword">return</span> fastq_path_list</span><br><span class="line"> <span class="keyword">elif</span> mode == <span class="string">"paired"</span>:</span><br><span class="line"> fastq_path_list1 = [<span class="string">f'trimgalore_result/<span class="subst">{i}</span>_1_val_1.fq.gz'</span> <span class="keyword">for</span> i <span class="keyword">in</span> group_fastq[group]]</span><br><span class="line"> fastq_path_list2 = [<span class="string">f'trimgalore_result/<span class="subst">{i}</span>_2_val_2.fq.gz'</span> <span class="keyword">for</span> i <span class="keyword">in</span> group_fastq[group]]</span><br><span class="line"> fastq_path_list = fastq_path_list1 + fastq_path_list2</span><br><span class="line"> <span class="keyword">return</span> fastq_path_list</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="keyword">def</span> <span class="title function_">get_fastq_path</span>(<span class="params">mode, filepath, group</span>):</span><br><span class="line"> <span class="string">'''</span></span><br><span class="line"><span class="string"> Get fastq path for each group.</span></span><br><span class="line"><span class="string"> '''</span></span><br><span class="line"> group_fastq = {}</span><br><span class="line"> <span class="keyword">with</span> <span class="built_in">open</span>(filepath, <span class="string">'r'</span>) <span class="keyword">as</span> f:</span><br><span class="line"> <span class="keyword">for</span> line <span class="keyword">in</span> f:</span><br><span class="line"> info = line.strip().split()</span><br><span class="line"> <span class="keyword">if</span> info[<span class="number">1</span>] <span class="keyword">not</span> <span class="keyword">in</span> group_fastq:</span><br><span class="line"> group_fastq[info[<span class="number">1</span>]] = [info[<span class="number">0</span>]]</span><br><span class="line"> <span class="keyword">else</span>:</span><br><span class="line"> group_fastq[info[<span class="number">1</span>]].append(info[<span class="number">0</span>])</span><br><span class="line"> </span><br><span class="line"> <span class="keyword">if</span> mode == <span class="string">"single"</span>:</span><br><span class="line"> fastq_path_list = [<span class="string">f'trimgalore_result/<span class="subst">{i}</span>_trimmed.fq.gz'</span> <span class="keyword">for</span> i <span class="keyword">in</span> group_fastq[group]]</span><br><span class="line"> <span class="keyword">return</span> <span class="string">' '</span>.join(fastq_path_list)</span><br><span class="line"> <span class="keyword">elif</span> mode == <span class="string">"paired"</span>:</span><br><span class="line"> fastq_path_list1 = [<span class="string">f'trimgalore_result/<span class="subst">{i}</span>_1_val_1.fq.gz'</span> <span class="keyword">for</span> i <span class="keyword">in</span> group_fastq[group]]</span><br><span class="line"> fastq_path_list2 = [<span class="string">f'trimgalore_result/<span class="subst">{i}</span>_2_val_2.fq.gz'</span> <span class="keyword">for</span> i <span class="keyword">in</span> group_fastq[group]]</span><br><span class="line"> <span class="keyword">return</span> [<span class="string">' '</span>.join(fastq_path_list1), <span class="string">' '</span>.join(fastq_path_list2)]</span><br></pre></td></tr></tbody></table></figure><p>这两个函数根据接收到的模式及 <code>group.txt</code> 内容,返回特定 sample 对应的 fastq 文件列表和路径,其中列表传输给 input 使其监视上游依赖 rule 的运行情况,而路径传输给特定参数以在 salmon 定量中对同一样本的测序数据进行合并。</p><p>这里涉及到的其他一些概念:</p><ul><li><strong>wildcards 是一个命名空间,在函数和 lambda 表达式中用于访问通配符。</strong><code>wildcards.sample</code> 只有在规则的输出、输入或其他字段中定义了 <code>{sample}</code> 占位符时才会存在。<strong>结合 lambda 和 wildcards 并通过自定义的处理函数可以获取需要动态规划的输入和输出。</strong>注意,直接在这些函数中给定 <code>{sample}</code> 是不可行的。</li><li>common.smk 同样需要在 Snakefile 中声明,此后该文件中定义的所有函数都可以被其他规则所识别。</li></ul><figure class="highlight python"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># Snakefile</span></span><br><span class="line">include: <span class="string">"rules/common.smk"</span></span><br></pre></td></tr></tbody></table></figure><p>到这里,Pipeline 的整体搭建就已完成。</p><h4 id="3、Pipeline-运行"><a href="#3、Pipeline-运行" class="headerlink" title="3、Pipeline 运行"></a>3、Pipeline 运行</h4><p>使用 snakemake 命令行运行 Pipeline:</p><figure class="highlight shell"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">cd $tutorial_path</span><br><span class="line">snakemake --core 16 --resources download_slots=4</span><br></pre></td></tr></tbody></table></figure><p>这里 <code>--core</code> 指定 snakemake 总共可以管理的 CPU 核数量,snakemake 将根据每个 rule 占用的 threads 自动分配任务,例如:</p><ul><li><p>如果一个 extract 要占用 8 个 threads,一个 salmon 要占用 4 个 threads。那么 snakemake 可能同时进行一个 extract 任务和两个 salmon 任务,<strong>确保提供的核被最大化利用(前提是这些任务的前置依赖都已经满足)</strong>。</p></li><li><p><code>--resources</code> 指定 snakemake 的其他分配资源,这些都是用户规定的。以上述命令为例,Snakemake 共有 4 个 download_slots 资源,而在需要 download_slots 资源运行的 rule 中,同时运行所需的资源总和将被限定在这个值以内。在该 Pipeline 中即最高只可同时并行四个下载任务。</p></li></ul><p>运行完成后,留意以下文件夹:</p><ul><li><code>log</code> 文件夹中包含各个环节运行时的输出日志文件。</li><li><code>rawfastq</code> 文件夹中为原始测序数据。</li><li><code>trimgalore_result </code> 文件夹中为过滤后的测序数据。</li><li><code>results</code> 文件夹中为各样本的定量结果。</li></ul><p>实测以上 Pipeline 能够正确运行,如果存在问题请前往 github repository 页面查看完整 Pipeline 并确定出错点:</p><p><a href="https://github.com/JuseTiZ/Blog-Snakemake-pipeline/tree/main/Tutorial-Pipeline">https://github.com/JuseTiZ/Blog-Snakemake-pipeline/tree/main/Tutorial-Pipeline</a></p><h2 id="拓展-Pipeline"><a href="#拓展-Pipeline" class="headerlink" title="拓展 Pipeline"></a>拓展 Pipeline</h2><p>以下内容不再详细解释 Pipeline 中如何具体实现,但原理较简单且具有一定实用性,因此这里做一些简单介绍。</p><h3 id="版本控制"><a href="#版本控制" class="headerlink" title="版本控制"></a>版本控制</h3><p>每个 rule 在运行时都可以指定一个 conda 环境,例如:</p><figure class="highlight python"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">rule download:</span><br><span class="line">......</span><br><span class="line"> conda:</span><br><span class="line"> <span class="string">"../envs/sratool.yaml"</span></span><br><span class="line"> ......</span><br></pre></td></tr></tbody></table></figure><p><strong>这里的相对路径是以 rule 所在 smk 文件开始寻找的</strong>,你可以在 <code>../envs/sratool.yaml</code> 中填写以下内容:</p><figure class="highlight yaml"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="attr">name:</span> <span class="string">sra</span></span><br><span class="line"><span class="attr">dependencies:</span></span><br><span class="line"> <span class="bullet">-</span> <span class="string">bioconda::sra-tools==3.1.0</span></span><br></pre></td></tr></tbody></table></figure><p>在运行该规则时,Snakemake 会寻找名为 sra 的环境,如果不存在则新建该环境并安装指定依赖(sra-tools)。</p><p>请注意,Snakemake 所有环境操作都是默认使用 <code>mamba</code> 进行的,如果你想使用 <code>conda</code> 进行需要在命令行中指定 <code>--conda-frontend conda</code>(不推荐)。</p><p>另外你也可以在 snakefile 中指定运行这套 pipeline 所需的最低版本,例如:</p><figure class="highlight python"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">from</span> snakemake.utils <span class="keyword">import</span> min_version</span><br><span class="line">min_version(<span class="string">"6.0"</span>)</span><br></pre></td></tr></tbody></table></figure><h3 id="性能监测"><a href="#性能监测" class="headerlink" title="性能监测"></a>性能监测</h3><p>每个 rule 在运行时都可以指定一个 benchmark 文件,例如:</p><figure class="highlight python"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">rule download:</span><br><span class="line">......</span><br><span class="line"> benchmark:</span><br><span class="line"> <span class="string">"logs/{srr}_download_prefetch.benchmark.txt"</span>,</span><br><span class="line"> ......</span><br></pre></td></tr></tbody></table></figure><p>Snakemake 会自动测量并记录该 rule 的执行时间、CPU 使用率、内存使用情况等信息并储存到 benchmark 文件中。<strong>这对于需要优化工作流和分析性能瓶颈的情况非常有用</strong>。</p><h2 id="再次改进的可能"><a href="#再次改进的可能" class="headerlink" title="再次改进的可能"></a>再次改进的可能</h2><p>不难看出,上述 Pipeline 依然存在很多可以改进的地方以增强 Pipeline 的可读性和可拓展性,但要做到这些可能会在一定程度上提升理解难度,因此如果你认为上述内容不算困难且想要进一步检验自己当前的能力,可以考虑对该 Pipeline 做以下改进:</p><ol><li>将 <code>group.txt</code> 换为 <code>sample.yaml</code>,在 <code>Snakefile</code> 中提取到 <code>config</code> 变量里,据此进行 rule all input 的指定(可通过动态函数进行),并在 salmon 规则中的 input 和 output 里使用更具效率的函数进行动态规划,<code>sample.yaml</code> 示例:</li></ol><figure class="highlight yaml"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="attr">samples:</span></span><br><span class="line"> <span class="attr">HeLa_Rep1:</span></span><br><span class="line"> <span class="attr">SRR:</span> <span class="string">"SRR25601734|SRR25601735"</span></span><br><span class="line"> <span class="attr">HeLa_Rep2:</span></span><br><span class="line"> <span class="attr">SRR:</span> <span class="string">"SRR25601736|SRR25601737"</span></span><br></pre></td></tr></tbody></table></figure><ol start="2"><li>将涉及单端双端判断的 rule 拆分成两个 rule(一个用于 single-end,一个用于 paired-end),并将 <code>mode</code> 参数从 <code>config.yaml</code> 中移除,使 Pipeline 能够同时处理单端和双端的数据。例如可以通过在上面提到的 <code>sample.yaml</code> 中添加每个样本的数据类型来进行单双端数据的混合处理:</li></ol><figure class="highlight yaml"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="attr">samples:</span></span><br><span class="line"> <span class="attr">HeLa_Rep1:</span></span><br><span class="line"> <span class="attr">SRR:</span> <span class="string">"SRR25601734|SRR25601735"</span></span><br><span class="line"> <span class="attr">type:</span> <span class="string">"paired"</span></span><br><span class="line"> <span class="attr">xxxx:</span></span><br><span class="line"> <span class="attr">SRR:</span> <span class="string">"SRRxxx"</span></span><br><span class="line"> <span class="attr">type:</span> <span class="string">"single"</span></span><br></pre></td></tr></tbody></table></figure><ol start="3"><li>添加下游分析部分,例如新建 <code>scripts</code> 文件夹存放自定义的用于提取表达矩阵的脚本,并在 Pipeline 中添加新的规则以对其进行实现(别忘了 rule all 的 input 部分也要进行对应更新)。</li></ol><p>前两者的具体实现可参考 repository 下的 <a href="https://github.com/JuseTiZ/Blog-Snakemake-pipeline/tree/main/ChIP-Pipeline">ChIP Pipeline</a>。</p></body></html>]]></content>
<summary type="html">本文为使用 Snakemake 搭建 pipeline 的详细教程,其中包括一个合格 Pipeline 的基本要求、管理方式及具体搭建步骤。也涉及到版本控制和性能监测等方面的内容。</summary>
<category term="学习" scheme="https://biojuse.com/categories/%E5%AD%A6%E4%B9%A0/"/>
<category term="生信" scheme="https://biojuse.com/categories/%E5%AD%A6%E4%B9%A0/%E7%94%9F%E4%BF%A1/"/>
<category term="生物信息学" scheme="https://biojuse.com/tags/%E7%94%9F%E7%89%A9%E4%BF%A1%E6%81%AF%E5%AD%A6/"/>
<category term="生信" scheme="https://biojuse.com/tags/%E7%94%9F%E4%BF%A1/"/>
</entry>
<entry>
<title>对 bedgraph 文件进行 lowess 平滑操作</title>
<link href="https://biojuse.com/2024/06/29/%E5%AF%B9%20bedgraph%20%E6%96%87%E4%BB%B6%E8%BF%9B%E8%A1%8C%20lowess%20%E5%B9%B3%E6%BB%91%E6%93%8D%E4%BD%9C/"/>
<id>https://biojuse.com/2024/06/29/%E5%AF%B9%20bedgraph%20%E6%96%87%E4%BB%B6%E8%BF%9B%E8%A1%8C%20lowess%20%E5%B9%B3%E6%BB%91%E6%93%8D%E4%BD%9C/</id>
<published>2024-06-29T03:30:00.000Z</published>
<updated>2024-06-29T03:35:25.317Z</updated>
<content type="html"><![CDATA[<html><head></head><body><p>在进行一些特定的功能基因组学数据分析时,我们可能需要对 bedgraph 文件中每个 bin 的值进行一定的平滑操作,以降低随机噪声的影响并提供更好的可视化效果。例如:</p><ul><li>Repli-seq / BrdU-seq 中量化得到的 Replication Timing</li><li>OK-seq / Pu-seq 中量化得到的 Replication Fork Directionality</li></ul><p>以下是一个用于对 bedgraph 进行 lowess 平滑操作的 python script:</p><figure class="highlight python"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> pandas <span class="keyword">as</span> pd</span><br><span class="line"><span class="keyword">import</span> statsmodels.api <span class="keyword">as</span> sm</span><br><span class="line"><span class="keyword">import</span> argparse</span><br><span class="line"></span><br><span class="line"><span class="keyword">def</span> <span class="title function_">get_args</span>():</span><br><span class="line"></span><br><span class="line"> parser = argparse.ArgumentParser(description=<span class="string">'Perform lowess smooth on bedgraph.'</span>)</span><br><span class="line"> </span><br><span class="line"> parser.add_argument(<span class="string">'--input'</span>, <span class="string">'-i'</span>, <span class="built_in">help</span>=<span class="string">'Input bedgraph file.'</span>, required=<span class="literal">True</span>)</span><br><span class="line"> parser.add_argument(<span class="string">'--output'</span>, <span class="string">'-o'</span>, <span class="built_in">help</span>=<span class="string">'Output smoothed bedgraph file.'</span>, required=<span class="literal">True</span>)</span><br><span class="line"> parser.add_argument(<span class="string">'--span'</span>, <span class="built_in">help</span>=<span class="string">'Span size of loess smoothing.'</span>, <span class="built_in">type</span>=<span class="built_in">int</span>, required=<span class="literal">True</span>)</span><br><span class="line"> parser.add_argument(<span class="string">"--chr"</span>, required=<span class="literal">True</span>,</span><br><span class="line"> <span class="built_in">help</span>=<span class="string">"The chrom to input. e.g. 1-22,X,Y"</span>)</span><br><span class="line"> </span><br><span class="line"> args = parser.parse_args()</span><br><span class="line"></span><br><span class="line"> <span class="keyword">return</span> args</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="keyword">def</span> <span class="title function_">parse_range</span>(<span class="params">value</span>):</span><br><span class="line"> result = []</span><br><span class="line"> <span class="keyword">for</span> part <span class="keyword">in</span> value.split(<span class="string">','</span>):</span><br><span class="line"> <span class="keyword">if</span> <span class="string">'-'</span> <span class="keyword">in</span> part:</span><br><span class="line"> start, end = part.split(<span class="string">'-'</span>)</span><br><span class="line"> result.extend(<span class="built_in">range</span>(<span class="built_in">int</span>(start), <span class="built_in">int</span>(end) + <span class="number">1</span>))</span><br><span class="line"> <span class="keyword">else</span>:</span><br><span class="line"> result.append(<span class="built_in">int</span>(part))</span><br><span class="line"> <span class="keyword">return</span> result</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="keyword">def</span> <span class="title function_">main</span>():</span><br><span class="line"></span><br><span class="line"> args = get_args()</span><br><span class="line"></span><br><span class="line"> data = pd.read_csv(args.<span class="built_in">input</span>, sep=<span class="string">'\t'</span>, header=<span class="literal">None</span>, names=[<span class="string">'chrom'</span>, <span class="string">'start'</span>, <span class="string">'end'</span>, <span class="string">'value'</span>])</span><br><span class="line"> data[<span class="string">'midpoint'</span>] = (data[<span class="string">'start'</span>] + data[<span class="string">'end'</span>]) / <span class="number">2</span></span><br><span class="line"></span><br><span class="line"> span_size = args.span</span><br><span class="line"> smoothed_data = []</span><br><span class="line"> chr_list = [<span class="string">f'chr<span class="subst">{i}</span>'</span> <span class="keyword">for</span> i <span class="keyword">in</span> parse_range(args.<span class="built_in">chr</span>)]</span><br><span class="line"></span><br><span class="line"> <span class="keyword">for</span> chrom <span class="keyword">in</span> data[<span class="string">'chrom'</span>].unique():</span><br><span class="line"> chrom_data = data[data[<span class="string">'chrom'</span>] == chrom]</span><br><span class="line"> <span class="keyword">if</span> chrom <span class="keyword">not</span> <span class="keyword">in</span> chr_list:</span><br><span class="line"> <span class="keyword">continue</span></span><br><span class="line"></span><br><span class="line"> chrom_length = chrom_data[<span class="string">'end'</span>].iloc[-<span class="number">1</span>] - chrom_data[<span class="string">'start'</span>].iloc[<span class="number">0</span>]</span><br><span class="line"> span_frac = span_size / chrom_length</span><br><span class="line"></span><br><span class="line"> lowess = sm.nonparametric.lowess(chrom_data[<span class="string">'value'</span>], chrom_data[<span class="string">'midpoint'</span>], frac=span_frac)</span><br><span class="line"> smoothed_df = pd.DataFrame(lowess, columns=[<span class="string">'midpoint'</span>, <span class="string">'smoothed_value'</span>])</span><br><span class="line"> chrom_data = chrom_data.reset_index(drop=<span class="literal">True</span>)</span><br><span class="line"> chrom_data[<span class="string">'smoothed_value'</span>] = smoothed_df[<span class="string">'smoothed_value'</span>]</span><br><span class="line"> smoothed_data.append(chrom_data)</span><br><span class="line"></span><br><span class="line"> smoothed_data = pd.concat(smoothed_data)</span><br><span class="line"> smoothed_data[[<span class="string">'chrom'</span>, <span class="string">'start'</span>, <span class="string">'end'</span>, <span class="string">'smoothed_value'</span>]].to_csv(args.output, sep=<span class="string">'\t'</span>, header=<span class="literal">False</span>, index=<span class="literal">False</span>)</span><br><span class="line"></span><br><span class="line"><span class="keyword">if</span> __name__ == <span class="string">'__main__'</span>:</span><br><span class="line"> main()</span><br></pre></td></tr></tbody></table></figure><p><strong>下载地址:</strong></p><p><a href="https://github.com/JuseTiZ/PyScript-for-CT/blob/main/bedgraph_lowess.py">https://github.com/JuseTiZ/PyScript-for-CT/blob/main/bedgraph_lowess.py</a></p><p><strong>依赖 module 安装:</strong></p><figure class="highlight shell"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">pip install pandas</span><br><span class="line">pip install statsmodels</span><br></pre></td></tr></tbody></table></figure><p><strong>参数详情:</strong></p><ul><li><code>--input</code> / <code>-i</code>,指定需要进行 lowess 平滑操作的 bedgraph 文件,该文件应当仅具有四列,且第一列染色体编号应以 <code>chr</code> 开头。</li><li><code>--output</code> / <code>-o</code>,指定输出的平滑后 bedgraph 文件,输出的新 bedgraph 中第四列为 LOWESS smooth 后的值。</li><li><code>--span</code>,指定平滑操作时使用的长度,脚本将根据每条染色体的总长确定用于平滑的数据比例。</li><li><code>--chr</code>,指定进行平滑操作的染色体编号,可使用 <code>-</code> 指定数字范围,也可使用逗号分隔,例如 <code>1-22,X,Y</code>。</li></ul><p><strong>应用示例:</strong></p><p>假设目前有一个通过 Repli-seq 计算得到的小鼠 RT(Replication Timing) bedgraph 文件 <code>RT.bedgraph</code>,通过以下命令进行 30w bp 的平滑:</p><figure class="highlight shell"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">python bedgraph_lowess.py -i RT.bedgraph -o RT.lowess.bedgraph --span 300000 --chr 1-19</span><br></pre></td></tr></tbody></table></figure><p>平滑前后 IGV track 示例:</p><p><img src="/pic2/bedgraphlowess.png"></p><p>请注意,平滑操作<strong>在减少噪音的同时,也损失了部分信息量</strong>,因此请根据自己当前使用的数据进行权衡,合理设置 <code>--span</code> 参数,一般情况下:</p><ul><li>数据的分辨率越高,该参数指定的值应当越低。反之亦然。</li><li>对信息精细程度的要求越高,该参数指定的值应当越低。反之亦然。</li></ul><p>例如对于某些 OK-seq 数据而言只需要 60kb 左右的 span size 即可。请根据研究需求或者数据来源文章指定恰当的值。</p></body></html>]]></content>
<summary type="html">在某些特别的 seq 数据处理中,我们可能要对得到的 bedgraph 文件进行平滑以消除噪音影响。本文介绍了一种基于 python 的平滑实现方法。</summary>
<category term="学习" scheme="https://biojuse.com/categories/%E5%AD%A6%E4%B9%A0/"/>
<category term="杂项" scheme="https://biojuse.com/categories/%E5%AD%A6%E4%B9%A0/%E6%9D%82%E9%A1%B9/"/>
</entry>
<entry>
<title>获取基因组上 intron 区域及对应链信息的方法</title>
<link href="https://biojuse.com/2024/06/09/%E8%8E%B7%E5%8F%96%E5%9F%BA%E5%9B%A0%E7%BB%84%E4%B8%8A%20intron%20%E5%8C%BA%E5%9F%9F%E5%8F%8A%E5%AF%B9%E5%BA%94%E9%93%BE%E4%BF%A1%E6%81%AF%E7%9A%84%E6%96%B9%E6%B3%95/"/>
<id>https://biojuse.com/2024/06/09/%E8%8E%B7%E5%8F%96%E5%9F%BA%E5%9B%A0%E7%BB%84%E4%B8%8A%20intron%20%E5%8C%BA%E5%9F%9F%E5%8F%8A%E5%AF%B9%E5%BA%94%E9%93%BE%E4%BF%A1%E6%81%AF%E7%9A%84%E6%96%B9%E6%B3%95/</id>
<published>2024-06-09T12:30:00.000Z</published>
<updated>2024-06-09T12:46:13.128Z</updated>
<content type="html"><![CDATA[<html><head></head><body><h2 id="流程"><a href="#流程" class="headerlink" title="流程"></a>流程</h2><p>前置条件:</p><ul><li>在环境变量中可调用的 <code>bedtools</code></li></ul><p>本文参考:</p><blockquote><p><strong>Get intronic and intergenic sequences based on gff file</strong> from Biostars</p><p><a href="https://www.biostars.org/p/112251/">https://www.biostars.org/p/112251/</a></p></blockquote><p>本文可满足的需求:</p><ul><li>得到特定区域的 bed 文件(例如 exon / intron 等)。</li><li>在得到区域信息的同时进行链信息的区分。</li></ul><h3 id="下载基因组注释文件(gtf)"><a href="#下载基因组注释文件(gtf)" class="headerlink" title="下载基因组注释文件(gtf)"></a>下载基因组注释文件(gtf)</h3><p>以人类最新版本的 gencode 注释为例:</p><figure class="highlight shell"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">wget https://ftp.ebi.ac.uk/pub/databases/gencode/Gencode_human/release_46/gencode.v46.basic.annotation.gtf.gz</span><br></pre></td></tr></tbody></table></figure><p>也可以选择已有的 gtf 文件进行。</p><h3 id="得到-transcript-和-exon-区域信息"><a href="#得到-transcript-和-exon-区域信息" class="headerlink" title="得到 transcript 和 exon 区域信息"></a>得到 transcript 和 exon 区域信息</h3><figure class="highlight shell"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line">GTF="/path/to/gencode.v46.basic.annotation.gtf.gz" # 改为自己实际的注释文件路径,建议使用压缩格式以兼容以下命令</span><br><span class="line">BASENAME=$(basename "$GTF" .gtf.gz)</span><br><span class="line"></span><br><span class="line">TRANSCRIPT_BED="${BASENAME}.transcript.bed"</span><br><span class="line">FORWARD_TRANS_BED="${BASENAME}.transcript.fors.bed"</span><br><span class="line">BACKWARD_TRANS_BED="${BASENAME}.transcript.bacs.bed"</span><br><span class="line">DOUBLE_TRANS_BED="${BASENAME}.transcript.doubletrans.bed"</span><br><span class="line">EXON_BED="${BASENAME}.exon.bed"</span><br><span class="line">INTRON_BED="${BASENAME}.intron.bed"</span><br><span class="line">CDS_BED="${BASENAME}.cds.bed"</span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">得到 transcript 区域</span></span><br><span class="line">awk '$3=="transcript" {print $1, $4-1, $5, $7}' OFS='\t' <(zcat $GTF) > $TRANSCRIPT_BED</span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">得到 exon 区域</span></span><br><span class="line">awk '$3=="exon" {print $1, $4-1, $5, $7}' OFS='\t' <(zcat $GTF) > $EXON_BED</span><br></pre></td></tr></tbody></table></figure><p>以上命令将得到 <code>.transcript.bed</code> 和 <code>.exon.bed</code> 结尾的文件,里面包含基因组上所有 transcript 和 exon 的信息。</p><h3 id="不关注链信息时"><a href="#不关注链信息时" class="headerlink" title="不关注链信息时"></a>不关注链信息时</h3><figure class="highlight shell"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta prompt_"># </span><span class="language-bash">合并排序 transcript 区域</span></span><br><span class="line">bedtools sort -i $TRANSCRIPT_BED | bedtools merge -i - > $TRANSCRIPT_BED.tmp </span><br><span class="line">mv $TRANSCRIPT_BED.tmp $TRANSCRIPT_BED</span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">合并排序 exon 区域</span></span><br><span class="line">bedtools sort -i $EXON_BED | bedtools merge -i - > $EXON_BED.tmp </span><br><span class="line">mv $EXON_BED.tmp $EXON_BED</span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">在 transcript 中排除 exon 得到 intron</span></span><br><span class="line">bedtools subtract -a $TRANSCRIPT_BED -b $EXON_BED > $INTRON_BED</span><br></pre></td></tr></tbody></table></figure><h3 id="关注链信息时"><a href="#关注链信息时" class="headerlink" title="关注链信息时"></a>关注链信息时</h3><figure class="highlight shell"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta prompt_"># </span><span class="language-bash">得到正负链信息</span></span><br><span class="line">awk '$4=="+"' $TRANSCRIPT_BED | bedtools sort -i - | bedtools merge -i - | awk 'OFS="\t"{print $0, "+"}' > $FORWARD_TRANS_BED</span><br><span class="line">awk '$4=="-"' $TRANSCRIPT_BED | bedtools sort -i - | bedtools merge -i - | awk 'OFS="\t"{print $0, "-"}' > $BACKWARD_TRANS_BED</span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">找出冲突区域(正负链上都存在 transcript)</span></span><br><span class="line">bedtools intersect -a $FORWARD_TRANS_BED -b $BACKWARD_TRANS_BED > $DOUBLE_TRANS_BED</span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">排除 transcript 冲突区域</span></span><br><span class="line">bedtools subtract -a <(cat $FORWARD_TRANS_BED $BACKWARD_TRANS_BED | bedtools sort -i -) -b $DOUBLE_TRANS_BED > $TRANSCRIPT_BED</span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">排除 exon 冲突区域</span></span><br><span class="line">awk '$3=="exon" {print $1, $4-1, $5, $7}' OFS='\t' <(zcat $GTF) | bedtools sort -i - | bedtools merge -i - > $EXON_BED</span><br><span class="line">bedtools intersect -a $TRANSCRIPT_BED -b $EXON_BED > $EXON_BED.tmp</span><br><span class="line">mv $EXON_BED.tmp $EXON_BED</span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">得到包含链信息的 intron</span></span><br><span class="line">bedtools subtract -a $TRANSCRIPT_BED -b $EXON_BED > $INTRON_BED</span><br></pre></td></tr></tbody></table></figure><h3 id="相关的用途"><a href="#相关的用途" class="headerlink" title="相关的用途"></a>相关的用途</h3><p>通过上述命令,同理也可以获得例如 CDS 或 UTR 的 bed 文件。下游分析中,我们可以通过这些 bed 文件筛选在特定区域中的突变进行相关探索:</p><figure class="highlight shell"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">bedtools intersect -a input.vcf -b CDS.bed > input.cds.vcf</span><br></pre></td></tr></tbody></table></figure><p>将 <code>input.vcf</code> 和 <code>CDS.bed</code> 请换为实际路径即可得到所有在 CDS 区域中的 variants。</p></body></html>]]></content>
<summary type="html">通过基因组注释文件得到基因组 intron 区域的 bed 文件,同时标注链信息。</summary>
<category term="学习" scheme="https://biojuse.com/categories/%E5%AD%A6%E4%B9%A0/"/>
<category term="生信" scheme="https://biojuse.com/categories/%E5%AD%A6%E4%B9%A0/%E7%94%9F%E4%BF%A1/"/>
<category term="生物信息学" scheme="https://biojuse.com/tags/%E7%94%9F%E7%89%A9%E4%BF%A1%E6%81%AF%E5%AD%A6/"/>
<category term="生信" scheme="https://biojuse.com/tags/%E7%94%9F%E4%BF%A1/"/>
<category term="基因组" scheme="https://biojuse.com/tags/%E5%9F%BA%E5%9B%A0%E7%BB%84/"/>
</entry>
<entry>
<title>Ensembl VEP plugins 的使用方法(Alphamissense、dbNSFP 等)</title>
<link href="https://biojuse.com/2024/06/09/Ensembl%20VEP%20plugins%20%E7%9A%84%E4%BD%BF%E7%94%A8%E6%96%B9%E6%B3%95%EF%BC%88Alphamissense%E3%80%81dbNSFP%20%E7%AD%89%EF%BC%89/"/>
<id>https://biojuse.com/2024/06/09/Ensembl%20VEP%20plugins%20%E7%9A%84%E4%BD%BF%E7%94%A8%E6%96%B9%E6%B3%95%EF%BC%88Alphamissense%E3%80%81dbNSFP%20%E7%AD%89%EF%BC%89/</id>
<published>2024-06-09T11:30:00.000Z</published>
<updated>2024-06-10T02:58:46.759Z</updated>
<content type="html"><![CDATA[<html><head></head><body><hr><h2 id="前言"><a href="#前言" class="headerlink" title="前言"></a>前言</h2><p>以下是相关的官网链接,如果想要得到除本文内容以外更全面深入的了解,建议跳转相关链接进行查阅:</p><blockquote><p>VEP plugins documentation:</p><p><a href="https://grch37.ensembl.org/info/docs/tools/vep/script/vep_plugins.html">https://grch37.ensembl.org/info/docs/tools/vep/script/vep_plugins.html</a></p><p>VEP install documentation:</p><p><a href="https://grch37.ensembl.org/info/docs/tools/vep/script/vep_download.html">https://grch37.ensembl.org/info/docs/tools/vep/script/vep_download.html</a></p></blockquote><h2 id="正文"><a href="#正文" class="headerlink" title="正文"></a>正文</h2><h3 id="安装-VEP"><a href="#安装-VEP" class="headerlink" title="安装 VEP"></a>安装 VEP</h3><p>此处强烈建议使用 Docker 或者 Singularity 直接拉取 VEP 镜像进行分析,因为在 VEP image 中已经内置好所有的 plugin,无需自己手动下载。</p><p>考虑到 Docker 对权限的要求更高,因此这里以普适性更强的 Singularity 为例(Docker 用户有需求可通过文章开头链接前往官网进行参考):</p><figure class="highlight shell"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta prompt_"># </span><span class="language-bash">拉取 VEP image</span></span><br><span class="line">singularity pull --name vep.sif docker://ensemblorg/ensembl-vep</span><br></pre></td></tr></tbody></table></figure><p>之后就可以通过 <code>singularity</code> 运行 VEP:</p><figure class="highlight shell"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">singularity exec vep.sif vep --help</span><br></pre></td></tr></tbody></table></figure><p>直接安装的方法:</p><figure class="highlight plaintext"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">git clone https://github.com/Ensembl/ensembl-vep.git</span><br><span class="line">cd ensembl-vep</span><br><span class="line">perl INSTALL.pl</span><br></pre></td></tr></tbody></table></figure><p><code>INSTALL.pl</code> 可以通过指定一系列参数来进行自定义安装,这里介绍其中主要需要注意的几个:</p><ul><li><code>--CACHE_VERSION</code> 选择特定的 Ensembl 版本,目前最新为 112,请根据自己正在使用的注释版本确定。</li><li><code>--CACHEDIR</code> 下载数据库的存储路径,默认为 <code>$HOME/.vep</code>,可自行修改。</li><li><code>--PLUGINS</code> 指定下载的插件(plugins),通过逗号分隔。也可通过 <code>--PLUGINS all</code> 使其下载全部插件。</li></ul><p>由于 <code>INSTALL.pl</code> 需要一定的依赖项,因此遇到安装报错时可前往其 <a href="https://grch37.ensembl.org/info/docs/tools/vep/script/vep_download.html">documentation</a> 查看是否存在依赖项缺失,此外 API 和数据库版本不同时可能存在兼容问题。但目前我使用最新版本的 VEP 进行旧版本数据库的注释是不存在任何问题的。</p><h3 id="下载数据库"><a href="#下载数据库" class="headerlink" title="下载数据库"></a>下载数据库</h3><p>通过 <code>INSTALL.pl</code> 安装的另一个弊端就是可能下载速度非常慢,因此这里介绍一个自行安装数据库的方法,对于使用 <code>singularity</code> 或者已经配置好 <code>vep</code> 的情况,可以使用以下命令:</p><figure class="highlight shell"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">mkdir vep_data</span><br><span class="line">cd vep_data</span><br><span class="line">wget -c ftp://ftp.ensembl.org/pub/release-112/variation/indexed_vep_cache/homo_sapiens_vep_112_GRCh38.tar.gz</span><br><span class="line">tar zxf homo_sapiens_vep_112_GRCh38.tar.gz</span><br></pre></td></tr></tbody></table></figure><p>使用其他版本时,可将上述网址中的 <code>112</code> 替换为其他版本号例如 <code>110</code> 等。</p><p>之后在运行 <code>vep</code> 时可以通过 <code>--cache_version</code> 指定需要使用的版本号。</p><h3 id="下载-plugins-需要的文件"><a href="#下载-plugins-需要的文件" class="headerlink" title="下载 plugins 需要的文件"></a>下载 plugins 需要的文件</h3><p>这里仅介绍 AlphaMissense 和 dbNSFP 两个插件的数据库构建方法,原因如下:</p><ul><li>AlphaMissense 对于非同义突变的影响预测具有目前最先进的性能。但由于其开发团队仅提供了 GENCODE V33(对应 Ensembl V98),因此很多更新版本注释中的突变可能没法找到其对应的 AlphaMissense 参数。且其 github 上仅提供模型架构而未提供训练后的权重信息,因此无法自行预测。但其结果依然是极具参考价值的。</li><li>dbNSFP 是一个集成数据库,里面包含了众多 Variant Effect Predictor 的结果,包括但不限于 CADD、LINSIGHT、ESM1b、EVE、AlphaMissense 等各种 score,安装了该插件的效果等同于安装许多其他插件,从效率上讲极具价值。如果选择安装该数据库则可以考虑跳过 AlphaMissense,注意该数据库文件较大请注意剩余存储。</li></ul><img src="/pic2/dbNSFP.png" style="zoom:80%;"><p>一些需要注意的事项:</p><ul><li>插件下载好不代表可以直接使用,因为它需要基于对应数据库才能运行。</li><li>AlphaMissense 是 vep 112 版本新发布的插件,不清楚旧版本 API 是否与其兼容。</li><li>dbNSFP 中<strong>仅包含非同义突变的注释信息</strong>,因此其仅会对那些存在 missense_variant 的位点进行注释。如果你还需要统计同义突变或者内含子突变的 score(例如 CADD 等软件包含其他类型突变的影响),那么使用 dbNSFP 可能不是最好的选择。</li><li>dbNSFP 本身使用的注释版本可能与 VEP 具有冲突,这可能导致相关的预测结果在不同版本间存在冲突,详见 <a href="https://github.com/Ensembl/VEP_plugins/issues/626">issue#626</a>。</li><li>建议将所有数据库下载到同一目录下的不同子目录中,方便进行管理和可能需要的路径绑定。</li></ul><h4 id="AlphaMissense-安装"><a href="#AlphaMissense-安装" class="headerlink" title="AlphaMissense 安装"></a>AlphaMissense 安装</h4><p>更多细节见:<a href="https://grch37.ensembl.org/info/docs/tools/vep/script/vep_plugins.html#alphamissense">https://grch37.ensembl.org/info/docs/tools/vep/script/vep_plugins.html#alphamissense</a></p><p>请自行选择安装该数据库的路径 <code>[PATH]</code>,然后运行以下命令:</p><figure class="highlight shell"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">cd [PATH]</span><br><span class="line">gsutil -m cp \</span><br><span class="line"> "gs://dm_alphamissense/AlphaMissense_hg19.tsv.gz" \</span><br><span class="line"> "gs://dm_alphamissense/AlphaMissense_hg38.tsv.gz" \</span><br><span class="line"> .</span><br></pre></td></tr></tbody></table></figure><p>此后对数据库进行构建,以使用 hg38 版本为例:</p><figure class="highlight shell"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">tabix -s 1 -b 2 -e 2 -f -S 1 AlphaMissense_hg38.tsv.gz</span><br></pre></td></tr></tbody></table></figure><p>建立好索引后,在运行 VEP 时可以通过以下命令进行 Alphamissense score 注释:</p><figure class="highlight shell"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">singularity exec /path/to/vep.sif -i variations.vcf --plugin AlphaMissense,file=/full/path/to/AlphaMissense_hg38.tsv.gz</span><br></pre></td></tr></tbody></table></figure><p>将 <code>vep.sif</code> 和 <code>AlphaMissense_hg38.tsv.gz</code> 的路径替换为自己的路径(详细运行示例可见下文)。</p><h4 id="dbNSFP-安装"><a href="#dbNSFP-安装" class="headerlink" title="dbNSFP 安装"></a>dbNSFP 安装</h4><p>更多细节见:<a href="https://grch37.ensembl.org/info/docs/tools/vep/script/vep_plugins.html#dbnsfp">https://grch37.ensembl.org/info/docs/tools/vep/script/vep_plugins.html#dbnsfp</a></p><p>dbNSFP 每个版本分为 <code>a</code> <code>c</code> 两个类型,其中 <code>a</code> 适用于 academic use,<code>c</code> 适用于 <code>commercial use</code>。后者中不包含以下 effect score:</p><blockquote><p>Polyphen2, VEST, REVEL, ClinPred, CADD, LINSIGHT, GenoCanyon</p></blockquote><p>以下部分以 <code>a</code> 类型为例,该文章编写时 dbNSFP 的最新版本为 v4.8,若有变动请见其 <a href="https://sites.google.com/site/jpopgen/dbNSFP">documentation</a> 页面。</p><p>请自行选择安装该数据库的路径 <code>[PATH]</code>,然后运行以下命令:</p><figure class="highlight shell"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">cd [PATH]</span><br><span class="line">wget https://dbnsfp.s3.amazonaws.com/dbNSFP4.8a.zip</span><br></pre></td></tr></tbody></table></figure><p>下载后,通过以下命令进行数据库的构建:</p><figure class="highlight shell"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line">version=4.8a</span><br><span class="line">unzip dbNSFP${version}.zip</span><br><span class="line">zcat dbNSFP${version}_variant.chr1.gz | head -n1 > h</span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">For hg38</span></span><br><span class="line">zgrep -h -v ^#chr dbNSFP${version}_variant.chr* | sort -k1,1 -k2,2n - | cat h - | bgzip -c > dbNSFP${version}_grch38.gz</span><br><span class="line">tabix -s 1 -b 2 -e 2 dbNSFP${version}_grch38.gz</span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">For hg19</span></span><br><span class="line">zgrep -h -v ^#chr dbNSFP${version}_variant.chr* | awk '$8 != "." ' | sort -k8,8 -k9,9n - | cat h - | bgzip -c > dbNSFP${version}_grch37.gz</span><br><span class="line">tabix -s 8 -b 9 -e 9 dbNSFP${version}_grch37.gz</span><br></pre></td></tr></tbody></table></figure><p>通过以下命令查看 dbNSFP 可以进行哪些 score 的注释:</p><figure class="highlight shell"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">cat h | tr '\t' '\n'</span><br></pre></td></tr></tbody></table></figure><p>以上命令会打印出所有可以进行注释的列,通过在参数中指定这些列进行相应的注释,以 AlphaMissense 为例:</p><figure class="highlight shell"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta prompt_">$ </span><span class="language-bash"><span class="built_in">cat</span> h | <span class="built_in">tr</span> <span class="string">'\t'</span> <span class="string">'\n'</span> | grep AlphaMissense</span></span><br><span class="line">AlphaMissense_score</span><br><span class="line">AlphaMissense_rankscore</span><br><span class="line">AlphaMissense_pred</span><br></pre></td></tr></tbody></table></figure><p>在运行 VEP 时可以通过以下命令进行 Alphamissense score 注释:</p><figure class="highlight shell"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">singularity exec /path/to/vep.sif -i variations.vcf --plugin dbNSFP,file=/path/to/dbNSFP${version}_grch38.gz,AlphaMissense_score</span><br></pre></td></tr></tbody></table></figure><p>如果要进行其他注释,则将 <code>AlphaMissense_score</code> 替换为对应的列名(即文件 <code>h</code> 中包含的那些名称)。如果要使用所有列,则指定 <code>ALL</code> 即可。</p><p>将 <code>vep.sif</code> 和 <code>dbNSFP${version}_grch38.gz</code> 的路径替换为自己的路径。</p><h3 id="进行注释"><a href="#进行注释" class="headerlink" title="进行注释"></a>进行注释</h3><p>以下是一个 dbNSFP 注释的示例:</p><figure class="highlight shell"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">singularity exec -B /path/to/database:/path/to/database /path/to/vep.sif \</span><br><span class="line"> vep --dir /path/to/vep_data \</span><br><span class="line"> --cache --cache_version [version] --offline --format vcf --vcf --force_overwrite --assembly GRCh38 \</span><br><span class="line"> --input_file [input vcf] \</span><br><span class="line"> --output_file [output vcf] \</span><br><span class="line"> --plugin dbNSFP,/path/to/database/dbNSFP${version}_grch38.gz,AlphaMissense_score,CADD_raw,phyloP100way_vertebrate</span><br></pre></td></tr></tbody></table></figure><p>注意事项:</p><ul><li><code>-B</code>:该参数用于将目录挂载到 singularity 中,不是必选项。但是如果在运行中,各个插件文件的<u>路径指定正确却依然返回找不到文件</u>时,则需要通过 -B 将插件文件的目录挂载到 singularity 容器中进行访问。比如如果 dbNSFP 的目录在 <code>/database/dbNSFP</code> 中,则可以通过 <code>-B /database:/database</code> 将其目录挂载到容器的相同位置上,从而进行访问。</li><li>将 <code>/path/to/vep.sif</code> / <code>/path/to/vep_data</code> / <code>[input vcf]</code> / <code>[output vcf]</code> 更改为自己的实际路径。</li><li><code>[version]</code> 指定下载的注释版本,如 <code>112</code>。</li><li>dbNSFP 插件中的文件路径改为自己的实际路径。</li><li>要指定更多 dbNSFP 的列,只需要通过逗号作为分隔符添加即可。</li></ul><p>或者你仅想进行 AlphaMissense 的注释:</p><figure class="highlight shell"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">singularity exec -B /path/to/database:/path/to/database /path/to/vep.sif \</span><br><span class="line"> vep --dir /path/to/vep_data \</span><br><span class="line"> --cache --cache_version [version] --offline --format vcf --vcf --force_overwrite --assembly GRCh38 \</span><br><span class="line"> --input_file [input vcf] \</span><br><span class="line"> --output_file [output vcf] \</span><br><span class="line"> --plugin AlphaMissense,file=/path/to/database/AlphaMissense_hg38.tsv.gz</span><br></pre></td></tr></tbody></table></figure><p>请根据自己的实际需求选择 <code>hg38</code> 或 <code>hg19</code> 版本。</p><h3 id="多进程并行"><a href="#多进程并行" class="headerlink" title="多进程并行"></a>多进程并行</h3><p>不难察觉到,VEP 的运行速度是非常慢的,如果想对基因组的所有 variants 进行注释可能需要花费大量的时间,因此可以通过以下几种方法降低所需时间:</p><ol><li>仅选择特定区域的 variants,例如只取出那些落在 CDS 区域的 variants 等。</li><li>通过多进程进行并行注释。</li></ol><p>关于如何选择仅在 CDS 区域的 variants 可见博客另一篇文章,这里仅提如何实现多进程并行。</p><p>首先,假设所有 variants 都在同一个文件里,那么一个简单的方法是将其拆分为不同染色体的 variants,然后对每一条染色体的 variants 进行并行注释:</p><figure class="highlight shell"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line">vcffile="example.vcf" # 请将该处的 vcf 替换为真实的 vcf 文件名称</span><br><span class="line">outname=$(basename "$vcffile" .vcf)</span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">保存 vcf header</span></span><br><span class="line">grep '^#' "$vcffile" > header.vcf</span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">输出每条染色体的 vcf</span></span><br><span class="line">awk -v outname="$outname" 'BEGIN {OFS="\t"} !/^#/ {print > outname"."$1".vcf.tmp"}' "$vcffile"</span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">整合 header 和 vcf</span></span><br><span class="line">mkdir -p subvcf</span><br><span class="line">for i in *.vcf.tmp;</span><br><span class="line">do</span><br><span class="line"> cat header.vcf "$i" > ./subvcf/"$(basename "$i" .tmp)"</span><br><span class="line"> rm "$i"</span><br><span class="line">done</span><br></pre></td></tr></tbody></table></figure><p>拆分步骤如上所示,并行请根据实际情况决定方案,例如通过 slurm 调度系统或者 parallel 命令等实现。此处以 parallel 为例:</p><figure class="highlight shell"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">ls ./subvcf/*.vcf | parallel -j [num] \</span><br><span class="line">'singularity exec -B /path/to/database:/path/to/database /path/to/vep.sif \</span><br><span class="line"> vep --dir /path/to/vep_data \</span><br><span class="line"> --cache --cache_version [version] --offline --format vcf --vcf --force_overwrite --assembly GRCh38 \</span><br><span class="line"> --input_file {} \</span><br><span class="line"> --output_file {.}.anno.vcf \</span><br><span class="line"> --plugin AlphaMissense,file=/path/to/database/AlphaMissense_hg38.tsv.gz'</span><br></pre></td></tr></tbody></table></figure><p>请将 <code>-j</code> 后的 <code>[num]</code> 替换为希望的并行作业数,最终的注释 vcf 文件将在 <code>subvcf</code> 中以 <code>.anno.vcf</code> 结尾。</p><img src="/pic2/vep_example1.png" style="zoom:80%;"><p>以上方案依然存在两个问题:</p><p>①、不同染色体上的 variants 数量差异很大。</p><p>②、这样仅能做到最高同时并行 <code>染色体数</code> 个任务。</p><p>因此,也可以通过将文件拆分为 variants 数量相等的若干个文件进行并行,以下是一个示例:</p><figure class="highlight shell"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br></pre></td><td class="code"><pre><span class="line">vcffile="example.vcf"</span><br><span class="line">outname=$(basename "$vcffile" .vcf)</span><br><span class="line">num_splits=10 # 希望的拆分数量</span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">保存 vcf header</span></span><br><span class="line">grep '^#' "$vcffile" > header.vcf</span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">计算突变数量</span></span><br><span class="line">total_variants=$(grep -v '^#' "$vcffile" | wc -l)</span><br><span class="line">variants_per_file=$(( (total_variants + num_splits - 1) / num_splits ))</span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">输出子 vcf 文件</span></span><br><span class="line">mkdir -p subvcf</span><br><span class="line">split_count=1</span><br><span class="line">variant_count=0</span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">使用 awk 按突变数量进行拆分(By GPT4.0)</span></span><br><span class="line">awk -v header="header.vcf" -v outname="$outname" -v variants_per_file="$variants_per_file" -v split_count="$split_count" -v variant_count="$variant_count" '</span><br><span class="line">BEGIN {</span><br><span class="line"> while ((getline < header) > 0) {</span><br><span class="line"> header_lines[++header_line_count] = $0</span><br><span class="line"> }</span><br><span class="line"> close(header)</span><br><span class="line">}</span><br><span class="line">!/^#/ {</span><br><span class="line"> if (variant_count % variants_per_file == 0) {</span><br><span class="line"> if (split_count > 1) close(output_file)</span><br><span class="line"> output_file = sprintf("./subvcf/%s.split%d.vcf", outname, split_count)</span><br><span class="line"> for (i = 1; i <= header_line_count; i++) {</span><br><span class="line"> print header_lines[i] > output_file</span><br><span class="line"> }</span><br><span class="line"> split_count++</span><br><span class="line"> }</span><br><span class="line"> print >> output_file</span><br><span class="line"> variant_count++</span><br><span class="line">}</span><br><span class="line">' "$vcffile"</span><br></pre></td></tr></tbody></table></figure><p>以上命令将把文件分为拆分为 10 个子 vcf 文件,并行的方法同之前所述。如果需要拆分为更多的子文件以设置更高的并行数量,仅需调整 <code>num_splits</code> 即可。</p><img src="/pic2/vep_example2.png" style="zoom:80%;"><h3 id="注释结果解释"><a href="#注释结果解释" class="headerlink" title="注释结果解释"></a>注释结果解释</h3><p>注释后,header 中会出现相应的说明字段,以 AlphaMissence 注释为例:</p><figure class="highlight plaintext"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">##INFO=<ID=CSQ,Number=.,Type=String,Description="Consequence annotations from Ensembl VEP. Format: Allele|Consequence|IMPACT|SYMBOL|Gene|Feature_type|Feature|BIOTYPE|EXON|INTRON|HGVSc|HGVSp|cDNA_position|CDS_position|Protein_position|Amino_acids|Codons|Existing_variation|DISTANCE|STRAND|FLAGS|SYMBOL_SOURCE|HGNC_ID|am_class|am_pathogenicity"></span><br><span class="line">##am_class=The AlphaMissense thresholds are: 'Likely benign' if score < 0.34, 'Likely pathogenic' if score > 0.564, 'ambiguous' otherwise -- see doi.org/10.1126/science.adg7492 for details; column from /data/alphamissense/AlphaMissense_hg38.tsv.gz</span><br><span class="line">##am_pathogenicity=Continuous AlphaMissense score between 0 and 1 which can be interpreted as the predicted probability of the variant being pathogenic; column from /data/alphamissense/AlphaMissense_hg38.tsv.gz</span><br></pre></td></tr></tbody></table></figure><p>这里 <code>INFO</code> 中多出的 <code>CSQ</code> 为 Ensemble VEP 的注释结果,其中以 <code>|</code> 分隔所有注释信息,相应位置上对应的注释说明可见 header 说明。此外:</p><ul><li>一个 variant 可能落在多个转录本中,因此对应的 <code>CSQ</code> 会出现多条结果(以 <code>,</code> 分隔)。</li><li>也有可能该 variant 并不在某个 score 的注释区域内(例如 AlphaMissense 仅注释非同义突变),此时对应位置将为空。</li></ul><h2 id="后记"><a href="#后记" class="headerlink" title="后记"></a>后记</h2><p>之前在 <a href="https://www.nature.com/articles/s41588-023-01465-0">esm1b</a> 的文章里看到他们用的就是 dbNSFP 来评估各个 VEP method 的表现,想一想先前我还傻楞地去一个一个下载,不禁感慨世界上有很多节省时间的方式,只是需要多花些时间、多长点见识才能了解到。</p><p>也希望这篇文章能帮其他人少走点弯路。</p></body></html>]]></content>
<summary type="html">本文将介绍如何使用 VEP 的各个插件进行全面的 variant effect 注释,同时也涉及到数据下载、相关版本注意事项和多进程并行方法等。</summary>
<category term="学习" scheme="https://biojuse.com/categories/%E5%AD%A6%E4%B9%A0/"/>
<category term="生信" scheme="https://biojuse.com/categories/%E5%AD%A6%E4%B9%A0/%E7%94%9F%E4%BF%A1/"/>
<category term="生物信息学" scheme="https://biojuse.com/tags/%E7%94%9F%E7%89%A9%E4%BF%A1%E6%81%AF%E5%AD%A6/"/>
<category term="生信" scheme="https://biojuse.com/tags/%E7%94%9F%E4%BF%A1/"/>
</entry>
<entry>
<title>fasterq-dump 下载 SRA 文件时报错的解决方法(err cmn_iter)</title>
<link href="https://biojuse.com/2024/05/10/fasterq-dump%20%E4%B8%8B%E8%BD%BD%20SRA%20%E6%96%87%E4%BB%B6%E6%97%B6%E6%8A%A5%E9%94%99%E7%9A%84%E8%A7%A3%E5%86%B3%E6%96%B9%E6%B3%95%EF%BC%88err%20cmn_iter%EF%BC%89/"/>
<id>https://biojuse.com/2024/05/10/fasterq-dump%20%E4%B8%8B%E8%BD%BD%20SRA%20%E6%96%87%E4%BB%B6%E6%97%B6%E6%8A%A5%E9%94%99%E7%9A%84%E8%A7%A3%E5%86%B3%E6%96%B9%E6%B3%95%EF%BC%88err%20cmn_iter%EF%BC%89/</id>
<published>2024-05-10T03:00:00.000Z</published>
<updated>2024-06-27T07:35:12.744Z</updated>
<content type="html"><![CDATA[<html><head></head><body><h2 id="正文"><a href="#正文" class="headerlink" title="正文"></a>正文</h2><p>这几天下载 SRA,遇到的错误有:</p><ul><li><p><code>fasterq-dump.3.1.0 err: cmn_iter.c cmn_read_uint8_array</code></p></li><li><p><code>fasterq-dump.3.1.0 err: cmn_iter.c cmn_read_String</code></p></li></ul><p>以前使用 <code>fasterq-dump</code> 时只是偶然出现这些问题,重新下载也都能解决,但最近有些 SRA 一直下载失败,经过调查发现这种错误在大文件下载时出现异常频繁,且多次下载并没法有效解决问题,因此需要一个替代的方法。</p><h3 id="解决方案"><a href="#解决方案" class="headerlink" title="解决方案"></a>解决方案</h3><h4 id="Prefetch"><a href="#Prefetch" class="headerlink" title="Prefetch"></a>Prefetch</h4><p>由于 <code>fasterq-dump</code> 直接通过 HTTP 下载得到 fastq 文件,该过程很可能由于一些问题中断从而导致下载失败。因此可以通过更稳定的 <code>prefetch</code> 先得到 sra 文件,再通过 <code>fasterq-dump</code> 提取 fastq 文件。</p><blockquote><p>fasterq-dump fetches SRR on the fly via HTTP and there could be fatal errors during the transfer.<br>prefetch eliminates transfer problems.</p></blockquote><p>具体操作:</p><figure class="highlight shell"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta prompt_">$ </span><span class="language-bash">prefetch --max-size 100000000 [SRR <span class="built_in">id</span>]</span></span><br><span class="line"><span class="meta prompt_">$ </span><span class="language-bash">fasterq-dump [SRR <span class="built_in">id</span>]/[SRR <span class="built_in">id</span>].sra --progress --details --split-files -v --threads [number of threads]</span></span><br></pre></td></tr></tbody></table></figure><p>使用 <code>prefetch</code> 下载的好处有两点:</p><ol><li>sra 文件占用的空间较小,因此下载速度更快。</li><li>下载如果因为某种原因中断,仍可以通过相同的命令进行断点重连。</li></ol><p>以下是一个使用 slurm 调度系统进行批量下载和读取的示例,没有调度系统的朋友也可以直接参考命令进行多下载任务并行:</p><figure class="highlight bash"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#!/bin/bash</span></span><br><span class="line"><span class="comment">#SBATCH -J download</span></span><br><span class="line"><span class="comment">#SBATCH -o download.out</span></span><br><span class="line"><span class="comment">#SBATCH -e download.err</span></span><br><span class="line"><span class="comment">#SBATCH -N 1</span></span><br><span class="line"><span class="comment">#SBATCH -n 4</span></span><br><span class="line"></span><br><span class="line">output_dir=<span class="string">"./rawfastq"</span></span><br><span class="line"><span class="built_in">mkdir</span> -p <span class="variable">$output_dir</span></span><br><span class="line"><span class="built_in">mkdir</span> -p tmp</span><br><span class="line"></span><br><span class="line"><span class="comment"># Download</span></span><br><span class="line"><span class="built_in">cat</span> download.list | parallel -j 4 --tmpdir ./tmp <span class="string">"prefetch --max-size 100000000 --progress --output-directory <span class="variable">$output_dir</span> {} ><span class="variable">$output_dir</span>/prefetch_{}.log 2>&1"</span></span><br></pre></td></tr></tbody></table></figure><p>其中 <code>download.list</code> 为一行一个 SRR id 的文件。</p><figure class="highlight bash"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#!/bin/bash</span></span><br><span class="line"><span class="comment">#SBATCH -J extract</span></span><br><span class="line"><span class="comment">#SBATCH -o extract.out</span></span><br><span class="line"><span class="comment">#SBATCH -e extract.err</span></span><br><span class="line"><span class="comment">#SBATCH -N 1</span></span><br><span class="line"><span class="comment">#SBATCH -n 16</span></span><br><span class="line"></span><br><span class="line">output_dir=<span class="string">"./rawfastq"</span></span><br><span class="line"><span class="built_in">mkdir</span> -p <span class="variable">$output_dir</span></span><br><span class="line"><span class="built_in">mkdir</span> -p tmp</span><br><span class="line"></span><br><span class="line"><span class="comment"># Extract</span></span><br><span class="line"><span class="built_in">cat</span> download.list | parallel -j 4 --tmpdir ./tmp <span class="string">"fasterq-dump <span class="variable">$output_dir</span>/{}/{}.sra* --progress --details --split-files -v --outdir <span class="variable">$output_dir</span> --threads 4 ><span class="variable">$output_dir</span>/fasterq-dump_{}.log 2>&1"</span></span><br><span class="line"><span class="comment"># gzip Compress</span></span><br><span class="line"><span class="built_in">ls</span> <span class="variable">$output_dir</span>/*fastq | parallel -j 16 gzip {}</span><br></pre></td></tr></tbody></table></figure><p>这里使用 <code>.sra*</code> 作为后缀的原因是有时下载的 sra 文件其尾缀可能为 <code>.sralite</code>,具体差别可见 <a href="https://www.ncbi.nlm.nih.gov/sra/docs/sra-data-formats/">SRA Data Formats</a>。</p><p>若想加速提取过程,可以根据自身情况调整并行数量和 <code>fasterq-dump</code> 使用的线程数量。以上方法<strong>经实测非常稳定,对于大文件而言也不会出现报错</strong>。</p><h4 id="ascp"><a href="#ascp" class="headerlink" title="ascp"></a>ascp</h4><p>有时 <code>prefetch</code> 下载速度极缓慢,因此选择速度更快很多的 <code>ascp</code> 也是很好的替代方案。</p><p>conda 下载:</p><figure class="highlight shell"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta prompt_"># </span><span class="language-bash">有 mamba 则用 mamba</span></span><br><span class="line">conda install -c hcc aspera-cli -y</span><br></pre></td></tr></tbody></table></figure><p>在 <a href="https://www.ebi.ac.uk/ena/browser/home">ENA Browser</a> 搜索对应的 Accession Number,</p><img src="/pic2/ENAbroser.png" style="zoom:80%;"><p>勾选 <code>fastq_aspera</code> 后下载 TSV:</p><img src="/pic2/ENAbroser2.png" style="zoom:50%;"><p>根据 <code>fastq_ftp</code> 列,制成以下类似文件:</p><figure class="highlight txt"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">/vol1/fastq/ERR418/003/ERR4181783/ERR4181783_1.fastq.gz</span><br><span class="line">/vol1/fastq/ERR418/003/ERR4181783/ERR4181783_2.fastq.gz</span><br></pre></td></tr></tbody></table></figure><p>假设其命名为 <code>download.list</code>,使用以下命令下载:</p><figure class="highlight shell"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">ascp -QT -k 1 -l 100m -P33001 -i /path/to/asperaweb_id_dsa.openssh --mode recv --user era-fasp --host fasp.sra.ebi.ac.uk --file-list ./download.list [output path]</span><br></pre></td></tr></tbody></table></figure><p>参数详解:</p><ul><li><code>-Q</code>:启用较少详细信息的输出模式(quiet mode)。</li><li><code>-T</code>:启用文件时间戳保留。文件传输完成后,目标文件的时间戳将与源文件相同。</li><li><code>-k 1</code>:断点续传。</li><li><code>-l 100m</code>:限制传输速率,最大传输速率为 100 Mbps。</li><li><code>-P 33001</code>:用于连接的端口号,<code>33001</code> 是 Aspera 使用的默认端口号。</li><li><code>-i /path/to/asperaweb_id_dsa.openssh</code>:指定私钥文件的路径,用于身份验证。位于<strong>安装 ascp 的环境</strong>目录中的 <strong>etc</strong> 下。</li></ul><img src="/pic2/ENAbroser3.png" style="zoom:80%;"><ul><li><code>--mode recv</code>:指定传输模式。<code>recv</code> 表示接收文件(下载)。</li><li><code>--user era-fasp</code>:指定连接使用的用户名。</li><li><code>--host fasp.sra.ebi.ac.uk</code>:指定连接的主机名或 IP 地址。</li><li><code>--file-list ./download.list</code>:指定包含待传输文件列表的文件。</li><li><code>[output path]</code>:存储下载文件的路径,改为自己的实际路径。</li></ul><p>不过需要注意,<code>ascp</code> 下载的数据有时会出现问题,进而导致下游分析如 <code>trim_galore</code> 在过滤 reads 时出错,以下是一些报错示例:</p><blockquote><p>cutadapt: error: Line xxx in FASTQ file is expected to start with ‘xxx’, but found ‘xxx’</p></blockquote><p>可以通过 <code>gunzip</code> 命令检查是否是由于 fastq 文件存在问题:</p><figure class="highlight shell"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta prompt_">$ </span><span class="language-bash">gunzip -t SRRxxx.fastq.gz</span></span><br><span class="line"></span><br><span class="line">gzip: SRRxxx.fastq.gz: invalid compressed data--crc error</span><br><span class="line"></span><br><span class="line">gzip: SRRxxx.fastq.gz: invalid compressed data--length error</span><br></pre></td></tr></tbody></table></figure><p>以上情况<strong>可能并不是因为下载过程中的网络问题</strong>,而是 <code>ascp</code> 下载的文件本身存在问题,经实测某些文件下载不存在问题的话,不管下载多少次都不会出错。而某些文件如果下载后存在问题,那么不管下载多少次都会存在问题,这同时也体现了 <code>prefetch</code> 的特点 —— 慢但稳定。</p><h3 id="参考资料"><a href="#参考资料" class="headerlink" title="参考资料"></a>参考资料</h3><p>本文解决方案皆来自 sra-tools Github issue:</p><blockquote><ul><li><p><a href="https://github.com/ncbi/sra-tools/issues/214">fasterq-dump err #214</a></p></li><li><p><a href="https://github.com/ncbi/sra-tools/issues/545">Fasterq-dump failing consistently #545</a></p></li></ul></blockquote></body></html>]]></content>
<summary type="html">本文将介绍当使用 fasterq-dump 下载序列不成功时其他的可行替代方法(prefetch 和 ascp) ,同时也提到 ascp 下载 fastq 文件时可能出现的问题和报错。</summary>
<category term="学习" scheme="https://biojuse.com/categories/%E5%AD%A6%E4%B9%A0/"/>
<category term="生信" scheme="https://biojuse.com/categories/%E5%AD%A6%E4%B9%A0/%E7%94%9F%E4%BF%A1/"/>
</entry>
<entry>
<title>提取 bwa 比对中唯一比对 reads(uniquely mapped reads)的方法</title>
<link href="https://biojuse.com/2024/05/03/%E6%8F%90%E5%8F%96%20bwa%20%E6%AF%94%E5%AF%B9%E4%B8%AD%E5%94%AF%E4%B8%80%E6%AF%94%E5%AF%B9%20reads%EF%BC%88uniquely%20mapped%20reads%EF%BC%89%E7%9A%84%E6%96%B9%E6%B3%95/"/>
<id>https://biojuse.com/2024/05/03/%E6%8F%90%E5%8F%96%20bwa%20%E6%AF%94%E5%AF%B9%E4%B8%AD%E5%94%AF%E4%B8%80%E6%AF%94%E5%AF%B9%20reads%EF%BC%88uniquely%20mapped%20reads%EF%BC%89%E7%9A%84%E6%96%B9%E6%B3%95/</id>
<published>2024-05-03T13:15:00.000Z</published>
<updated>2025-01-14T03:22:15.990Z</updated>
<content type="html"><![CDATA[<html><head></head><body><p>本文由 Juse 基于以下资料进行撰写:</p><blockquote><p><a href="https://www.seqanswers.com/forum/bioinformatics/bioinformatics-aa/49537-how-to-extract-uniquely-mapped-reads-from-bam-sam-produced-by-bwa-mem">How to extract uniquely mapped reads from bam/sam produced by bwa-mem?</a> from SEQanswers</p><p><a href="https://www.biostars.org/p/256448/">Obtaining uniquely mapped reads from BWA mem alignment (filtering by q score does not seem to do the trick in my case)</a> from Biostars</p><p><a href="https://bioinformatics.stackexchange.com/questions/508/obtaining-uniquely-mapped-reads-from-bwa-mem-alignment">Obtaining uniquely mapped reads from BWA mem alignment</a> from StackExchange</p></blockquote><p>在此感谢 community 中各位大佬的无私分享,关于 SAM format 的详细说明可见:</p><p><a href="https://samtools.github.io/hts-specs/SAMv1.pdf">https://samtools.github.io/hts-specs/SAMv1.pdf</a></p><h3 id="正文"><a href="#正文" class="headerlink" title="正文"></a>正文</h3><p>在某些文章中,有时我们会看到作者提及到在后续分析中,ta 只考虑了 <u><strong>uniquely mapping reads</strong></u>(后文统称唯一比对)。从直觉上出发,使用唯一比对的思路不难理解 —— 这些比对更加精确,并使后续的分析具有更好的解释性。</p><p>目前来说,得到唯一比对的最主流方法是直接通过 MAPQ 进行过滤,但这并不能得到严格意义上的唯一比对,因为部分 reads 在经过该过滤后仍然具有多重比对。不过这里需要明确一点:通过 MAPQ 过滤后仍存在的多重比对数量其实已经很少,如 Biostars 中的帖主所示:</p><blockquote><p>For the one sample I am using to test out commands, I filtered my data so I only have properly paired reads and mapped reads (in the case of my unpaired reads) and also filtered by q score (I get nearly the same results at q of 10, 20, or 30, so it's not an issue of changing the q score level), merged all my bam files, and obtained 193,998 reads total for that sample. When I open the bam file in Geneious and count the number of reads for each locus they add up to 194, 050. I realize the difference between these two numbers is an incredibly small number of reads.</p></blockquote><p>因此,<u><strong>仅使用 MAPQ 进行过滤看上去也是可行的</strong></u>(如果你能接受极小一部分 “可能具有多个比对” 的 reads)。并且严格意义上说,唯一比对这一概念本身就具有局限性 —— 比对时所使用的参数如果过于宽松,那么具有多重比对的 reads 数量也会大大增加。</p><p>不过,如果实在想要避免多重比对带来的影响,可以根据 bwa 比对中的一些 Alignment Tags 来进行过滤,在 bwa 中,拥有多重比对的 reads 会出现以下一些 Tag:</p><ul><li><code>XA</code>,该 flag 中描述了对应 read 的 Alternative hits。</li><li><code>SA</code>,该 flag 用于标识嵌合的比对结果(Supplementary Alignment)。</li></ul><p>这两个 flag 的格式非常相似,其中 [XA] 是 bwa 等一部分比对软件使用的 flag。更详细信息可见下文说明。</p><p>因此,如果要过滤出唯一比对,<u><strong>只需要对这两个 flag 进行筛选</strong></u>:</p><figure class="highlight shell"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta prompt_">$ </span><span class="language-bash">sambamba view -t 12 -h -f bam -F <span class="string">"mapping_quality >= 1 and not (unmapped or secondary_alignment) and not ([XA] != null or [SA] != null)"</span> [input bam] -o [output bam]</span></span><br></pre></td></tr></tbody></table></figure><p>sambamba -F 中的各个 filter tag 说明:</p><ul><li><code>mapping_quality >= 1</code>:要求比对质量分数至少为 1。</li><li><code>not (unmapped or secondary_alignment)</code>:不满足 unmapped 或 secondary_alignment 条件。<ul><li><code>unmapped</code>:未比对上的 reads。</li><li><code>secondary_alignment</code>:同一 read 除了主比对之外的次比对记录。</li></ul></li><li><code>not ([XA] != null or [SA] != null)</code>:不存在 [XA] tag 或 [SA] tag。<ul><li><code>[XA]</code>:当 read 完整地比对到了多个位置时,比对软件会选择最佳的一个作为 primary (主比对),其他的标记为 secondary (次比对)。而 [XA] 和 secondary_alignment 的区别在于前者在<strong>主比对记录中进行次比对结果的标注</strong>,后者则<strong>将次比对结果进行单独记录</strong>。相比之下,[XA] 能够节省存储空间。</li><li><code>[SA]</code>:指 read 的不同部分比对到了不同的位置,可能由结构变异、基因融合、错误组装等因素导致。</li></ul></li></ul><p>以上<strong>过滤使用的 filter tag 可根据自身需求进行灵活调整</strong>,上述命令将过滤<strong>未比对的 reads</strong> 并<strong>保留有且仅有唯一比对位置的 reads</strong>。</p></body></html>]]></content>
<summary type="html">本文介绍了使用 sambamba 提取 bwa 比对中唯一比对 reads 的方法,同时对其中的思路进行了探讨展开。</summary>
<category term="学习" scheme="https://biojuse.com/categories/%E5%AD%A6%E4%B9%A0/"/>
<category term="杂项" scheme="https://biojuse.com/categories/%E5%AD%A6%E4%B9%A0/%E6%9D%82%E9%A1%B9/"/>
</entry>
<entry>
<title>bismark 分析 Bisulfite-Seq 数据的流程示例</title>
<link href="https://biojuse.com/2024/04/20/bismark%20%E5%88%86%E6%9E%90%20Bisulfite-Seq%20%E6%95%B0%E6%8D%AE%E7%9A%84%E6%B5%81%E7%A8%8B%E7%A4%BA%E4%BE%8B/"/>
<id>https://biojuse.com/2024/04/20/bismark%20%E5%88%86%E6%9E%90%20Bisulfite-Seq%20%E6%95%B0%E6%8D%AE%E7%9A%84%E6%B5%81%E7%A8%8B%E7%A4%BA%E4%BE%8B/</id>
<published>2024-04-20T03:05:00.000Z</published>
<updated>2024-04-27T07:29:08.084Z</updated>
<content type="html"><![CDATA[<html><head></head><body><hr><h2 id="前言"><a href="#前言" class="headerlink" title="前言"></a>前言</h2><p>以下是相关的官网链接和参考资料,如果想要得到除本文内容以外更全面深入的了解,建议直接跳转相关链接进行查阅:</p><blockquote><p>Bismark github:</p><p><a href="https://github.com/FelixKrueger/Bismark">https://github.com/FelixKrueger/Bismark</a></p><p>Bismark documentation:</p><p><a href="https://felixkrueger.github.io/Bismark/">https://felixkrueger.github.io/Bismark/</a></p><p>本文比对及去重等流程均参考自 Bismark documentation</p></blockquote><p>此外,以下内容在本文中不会涉及到,有需要请自行探索:</p><ul><li>数据的质控</li><li>除 Bismark 以外其他软件的安装</li></ul><p>通过以下流程可以得到:</p><ul><li>基因组上 CpG 位点的甲基化信息</li></ul><p>请阅读完全文后再进行相关分析,建议先使用 bismark 的示例数据观察相关命令是否存在问题。</p><h2 id="正文"><a href="#正文" class="headerlink" title="正文"></a>正文</h2><p>下载最新版本的 bismark(至 2024/04/19):</p><figure class="highlight shell"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta prompt_">$ </span><span class="language-bash">wget https://github.com/FelixKrueger/Bismark/archive/refs/tags/v0.24.2.tar.gz</span></span><br></pre></td></tr></tbody></table></figure><p>也可前往 github release 下载指定版本或可能已存在的更新版本:</p><p><a href="https://github.com/FelixKrueger/Bismark/releases">https://github.com/FelixKrueger/Bismark/releases</a></p><p>下载后解压并将对应文件夹置入环境变量:</p><figure class="highlight shell"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta prompt_">$ </span><span class="language-bash">tar xzf Bismark-0.24.2.tar.gz</span></span><br><span class="line"><span class="meta prompt_">$ </span><span class="language-bash"><span class="built_in">echo</span> <span class="string">'export PATH="'</span>$(<span class="built_in">readlink</span> -f Bismark-0.24.2)<span class="string">':$PATH"'</span> >> ~/.bashrc</span></span><br><span class="line"><span class="meta prompt_">$ </span><span class="language-bash"><span class="built_in">source</span> ~/.bashrc</span></span><br></pre></td></tr></tbody></table></figure><p>由于 bismark 中比对等操作均由 bismark 本身调用比对软件进行,因此在运行后续代码前,请确保正确版本的 <code>Bowtie2</code> 或 <code>HISAT2</code> 已经被置入环境变量中,如果想自行指定,可在后续执行时添加以下参数:</p><figure class="highlight plaintext"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">--path_to_bowtie2 </../../bowtie2> or</span><br><span class="line">--path_to_hisat2 </../../hisat2></span><br></pre></td></tr></tbody></table></figure><p>bismark 默认使用 bowtie2,除非特别指定 <code>--hisat2</code>。</p><h3 id="比对"><a href="#比对" class="headerlink" title="比对"></a>比对</h3><p>比对前,使用 bismark 构建基因组 <code>C>T</code> <code>G>A</code> 的索引:</p><figure class="highlight shell"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta prompt_">$ </span><span class="language-bash">bismark_genome_preparation --verbose --parallel [thread] [path]</span></span><br></pre></td></tr></tbody></table></figure><ul><li><code>path</code> 换为基因组序列文件储存的路径,bismark 将自动识别 <code>.fa</code> 及 <code>.fasta</code> 文件并建立索引(压缩格式 <code>.gz</code> 也能识别)。</li><li><code>thread</code> 处填入使用的线程数量,注意最终将会使用 <code>2 * thread</code> 个线程。</li></ul><p>在构建完索引后,就可以通过 bismark 对数据进行比对,在比对前,建议先记录版本信息:</p><figure class="highlight shell"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta prompt_">$ </span><span class="language-bash">bismark --version > bismark.version 2>&1</span></span><br></pre></td></tr></tbody></table></figure><p>比对命令(单端):</p><figure class="highlight shell"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta prompt_">$ </span><span class="language-bash">bismark -L [seed length] -N [mismatch number] --genome [path] --parallel [thread] -o [output_dir] [fastq] > [logfile] 2>&1</span></span><br></pre></td></tr></tbody></table></figure><p>比对命令(双端):</p><figure class="highlight shell"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta prompt_">$ </span><span class="language-bash">bismark -L [seed length] -N [mismatch number] --genome [path] --parallel [thread] -o [output_dir] -1 [fastq_R1] -2 [fastq_R2] > [logfile] 2>&1</span></span><br></pre></td></tr></tbody></table></figure><p>相关参数解释:</p><ul><li><code>seed length</code> 指定比对过程中使用的基础片段的长度(默认为 20),最大可设置为 32,该值越小时比对越慢,但同时也增加了召回率。该选项只在 Bowtie2 可用。</li><li><code>mismatch number</code> 指定比对过程中基础片段允许的错配数量(默认为 0)。可设置为 1,设置为 1 时比对会减慢很多,但同样增加了召回率。该选项只在 Bowtie2 可用。</li><li><code>thread</code> 指定并行的实例,注意其不是单纯的线程数,由于一个 <code>bismark</code> 进程就已经使用了多个核,以小鼠基因组为例,该值设置为 4 时将会使用大约 20 个核以及 40GB 左右的 RAM。因此请根据基因组大小、空闲的内存及核数量对该参数进行调整。</li><li><code>path</code> 即构建索引时使用的 <code>path</code>。</li><li><code>output_dir</code> 为输出的目录,<code>fastq</code> 指定测序数据文件,<code>logfile</code> 记录比对过程中的屏幕输出。</li></ul><p><strong>注意!</strong>如果测序数据由 <a href="https://www.illumina.com/science/sequencing-method-explorer/kits-and-arrays/pbat.html">PBAT</a> 建库得到,需要添加 <code>--pbat</code> 参数。此外,bismark 也提供了 <code>--local</code> 参数,指定此参数可以提高该文库类型的 map 比率,但是在 documentation 中 bismark 团队并不推荐这么做。</p><p>比对完成后,请先检查比对情况,相关的比对报告将储存在 <code>output_dir</code> 中以 <code>_report.txt</code> 结尾的文件里,如果是单端数据且使用 Bowtie2 比对,则相关报告文件将以 <code>_bismark_bt2_SE_report.txt</code> 结尾。打开文件,检查其中 <u>Mapping efficiency</u> 一项:</p><figure class="highlight plaintext"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line">Final Alignment report</span><br><span class="line">======================</span><br><span class="line">Sequences analysed in total:1157278848</span><br><span class="line">Number of alignments with a unique best hit from the different alignments:736261309</span><br><span class="line">Mapping efficiency:63.6%</span><br><span class="line">Sequences with no alignments under any condition:337204612</span><br><span class="line">Sequences did not map uniquely:83812927</span><br><span class="line">Sequences which were discarded because genomic sequence could not be extracted:29</span><br></pre></td></tr></tbody></table></figure><p>如果 Mapping efficiency 在可接受范围内,则可进行后续分析。若该值过低(例如不超过 30%),则需考虑更改过滤参数以提升该值。一个折中的选择是适当提升 <code>seed length</code> 并设置 <code>mismatch number</code> 为 1。</p><p>考虑到比对的用时都较长,因此在第一次比对时就应尽量根据实际情况决定一个好的参数起点,例如:</p><ul><li>测序数据的 reads 长度?是单端还是双端?</li><li>测序数据的质量如何?</li></ul><h3 id="去重"><a href="#去重" class="headerlink" title="去重"></a>去重</h3><p>基因组上相同位置的比对可能是由 PCR 扩增导致的,删除重复的 reads 有助于避免 PCR 引入的序列 bias 并提高后续相关分析的准确性。但请注意,<strong>不建议对目标富集型文库(target enrichment-type library)例如 RRBS 及 amplicon 等进行该操作</strong>,因为在这些类型的文库中,重复序列可能是有意义的。</p><figure class="highlight shell"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta prompt_">$ </span><span class="language-bash">deduplicate_bismark --version > deduplicate_bismark.version 2>&1</span></span><br></pre></td></tr></tbody></table></figure><figure class="highlight shell"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta prompt_">$ </span><span class="language-bash">deduplicate_bismark --output_dir [output_dir] --outfile [prefix] [files] > [logfile] 2>&1</span></span><br></pre></td></tr></tbody></table></figure><ul><li><code>output_dir</code> 填入去重后的文件输出目录。</li><li><code>prefix</code> 填入去重后的文件前缀名称。</li><li><code>files</code> 填入需要去重的文件。<code>logfile</code> 填入记录屏幕输出的日志文件。</li></ul><p>如果此处想要将多个比对结果放在一起进行去重,则需指定 <code>--multiple</code> 参数,此时 bismark 将会把所有的输入文件视为单个样本连接在一起并进行去重。</p><p>最后的去重结果将在以 <code>.deduplication_report.txt</code> 结尾的文件中,该文件里将展示共有多少比对被移除。</p><h3 id="统计甲基化信息"><a href="#统计甲基化信息" class="headerlink" title="统计甲基化信息"></a>统计甲基化信息</h3><p>该步使用的 <code>bismark_methylation_extractor</code> 命令具有非常多的可选参数,建议通过 <code>bismark_methylation_extractor --help</code> 查看详细信息,此处给出个人使用的命令:</p><figure class="highlight shell"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta prompt_">$ </span><span class="language-bash">bismark_methylation_extractor --version > bismark_methylation_extractor.version 2>&1</span></span><br></pre></td></tr></tbody></table></figure><figure class="highlight shell"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta prompt_">$ </span><span class="language-bash">bismark_methylation_extractor --gzip --bedGraph [bamfile] --output_dir [output_dir] --parallel [thread] > [logfile] 2>&1</span></span><br></pre></td></tr></tbody></table></figure><p><code>bamfile</code> 处填入经过上述处理后得到的最终 bam 文件。此处 <code>--gzip</code> 表示输出文件以 gzip 进行压缩,<code>--bedgraph</code> 使 bismark 输出 bedgraph 文件。也可不使用 <code>--bedgraph</code> 参数并通过结果文件自行处理生成。</p><p>通过上述命令将得到以下尾缀结尾的文件:</p><ul><li><code>.bismark.cov.gz</code> 该文件共六列,分别代表:染色体、起始位点(1 坐标)、终止位点、甲基化比例、甲基化的 read count、非甲基化的 read count。</li><li><code>.bedGraph.gz</code> 该文件共四列,分别代表:染色体、起始位点(0 坐标)、终止位点、甲基化比例。</li><li><code>.M-bias.txt</code> 该文件展示了 reads 中每个 position 的平均甲基化水平,可通过画图可视化,偏离水平线可能表示存在 bias [<a href="https://www.nature.com/articles/nrg3273#glossary">Bock 2012, Nat Rev Genet</a>]。</li><li><code>_splitting_report.txt</code> 相关信息的统计汇总。</li></ul><p>通过 <code>.bismark.cov.gz</code> 生成 <code>.bedGraph.gz</code> 的方式:</p><figure class="highlight shell"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta prompt_">$ </span><span class="language-bash">zcat xxx.bismark.cov.gz | awk -F<span class="string">'\t'</span> <span class="string">'OFS="\t" {print $1, $2-1, $3, $4}'</span> | gzip > xxx.bedGraph.gz</span></span><br></pre></td></tr></tbody></table></figure><p>此后可以通过 bedgraph 文件生成 bigWig 文件,请注意,由于 <code>bedGraphToBigWig</code> 并没法输入压缩文件,因此你可能需要对上述文件进行解压,或者不使用 <code>gzip</code> 进行压缩:</p><figure class="highlight shell"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta prompt_">$ </span><span class="language-bash">bedGraphToBigWig xxx.bedGraph genome.chrom.sizes output.bw</span></span><br></pre></td></tr></tbody></table></figure><p>关于 <code>chrom.sizes</code> 文件的获取方式可参考之前的 <a href="https://biojuse.com/2024/04/16/%E9%80%9A%E8%BF%87%20bowtie2%20+%20macs3%20%E5%88%86%E6%9E%90%20ChIP-Seq%20%E6%95%B0%E6%8D%AE/#Signal-P-value-amp-Fold-change-over-control">ChIP-seq 文章</a>。</p><p>以下是 bismark documentation 中给出的示例 M-bias plot(仅为示例,并不代表这种属于正常情况):</p><img src="https://felixkrueger.github.io/Bismark/images/PBAT_SE_M-bias.jpg"><h2 id="后记"><a href="#后记" class="headerlink" title="后记"></a>后记</h2><p>bisulfite-seq 数据的分析也可以通过 <a href="https://github.com/heathsc/gemBS">gemBS</a> Pipeline 直接进行,请注意该 Pipeline 目前仅支持双端数据。</p><p>也不必过多担心参数的选择,大多数情况下可能仅有 <code>bismark</code> 的 <code>-L</code> 和 <code>-N</code> 需要进行调整,如果不知道应该设置多少为宜建议统一使用默认参数,再根据结果进行修改。</p></body></html>]]></content>
<summary type="html">本文将介绍如何使用 bismark 分析 Bisulfite-Seq 数据,同时也将提及到一些设定参数时需要注意的事项。</summary>
<category term="学习" scheme="https://biojuse.com/categories/%E5%AD%A6%E4%B9%A0/"/>
<category term="生信" scheme="https://biojuse.com/categories/%E5%AD%A6%E4%B9%A0/%E7%94%9F%E4%BF%A1/"/>
<category term="生物信息学" scheme="https://biojuse.com/tags/%E7%94%9F%E7%89%A9%E4%BF%A1%E6%81%AF%E5%AD%A6/"/>
<category term="生信" scheme="https://biojuse.com/tags/%E7%94%9F%E4%BF%A1/"/>
</entry>
<entry>
<title>通过 bowtie2 + macs3 分析 ChIP-Seq 数据</title>
<link href="https://biojuse.com/2024/04/16/%E9%80%9A%E8%BF%87%20bowtie2%20+%20macs3%20%E5%88%86%E6%9E%90%20ChIP-Seq%20%E6%95%B0%E6%8D%AE/"/>
<id>https://biojuse.com/2024/04/16/%E9%80%9A%E8%BF%87%20bowtie2%20+%20macs3%20%E5%88%86%E6%9E%90%20ChIP-Seq%20%E6%95%B0%E6%8D%AE/</id>
<published>2024-04-16T03:30:00.000Z</published>
<updated>2024-12-12T12:08:26.314Z</updated>
<content type="html"><![CDATA[<html><head></head><body><hr><h2 id="前言"><a href="#前言" class="headerlink" title="前言"></a>前言</h2><p>以下是相关的官网链接和参考资料,如果想要得到除本文内容以外更全面深入的了解,建议直接跳转相关链接进行查阅:</p><blockquote><p>MACS3 github:</p><p><a href="https://github.com/macs3-project/MACS">https://github.com/macs3-project/MACS</a></p><p>MACS3 documentation:</p><p><a href="https://macs3-project.github.io/MACS/">https://macs3-project.github.io/MACS/</a></p><p>本文比对及去重等流程参考自以下资料:</p><ul><li><a href="https://hbctraining.github.io/Intro-to-ChIPseq/lessons/03_align_and_filtering.html">Alignment and filtering</a> from Harvard Chan Bioinformatics Core (HBC)</li><li><a href="https://www.encodeproject.org/pipelines/ENCPL612HIG/">Histone ChIP-seq pipeline</a> from ENCODE project (<strong>Version 2.0</strong> with bowtie2)</li></ul><p>本文流程根据以下资料进行过优化:</p><ul><li><a href="https://github.com/biod/sambamba/issues/477">sambamba -F "not duplicate" processed bam still have duplicated</a> (sambamba issue#477) (Update 2024/4/24)</li><li><a href="https://www.nature.com/articles/s41598-019-45839-z">Encode blacklist</a> (Update 2024/4/24)</li></ul></blockquote><p>以下内容在本文中不会涉及到:</p><ul><li>数据的质控</li><li>除 macs3 以外其他软件的安装</li></ul><p>你可以考虑参考以下 github repository 安装用于 ChIP-seq 数据处理的 conda 环境,可补齐下文中需要的上游分析软件:</p><p><a href="https://github.com/JuseTiZ/Blog-Snakemake-pipeline/">https://github.com/JuseTiZ/Blog-Snakemake-pipeline/</a></p><h2 id="正文"><a href="#正文" class="headerlink" title="正文"></a>正文</h2><p>使用 pip 安装 macs3:</p><figure class="highlight shell"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta prompt_">$ </span><span class="language-bash">pip install macs3</span></span><br></pre></td></tr></tbody></table></figure><p>如果安装过程中无法安装依赖 <code>cykhash</code>,可以尝试使用 mamba 进行安装:</p><figure class="highlight shell"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta prompt_">$ </span><span class="language-bash">mamba install -c conda-forge cykhash</span></span><br></pre></td></tr></tbody></table></figure><p>安装后可以输入 <code>macs3 --version</code> 查看是否成功安装。</p><h3 id="比对"><a href="#比对" class="headerlink" title="比对"></a>比对</h3><p>比对前,使用 bowtie2 构建基因组的索引:</p><figure class="highlight shell"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta prompt_">$ </span><span class="language-bash">bowtie2-build genome.fa indexname</span></span><br></pre></td></tr></tbody></table></figure><p>将以上代码中的 <code>genome.fa</code> 替换为自己的基因组文件,<code>indexname</code> 替换为想要设定的索引名称,后续比对将用到 <code>indexname</code>。</p><p>构建后,对数据进行比对得到 sam 文件:</p><figure class="highlight shell"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta prompt_">$ </span><span class="language-bash">bowtie2 --threads 4 \</span></span><br><span class="line"><span class="language-bash"> -q -x indexname -U chip-seq.fastq.gz \</span></span><br><span class="line"><span class="language-bash"> -S output.sam > bowtie2.log 2>&1</span></span><br></pre></td></tr></tbody></table></figure><ul><li><code>--threads</code> 使用的线程数量</li><li><code>-X</code> 指定索引</li><li><code>-U</code> 质控后的测序数据文件</li><li><code>-S</code> 输出的 sam 文件</li></ul><p>将 <code>indexname</code> 替换为之前建立的索引名称,将 <code>chip-seq.fastq.gz</code> 替换为 chip-seq 的数据,如果是双端则需进行一定修改,考虑到 chip-seq 数据一般都是单端数据此处不做拓展。该过程的屏幕输出将记录在 <code>bowtie2.log</code> 中(例如比对率等)。</p><p>以上命令在 slurm 调度系统下的一个并行示例:</p><figure class="highlight bash"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#!/bin/bash</span></span><br><span class="line"><span class="comment">#SBATCH -J alignment</span></span><br><span class="line"><span class="comment">#SBATCH -o alignment.out</span></span><br><span class="line"><span class="comment">#SBATCH -e alignment.err</span></span><br><span class="line"><span class="comment">#SBATCH -n 24</span></span><br><span class="line"></span><br><span class="line">input_dir=<span class="string">"./fastq"</span></span><br><span class="line">output_dir=<span class="string">"./bowtie2_alignment"</span></span><br><span class="line"></span><br><span class="line"><span class="built_in">mkdir</span> -p <span class="string">"<span class="variable">${output_dir}</span>"</span></span><br><span class="line"></span><br><span class="line">bowtie2 --version > bowtie2.version 2>&1</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="title">align_fastq</span></span>() {</span><br><span class="line"> <span class="built_in">local</span> fastq_file=<span class="string">"<span class="variable">$1</span>"</span></span><br><span class="line"> <span class="built_in">local</span> sam_file=<span class="string">"<span class="variable">${output_dir}</span>/<span class="subst">$(basename <span class="string">"<span class="variable">${fastq_file}</span>"</span> .fq.gz)</span>.sam"</span></span><br><span class="line"> <span class="built_in">local</span> log_file=<span class="string">"<span class="variable">${output_dir}</span>/<span class="subst">$(basename <span class="string">"<span class="variable">${fastq_file}</span>"</span> .fq.gz)</span>.log"</span></span><br><span class="line"></span><br><span class="line"> bowtie2 --threads 4 -q -x indexname -U <span class="string">"<span class="variable">$fastq_file</span>"</span> -S <span class="string">"<span class="variable">$sam_file</span>"</span> > <span class="string">"<span class="variable">$log_file</span>"</span> 2>&1</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="built_in">export</span> -f align_fastq</span><br><span class="line"><span class="built_in">export</span> input_dir</span><br><span class="line"><span class="built_in">export</span> output_dir</span><br><span class="line"></span><br><span class="line">parallel --<span class="built_in">jobs</span> 6 align_fastq ::: <span class="string">"<span class="variable">${input_dir}</span>"</span>/*.fq.gz</span><br></pre></td></tr></tbody></table></figure><p>上述脚本将从当前目录下的 <code>fastq</code> 文件夹里读取所有 <code>.fq.gz</code> 结尾的文件,并通过 <code>bowtie2</code> 进行比对,索引为 <code>indexname</code>。该过程将并行 6 个比对任务,每个比对任务使用 4 个线程,通过 slurm 使用 24 个 CPU。</p><p>请根据个人情况(如空闲内存、集群信息等)进行修改以保证正常运行。在比对结束后,请对相关 log 文件进行检查,确保比对率等信息未出现问题。</p><h3 id="排序及去重"><a href="#排序及去重" class="headerlink" title="排序及去重"></a>排序及去重</h3><p>由于 PCR 过程中可能部分片段有 bias(被过度扩增),将这些片段去重将有助于降低 call peak 时的假阳性。</p><p>单个运行时的示例:</p><figure class="highlight shell"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta prompt_">$ </span><span class="language-bash">samtools view -h -S -b -o [output_unsorted_bam] [input_sam_file] <span class="comment"># 转为 bam</span></span></span><br><span class="line"><span class="meta prompt_">$ </span><span class="language-bash">sambamba <span class="built_in">sort</span> -t 4 -o [output_sorted_bam] [input_unsorted_bam] <span class="comment"># 对 bam 排序</span></span></span><br><span class="line"><span class="meta prompt_">$ </span><span class="language-bash">sambamba markdup -t 4 [output_markdup_bam] [input_sorted_bam] <span class="comment"># 标记 duplicate</span></span></span><br><span class="line"><span class="meta prompt_">$ </span><span class="language-bash">sambamba view -h -t 4 -f bam -F <span class="string">"[XS] == null and not unmapped and not duplicate"</span> [input_markdup_bam] > [output_filter_bam] <span class="comment"># 过滤及去重</span></span></span><br></pre></td></tr></tbody></table></figure><p>slurm 调度系统下的批量运行示例:</p><figure class="highlight bash"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#!/bin/bash</span></span><br><span class="line"><span class="comment">#SBATCH -J sam2bam</span></span><br><span class="line"><span class="comment">#SBATCH -o sam2bam.out</span></span><br><span class="line"><span class="comment">#SBATCH -e sam2bam.err</span></span><br><span class="line"><span class="comment">#SBATCH -n 24</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># Define directories</span></span><br><span class="line">input_dir=<span class="string">"./bowtie2_alignment"</span></span><br><span class="line">output_dir=<span class="string">"./bamfiles"</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># Create output directory</span></span><br><span class="line"><span class="built_in">mkdir</span> -p <span class="string">"<span class="variable">${output_dir}</span>"</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># Record versions</span></span><br><span class="line">samtools --version > samtools.version 2>&1</span><br><span class="line">sambamba --version > sambamba.version 2>&1</span><br><span class="line"></span><br><span class="line"><span class="comment"># Function to process each SAM file into BAM format</span></span><br><span class="line"><span class="function"><span class="title">process_sam_to_bam</span></span>() {</span><br><span class="line"> <span class="built_in">local</span> sam_file=<span class="string">"<span class="variable">$1</span>"</span></span><br><span class="line"> <span class="built_in">local</span> base_name=<span class="string">"<span class="variable">${output_dir}</span>/<span class="subst">$(basename <span class="string">"<span class="variable">${sam_file}</span>"</span> .sam)</span>"</span></span><br><span class="line"> <span class="built_in">local</span> unsorted_bam=<span class="string">"<span class="variable">${base_name}</span>.unsorted.bam"</span></span><br><span class="line"> <span class="built_in">local</span> sorted_bam=<span class="string">"<span class="variable">${base_name}</span>.sorted.bam"</span></span><br><span class="line"> <span class="built_in">local</span> marked_bam=<span class="string">"<span class="variable">${base_name}</span>.marked.bam"</span></span><br><span class="line"> <span class="built_in">local</span> final_bam=<span class="string">"<span class="variable">${base_name}</span>.bam"</span></span><br><span class="line"></span><br><span class="line"> <span class="comment"># Convert SAM to BAM</span></span><br><span class="line"> samtools view -h -S -b -o <span class="string">"<span class="variable">${unsorted_bam}</span>"</span> <span class="string">"<span class="variable">${sam_file}</span>"</span></span><br><span class="line"></span><br><span class="line"> <span class="comment"># Sort BAM file</span></span><br><span class="line"> sambamba <span class="built_in">sort</span> -t 4 -o <span class="string">"<span class="variable">${sorted_bam}</span>"</span> <span class="string">"<span class="variable">${unsorted_bam}</span>"</span></span><br><span class="line"> <span class="built_in">rm</span> <span class="string">"<span class="variable">${unsorted_bam}</span>"</span></span><br><span class="line"> </span><br><span class="line"> <span class="comment"># Mark duplicate</span></span><br><span class="line"> sambamba markdup -t 4 <span class="string">"<span class="variable">${sorted_bam}</span>"</span> <span class="string">"<span class="variable">${marked_bam}</span>"</span></span><br><span class="line"> <span class="built_in">rm</span> <span class="string">"<span class="variable">${sorted_bam}</span>"</span></span><br><span class="line"></span><br><span class="line"> <span class="comment"># Filter BAM file</span></span><br><span class="line"> sambamba view -h -t 4 -f bam -F <span class="string">"[XS] == null and not unmapped and not duplicate"</span> <span class="string">"<span class="variable">${marked_bam}</span>"</span> > <span class="string">"<span class="variable">${final_bam}</span>"</span></span><br><span class="line"> <span class="built_in">rm</span> <span class="string">"<span class="variable">${marked_bam}</span>"</span></span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="comment"># Export function and variables for parallel execution</span></span><br><span class="line"><span class="built_in">export</span> -f process_sam_to_bam</span><br><span class="line"><span class="built_in">export</span> input_dir</span><br><span class="line"><span class="built_in">export</span> output_dir</span><br><span class="line"></span><br><span class="line"><span class="comment"># Execute processing in parallel</span></span><br><span class="line">parallel --<span class="built_in">jobs</span> 6 process_sam_to_bam ::: <span class="string">"<span class="variable">${input_dir}</span>"</span>/*.sam</span><br></pre></td></tr></tbody></table></figure><p>以上注释均通过 ChatGPT 添加,请确保可以通过环境变量直接调用 <code>samtools</code> 和 <code>sambamba</code>。该脚本主要做了以下工作:</p><ul><li><code>samtools</code> 将 <code>sam</code> 转换为 <code>bam</code> 格式。</li><li><code>sambamba</code> 标记重复 reads。</li><li><code>sambamba</code> 对文件进行排序和索引,此后对其进行去重。</li></ul><p>以下是过滤规则:</p><ul><li><p><code>[XS] == null</code>:</p><ul><li>过滤掉具有 <code>XS</code> 标签的比对,选出比对位置唯一或最佳的比对(primary alignments),即没有其他次优的比对位置。</li></ul></li><li><p><code>not unmapped</code>:</p><ul><li>过滤未成功比对到参考基因组的序列。</li></ul></li><li><p><code>not duplicate</code>:</p><ul><li>过滤掉标记为重复的比对。在使用 PCR 方法扩增样本时,会产生重复的 reads。</li></ul></li></ul><p>通过上述命令,就能得到所有后续分析中 macs3 所需要使用到的 bam 文件。如果想要将不同 replicate 的数据放在一起获得最终 bedGraph 文件,可在该步后对同一处理下所有 bam 文件进行合并。</p><h3 id="Filtering-out-Blacklisted-Regions"><a href="#Filtering-out-Blacklisted-Regions" class="headerlink" title="Filtering out Blacklisted Regions"></a>Filtering out Blacklisted Regions</h3><p>详细可见:<a href="https://www.nature.com/articles/s41598-019-45839-z">The ENCODE Blacklist: Identification of Problematic Regions of the Genome</a></p><p>基因组中部分区域的序列高度重复,此外现有基因组版本也可能存在基因组组装错误所导致的 artifact。这些因素都可能导致 signal 出现异常,从而增加假阳性。解决这一问题的方法之一是过滤掉这些区域中的 alignment。</p><p>一些模式物种的 blacklist 文件可以在以下 github repositories 获得:</p><p><a href="https://github.com/Boyle-Lab/Blacklist/">https://github.com/Boyle-Lab/Blacklist/</a></p><p><a href="https://github.com/dozmorovlab/excluderanges">https://github.com/dozmorovlab/excluderanges</a></p><p>请注意选择正确的基因组版本,如果目标物种的 blacklist 文件并不存在于以上 repositories 中,可以自行通过 Encode Blacklist 软件识别。</p><p>以下是使用 deeptools <code>alignmentSieve</code> 过滤 blacklist 的方法:</p><figure class="highlight shell"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta prompt_">$ </span><span class="language-bash">alignmentSieve --blackListFileName blacklist.bed.gz --filterMetrics filterMetricBlacklist.txt -p 8 -b input.bam -o output.bam</span></span><br></pre></td></tr></tbody></table></figure><ul><li><code>--blackListFileName</code> 指定 blacklist region file。</li><li><code>-p</code> 指定使用线程数,<code>-b</code> 和 <code>-o</code> 指定输入和输出 bam 文件。</li></ul><p>如果过滤的为 ATAC-seq 数据,则还需添加 <code>--ATACshift</code> 参数。在 <code>filterMetricBlacklist.txt</code> 中可以看到总 reads 数和过滤后留存的 reads 数。</p><p>由于该步骤并非必需,因此个人看需求选择是否加入到 <strong><u>排序及去重</u></strong> 部分的 Pipeline 中。</p><h3 id="macs3-call-peak"><a href="#macs3-call-peak" class="headerlink" title="macs3 call peak"></a>macs3 call peak</h3><p>一般而言,CHIP-seq(染色质免疫沉淀测序)实验中,通常包括 treat 组和 control 组,后者用于提供实验的背景信号,帮助区分特异性的信号和非特异性的背景噪音。通常有两种主要的对照方式:</p><ul><li><strong>Input control</strong>:在这种对照中,不进行抗体沉淀,直接使用同一样本的一部分进行 DNA 提取和测序。</li><li><strong>Mock IP control</strong>:这种对照使用不特异的抗体(如与目标蛋白无关的抗体或前清液)来进行免疫沉淀。</li></ul><p>因此,假设目前已经有了 treat 和 control 的 bam files,那么可以通过以下命令来进行 callpeak:</p><figure class="highlight shell"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta prompt_">$ </span><span class="language-bash">macs3 callpeak -t [treat bam] -c [control bam] -f BAM -n [outname] --broad -g [species] -B --broad-cutoff 0.1</span></span><br></pre></td></tr></tbody></table></figure><p>以上命令适用于 <u>broad peak calling on Histone Mark ChIP-seq</u>,如果是其他 ChIP-seq 数据,请根据 github 上的 usage 示例进行相应修改。以 TF ChIP-seq 为例,示例命令如下:</p><figure class="highlight shell"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta prompt_">$ </span><span class="language-bash">macs3 callpeak -t [treat bam] -c [control bam] -f BAM -g [species] -n [outname] -B -q 0.01</span></span><br></pre></td></tr></tbody></table></figure><p>由于 macs3 的 <code>bdgdiff</code> 只能处理一个重复下的情况,因此如果单个样本有多个重复,在 <code>callpeak</code> 步骤中可以一起输入(即 <code>-t</code> 和 <code>-c</code> 可以接多个 bam 文件)。或者也可以选择每个重复单独进行 <code>callpeak</code>,然后使用其他工具例如 <code>DESeq2</code> 或 <code>edgeR</code> 进行后续的比较分析。</p><p>这里将对应参数后的输入依据自己的实际情况和需求进行修改,着重提几个参数:</p><ul><li><p><code>-n</code> 输出文件的前缀(可包括输出路径)。</p></li><li><p><code>-g</code> 有效基因组大小,目前 macs3 内置有:</p></li></ul><blockquote><p> hs for human (2,913,022,398)</p><p> mm for mouse (2,652,783,500)</p><p> ce for C. elegans (100,286,401)</p><p> dm for fruitfly (142,573,017)</p><p> Default:hs</p></blockquote><ul><li><code>-B</code> 生成 bedgraph 文件,该文件可用于后续计算得到 signal p-value 或 fold change over control 的 bigWig 文件。</li><li><code>-f</code> 指定输入的文件类型,该选项可留空以让 macs3 自行检查,不过<strong>如果输入的文件为双端配对数据则需自行指定</strong>(BAMPE 或 BEDPE)。</li></ul><p>如果分析的物种有效基因组大小在 macs3 中没有内置,且在 deeptools 上也没给出,可以通过以下方法进行计算:</p><ul><li><p>下载 <code>faCount</code>:<code>wget https://hgdownload.soe.ucsc.edu/admin/exe/linux.x86_64/faCount</code></p></li><li><p>统计物种非 N 碱基数量:<code>faCount genome.fa -summary > genome.faCount.report</code></p></li><li><p>计算:<code>awk 'NR==2 {print $3+$4+$5+$6}' genome.faCount.report</code></p></li></ul><p>将 faCount 后的 <code>genome.fa</code> 替换为自己的基因组文件后,就能得到相应的信息,例如 rheMac10 基因组的非 N 碱基数量为 2936892725。此外也可以 <code>uniquely mappable regions</code> 确定。关于这两种方法的区别,可见 <a href="https://deeptools.readthedocs.io/en/develop/content/feature/effectiveGenomeSize.html">Effective Genome Size</a>。</p><p>由于 macs3 的默认值均根据非 N 碱基数量确定,因此这里只讨论 faCount。</p><p>确定相关参数后,<code>macs3 callpeak</code> 将产生相关的 peak 信息文件,若仅需要 peak 信息则进行到该步即完成任务。不添加 <code>-B</code> 参数时会生成的一些文件:</p><ul><li><code>*_peaks.narrowPeak</code>:包含了每个 peak 的详细信息,包括峰的起始和终止位置、峰的名称、峰的得分、以及峰顶相对于峰起始位置的偏移值。</li><li><code>*_summits.bed</code>:包含了每个 peak 的峰顶位置,即信号最强的点。每一行通常表示一个峰顶,包含染色体、峰顶的起始位置、终止位置(起始位置+1),以及峰的强度值。</li><li><code>*_peaks.xls</code>:详细结果文件,包含产生该文件所使用的命令,各参数的情况,以及峰的各个信息等。</li></ul><h3 id="Signal-P-value-amp-Fold-change-over-control"><a href="#Signal-P-value-amp-Fold-change-over-control" class="headerlink" title="Signal P-value & Fold change over control"></a>Signal P-value & Fold change over control</h3><p>如果在 call peak 步骤中添加了 <code>-B</code> 参数,那么此时应该就已经生成了 treat 组和 control 组的 bed 文件,通过比较这两个 bed 文件,可以得到基因组上不同位置的 <code>signal p-value</code> 或者 `fold change over control,该结果适用于分析和比较整个基因组的信号(而不仅限于 peak 区域)。</p><p>以下是一个运行示例,该例子将产生 Signal P-value 文件,其中第四列为 <code>-log10(pvalue)</code>,因此第四列越大,该处的 signal 越显著:</p><figure class="highlight shell"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta prompt_">$ </span><span class="language-bash">macs3 bdgcmp -t treatment.bedGraph -c control.bedGraph -m ppois -p 1.0 -S 1.0 -o output.bedGraph</span></span><br></pre></td></tr></tbody></table></figure><p>各参数含义详细可见 <a href="https://github.com/macs3-project/MACS/blob/master/docs/bdgcmp.md">documentation</a>,这里提几个重要的:</p><ul><li><code>-m</code> 计算第四列 score 时所用的方法,<code>ppois</code> 即泊松 p 值,选择 <code>FE</code> 则能得到 <code>fold change over control</code> 信息。</li><li><code>-p</code> 为每个计数添加 x 个伪计数,尤其在对数转换时可以避免计数为 0 造成的计算问题,此外也有助于减少因样本稀疏导致的统计波动。</li><li><code>-S</code> 设置处理组(treatment)和对照组(control)数据的缩放因子,如果在 call peak 时未指定 <code>--SPMR</code> 参数,则该项设定为 1 即可。</li></ul><p>对于输出后的 bedgraph 文件,可以通过 <code>bedGraphToBigWig</code> 转为 bigWig 文件:</p><figure class="highlight shell"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta prompt_">$ </span><span class="language-bash">wget https://hgdownload.soe.ucsc.edu/admin/exe/linux.x86_64/bedGraphToBigWig <span class="comment"># 下载工具</span></span></span><br><span class="line"><span class="meta prompt_">$ </span><span class="language-bash">bedGraphToBigWig output.bedGraph genome.chrom.sizes output.bw</span></span><br></pre></td></tr></tbody></table></figure><p>每个物种的 <code>genome.chrom.sizes</code> 文件可在相应的 UCSC Genome Browser goldenpath 中得到,如果所分析物种尚未在基因组浏览器上记载,可自行通过 <code>samtools</code> 或 <code>Biopython</code> 得到。例:</p><figure class="highlight bash"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">samtools faidx reference.fasta</span><br><span class="line"><span class="built_in">cut</span> -f1,2 reference.fasta.fai > chrom.sizes</span><br></pre></td></tr></tbody></table></figure><p>如果此处存在一个样本下有多个重复的情况,并且已经对每个重复都单独计算得到了 bed 文件,你也可以通过 macs3 的 <code>cmbreps</code> 对不同的重复进行合并。例如以 <code>signal p-value</code> 为例:</p><figure class="highlight shell"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta prompt_">$ </span><span class="language-bash">macs3 cmbreps -i replicate1.bedGraph replicate2.bedGraph replicate3.bedGraph -o combined.bedGraph --method fisher</span></span><br></pre></td></tr></tbody></table></figure><p>其通过费舍尔联合概率检验合并 p 值并计算得到新 p 值。</p><p>对于 <code>fold change over control</code>,可将 <code>-m</code> 后的 <code>fisher</code> 换为 <code>mean</code> 进行。</p><h2 id="后记"><a href="#后记" class="headerlink" title="后记"></a>后记</h2><p>以上流程已被打包为一个完整的 Snakemake Pipeline,可在以下链接中获取:</p><p><a href="https://github.com/JuseTiZ/Blog-Snakemake-pipeline/tree/main/ChIP-Pipeline">https://github.com/JuseTiZ/Blog-Snakemake-pipeline/tree/main/ChIP-Pipeline</a></p><p>该 Pipeline 的理解和使用可能需要一定的 Snakemake 语法基础。</p><p>考虑到 ChIP-seq 下游分析能弄的东西五花八门,所以这篇文章就只介绍到如何产生结果,对于相关结果的解释和分析就各看需求了。</p></body></html>]]></content>
<summary type="html">本文将介绍如何使用 bowtie2 + macs3 分析 ChIP-seq 数据,同时也涉及到报错解决和非模式物种的参数确定等。</summary>
<category term="学习" scheme="https://biojuse.com/categories/%E5%AD%A6%E4%B9%A0/"/>
<category term="生信" scheme="https://biojuse.com/categories/%E5%AD%A6%E4%B9%A0/%E7%94%9F%E4%BF%A1/"/>
<category term="生物信息学" scheme="https://biojuse.com/tags/%E7%94%9F%E7%89%A9%E4%BF%A1%E6%81%AF%E5%AD%A6/"/>
<category term="生信" scheme="https://biojuse.com/tags/%E7%94%9F%E4%BF%A1/"/>
</entry>
<entry>
<title>远程服务器无 root 权限时 LightGBM GPU 版的安装方法</title>
<link href="https://biojuse.com/2024/04/02/%E8%BF%9C%E7%A8%8B%E6%9C%8D%E5%8A%A1%E5%99%A8%E6%97%A0%20root%20%E6%9D%83%E9%99%90%E6%97%B6%20LightGBM%20GPU%20%E7%89%88%E7%9A%84%E5%AE%89%E8%A3%85%E6%96%B9%E6%B3%95/"/>
<id>https://biojuse.com/2024/04/02/%E8%BF%9C%E7%A8%8B%E6%9C%8D%E5%8A%A1%E5%99%A8%E6%97%A0%20root%20%E6%9D%83%E9%99%90%E6%97%B6%20LightGBM%20GPU%20%E7%89%88%E7%9A%84%E5%AE%89%E8%A3%85%E6%96%B9%E6%B3%95/</id>
<published>2024-04-02T13:40:00.000Z</published>
<updated>2024-12-13T02:34:39.618Z</updated>
<content type="html">< for more info. View Jupyter [log](command:jupyter.viewOutput) for further details.</span><br></pre></td></tr></tbody></table></figure></blockquote><p>在上述 CUDA version 编译过程中,如果在 CMake 时发生以下错误:</p><figure class="highlight plaintext"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">x86_64-conda-linux-gnu-cc: error: unrecognized command-line option '-march'</span><br></pre></td></tr></tbody></table></figure><p>解决方案:打开 <code>build</code> 文件夹中的 <code>CMakeCache.txt</code>,搜索 <code>-march</code>,找到类似以下这段的内容:</p><figure class="highlight plaintext"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">//Flags used by the C compiler during all build types.</span><br><span class="line">CMAKE_C_FLAGS:STRING=-march=nocona -mtune=haswell -ftree-vectorize -fPIC -fstack-protector-strong -fno-plt -O2 -ffunction-sections -pipe -isystem /public/home/xxxx/mambaforge/envs/kaggle/include -march=nocona -mtune=haswell -ftree-vectorize -fPIC -fstack-protector-strong -fno-plt -O2 -ffunction-sections -pipe -isystem /public/home/xxxx/mambaforge/envs/ncsvp/include -march</span><br></pre></td></tr></tbody></table></figure><p>将<strong>最后的</strong> <code>-march</code> 删除再重新运行 <code>cmake -DUSE_CUDA=1 ..</code>,如果成功则继续运行 <code>make -j4</code>。</p><p>如果与上述相关内容有所出入,则可自己根据具体情况尝试修改 <code>march</code> 相关内容。</p><h3 id="安装"><a href="#安装" class="headerlink" title="安装"></a>安装</h3><p>编译完成后,你已经可以使用 Linux 下的 LightGBM,如果要继续安装 Python LightGBM,则还需进行以下操作:</p><p>返回到 <code>LightGBM</code> 目录,并安装 Python 接口:</p><figure class="highlight shell"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta prompt_">$ </span><span class="language-bash"><span class="built_in">cd</span> ../</span></span><br><span class="line"><span class="meta prompt_">$ </span><span class="language-bash">sh ./build-python.sh install --precompile</span></span><br></pre></td></tr></tbody></table></figure><p>安装好 LightGBM Module 后,就可以使用 <code>device='CUDA'</code> 调用 GPU 进行加速。</p><p>关于以上流程,更详细内容可以移至文章开头的 github issue 查看。</p><h2 id="后记"><a href="#后记" class="headerlink" title="后记"></a>后记</h2><p>其实去年我也尝试过在服务器上安装 LightGBM GPU,但折腾了一段时间并没有搞成功,所以也就放弃了。</p><p>那么为什么现在又弄了呢?这个动机可以追溯到上个月在 Kaggle 上打 PlayGround 竞赛的时候。因为 LightGBM 没有 GPU 加速实在是跑的太慢,而我加入竞赛的时间又比较晚(只剩六七天就结束了),所以我选择了使用自己的电脑来做 XGBoost 和 LightGBM GPU 的 HPO。所幸最后的结果是不错的 —— 最好的结果可以排第八名,可惜选错了 submission<del>(盲目相信 public score 的代价)</del>。</p><p>离题了,如上所述,虽然拿着自己电脑的 2060 跑确实比 CPU 要快很多,但是每天拿着一个游戏本跑来跑去,还要早去课室为它霸占充电位以及忍受它狂躁的风扇声和令人发指的续航能力,实在是让人有些心力交瘁。看着服务器上三台 3090,我还是下定决心在服务器上也安装一个。</p><p>所幸最后安装成功,在这里记录下自己走的弯路,希望能帮助别人省些时间……</p></body></html>]]></content>
<summary type="html">本文将介绍如何在 Linux 系统上无 root 权限的情景下安装 LightGBM GPU,从而实现使用服务器显卡进行 GPU 加速。</summary>
<category term="学习" scheme="https://biojuse.com/categories/%E5%AD%A6%E4%B9%A0/"/>
<category term="机器学习" scheme="https://biojuse.com/categories/%E5%AD%A6%E4%B9%A0/%E6%9C%BA%E5%99%A8%E5%AD%A6%E4%B9%A0/"/>
</entry>
<entry>
<title>全基因组 CpG (or nonCpG) 位点 bed 文件的获取方式</title>
<link href="https://biojuse.com/2024/03/18/%E5%85%A8%E5%9F%BA%E5%9B%A0%E7%BB%84%20CpG%20(or%20nonCpG)%20%E4%BD%8D%E7%82%B9%20bed%20%E6%96%87%E4%BB%B6%E7%9A%84%E8%8E%B7%E5%8F%96%E6%96%B9%E5%BC%8F/"/>
<id>https://biojuse.com/2024/03/18/%E5%85%A8%E5%9F%BA%E5%9B%A0%E7%BB%84%20CpG%20(or%20nonCpG)%20%E4%BD%8D%E7%82%B9%20bed%20%E6%96%87%E4%BB%B6%E7%9A%84%E8%8E%B7%E5%8F%96%E6%96%B9%E5%BC%8F/</id>
<published>2024-03-18T07:00:00.000Z</published>
<updated>2024-03-20T08:16:30.929Z</updated>
<content type="html"><![CDATA[<html><head></head><body><p><a href="https://en.wikipedia.org/wiki/CpG_site">CpG 位点</a>是基因组上的一种特殊序列,它在 DNA 的结构和功能中起着重要作用。其组成和甲基化影响着基因组上各区域的调控,是表观遗传学领域中重要的研究目标。</p><p>本文中的脚本主要用于提取基因组中 CpG 位点的位置,以方便一些着重于 CpG 位点的下游分析进行。此外在部分场景下,我们可能希望排除 CpG 位点进行分析(因为其独特的性质例如高突变率等),因此该脚本也可产生 AT&CG(nonCpG) 位点信息文件。</p><p>需要准备的文件和条件有:</p><ul><li>基因组序列文件</li><li>Biopython 库(<code>pip install biopython</code>)</li></ul><p>可能需要准备的前置条件:</p><ul><li>已被放置于 <code>$PATH</code> 环境变量中的 <code>bedtools</code></li></ul><p>脚本内容:</p><figure class="highlight python"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">from</span> Bio <span class="keyword">import</span> SeqIO</span><br><span class="line"><span class="keyword">import</span> os</span><br><span class="line"><span class="keyword">import</span> argparse</span><br><span class="line"><span class="keyword">import</span> gzip</span><br><span class="line"><span class="keyword">import</span> subprocess</span><br><span class="line"></span><br><span class="line"><span class="keyword">def</span> <span class="title function_">get_args</span>():</span><br><span class="line"> parser = argparse.ArgumentParser(description=<span class="string">"Use to extract AT/CG(nonCpG) & CpG sites."</span>)</span><br><span class="line"> </span><br><span class="line"> input_group = parser.add_argument_group(<span class="string">"Input"</span>)</span><br><span class="line"> input_group.add_argument(<span class="string">"-g"</span>, <span class="string">"--genome"</span>, required=<span class="literal">True</span>, <span class="built_in">help</span>=<span class="string">"The path of genome sequence file."</span>)</span><br><span class="line"> input_group.add_argument(<span class="string">"-c"</span>, <span class="string">"--chr"</span>, required=<span class="literal">True</span>, <span class="built_in">help</span>=<span class="string">"The target chromosome to extract."</span>)</span><br><span class="line"></span><br><span class="line"> option_group = parser.add_argument_group(<span class="string">"Optional parameters"</span>)</span><br><span class="line"> option_group.add_argument(<span class="string">"--onlycpg"</span>, action=<span class="string">"store_true"</span>, <span class="built_in">help</span>=<span class="string">"Only extract CpG sites."</span>)</span><br><span class="line"> option_group.add_argument(<span class="string">"--merge"</span>, action=<span class="string">"store_true"</span>, <span class="built_in">help</span>=<span class="string">"Use bedtools to merge bed files."</span>)</span><br><span class="line"> option_group.add_argument(<span class="string">"--gzip"</span>, action=<span class="string">"store_true"</span>, <span class="built_in">help</span>=<span class="string">"Use gzip to compress output."</span>)</span><br><span class="line"> option_group.add_argument(<span class="string">"--nosoftmask"</span>, action=<span class="string">"store_true"</span>, <span class="built_in">help</span>=<span class="string">"Remove soft-masked where repeats are in lower-case text."</span>)</span><br><span class="line"></span><br><span class="line"> output_group = parser.add_argument_group(<span class="string">"Output"</span>)</span><br><span class="line"> output_group.add_argument(<span class="string">"-n"</span>, <span class="string">"--name"</span>, <span class="built_in">help</span>=<span class="string">"The name of output file."</span>)</span><br><span class="line"> output_group.add_argument(<span class="string">"-p"</span>, <span class="string">"--path"</span>, <span class="built_in">help</span>=<span class="string">"The path of output file."</span>, default=<span class="string">'./'</span>)</span><br><span class="line"> </span><br><span class="line"> args = parser.parse_args()</span><br><span class="line"> <span class="keyword">if</span> <span class="keyword">not</span> args.name:</span><br><span class="line"> args.name = os.path.splitext(os.path.basename(args.genome))[<span class="number">0</span>]</span><br><span class="line"> </span><br><span class="line"> <span class="keyword">return</span> args</span><br><span class="line"></span><br><span class="line"><span class="keyword">def</span> <span class="title function_">process_command</span>(<span class="params">command</span>):</span><br><span class="line"> result = subprocess.run(command, shell=<span class="literal">True</span>, stdout=subprocess.PIPE, stderr=subprocess.PIPE)</span><br><span class="line"> <span class="keyword">if</span> result.returncode != <span class="number">0</span>:</span><br><span class="line"> <span class="built_in">print</span>(<span class="string">f"Error when executing command: <span class="subst">{command}</span>\n<span class="subst">{result.stderr.decode()}</span>"</span>)</span><br><span class="line"></span><br><span class="line"><span class="keyword">def</span> <span class="title function_">main</span>():</span><br><span class="line"> args = get_args()</span><br><span class="line"></span><br><span class="line"> <span class="keyword">with</span> gzip.<span class="built_in">open</span>(args.genome, <span class="string">"rt"</span>) <span class="keyword">if</span> args.genome.endswith(<span class="string">".gz"</span>) <span class="keyword">else</span> <span class="built_in">open</span>(args.genome, <span class="string">"r"</span>) <span class="keyword">as</span> genome_file:</span><br><span class="line"> chr_num = <span class="string">"chr"</span> + args.<span class="built_in">chr</span>.replace(<span class="string">"chr"</span>, <span class="string">""</span>)</span><br><span class="line"> cpg_bed_name = os.path.join(args.path, <span class="string">f"<span class="subst">{args.name}</span>_<span class="subst">{chr_num}</span>_CpGsites.bed.tmp"</span>)</span><br><span class="line"> atcg_bed_name = os.path.join(args.path, <span class="string">f"<span class="subst">{args.name}</span>_<span class="subst">{chr_num}</span>_ATnonCpGsites.bed.tmp"</span>)</span><br><span class="line"> </span><br><span class="line"> <span class="keyword">with</span> <span class="built_in">open</span>(cpg_bed_name, <span class="string">"w"</span>) <span class="keyword">as</span> cpg_bed, <span class="built_in">open</span>(atcg_bed_name, <span class="string">"w"</span>) <span class="keyword">as</span> atcg_bed:</span><br><span class="line"> <span class="keyword">for</span> record <span class="keyword">in</span> SeqIO.parse(genome_file, <span class="string">"fasta"</span>):</span><br><span class="line"> <span class="keyword">if</span> record.<span class="built_in">id</span> != args.<span class="built_in">chr</span>:</span><br><span class="line"> <span class="keyword">continue</span></span><br><span class="line"> <span class="keyword">if</span> <span class="keyword">not</span> args.nosoftmask:</span><br><span class="line"> seq = <span class="built_in">str</span>(record.seq).upper()</span><br><span class="line"> <span class="keyword">else</span>:</span><br><span class="line"> seq = <span class="built_in">str</span>(record.seq)</span><br><span class="line"></span><br><span class="line"> <span class="keyword">for</span> i, nuc <span class="keyword">in</span> <span class="built_in">enumerate</span>(seq):</span><br><span class="line"> <span class="keyword">if</span> nuc == <span class="string">"N"</span>:</span><br><span class="line"> <span class="keyword">continue</span></span><br><span class="line"> <span class="keyword">if</span> nuc <span class="keyword">in</span> [<span class="string">"A"</span>, <span class="string">"T"</span>] <span class="keyword">and</span> <span class="keyword">not</span> args.onlycpg:</span><br><span class="line"> atcg_bed.write(<span class="string">f"<span class="subst">{chr_num}</span>\t<span class="subst">{i}</span>\t<span class="subst">{i+<span class="number">1</span>}</span>\n"</span>)</span><br><span class="line"> <span class="keyword">elif</span> nuc <span class="keyword">in</span> [<span class="string">"C"</span>, <span class="string">"G"</span>]:</span><br><span class="line"> <span class="keyword">if</span> (nuc == <span class="string">"C"</span> <span class="keyword">and</span> i + <span class="number">1</span> < <span class="built_in">len</span>(seq) <span class="keyword">and</span> seq[i + <span class="number">1</span>] == <span class="string">"G"</span>) <span class="keyword">or</span> (nuc == <span class="string">"G"</span> <span class="keyword">and</span> i > <span class="number">0</span> <span class="keyword">and</span> seq[i - <span class="number">1</span>] == <span class="string">"C"</span>):</span><br><span class="line"> cpg_bed.write(<span class="string">f"<span class="subst">{chr_num}</span>\t<span class="subst">{i}</span>\t<span class="subst">{i+<span class="number">1</span>}</span>\n"</span>)</span><br><span class="line"> <span class="keyword">elif</span> <span class="keyword">not</span> args.onlycpg:</span><br><span class="line"> atcg_bed.write(<span class="string">f"<span class="subst">{chr_num}</span>\t<span class="subst">{i}</span>\t<span class="subst">{i+<span class="number">1</span>}</span>\n"</span>)</span><br><span class="line"> </span><br><span class="line"> <span class="keyword">for</span> bed_file <span class="keyword">in</span> [cpg_bed_name, atcg_bed_name] <span class="keyword">if</span> <span class="keyword">not</span> args.onlycpg <span class="keyword">else</span> [cpg_bed_name]:</span><br><span class="line"> outfile = bed_file.replace(<span class="string">".tmp"</span>, <span class="string">""</span>)</span><br><span class="line"> <span class="keyword">if</span> args.merge:</span><br><span class="line"> command = <span class="string">f"bedtools merge -i <span class="subst">{bed_file}</span> > <span class="subst">{outfile}</span> && rm <span class="subst">{bed_file}</span>"</span></span><br><span class="line"> <span class="keyword">else</span>:</span><br><span class="line"> command = <span class="string">f"mv <span class="subst">{bed_file}</span> <span class="subst">{outfile}</span>"</span></span><br><span class="line"> process_command(command)</span><br><span class="line"> <span class="keyword">if</span> args.gzip:</span><br><span class="line"> process_command(<span class="string">f"gzip -f <span class="subst">{outfile}</span>"</span>)</span><br><span class="line"> </span><br><span class="line"> <span class="keyword">if</span> args.onlycpg:</span><br><span class="line"> os.remove(atcg_bed_name)</span><br><span class="line"></span><br><span class="line"><span class="keyword">if</span> __name__ == <span class="string">"__main__"</span>:</span><br><span class="line"> main()</span><br></pre></td></tr></tbody></table></figure><p>将上述内容保存在一个名为 <code>get_sites.py</code> 的文件内,或者点击<a href="https://github.com/JuseTiZ/PyScript-for-CT/blob/main/get_sites.py">此处</a>下载。</p><p>运行示例(以 hg38 人类基因组为例,提取其在 21 号染色体上的 CpG 位点位置信息):</p><figure class="highlight shell"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta prompt_">$ </span><span class="language-bash">python get_sites.py -g hg38.fa -c chr21 --merge --gzip -n GRCh38</span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">python get_sites.py -g [sequence file] -c [chr] --merge --gzip -n [outname]</span></span><br></pre></td></tr></tbody></table></figure><p>最后将会得到名为 <code>GRCh38_chr21_ATnonCpGsites.bed.gz</code> 和 <code>GRCh38_chr21_CpGsites.bed.gz</code> 的文件,以下是各参数说明:</p><ul><li><code>-g</code> 指定参考基因组序列文件,<code>.gz</code> 压缩格式可以被自动识别。</li><li><code>-c</code> 指定要提取位点信息的染色体,需和序列文件中的序列 id 一致。</li><li><code>--merge</code> 在提取完位点信息后,调用 <code>bedtools</code> 对输出文件进行合并,将每行 1bp 的 bed 文件合并为区间。该选项要求 <code>bedtools</code> 可以直接调用,否则会出现错误。bedtools 的安装可以直接通过 <code>conda install -c bioconda bedtools</code> 实现。</li><li><code>--gzip</code> 在提取完位点信息后(如果指定了 <code>--merge</code> 则在合并后),对输出文件进行压缩。</li><li><code>-n</code> 指定输出文件的前缀。如果命令中未给定,则默认为序列文件的前缀。</li><li><code>-p</code> 指定输出文件的路径。如果命令中未给定,则默认为运行脚本时所处的路径。</li></ul><p>此外,如果在运行脚本时指定了 <code>--onlycpg</code>,则仅产生 CpG 位点位置文件。如果在运行脚本时指定了 <code>--nosoftmask</code>,则跳过<a href="https://grch37.ensembl.org/info/genome/genebuild/assembly_repeats.html">软掩蔽区域</a>。</p><p>因为该脚本针对特定染色体进行,因此可以批量运行脚本以同时处理多条染色体,示例:</p><figure class="highlight shell"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta prompt_">$ </span><span class="language-bash"><span class="keyword">for</span> i <span class="keyword">in</span> {1..23};</span></span><br><span class="line">do</span><br><span class="line">python get_sites.py -g hg38.fa -c chr"$i" --merge --gzip -n GRCh38 &</span><br><span class="line">done</span><br></pre></td></tr></tbody></table></figure><p>请保证计算机或服务器有足够的 CPU 和内存进行批量运行,此处更建议使用 <code>parallel</code> 来进行并行数量控制。如果在服务器上有作业调度系统,也可以合理利用,例如 slurm 的作业数组等,以下是一个 slurm 作业数组运行的示例:</p><figure class="highlight shell"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta prompt_">#</span><span class="language-bash">!/bin/bash</span></span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_">#</span><span class="language-bash">SBATCH --job-name=getsites</span></span><br><span class="line"><span class="meta prompt_">#</span><span class="language-bash">SBATCH --nodelist=yournode</span></span><br><span class="line"><span class="meta prompt_">#</span><span class="language-bash">SBATCH --ntasks=1</span></span><br><span class="line"><span class="meta prompt_">#</span><span class="language-bash">SBATCH --array=1-23%10</span></span><br><span class="line"><span class="meta prompt_">#</span><span class="language-bash">SBATCH --mail-user=youremail</span></span><br><span class="line"><span class="meta prompt_">#</span><span class="language-bash">SBATCH --mail-type=END</span></span><br><span class="line"></span><br><span class="line">python get_sites.py -g hg38.fa -c chr"$SLURM_ARRAY_TASK_ID" --merge --gzip -n GRCh38</span><br></pre></td></tr></tbody></table></figure><p>产生结果示例:</p><figure class="highlight shell"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta prompt_">$ </span><span class="language-bash">zcat GRCh38_chr21_CpGsites.bed.gz | <span class="built_in">head</span> -n 5</span></span><br></pre></td></tr></tbody></table></figure><figure class="highlight plaintext"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">chr21 5010008 5010010</span><br><span class="line">chr21 5010053 5010055</span><br><span class="line">chr21 5010215 5010217</span><br><span class="line">chr21 5010331 5010333</span><br><span class="line">chr21 5010335 5010337</span><br></pre></td></tr></tbody></table></figure><h2 id="后记"><a href="#后记" class="headerlink" title="后记"></a>后记</h2><p>虽说这半年已经写了非常多的 script,但是翻来翻去感觉都属于针对性过强的类型,除了我大概率也没有人能用得上。因此最后只能选定本文中这个短小精悍<del>(没啥难度)</del>的脚本作为分享<del>(水文)</del>,或许能帮到有需要的人。</p><p>此外也还有一个和本文类似的脚本,主要用来提取全基因组上所有四倍简并位点的位置信息。之后如果有需要的话会补充在这篇文章里面。</p></body></html>]]></content>
<summary type="html">在制作 bw 文件时我们可能需要用到特定的位点,本文将介绍获得基因组上 CpG 位点信息的方法。</summary>
<category term="学习" scheme="https://biojuse.com/categories/%E5%AD%A6%E4%B9%A0/"/>
<category term="杂项" scheme="https://biojuse.com/categories/%E5%AD%A6%E4%B9%A0/%E6%9D%82%E9%A1%B9/"/>
</entry>
<entry>
<title>Clash for windows 中让某些域名绕过代理</title>
<link href="https://biojuse.com/2024/02/20/Clashforwindow/"/>
<id>https://biojuse.com/2024/02/20/Clashforwindow/</id>
<published>2024-02-20T13:00:00.000Z</published>
<updated>2024-07-26T01:47:01.718Z</updated>
<content type="html"><![CDATA[<html><head></head><body><p>众所周知,Clash for windows 的作者已经删库跑路许久,而在使用这个软件到现在我也终于忍不住想要解决某些域名绕过代理的问题。我已经受够了每次进 web of science 查文献亦或是在 Science 官网上看文章都要关掉代理才能进去的痛楚了。</p><p>在搜索网上的解决方案时,部分文章说可以在 Settings>System Proxy>Bypass Domain/IPNet 中设置相应域名解决,但是我发现我新加域名进入后我的梯子就会直接整个没用。当然这发生在大约半年前的时候,那时的我选择了将这件事暂时搁置,直到现在。</p><p>这次再次寻找解决方法,终于找到个适用于我的,趁这个机会写在此处,希望能帮到其他有需求的朋友,当然也有可能某天这篇文章会因为不可抗力消失。</p><h3 id="解决方案"><a href="#解决方案" class="headerlink" title="解决方案"></a>解决方案</h3><p>首先点开 <code>Profiles</code>,选择自己的梯子右键,点开 <code>Parsers</code> 并选择 <code>Edit Parsers</code>。</p><p><img src="/pic2/cfw1.png"></p><p>将里面的内容处理成以下格式:</p><figure class="highlight plaintext"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">parsers: # array</span><br><span class="line"> - url: 梯子 url</span><br><span class="line"> yaml:</span><br><span class="line"> prepend-rules:</span><br><span class="line"> - DOMAIN-SUFFIX,www.science.org,DIRECT</span><br></pre></td></tr></tbody></table></figure><p><img src="/pic2/cfw2.png"></p><p>将 url 后的内容换成自己的梯子 url,注意<strong>不要破坏缩进,yaml 和 url 需要对齐才能正常发挥作用</strong>,后面可以通过以下格式在 prepend-rules 下添加域名:</p><ul><li>DOMAIN-SUFFIX,域名,DIRECT</li></ul><p>对于 Web of science,我填入以下几个规则后成功让 Web of science 绕过代理,但不清楚其中最关键的是哪些(亦或是都需要):</p><figure class="highlight plaintext"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">- DOMAIN-SUFFIX,snowplow.apps.clarivate.com,DIRECT</span><br><span class="line">- DOMAIN-SUFFIX,access.clarivate.com,DIRECT</span><br><span class="line">- DOMAIN-SUFFIX,www.webofscience.com,DIRECT</span><br><span class="line">- DOMAIN-SUFFIX,snowplow-collector.userintel.prod.sp.aws.clarivate.net,DIRECT</span><br><span class="line">- DOMAIN-SUFFIX,www.webofknowledge.com,DIRECT</span><br></pre></td></tr></tbody></table></figure><p>有需求的朋友可以将上面这段复制到 <code>prepend-rules</code> 之后。</p></body></html>]]></content>
<summary type="html">绕过域名代理,让不需要梯子的网站实现不翻梯子自由。</summary>
<category term="学习" scheme="https://biojuse.com/categories/%E5%AD%A6%E4%B9%A0/"/>
<category term="杂项" scheme="https://biojuse.com/categories/%E5%AD%A6%E4%B9%A0/%E6%9D%82%E9%A1%B9/"/>
</entry>
</feed>