单细胞转录组中转座元件表达定量:从注释处理到矩阵构建的完整流程
2026/9/16 16:10:06 网站建设 项目流程

简介:本资源是一套面向生物信息学研究者与单细胞数据分析人员的转座元件(TEs)表达量化工具源码,专为解决单细胞测序数据中TEs异质性表达难以精准捕获的技术难点而设计。包内共42个文件,涵盖21个Python脚本(实现核心算法与数据处理)、6个Shell脚本(支持流程自动化与环境构建)、2个Jupyter Notebook(含Figure4/Figure6等可视化分析示例)、1个GTF注释文件、1个BED坐标文件、1个BAM测序比对文件及配套IDX索引,另有scTE可执行二进制文件与scTE_build等专用构建工具,整体压缩包大小34.63MB。目前已有324人学习下载,适合具备基础Linux命令与Python编程能力的中高级用户。使用者可直接复现从BAM输入、TEs注释映射、表达矩阵生成到差异TEs识别与可视化(如plots-alltes.py、marker_genes.py等)的完整分析链,尤其example目录提供了端到端实操范例,显著降低单细胞TEs研究门槛。

1. 项目缘起:从单细胞数据中挖掘“暗物质”的冲动

在单细胞转录组测序(scRNA-seq)成为常规分析手段的今天,我们早已习惯了在基因表达矩阵上做文章。差异表达、细胞聚类、轨迹推断……这些分析流程已经相当成熟。但不知道你有没有过这样的感觉:我们似乎只关注了基因组里那不到2%的编码基因区域,而占基因组近一半的转座元件(Transposable Elements, TEs),就像一片沉默的“暗物质”,在常规分析流程中被有意无意地忽略了。

我最初接触这个领域,是因为在一个肿瘤免疫的单细胞项目中,常规的基因标记无法完美解释某一群细胞的异质性。偶然间,我看到一篇文献提到,某些内源性逆转录病毒(ERV)元件的表达可能与细胞应激和免疫逃逸相关。于是,我尝试在现有的单细胞数据里找找TEs的表达信号。结果发现,这事儿比想象中麻烦得多。主流的比对工具(如STAR、Cell Ranger)默认的参考基因组注释文件(如GENCODE、Ensembl)主要针对基因,对TEs的注释要么不全,要么直接当成重复序列给“屏蔽”或随机分配了。直接拿原始的比对文件(BAM)去数TEs的reads,结果噪音大得惊人,根本没法用。

这就是这个项目的起点:我需要一套可靠、灵活、可复现的流程,从原始的单细胞测序数据(fastq文件)开始,精准地量化每一个细胞中每一个TE家族(或亚家族)的表达量,最终生成一个可以与Seurat、Scanpy等主流单细胞分析工具无缝对接的TE表达矩阵。这不仅仅是跑一个工具,而是涉及从基因组注释准备、序列比对策略、到定量计数和矩阵构建的完整工程。网上能找到的零散脚本要么年久失修,要么假设太多,无法直接用于生产级别的分析。所以,我决定自己从头设计并实现一套源码。

2. 核心挑战:为什么给TEs做定量是个“脏活累活”

在动手写代码之前,必须把背后的“坑”想明白。给TEs做单细胞层面的表达定量,至少面临三大核心挑战,这也是设计源码时必须解决的工程问题。

2.1 挑战一:参考基因组的“身份模糊”问题

TEs在基因组中具有高度的序列相似性和多拷贝特性。一个特定的TE亚家族(如L1HS)可能在基因组中有成百上千个拷贝位点(loci)。当我们拿到一段测序read时,它可能来源于这个TE家族的任何一个拷贝,甚至可能因为序列高度相似而比对到多个位点。在单细胞数据中,每个细胞的测序深度有限,这种多映射(multi-mapping)read的比例会更高。

注意:传统的基因定量工具(如featureCounts)在处理多映射read时,通常采取“忽略”或“随机分配”的策略,这对于具有唯一性的基因是可行的,但对于TEs,这会导致定量结果严重失真,丢失大量真实信号。

