이 장에서는 Snakemake를 활용하여 전사체 분석 파이프라인을 구축하는 방법을 다룬다. 전사체 분석의 이론적 배경, RNA-seq의 원리, 정량화 및 차등 발현 분석에 대한 내용은 9장 전사체학 기초를 참조한다.
Snakemake는 파이썬 기반의 워크플로우 관리 도구로, 생명정보학 분석에서 재현 가능한 파이프라인을 구축하는 데 널리 사용된다. Snakemake의 주요 특징은 다음과 같다:
conda를 사용하여 Snakemake를 설치한다.
$ conda activate bioinfo
$ conda install snakemake
Snakemake 워크플로우는 Snakefile에 정의되며, 각 작업은 rule로 표현된다.
rule 규칙명:
input:
"인풋 파일명"
output:
"아웃풋 파일명"
shell:
"쉘 명령"
실제 예시로 BWA-MEM을 이용한 매핑 규칙을 살펴보면:
rule bwa_map:
input:
"data/genome.fa",
"data/samples/A.fastq"
output:
"mapped_reads/A.bam"
shell:
"bwa mem {input} | samtools view -Sb - > {output}"
위 규칙을 실행하면 bwa mem 명령이 수행되어 mapped_reads/A.bam 파일이 생성된다.
Snakemake에서는 와일드카드를 사용하여 여러 샘플에 대해 동일한 규칙을 적용할 수 있다.
rule bwa_map:
input:
"data/genome.fa",
"data/samples/{sample}.fastq"
output:
"mapped_reads/{sample}.bam"
shell:
"bwa mem {input} | samtools view -Sb - > {output}"
다음과 같이 실행하면 A와 B 샘플 모두에 대해 매핑이 수행된다:
$ snakemake --cores 1 mapped_reads/A.bam mapped_reads/B.bam
Snakemake는 세 가지 실행 블록을 지원한다:
shell 블록: 쉘 명령을 실행한다.
rule example_shell:
input: "input.txt"
output: "output.txt"
shell: "cat {input} > {output}"
script 블록: 외부 파이썬 스크립트를 실행한다.
rule example_script:
input: "input.txt"
output: "output.txt"
script: "scripts/process.py"
run 블록: 인라인 파이썬 코드를 실행한다.
rule example_run:
input: "input.txt"
output: "output.txt"
run:
with open(input[0]) as f:
data = f.read()
with open(output[0], 'w') as f:
f.write(data.upper())
여러 규칙을 정의하면 Snakemake가 파일 의존성을 자동으로 추적하여 순차적으로 실행한다.
rule rule1:
input: "파일1"
output: "파일2"
shell: "명령1"
rule rule2:
input: "파일2"
output: "파일3"
shell: "명령2"
파일3을 생성하려면 먼저 파일2가 필요하므로, Snakemake는 rule1을 먼저 실행한 후 rule2를 실행한다:
$ snakemake --cores 1 파일3
전사체 분석 파이프라인은 다음과 같은 단계로 구성된다:
작업 디렉토리를 생성하고 필요한 도구를 설치한다.
$ mkdir -p ~/week6
$ cd ~/week6
$ conda activate bioinfo
$ conda install star cutadapt fastqc
STAR 정렬을 위해서는 참조 유전체 인덱스가 필요하다. 인덱스 생성에는 참조 유전체 FASTA 파일과 유전자 주석 GTF 파일이 필요하다.
STAR --runThreadN 4 \
--runMode genomeGenerate \
--genomeDir star_index \
--genomeFastaFiles /path/to/reference.fa \
--sjdbGTFfile /path/to/annotation.gtf
주요 옵션 설명:
| 옵션 | 설명 |
|---|---|
| —runThreadN | 사용할 CPU 코어 수 |
| —runMode | 실행 모드 (genomeGenerate: 인덱스 생성) |
| —genomeDir | 인덱스가 저장될 디렉토리 |
| —genomeFastaFiles | 참조 유전체 FASTA 파일 |
| —sjdbGTFfile | 유전자 주석 GTF 파일 |
본 실습에서는 애기장대(Arabidopsis thaliana) 참조 유전체를 사용한다:
$ STAR --runThreadN 4 \
--runMode genomeGenerate \
--genomeDir star_index \
--genomeFastaFiles /bce/omics/references/arabidopsis/GCF_000001735.4/GCF_000001735.4_TAIR10.1_genomic.fna \
--sjdbGTFfile /bce/omics/references/arabidopsis/GCF_000001735.4/GCF_000001735.4_TAIR10.1_genomic.gtf
전체 파이프라인을 정의하는 Snakefile을 작성한다.
# 샘플 목록 정의
SAMPLES = ["SRR4420293", "SRR4420294", "SRR4420295",
"SRR4420296", "SRR4420297", "SRR4420298"]
# 참조 유전체 경로
REFERENCE_DIR = "/bce/omics/references/arabidopsis/GCF_000001735.4"
STAR_INDEX = "star_index"
# 기본 규칙: 모든 샘플에 대해 파이프라인 실행
rule all:
input:
expand("fastqc/{sample}_1_fastqc.html", sample=SAMPLES),
expand("fastqc/{sample}_2_fastqc.html", sample=SAMPLES),
expand("star_output/{sample}/ReadsPerGene.out.tab", sample=SAMPLES)
# FastQC 품질 관리
rule fastqc:
input:
r1 = "data/{sample}_1.fastq.gz",
r2 = "data/{sample}_2.fastq.gz"
output:
html1 = "fastqc/{sample}_1_fastqc.html",
html2 = "fastqc/{sample}_2_fastqc.html",
zip1 = "fastqc/{sample}_1_fastqc.zip",
zip2 = "fastqc/{sample}_2_fastqc.zip"
shell:
"""
fastqc {input.r1} {input.r2} -o fastqc/
"""
# Cutadapt 어댑터 제거
rule cutadapt:
input:
r1 = "data/{sample}_1.fastq.gz",
r2 = "data/{sample}_2.fastq.gz"
output:
r1 = "trimmed/{sample}_1.trimmed.fastq.gz",
r2 = "trimmed/{sample}_2.trimmed.fastq.gz"
params:
adapter = "AGATCGGAAGAGC", # Illumina Universal Adapter
polya = "A" * 20 # poly-A tail
shell:
"""
cutadapt -a {params.adapter} -A {params.adapter} \
-a {params.polya} -A {params.polya} \
-o {output.r1} -p {output.r2} \
{input.r1} {input.r2} \
--minimum-length 20
"""
# STAR 정렬 및 정량화
rule star_align:
input:
r1 = "trimmed/{sample}_1.trimmed.fastq.gz",
r2 = "trimmed/{sample}_2.trimmed.fastq.gz"
output:
bam = "star_output/{sample}/Aligned.sortedByCoord.out.bam",
counts = "star_output/{sample}/ReadsPerGene.out.tab"
params:
index = STAR_INDEX,
outdir = "star_output/{sample}/"
threads: 4
shell:
"""
STAR --genomeDir {params.index} \
--runThreadN {threads} \
--readFilesIn {input.r1} {input.r2} \
--readFilesCommand zcat \
--outSAMtype BAM SortedByCoordinate \
--quantMode GeneCounts \
--outFileNamePrefix {params.outdir} \
--outTmpDir /tmp/{wildcards.sample}_star
"""
파이프라인을 실행하기 전에 dry-run으로 실행 계획을 확인한다:
$ snakemake --dry-run
실제 실행:
$ snakemake --cores 4
특정 파일만 생성하려면:
$ snakemake --cores 4 star_output/SRR4420293/ReadsPerGene.out.tab
| 옵션 | 설명 |
|---|---|
| —dry-run (-n) | 실행하지 않고 계획만 출력 |
| —cores (-j) | 사용할 CPU 코어 수 |
| —forceall (-F) | 모든 규칙을 강제로 재실행 |
| —printshellcmds (-p) | 실행되는 쉘 명령 출력 |
| —dag | 의존성 그래프를 DOT 형식으로 출력 |
STAR의 --quantMode GeneCounts 옵션을 사용하면 유전자별 리드 카운트가 포함된 파일이 생성된다.
$ head star_output/SRR4420293/ReadsPerGene.out.tab
파일 구조:
| 열 | 설명 |
|---|---|
| 1열 | 유전자 ID |
| 2열 | Unstranded 카운트 |
| 3열 | Forward strand 카운트 |
| 4열 | Reverse strand 카운트 |
파일 처음 4줄은 통계 정보를 포함한다:
| 행 | 설명 |
|---|---|
| N_unmapped | 매핑되지 않은 리드 수 |
| N_multimapping | 다중 매핑 리드 수 |
| N_noFeature | 유전자 영역에 해당하지 않는 리드 수 |
| N_ambiguous | 여러 유전자에 걸친 리드 수 |
RNA-seq 라이브러리는 방향성(strandedness)에 따라 unstranded, forward stranded, reverse stranded로 구분된다. 실험에 사용된 라이브러리 유형에 맞는 열을 선택해야 한다.
방향성을 확인하려면 2열, 3열, 4열의 합계를 비교한다. 대부분의 카운트가 특정 열에 집중되어 있다면 해당 방향의 stranded 라이브러리이다.
expand 함수는 와일드카드를 여러 값으로 확장한다.
expand("data/{sample}/processed.txt", sample=["A", "B", "C"])
# 결과: ["data/A/processed.txt", "data/B/processed.txt", "data/C/processed.txt"]
multiext 함수는 하나의 기본 경로에 여러 확장자를 추가한다.
multiext("results/sample1", ".pdf", ".txt", ".png")
# 결과: ["results/sample1.pdf", "results/sample1.txt", "results/sample1.png"]
복잡한 파이프라인에서는 설정을 별도의 YAML 파일로 분리할 수 있다.
config.yaml:
samples:
- SRR4420293
- SRR4420294
- SRR4420295
reference_dir: /bce/omics/references/arabidopsis/GCF_000001735.4
threads: 4
Snakefile에서 설정 파일 사용:
configfile: "config.yaml"
SAMPLES = config["samples"]
REFERENCE_DIR = config["reference_dir"]
| 조건 | 반복 1 | 반복 2 | 반복 3 |
|---|---|---|---|
| WT | SRR4420293 | SRR4420294 | SRR4420295 |
| atrx-1 | SRR4420296 | SRR4420297 | SRR4420298 |