前面已经完成了qiime2-sidle插件的安装,测试方法就是输入qiime:
sidle Plugin for kmer-based marker gene reconstruction 出现了上面的选项,应该就说明已经安装成功了。
数据库准备 数据库准备是一劳永逸的,前面我们已经完成了数据库过滤的步骤
准备一个区域数据库 这一步是提取一个区域的数据库,基于K-mer,为了提升内存效率,把简并碱基和重复kmer作为一条序列。
# 首先,使用feature-classifier插件的extract-reads提取,那么对于6V区的SMURF应该是:# 2.2 序列提取# 74f 315R V1-V2qiime feature-classifier extract-reads \ --i-sequences sidle-db-full-degen-filtered-phylum-def-sequences.qza \ --p-f-primer TGGCGGACGGGTGAGTAA \ --p-r-primer CTGCTGCCTCCCGTAGGA \ --o-reads sidle-db-filt-j1.qza # 316F 484R V3部分 qiime feature-classifier extract-reads \ --i-sequences sidle-db-full-degen-filtered-phylum-def-sequences.qza \ --p-f-primer TCCTACGGGAGGCAGCAG \ --p-r-primer TATTACCGCGGCTGCTGG \ --o-reads sidle-db-filt-j2.qza # 486F 650R V3部分-v4部分 qiime feature-classifier extract-reads \ --i-sequences sidle-db-full-degen-filtered-phylum-def-sequences.qza \ --p-f-primer CAGCAGCCGCGGTAATAC \ --p-r-primer CGCATTTCACCGCTACAC \ --o-reads sidle-db-filt-j3.qza # 752F 911 R V5 qiime feature-classifier extract-reads \ --i-sequences sidle-db-full-degen-filtered-phylum-def-sequences.qza \ --p-f-primer AGGATTAGATACCCTGGT \ --p-r-primer GAATTAAACCACATGCTC \ --o-reads sidle-db-filt-j4.qza # 901F 1057R V6 qiime feature-classifier extract-reads \ --i-sequences sidle-db-full-degen-filtered-phylum-def-sequences.qza \ --p-f-primer GCACAAGCGGTGGAGCAT \ --p-r-primer CGCTCGTTGCGGGACTTA \ --o-reads sidle-db-filt-j5.qza # 1143F 1336R V7 V8 qiime feature-classifier extract-reads \ --i-sequences sidle-db-full-degen-filtered-phylum-def-sequences.qza \ --p-f-primer AGGAAGGTGGGGATGACG \ --p-r-primer CCCGGGAACGTATTCACC \ --o-reads sidle-db-filt-j6.qza1234567891011121314151617181920212223242526272829303132333435363738 上sidle插件,文档介绍这里和原方法略有区别,原算法是允许2个碱基不一致,而这里用的80%,作者说可以用–p-identity 参数,但是没找到。。。
# 可以给region起个别名,看喜好起即可 # P1 qiime sidle prepare-extracted-region \ --i-sequences sidle-db-filt-j1.qza \ --p-region "P1" \ --p-fwd-primer TGGCGGACGGGTGAGTAA \ --p-rev-primer CTGCTGCCTCCCGTAGGA \ --p-trim-length 100 \ --o-collapsed-kmers sidle-db-P1-100nt-kmers.qza \ --o-kmer-map sidle-db-P1-100nt-map.qza # P2 qiime sidle prepare-extracted-region \ --i-sequences sidle-db-filt-j2.qza \ --p-region "P2" \ --p-fwd-primer TCCTACGGGAGGCAGCAG \ --p-rev-primer TATTACCGCGGCTGCTGG \ --p-trim-length 100 \ --o-collapsed-kmers sidle-db-P2-100nt-kmers.qza \ --o-kmer-map sidle-db-P2-100nt-map.qza # P3 qiime sidle prepare-extracted-region \ --i-sequences sidle-db-filt-j3.qza \ --p-region "P3" \ --p-fwd-primer CAGCAGCCGCGGTAATAC \ --p-rev-primer CGCATTTCACCGCTACAC \ --p-trim-length 100 \ --o-collapsed-kmers sidle-db-P3-100nt-kmers.qza \ --o-kmer-map sidle-db-P3-100nt-map.qza # P4 qiime sidle prepare-extracted-region \ --i-sequences sidle-db-filt-j4.qza \ --p-region "P4" \ --p-fwd-primer AGGATTAGATACCCTGGT \ --p-rev-primer GAATTAAACCACATGCTC \ --p-trim-length 100 \ --o-collapsed-kmers sidle-db-P4-100nt-kmers.qza \ --o-kmer-map sidle-db-P4-100nt-map.qza # P5 qiime sidle prepare-extracted-region \ --i-sequences sidle-db-filt-j5.qza \ --p-region "P5" \ --p-fwd-primer GCACAAGCGGTGGAGCAT \ --p-rev-primer CGCTCGTTGCGGGACTTA \ --p-trim-length 100 \ --o-collapsed-kmers sidle-db-P5-100nt-kmers.qza \ --o-kmer-map sidle-db-P5-100nt-map.qza # P6 qiime sidle prepare-extracted-region \ --i-sequences sidle-db-filt-j6.qza \ --p-region "P6" \ --p-fwd-primer AGGAAGGTGGGGATGACG \ --p-rev-primer CCCGGGAACGTATTCACC \ --p-trim-length 100 \ --o-collapsed-kmers sidle-db-P6-100nt-kmers.qza \ --o-kmer-map sidle-db-P6-100nt-map.qza 这步会输出含简并的序列,移除重复序列和一个kmer映射文件,可以qiime可视化,给出原始数据库序列名称(db-seq)、序列名称(seq-name)、区域标识(Kmer)、引物(fwd-primer和rev-primer)、区域(Region)和序列长度(Trim-Length)之间的关系。
# 如果参考序列不能覆盖正反向引物,可以把--p-trim-length设置为负值,增加个参数--p-reverse-complement-result --i-sequences sidle-db-filt-jl.qza \ --p-region "Batman" \ --p-fwd-primer TATTACCGCGGCTGCTGG \ --p-rev-primer TCCTACGGGAGGCAGCAG \ --p-trim-length -100 \ --p-reverse-complement-result \ --o-collapsed-kmers sidle-db-batman-100nt-kmers.qza \ --o-kmer-map sidle-db-batman-100nt-map.qza
完成了前面的数据库准备,下面就是reads的准备,基本过程就是把reads拆成对应不同引物的几个部分,后面再重建合并在一起啦。首先声明,这个方法还在开发和完善之路,最近一次更新在这个月,可能结果会有变动,应该说还处于beta版本中,不建议在生产环境中使用。 这里就有几种情况啦,一种是已经每个样本每个V区拆好的数据,另一种是每个样本几个V区混在一起的数据,或者完全没拆的数据。这里根据SMURF的示例,按第二种情况进行,应该是最常见的情况。下面是具体步骤:
Reads准备 尽管SMURF依赖于质控过滤,还是推荐继续使用去噪的方法。推荐使用现有的方法进行预处理,当然可以用别的方法替代,这只是一个例子。 简单来说步骤就是分而治之,最后合并,作者也说了这个方法其实是可以用来meta分析的,但是我还是对meta分析持怀疑态度的,毕竟每个实验室使用的方法区别那么大,样本保存条件不一样,提取方法有区别,再有就是PCR扩增区域、引物和酶也是有区别,还有建库方法的不一致,这样下来,区别差到天涯海角了,meta分析只能得出一个有问题的结论吧!16S/宏基因组,微生物、微生态的研究亟需一个标准化吧,否则每个结果只能对每个实验室的方法负责了,完全失去了可比性。对于这篇文章中使用的引物,我发现多数不是最常用的引物,所以结果是不是有偏差,也是一个值得思考的问题呀! 好,回归正题!
拆数据 我们这里用的是PE150的示例数据,没有进行样本拆分,那么使用多q2-cutadapt的trim-paired切去引物,–p-discard-untrimmed移除没有引物的序列。如果正反向序列不能拼接,当做单独的序列进行处理。
首先,导入数据,导入前重命名一下,以适应导入格式要求,个人觉得这样导入最简单。
# 重命名 mv Example_L001_R1_001.fastq.gz 1_Example_L001_R1_001.fastq.gz mv Example_L001_R2_001.fastq.gz 1_Example_L001_R2_001.fastq.gz # 导入 qiime tools import \ --type 'SampleData[PairedEndSequencesWithQuality]' \ --input-path . \ --input-format CasavaOneEightSingleLanePerSampleDirFmt \ --output-path demux.qza 拆分区域数据
# P1 qiime cutadapt trim-paired \ --i-demultiplexed-sequences demux.qza \ --p-front-f TGGCGGACGGGTGAGTAA \ --p-front-r CTGCTGCCTCCCGTAGGA \ --p-discard-untrimmed \ --p-error-rate 0.15 \ --o-trimmed-sequences ./P1_demux.qza # P2 qiime cutadapt trim-paired \ --i-demultiplexed-sequences demux.qza \ --p-front-f TCCTACGGGAGGCAGCAG \ --p-front-r TATTACCGCGGCTGCTGG \ --p-discard-untrimmed \ --p-error-rate 0.15 \ --o-trimmed-sequences ./P2_demux.qza # P3 qiime cutadapt trim-paired \ --i-demultiplexed-sequences demux.qza \ --p-front-f CAGCAGCCGCGGTAATAC \ --p-front-r CGCATTTCACCGCTACAC \ --p-discard-untrimmed \ --p-error-rate 0.15 \ --o-trimmed-sequences ./P3_demux.qza # P4 qiime cutadapt trim-paired \ --i-demultiplexed-sequences demux.qza \ --p-front-f AGGATTAGATACCCTGGT \ --p-front-r GAATTAAACCACATGCTC \ --p-discard-untrimmed \ --p-error-rate 0.15 \ --o-trimmed-sequences ./P4_demux.qza # P5 qiime cutadapt trim-paired \ --i-demultiplexed-sequences demux.qza \ --p-front-f GCACAAGCGGTGGAGCAT \ --p-front-r CGCTCGTTGCGGGACTTA \ --p-discard-untrimmed \ --p-error-rate 0.15 \ --o-trimmed-sequences ./P5_demux.qza # P6 qiime cutadapt trim-paired \ --i-demultiplexed-sequences demux.qza \ --p-front-f AGGAAGGTGGGGATGACG \ --p-front-r CCCGGGAACGTATTCACC \ --p-discard-untrimmed \ --p-error-rate 0.15 \ --o-trimmed-sequences ./P6_demux.qza 从得到的数据看,各个区域的数据分布不是太一致,是不是多重PCR做的,引物偏好性有一定影响,所以这里面的影响也值得思考哈。
-rw-r--r-- 1 zjd zjd 2.6M Jan 31 11:00 P1_demux.qza -rw-r--r-- 1 zjd zjd 466K Jan 31 11:32 P2_demux.qza -rw-r--r-- 1 zjd zjd 13M Jan 31 11:33 P3_demux.qza -rw-r--r-- 1 zjd zjd 11M Jan 31 11:34 P4_demux.qza -rw-r--r-- 1 zjd zjd 3.5M Jan 31 11:34 P5_demux.qza -rw-r--r-- 1 zjd zjd 22M Jan 31 11:35 P6_demux.qza 去噪 这里发现官方推荐的两去噪方法均报错呢,于是用了qiime2 vsearch解决。
# ######## # Vsearch ########### for i in {1..6} do qiime vsearch join-pairs \ --i-demultiplexed-seqs P${i}_demux.qza \ --o-joined-sequences P${i}_demux-joined.qzatime qiime quality-filter q-score \ --i-demux P${i}_demux-joined.qza \ --o-filtered-sequences P${i}_demux-joined-filtered.qza \ --o-filter-stats P${i}_demux-joined-filter-stats.qza qiime vsearch dereplicate-sequences \ --i-sequences P${i}_demux-joined-filtered.qza \ --o-dereplicated-table P${i}_table.qza \ --o-dereplicated-sequences P${i}_rep-seqs.qzaecho vsearch denovo startdate#denovo pick otuqiime vsearch cluster-features-de-novo \ --i-table P${i}_table.qza \ --i-sequences P${i}_rep-seqs.qza \ --p-perc-identity 0.99 \ --o-clustered-table P${i}_table-dn-99.qza \ --o-clustered-sequences P${i}_rep-seqs-dn-99.qza echo vsearch end done 以下是我走过的弯路(可以略过): dada2和deblur,两个算法,习惯于用第一个啦,遗憾报错,换了个2020.2月版本依然,上后者。
#dada2for i in {1..6} do qiime dada2 denoise-paired \ --i-demultiplexed-seqs P${i}_demux.qza \ --p-trim-left-f 0 \ --p-trim-left-r 0 \ --p-trunc-len-f 0 \ --p-trunc-len-r 0 \ --o-table ${i}_table.qza \ --o-representative-sequences P${i}_rep-seqs.qza \ --o-denoising-stats P${i}_denoising-stats.qza done # Plugin error from dada2: # An error was encountered while running DADA2 in R (return code 1), please inspect stdout and stderr to learn more.# Debug info has been saved to /tmp/qiime2-q2cli-err-wqromfhv.log12345678910111213141516 deblur
##############选项2,deblur,耗时也较长# 序列质控6152.75s for i in {1..6} do qiime vsearch join-pairs \ --i-demultiplexed-seqs P${i}_demux.qza \ --o-joined-sequences P${i}_demux-joined.qzatime qiime quality-filter q-score \ --i-demux P${i}_demux-joined.qza \ --o-filtered-sequences P${i}_demux-joined-filtered.qza \ --o-filter-stats P${i}_demux-joined-filter-stats.qza# # # deblur去噪生成特征表time qiime deblur denoise-16S \ --i-demultiplexed-seqs P${i}_demux-joined.qza \ --p-sample-stats \ --o-representative-sequences P${i}_rep-seqs-deblur.qza \ --o-table P${i}_table-deblur.qza \ --o-stats P${i}_deblur-stats.qza done time qiime deblur denoise-16S \ --i-demultiplexed-seqs P1_demux-joined-filtered.qza \ --p-trim-length 236 \ --p-sample-stats \ --o-representative-sequences P1_rep-seqs-deblur.qza \ --o-table P1_table-deblur.qza \ --o-stats P1_deblur-stats.qza qiime sidle trim-dada2-posthoc \ --i-table table-dada2.qza \ --i-representative-sequences rep-seqs-dada2.qza \ --p-trim-length 100 \ --o-trimmed-table table-dada2-100nt.qza \ --o-trimmed-representative-sequences rep-seq-dada2-100nt.qza qiime demux summarize \ --i-data P1_demux-joined.qza --o-visualization demux-subsample.qzv 继续前面的文档学习,地址地这里啦! 官方文档 SMURF 算法的核心是基于基于 kmer 的短区域重建到全长框架中。有两个步骤,首先是ASV在单个区域基于kmer进行比对,然后完整的序列集组装成重建的计数表。
区域比对 第一步是每个区域把序列比对到数据库,使用 align-regional-kmers
命令,我们前面使用 --kmer-db-fp
选项设置了数据库,使用 --rep-seq-fp
选项传递ASV序列,最后是区域定义,来自前面你给区域起的别名,要完全一致。比对是一个开心的可并行任务,我们可以通过多多线程提升性能( --p-n-workers
参数)。
# 继续循环解决啦for i in {1..6} doqiime sidle align-regional-kmers \ --i-kmers ../database/../database/sidle-db-P${i}-100nt-kmers.qza \ --i-rep-seq P${i}_rep-seq-100nt.qza \ --p-region P${i} \ --p-n-workers 4 \ --o-regional-alignment alignment/P${i}_align-map.qza done 这将输出一个对齐文件和任何不会与数据库对齐的 ASV 序列,以保留您自己的记录。另外,你可以设置与参考序列不同的长度,使用 --p-max-mismatch
参数(2-130)ps.我有点怀疑这样做有没有问题呀! 您可能会发现,如果您有更长的 kmers,您可能需要相应地增加此参数。较低的(更严格的)值将增加丢弃的序列的数量,而较高的数字可能意味着您的匹配项质量较低。您可能会发现,如果您有更长的 kmers,您可能需要相应地增加此参数。较低的(更严格的)值将增加丢弃的序列的数量,数字越高可能意味着匹配项的质量越低。
表重建 这步里,首先,是区域片段重新比对到完整的数据库序列,然后相对丰度使用一个优化的步骤进行计算,最后生成重建的计数表。 per-nucleotide-error
参数和 maximum-mismatch
参数,决定了比对和错配的比例,Ps.我的理解是过程中会产生错误累积。 min-abundance
决定了要排队的数据库序列的最小丰度,这个参数在某种意义上取决于测序深度和你的偏好。 最后,还是可以通过多多线程提升性能( --p-n-workers
参数)。 下面就是重建命令了,有点长呀:
qiime sidle reconstruct-counts \ --p-region P1 \ --i-kmer-map ../database/sidle-db-P1-100nt-map.qza \ --i-regional-alignment P1_align-map.qza \ --i-regional-table P1_table-100nt.qza \ --p-region P2 \ --i-kmer-map ../database/sidle-db-P2-100nt-map.qza \ --i-regional-alignment P2_align-map.qza\ --i-regional-table P2_table-100nt.qza \ --p-region P3 \ --i-kmer-map ../database/sidle-db-P3-100nt-map.qza \ --i-regional-alignment P3_align-map.qza \ --i-regional-table P3_table-100nt.qza \ --p-region P4 \ --i-kmer-map ../database/sidle-db-P4-100nt-map.qza \ --i-regional-alignment P4_align-map.qza \ --i-regional-table P4_table-100nt.qza \ --p-region P5 \ --i-kmer-map ../database/sidle-db-P5-100nt-map.qza \ --i-regional-alignment P5_align-map.qza \ --i-regional-table P5_table-100nt.qza \ --p-n-workers 8 \ --o-reconstructed-table league_table.qza \ --o-reconstruction-summary league_summary.qza \ --o-reconstruction-map league_map.qza 好像这步是超级消耗资源的,我设置了个8核心,资源消耗竟然是*5的,用上了全部40核心的资源。。。不过几分钟就结束了,那么如果设置1个核心,可能是需要8倍时间的。 该命令将生成一个计数表、一个包含有关映射到某个区域的数据库Kmer数量以及ASV ID 的详细信息的文件,以及一个需要进行分类重建的映射。
#可视化看下 qiime feature-table summarize \ --i-table reconstruction/league_table.qza \ --o-visualization reconstruction/league_table.qzv 这里我是用了一个样本,133个汇总的feature(也就是以前的OTU),40598条等效数据库序列。 您会注意到一些功能ID包含|字符,例如,1764594|195532|4471854。这意味着这两个数据库的序列在重建过程中不能被解析 ,因此我们将该序列分配给这两个区域。重建中使用的区域越多,就越有可能准确地重建数据库序列。 第二个输出是summary 。总结可以用来评估重建的质量;更多细节见SMURF文章 原稿 。默认情况下,摘要会将退化kmer视为唯一序列;您可以使用 count-degenerates
参数更改行为;如果为false,则仅当kmer属于唯一参考序列时才会对其进行计数。您可以通过将元数据制表来查看摘要。
# 汇总摘要 qiime metadata tabulate \ --m-input-file league_summary.qza \ --o-visualization league_summary.qzv 几个V区的计数明细和汇总
物种重建 重建特征表之后,需要重建物种,特别的,如果多个数据库序列不能得到处理时。该功能获取重建过程中生成的数据库映射和与数据库相关联的分类,并返回重建的分类。 有三种可能,第一,有相同的全部物种分类信息;第二,在一些点上有区别;第三,前面一直相同,直到一个缺失。 相同的情况最简单,二取一即可。有些情况下,可能物种分类在高水平上(这里是种)会不一样,例如下面这个,这种情况下会取到属,而不是种。
1236 k__Bacteria; p__Firmictues; c__Clostridia; o__Clostridiales; f__Lachnospiraceae; g__Blautia; s__obeum 1237 k__Bacteria; p__Firmictues; c__Clostridia; o__Clostridiales; f__Lachnospiraceae; g__Roseburia; s__12 --database
参数允许选择一个数据库进行,如 greengenes, silva 或不提供。如果是greengenes 或 silva,一些专门的数据库清理将会自动进行,特别是缺失和不明处理参数。例如:
k__Bacteria; p__Proteobacteria; c__Gammaproteobacteria; o__Entrobacteriales; f__Enterobacteriaceae; g__; s__1 将会整理成:
k__Bacteria; p__Proteobacteria; c__Gammaproteobacteria; o__Entrobacteriales; f__Enterobacteriaceae; g__unsp. f. Enterobacteriaceae; s__unsp. f. Enterobacteriaceae1 这里我们用的是greengenes,
qiime sidle reconstruct-taxonomy \ --i-reconstruction-map league_map.qza \ --i-taxonomy 。../database/sidle-db-taxonomy.qza \ --p-database 'greengenes' \ --p-define-missing 'inherit' \ --o-reconstructed-taxonomy ./league_taxonomy.qza 进化树重建 最后一步便是重建进化树了,如果不能解析参考序列,则不能简单地从数据库继承系统发育树。因此,我们需要重建一个新的系统树。我们以两种方式处理序列:
我们可以随机选择一个序列来映射重建的区域。然而,当有几个序列组合在一起时,这可能不起作用。因此,如果我们不能解析数据库序列,我们可以从组合的数据中计算一个融合序列 ,在我们能够绘制的区域中提取它们,然后这些一致的序列可以被插入到使用SEPP 或类似的系统发育参考主干中(必须使用相同的数据库版本)。
因此,第一步,对不能解析的序列重建共识序列,这一步官方教程的结果应该有问题,看报错信息进行了更正。
qiime sidle reconstruct-fragment-rep-seqs \ --p-region P1 \ --i-kmer-map ../database/sidle-db-P1-100nt-map.qza \ --p-region P2 \ --i-kmer-map ../database/sidle-db-P2-100nt-map.qza \ --p-region P3 \ --i-kmer-map ../database/sidle-db-P3-100nt-map.qza \ --p-region P4 \ --i-kmer-map ../database/sidle-db-P4-100nt-map.qza \ --p-region P5 \ --i-kmer-map ../database/sidle-db-P5-100nt-map.qza \ --i-reconstruction-map league_map.qza \ --i-reconstruction-summary league_summary.qza \ --i-aligned-sequences ../database/sidle-db-aligned-sequences.qza \ --o-representative-fragments league-rep-seq-fragments.qza 现在,我们可以将序列放入参考树中了,首先下载参考树:
wget -O "sepp-refs-gg-13-8.qza" \ "https://data.qiime2.org/2020.11/common/sepp-refs-gg-13-8.qza" 然后,插入序列:
qiime fragment-insertion sepp \ --i-representative-sequences league-rep-seq-fragments.qza \ --i-reference-database sepp-refs-gg-13-8.qza \ --o-tree league-tree.qza \ --o-placements league-placements.qza 最后,就可以继续常规的qiime2分析流程了,多样性,统计等等,能不能用picrust2分析呢?或许也可以的。
好了,一波三折,终于完成了这个教程的学习,不得不说这个技术好像还不够成熟,特别是qiime2的这个插件。
转载本文请联系原作者获取授权,同时请注明本文来自赵加栋科学网博客。 链接地址: https://blog.sciencenet.cn/blog-623545-1270944.html
上一篇:
SMURF(5R)-Science封面文章使用的16S新流程(二) 下一篇:
Kraken2 Vs qiime2 16S物种注释