设计对策:我们不能在单个拷贝(locus)的层面进行定量,那将是一团乱麻。必须提升一个层级,在TE亚家族(subfamily)甚至家族(family)的层面进行聚合定量。我们的目标是回答“这个细胞里,L1家族的表达活性高不高?”,而不是“这个细胞里,染色体X上第123456号位点的这个L1拷贝表达了多少”。因此,源码设计的核心思路之一是将基因组上所有属于同一个TE亚家族的区间(features)合并,作为一个整体的“元特征(meta-feature)”进行read计数

2.2 挑战二:与宿主基因的“纠缠不清”问题

许多TEs嵌入在基因的内含子或调控区域内。一条来源于宿主基因的RNA-seq read,很可能同时覆盖了基因的外显子和内含子区的TE序列。如果我们简单地将所有比对到TE区域的read都算作TE表达,就会引入巨大的背景噪音,将宿主基因的转录本错误地归类为TE表达。

设计对策:必须进行精细的链特异性(strand-specific)重叠特征(feature overlapping)处理。我们的源码需要实现一个过滤逻辑:只有当一条read特异性地比对到TE区域,且没有更优先地比对到某个编码基因的外显子区域时,才将其计入TE的表达量。这通常需要分步进行:先定量基因,再定量TEs,并排除那些可以被基因解释的reads。

2.3 挑战三:单细胞技术引入的“数据稀疏”与“技术噪音”

单细胞数据本身就有UMI(Unique Molecular Identifier)计数、高dropout率(基因检出率低)等特点。TEs的表达水平通常比管家基因低好几个数量级,这使得TE表达矩阵比基因表达矩阵更加稀疏,信噪比更低。直接套用为高表达基因设计的标准化、降维方法可能会失效。

设计对策:在定量阶段,我们必须充分利用UMI信息进行去重,确保每个转录本分子只计数一次,这是提高信噪比的第一步。在生成矩阵后,源码应提供一些基础的过滤建议,例如,只保留在至少一定比例细胞中(如0.1%)表达的TE特征,以防止后续分析被大量零值淹没。同时,我们需要明确,下游的差异分析或聚类可能需要专门为稀疏、低丰度数据设计的方法(如零膨胀模型)。

3. 源码设计蓝图:模块化构建端到端流程

基于以上挑战,我将整个流程设计为四个核心模块,源码也将按此组织,确保高内聚、低耦合,方便他人复用和修改。整个流程的输入是双端测序的fastq文件,输出是一个细胞×TE特征的表达矩阵(MTX格式或CSV)。

graph TD A[原始fastq数据] --> B(模块一: 参考准备); B --> C(模块二: 序列比对); C --> D(模块三: TE定量); D --> E(模块四: 矩阵构建与过滤); E --> F[细胞 x TE特征表达矩阵]; subgraph B [模块一: 参考准备] B1[获取基因组与注释] --> B2[处理TE注释 GTF] --> B3[创建TE元特征]; end subgraph C [模块二: 序列比对] C1[使用STAR进行基因组比对] --> C2[输出带标签的BAM]; end subgraph D [模块三: TE定量] D1[基于TE元特征GTF] --> D2[使用featureCounts计数] --> D3[处理多映射Reads]; end subgraph E [模块四: 矩阵构建与过滤] E1[聚合细胞计数] --> E2[生成稀疏矩阵] --> E3[基于细胞与特征过滤]; end

3.1 模块一:参考基因组与注释文件预处理

这是所有分析的基石,也是最容易出错的一步。我们需要两个核心文件:

  1. 基因组FASTA文件:例如GRCh38.p13。
  2. 综合注释GTF文件:需要包含完整的基因注释高质量的TE注释

基因注释可以从GENCODE获取。TE注释则是关键,推荐使用像rmsk-hg38.gtf这样的文件,它来源于UCSC的RepeatMasker追踪,包含了每个TE拷贝的基因组坐标、家族/亚家族分类和链信息。但直接使用这个文件有问题:它包含数十万个独立的TE区间,直接用于定量会导致特征数量爆炸。

源码关键实现(preprocess_reference.py

  1. 解析与聚合:读取rmsk.gtf,按照gene_id(这里实际上是TE亚家族名,如L1HS_int) 或family_id(如LINE/L1)字段进行聚合。将属于同一个亚家族的所有基因组区间合并。
  2. 创建“元特征”GTF:为每个TE亚家族生成一个新的GTF条目。这个条目的染色体范围可以覆盖该家族所有拷贝的起止(或简单地用第一个拷贝代表),关键是要有唯一的gene_id(如TE_L1HS)和gene_name
  3. 与基因注释合并:将处理后的TE“元特征”GTF与标准的基因GTF文件合并,生成一个综合的参考注释文件combined.gtf。这个文件将用于后续的比对索引构建和定量。

实操心得:务必检查合并后的GTF中,TE特征的gene_id不要与任何标准基因的gene_id重名。我习惯为所有TE的gene_id加上TE_前缀。此外,RepeatMasker注释中有些条目分类为“Simple_repeat”或“Low_complexity”,这些通常不是我们关注的转座元件,可以在预处理时过滤掉。

3.2 模块二:基于STAR的序列比对与标签处理

使用STAR进行比对,是因为它速度快,且能很好地处理剪接和生成基因组映射信息。关键步骤是使用我们上一步生成的combined.gtf来构建基因组索引。

源码关键实现(run_star_align.py

  1. 构建索引STAR --runMode genomeGenerate --genomeDir /path/to/index --genomeFastaFiles genome.fa --sjdbGTFfile combined.gtf --sjdbOverhang 100。这里的sjdbOverhang需要根据你的测序读长设置。
  2. 进行比对:对每个细胞的fastq文件运行STAR。这里要特别注意一个参数:--outSAMmultNmax 1。这个参数控制每条read允许报告的最大比对位点数。设置为1意味着STAR只会输出它认为“最佳”的唯一比对位置。对于TEs定量,这通常不是最优选择,因为它会丢弃所有多映射read,而其中可能包含真实的TE信号。
  3. 更优策略:一个更好的做法是允许报告多个比对(例如--outSAMmultNmax 10),并在输出的SAM/BAM文件中保留所有可能的比对位置。然后,在定量模块(featureCounts)中,使用其-M(多映射)和--fraction(分数分配)功能来处理这些read。这样能更公平地分配多映射read的计数。

3.3 模块三:使用featureCounts进行链特异性定量

这是定量的核心。我们将使用Subread包中的featureCounts工具,因为它支持对重叠特征的处理,并且能很好地与上述策略配合。

源码关键实现(quantify_te.py

  1. 准备特征文件:我们需要两个独立的GTF文件。一个是genes.gtf(仅含标准基因),另一个是te_meta_features.gtf(仅含我们聚合后的TE元特征)。
  2. 分步定量
    • 第一步,定量基因featureCounts -a genes.gtf -o gene_counts.txt -R BAM aln.bam -s 2-s 2表示链特异性反转录(对于常见的Illumina TruSeq文库)。-R BAM会输出一个按特征(基因)标记好的BAM文件,其中每条read都被打上了它所属基因的标签(XT标签)。
    • 第二步,定量TEfeatureCounts -a te_meta_features.gtf -o te_counts.txt -R BAM aln.bam -s 2 -M --fraction -O --minOverlap 10。这里参数是关键:
      • -M:计数多映射read。
      • --fraction:将多映射read按比例分配给其能比对到的所有特征。这是处理TE多拷贝问题的核心。
      • -O:允许read与多个特征重叠(一个read可能跨多个TE拷贝区域)。
      • --minOverlap 10:要求read与特征至少有10bp的重叠才被计数,提高特异性。
      • 最重要的:输入BAM文件是上一步生成的、已经被基因标记过的BAM。featureCounts会优先考虑已经带有基因标签(XT)的read。这意味着,如果一条read既能比对到基因A,又能比对到TE B,由于我们先运行了基因定量,它已经被标记为基因A,那么在TE定量时就会被排除。这完美解决了“宿主基因纠缠”问题。

3.4 模块四:细胞水平矩阵构建与初步过滤

上一步的featureCounts会为每个样本(细胞)输出一个计数文件。我们需要将所有细胞的TE计数汇总成一个矩阵。

源码关键实现(build_expression_matrix.py

  1. 解析计数文件:循环读取每个细胞te_counts.txt文件中的Assignment列(即每个TE特征的原始计数)。
  2. 构建字典:创建一个嵌套字典:matrix[cell_barcode][te_feature_id] = count
  3. 转换为稀疏矩阵:使用scipy.sparse库的csr_matrix来存储这个矩阵,因为最终矩阵的绝大多数值都是0。格式为:(细胞数量 × TE特征数量)。
  4. 基础过滤
    • 细胞过滤:通常我们会根据基因定量时的质控结果(如线粒体基因比例、总UMI数)来过滤细胞。这里假设我们已经有一个优质细胞的名单good_cells.txt
    • 特征(TE)过滤:移除在极少细胞中表达的TE。例如,只保留在至少n个细胞中表达计数>0的TE特征。这个n可以根据数据量灵活设置,比如总细胞数的0.1%。te_matrix_filtered = te_matrix[:, (te_matrix > 0).sum(axis=0) >= min_cells]
  5. 输出:将过滤后的稀疏矩阵保存为Matrix Market (.mtx)格式,并同时生成对应的细胞条形码文件(barcodes.tsv)和TE特征名文件(features.tsv)。这样,这个矩阵就可以直接使用Seurat::ReadMtx()scanpy.pp.read_10x_mtx()读入,无缝接入下游分析流程。

4. 实战部署:从零跑通一个示例流程

理论说再多,不如亲手跑一遍。假设我们有一套10x Genomics标准的单细胞RNA-seq数据(样本SC01),下面是如何使用这套源码的步骤。

4.1 环境准备与依赖安装

首先,确保你的Linux服务器或计算节点上有足够的存储和内存。我们需要安装以下工具,源码会调用它们:

  • STAR:用于比对。建议从源码编译安装,以获得最佳性能。
  • Subread:包含featureCounts。同样推荐源码安装。
  • Python 3.8+:运行我们的主控脚本。需要安装pysam,pandas,scipy等库。

你可以创建一个Conda环境来管理:

conda create -n sc-te python=3.9 conda activate sc-te conda install -c bioconda star subread pip install pysam pandas scipy

4.2 数据与参考基因组准备

  1. 下载数据:将样本SC01的fastq文件(SC01_S1_L001_R1_001.fastq.gz,SC01_S1_L001_R2_001.fastq.gz)放在./fastq/目录下。
  2. 下载参考
    • 从GENCODE下载人类基因组FASTA(GRCh38.primary_assembly.genome.fa)和综合注释GTF(gencode.v44.annotation.gtf)。
    • 从UCSC下载RepeatMasker注释GTF(rmsk.gtf)。可以使用UCSC工具集中的genePredToGtf进行转换,或者直接寻找现成的GTF格式文件。
  3. 运行预处理脚本
python preprocess_reference.py \ --gencode_gtf gencode.v44.annotation.gtf \ --rmsk_gtf rmsk.gtf \ --output_combined combined.gtf \ --output_te_only te_features.gtf \ --te_prefix "TE_"

这个脚本会生成combined.gtfte_features.gtf

4.3 运行端到端分析流水线

我编写了一个主控脚本main.py,将上述模块串联起来。你需要创建一个配置文件config_SC01.yaml

sample_id: "SC01" fastq_dir: "./fastq" genome_fasta: "/path/to/GRCh38.primary_assembly.genome.fa" combined_gtf: "./processed/combined.gtf" te_gtf: "./processed/te_features.gtf" star_index_dir: "./star_index" output_dir: "./results_SC01" threads: 16

然后运行:

python main.py --config config_SC01.yaml

主控脚本会依次执行:

  1. 使用combined.gtf构建STAR索引(如果尚未构建)。
  2. 对每个细胞的fastq进行STAR比对,输出BAM。
  3. 对每个细胞的BAM,先运行featureCounts定量基因,再运行featureCounts定量TE。
  4. 收集所有细胞的TE计数,构建稀疏矩阵并过滤。
  5. 最终在./results_SC01/目录下生成te_expression_matrix.mtx,te_barcodes.tsv,te_features.tsv

4.4 下游分析初探:在Seurat中查看TE表达

拿到矩阵后,就可以和你的基因表达矩阵一起分析了。在R中:

library(Seurat) # 读取基因表达矩阵(标准流程) pbmc.data <- Read10X(data.dir = "/path/to/gene_expression_folder") pbmc <- CreateSeuratObject(counts = pbmc.data, project = "SC01", min.cells = 3, min.features = 200) # 读取TE表达矩阵 te.data <- ReadMtx(mtx = "results_SC01/te_expression_matrix.mtx", cells = "results_SC01/te_barcodes.tsv", features = "results_SC01/te_features.tsv") # 将TE矩阵作为一个新的Assay添加到Seurat对象中 pbmc[["TE"]] <- CreateAssayObject(counts = te.data) # 现在,你可以像操作基因一样操作TE了 DefaultAssay(pbmc) <- "TE" # 计算TE表达的百分比 pbmc <- PercentageFeatureSet(pbmc, pattern = "^L1", col.name = "percent.L1", assay = "TE") # 可视化某个TE家族在UMAP上的表达 FeaturePlot(pbmc, features = "TE_L1HS", assay = "TE", order = TRUE)

通过这种方式,你可以探索TEs表达是否定义了新的细胞亚群,或者与某些病理状态、发育阶段相关。

5. 避坑指南与性能优化经验谈

在实际运行中,我踩过不少坑,这里分享几个关键点。

5.1 内存与存储的“巨兽”

STAR构建索引和比对非常耗内存。对于人类基因组,建议给STAR索引构建分配至少32GB内存,比对时每个线程也需要数GB。featureCounts处理标记BAM时,如果使用-R BAM选项,会生成一个与原始BAM几乎等大的中间文件,磁盘空间要预留充足。建议:使用高性能计算集群的队列系统,并定期清理中间BAM文件。

5.2 TE注释版本的一致性

不同来源的RepeatMasker注释(UCSC vs. ENSEMBL vs. Dfam)对TE家族/亚家族的命名和分类可能略有不同。务必确保你使用的rmsk.gtf与你的基因组版本(GRCh38/hg38)严格对应,并且在整个项目中固定使用同一个来源的注释。混合使用会导致结果无法比较。

5.3 定量准确性的权衡:--fraction的利与弊

使用--fraction分配多映射read,在数学上更公平,但会引入分数计数(如0.5),使得最终矩阵成为“非整数”矩阵。有些下游统计工具可能要求整数输入。一种折衷方案是,先使用分数计数进行探索性分析和筛选,在确定关键TE特征后,再用更严格的唯一比对计数(-M但不加--fraction)进行验证和可视化。

5.4 细胞数量扩展的挑战

当细胞数量达到数万甚至数十万时,为每个细胞单独运行featureCounts会成为瓶颈。优化策略

  1. 使用细胞ranger的分子计数信息:如果你有Cell Ranger输出的possorted_genome_bam.bam,这个BAM已经包含了所有细胞的比对信息,并且有细胞条形码(CB)和UMI(UB)标签。可以尝试用samtools按细胞条形码拆分BAM,或者直接使用支持按标签(CB)计数的工具,如Drop-seq toolsDigitalExpression,但需要对其功能进行改造以支持TE特征。
  2. 并行化与批处理:我们的源码主控脚本应支持将细胞列表分批次,并行提交多个featureCounts作业,最后再合并结果。这是目前最实用的扩展方案。

5.5 下游分析的“冷启动”

即使得到了TE矩阵,如何分析也是个新课题。不要直接套用为高表达基因设计的HVG(高变基因)选择、PCA降维和聚类方法。TE表达数据更稀疏、更嘈杂。可以尝试:

  • 特征选择:使用在更多细胞中表达的TE(表达细胞比例),或者使用专门为稀疏数据设计的差异丰度检验方法(如来自微生物组学的ANCOM思想)来筛选有变化的TE。
  • 降维与可视化:考虑使用适合计数数据的降维方法,如GLM-PCA潜在狄利克雷分配(LDA),而不是标准的PCA。t-SNE和UMAP虽然可以用,但需要仔细调整其参数(如min_dist,n_neighbors),因为稀疏数据中的距离度量可能不可靠。

这套源码的设计初衷,就是提供一个坚实、透明的起点,把“脏活累活”自动化、标准化。它可能不是最快的,也不是功能最全的,但它清晰地揭示了从原始数据到表达矩阵的每一步逻辑,让你能完全掌控整个过程,并根据自己项目的具体需求进行调整。单细胞世界的“暗物质”探测才刚刚开始,希望这套工具能帮你打开一扇新的大门。

本文还有配套的精品资源,点击获取

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询