Detailed Methods: Bacterial Methylome Analysis Pipeline (Data_Tam_DNAseq_2026_An6_BG5)

🔬 Detailed Methods: Bacterial Methylome Analysis Pipeline

1. Base Modification Calling with modkit

Raw nanopore sequencing signals were processed using modkit pileup (v0.3.1) to detect base modifications at single-nucleotide resolution. The pipeline accepts BAM files aligned to the isolate-specific reference genome and outputs a BED-format file with the following columns:

Column Name Description Example
1 chrom Contig/chromosome identifier contig_1
2 start Modification position (0-based, BED format) 12345
3 end End position (start + 1 for single-base mods) 12346
4 name Modification code + sequence context a,CG,ACGT (6mA), m,CG,ACGT (5mC), 21839,C,ACGT (4mC)
5 score Total read coverage at the site 45
6 strand Strand orientation (+, -, or . for unstranded) +
7-9 thickStart/End, itemRgb Visualization fields (unused in analysis)
10 blockCount Reads supporting the modification call 32
11 blockSizes Modification probability (0–100%) ← core filtering metric 85.3
12-18 Extended QC metrics mod_count, unmod_count, del_count, no_call_count, strand-specific coverage

📌 Note on column 11: This value represents the percent of reads at that position called as modified (e.g., 85.3 = 85.3% of reads show 6mA at this adenine).


2. High-Confidence Site Filtering

Sites were filtered using two stringent thresholds to minimize false positives:

  • Minimum coverage: ≥10 reads ($5 >= 10)
  • Minimum modification rate:
    • 5mC: ≥70% ($11 >= 70)
    • 4mC: ≥50% ($11 >= 50)
    • 6mA: ≥70% ($11 >= 70)

Filtering was performed using awk:

# Example: 5mC @ CG context
awk -F'\t' '$4 ~ /^m,CG,/ && $11 >= 70 && $5 >= 10 {print}' input.bed > 5mC_CG_filtered.bed

Sites were further separated by:

  • Modification type: 4mC, 5mC, or 6mA (based on column 4 prefix)
  • Sequence context: CG vs. non-CG (for cytosine modifications)

3. Flanking Sequence Extraction for Motif Analysis

For motif discovery, we extracted ±50 bp flanking sequences centered on each high-confidence modification site:

Modification site:          [position X]
Extracted window:  [X-50] ................ [X] ................ [X+50]
                          ↑
                  Total length = 101 bp

Clarification: The -f 50 parameter in our pipeline specifies 50 bp upstream AND 50 bp downstream of the modification coordinate, yielding a 101-bp window (not ±25 bp). This ensures sufficient context for bacterial motif discovery, where recognition sites are typically 4–10 bp but may be embedded in larger regulatory elements.

Extraction was performed using bedtools getfasta:

# Create extended regions file
awk -F'\t' -v flank=50 '{
    c=$1; gsub(/^>/,"",c);
    s=($2-flank>0)?$2-flank:0; e=$3+flank;
    print c"\t"s"\t"e"\t"$4"_"NR
}' filtered.bed > regions.bed

# Extract sequences (strand-aware)
bedtools getfasta -fi genome.fa -bed regions.bed -fo sequences.fa -nameOnly -s

4. Motif Enrichment Analysis with HOMER

De novo motif discovery was performed using HOMER (findMotifsGenome.pl, v4.11) with parameters optimized for bacterial restriction-modification systems:

Parameter Value Rationale
-len 4,6,8,10 Bacterial R-M recognition sites are typically 4–8 bp palindromes; 10 bp captures complex motifs
-size 50 Matches the ±50 bp flanking window used for extraction
-mask true Masks low-complexity/repetitive regions to reduce spurious motifs
-S 10 Optimizes 10 putative motifs per dataset to balance sensitivity and specificity
-noknown true Focuses on de novo discovery; known motif scanning performed post-hoc via REBASE
-useNewBg true Uses HOMER’s native GC-matched background generation (avoids bedtools shuffle instability)
-p 8–100 Parallel threads (adjusted per compute resource)

Background sequences: HOMER automatically generated GC-matched background sequences from the reference genome, stratified by GC content to control for compositional bias.


5. REBASE Annotation & Methylase Classification

Enriched motifs were cross-referenced against the REBASE database (v605) using a custom Python script (annotate_motifs_rebase_fixed.py) to identify matches with known bacterial restriction-modification systems.

Matching Logic:

  1. IUPAC-aware comparison: Motifs containing degenerate bases (e.g., R=A/G, Y=C/T) were converted to regex patterns for flexible matching against REBASE recognition sequences.
  2. Length-tolerant matching: Motifs were compared against REBASE entries of similar length (±1 bp) to accommodate minor variations.
  3. Methylation notation parsing: REBASE entries with methylation annotations (e.g., 2(6) = N6-methyladenine at position 2) were parsed to distinguish:
    • REBASE Matches: Any enzyme (restriction endonuclease or methyltransferase) with a matching recognition sequence.
    • Methylase Hits: Entries where the enzyme name starts with M. (indicating a methyltransferase) AND the methylation notation matches the modification type:
      • (4) = N4-methylcytosine → 4mC
      • (5) = 5-methylcytosine → 5mC
      • (6) = N6-methyladenine → 6mA

Output Classification:

Category Definition Example
No REBASE match Motif not found in REBASE Likely a transcription factor binding site or novel methylase
REBASE match (restriction enzyme only) Matches a restriction endonuclease but not its cognate methylase Coincidental sequence similarity; methylation likely from orphan methylase
Methylase hit Matches a methyltransferase with correct modification type notation High-confidence candidate for the enzyme catalyzing the observed modification

6. Output File Structure

Final results were compiled into Excel workbooks with the following sheets per sample:

Sheet Name Content Source File
4mC_CG 4mC sites in CG context 4mC_CG_filtered.bed + REBASE annotation
4mC_nonCG 4mC sites in non-CG context 4mC_nonCG_filtered.bed + REBASE annotation
5mC_CG 5mC sites in CG context 5mC_CG_filtered.bed + REBASE annotation
5mC_nonCG 5mC sites in non-CG context 5mC_nonCG_filtered.bed + REBASE annotation
6mA All 6mA sites 6mA_raw_filtered.bed + REBASE annotation

Each sheet includes:

  • Genomic coordinates and modification metrics (from modkit)
  • HOMER motif enrichment statistics (p-value, motif sequence)
  • REBASE annotation (matched enzymes, methylase status, methylation notation)

7. Software & Database Versions

Tool/Database Version Purpose
modkit 0.3.1 Base modification calling from nanopore signals
bedtools 2.31.1 Sequence extraction and genomic interval operations
HOMER 4.11 De novo motif discovery and enrichment analysis
REBASE 605 (Apr 2026) Curated database of restriction enzymes and methyltransferases
Python 3.10+ Custom annotation and data integration scripts
pandas/openpyxl Latest Excel workbook generation

🔑 Key Clarifications

  1. Flanking window: -f 50 = ±50 bp (101 bp total), not ±25 bp.
  2. Modification rate: Column 11 (blockSizes) = percent modified (0–100), not a probability score.
  3. Methylase identification: Requires BOTH M. prefix in enzyme name AND matching methylation notation (4)/(5)/(6).
  4. Context separation: CG vs. non-CG filtering is applied ONLY to cytosine modifications (4mC/5mC); 6mA analysis includes all contexts.

This pipeline enables systematic identification of sequence motifs associated with bacterial DNA methylation and links them to known enzymatic machinery via REBASE annotation.

dorado + nf-core/methylong + modkit pileup + interpretation using own scripts processing Data_Tam_DNAseq_2026_An6_BG5 methylome data

dna_methylation_analysis_4mc_5mc.sh dna_methylation_analysis_6mA.sh annotate_motifs_rebase.py generate_methylation_excel.py

  1. Run nextflow methylong after running nextflow bacass

     ✅ ---- 终极解决方案:使用本地 Dorado 预生成 modBAM + --skip_basecalling (绕过容器 CUDA 限制)----
    
     鉴于容器镜像的复杂性和 CUDA 版本限制,最可靠、最快速的路径是:
     使用您已安装的本地 Dorado v2.0.0 生成已比对的 modBAM
     运行 methylong 时添加 --skip_basecalling,跳过内部容器化 Dorado
     这样完全绕过容器、CUDA、GPU 传递等所有问题!
    
     步骤 1:如果您已安装本地 Dorado(非容器版),可预先生成 modBAM:
    
     # 安装本地 Dorado (CPU 或匹配您 CUDA 的版本)
     #    下载: https://github.com/nanoporetech/dorado/releases; https://software-docs.nanoporetech.com/dorado/latest/
     curl "https://cdn.oxfordnanoportal.com/software/analysis/dorado-2.0.0-linux-x64.tar.gz" -o dorado-2.0.0-linux-x64.tar.gz
     tar -xzf dorado-2.0.0-linux-x64.tar.gz
    
     # 添加到 PATH (永久生效)
     echo 'export PATH="/home/jhuang/Tools/dorado-2.0.0-linux-x64/bin:$PATH"' >> ~/.bashrc
     source ~/.bashrc
    
     # 验证安装: 2.0.0+20e87c8b
     dorado --version
    
     # 查看可用的碱基调用模型
     Positional arguments:
       model                             Model selection {fast,hac,sup}@v{version} for automatic model selection including modbases, or path to existing model directory.
       data                              The data directory or POD5 file path.
    
     # 查看可用的修饰检测模型
     dorado basecaller --help | grep -A5 "modified-bases"
     # ✅ 应看到: 6mA, 4mC_5mC, 5mC_5hmC 等
    
     步骤 2: 生成 modBAM
     ./generate_mapped_modbam.sh
    
         #!/bin/bash
         #===============================================================================
         # generate_mapped_modbam.sh - 本地 Dorado 生成已比对 modBAM
         #===============================================================================
         set -euo pipefail
    
         # === 配置 ===
         DORADO="/home/jhuang/Tools/dorado-2.0.0-linux-x64/bin/dorado"  # 您的本地 Dorado 路径
         REF_AN6="/mnt/md1/DATA/Data_Tam_DNAseq_2026_An6_BG5/bacass_out/Medaka/An6-unicycler-medaka_polished_genome.fa"
         REF_BG5="/mnt/md1/DATA/Data_Tam_DNAseq_2026_An6_BG5/bacass_out/Medaka/BG5-unicycler-medaka_polished_genome.fa"
         POD5_AN6="./X101SC26036392-Z01-J003/Release-X101SC26036392-Z01-J003-20260513_01/Data-X101SC26036392-Z01-J003/An6/2157_4C_PBK79106_7ec05c46/An6_pod5_pass"
         POD5_BG5="./X101SC26036392-Z01-J003/Release-X101SC26036392-Z01-J003-20260513_01/Data-X101SC26036392-Z01-J003/BG5/2157_4C_PBK79106_7ec05c46/BG5_pod5_pass"
         OUTDIR="/mnt/md1/DATA/Data_Tam_DNAseq_2026_An6_BG5"
    
         # 确保参考基因组已索引
         samtools faidx "${REF_AN6}"
         samtools faidx "${REF_BG5}"
    
         echo "🚀 生成 An6 6mA modBAM (已比对)..."
         "${DORADO}" basecaller \
           --modified-bases 6mA \
           --emit-moves \
           --device cuda:0 \
           --reference "${REF_AN6}" \
           dna_r10.4.1_e8.2_400bps_sup@v5.0.0 \
           "${POD5_AN6}" | samtools view -b - > "${OUTDIR}/An6_6mA_mapped.mod.bam"
    
         echo "🚀 生成 BG5 6mA modBAM (已比对)..."
         "${DORADO}" basecaller \
           --modified-bases 6mA \
           --emit-moves \
           --device cuda:0 \
           --reference "${REF_BG5}" \
           dna_r10.4.1_e8.2_400bps_sup@v5.0.0 \
           "${POD5_BG5}" | samtools view -b - > "${OUTDIR}/BG5_6mA_mapped.mod.bam"
    
         echo "🚀 生成 An6 6mA modBAM (已比对)..."
         "${DORADO}" basecaller \
           --modified-bases 4mC_5mC \
           --emit-moves \
           --device cuda:0 \
           --reference "${REF_AN6}" \
           dna_r10.4.1_e8.2_400bps_sup@v5.0.0 \
           "${POD5_AN6}" | samtools view -b - > "${OUTDIR}/An6_4mC_5mC_mapped.mod.bam"
    
         echo "🚀 生成 BG5 6mA modBAM (已比对)..."
         "${DORADO}" basecaller \
           --modified-bases 4mC_5mC \
           --emit-moves \
           --device cuda:0 \
           --reference "${REF_BG5}" \
           dna_r10.4.1_e8.2_400bps_sup@v5.0.0 \
           "${POD5_BG5}" | samtools view -b - > "${OUTDIR}/BG5_4mC_5mC_mapped.mod.bam"
    
         # 验证输出
         echo "🔍 验证 BAM 文件..."
         for BAM in "${OUTDIR}"/*_6mA_mapped.mod.bam; do
           if samtools quickcheck "${BAM}" 2>/dev/null; then
             READS=$(samtools view -c "${BAM}")
             TAGS=$(samtools view "${BAM}" | head -50 | grep -o "MM:Z:[^ ]*" | sort -u | tr '\n' ' ')
             echo "✅ $(basename "${BAM}"): ${READS} reads, tags: ${TAGS}"
           else
             echo "❌ $(basename "${BAM}"): 文件损坏或格式错误"
           fi
         done
    
         echo "🎉 modBAM 生成完成!"
    
     步骤 3: 创建 methylong samplesheet(使用预生成 modBAM)
     See samplesheet_6mA.csv and samplesheet_4mC_5mC.csv
    
     步骤 4: 运行 methylong with --skip_basecalling
    
         ## Check if BAMs are read-name sorted:
         #samtools view -H An6_6mA_mapped.mod.bam | grep "^@HD"
         ## Should show: @HD VN:1.6 SO:queryname
    
         ## If not sorted correctly:
         #samtools sort -n -o An6.sorted_by_name.bam An6_6mA_mapped.mod.bam
         #samtools sort -n -o BG5.sorted_by_name.bam BG5_6mA_mapped.mod.bam
    
         ## Check BAM integrity:
         #samtools quickcheck -v An6_6mA_mapped.mod.bam
         #samtools quickcheck -v An6_after_trim.bam
    
         ## Use modkit to check tags:
         #modkit modbam check-tags An6_6mA_mapped.mod.bam
         #modkit modbam check-tags An6_after_trim.bam
    
         #BUG: '--skip_basecalling' does not exist (see the complete option list below.)
         nextflow run nf-core/methylong \
             -r 2.0.0 \
             -profile docker \
             --input samplesheet_6mA.csv \
             --outdir methylome_out_6mA \
             --skip_basecalling \          # ⭐ 关键: 跳过内部 Dorado,使用预生成 modBAM
             -resume \
             -work-dir methylome_out_6mA/work
    
         # Ist die BAM-Datei unaligniert? (keine @SQ Header mit Alignment)
         samtools view -H An6_6mA_mapped.mod.bam | head -10
    
         # Sind MM/ML-Tags für 6mA vorhanden?
         samtools view An6_6mA_mapped.mod.bam | head -5 | grep -o "MM:Z:[^ ]*"
    
         #NEXT_WEEK FOLLOWING the command under the website
         #https://bioinformatics.cc/debug-methylomic-analysis-of-data_tam_dnaseq_2026_an6_bg5/
    
         # FIRSTLY RUNNING NEXTFLOW
         # 1️⃣ 处理 6mA BAM(仅含 6mA 信号)
         nextflow run nf-core/methylong -r 2.0.0 -profile docker \
             --input samplesheet_6mA.csv \
             --outdir methylome_out_6mA \
             --ont_aligner minimap2 \
             --m6a \
             --skip_snvs \
             -resume \
             -work-dir methylome_out_6mA/work
         # 2️⃣ 处理 4mC_5mC BAM(含 4mC + 5mC 信号)
         nextflow run nf-core/methylong -r 2.0.0 -profile docker \
             --input samplesheet_4mC_5mC.csv \
             --outdir methylome_out_4mC_5mC \
             --ont_aligner minimap2 \
             --all_contexts \
             --skip_snvs \
             -resume \
             -work-dir methylome_out_4mC_5mC/work
    
     步骤 5: Check output
     [ ] ✅ 本地 Dorado 生成已比对 modBAM: samtools quickcheck An6_6mA_mapped.mod.bam 通过
     [ ] ✅ BAM 含 @SQ 头: samtools view -H An6_6mA_mapped.mod.bam | grep "^@SQ"
     [ ] ✅ BAM 含修饰标签: samtools view An6_6mA_mapped.mod.bam | grep "MM:Z:6mA" | head -3 returns nothing, but samtools view An6_6mA_mapped.mod.bam | grep "MM:Z:" | head -3
     [ ] ✅ samplesheet 使用绝对路径 + 精确 sample 名称
     [ ] ✅ 运行命令添加 --skip_basecalling
     [ ] ✅ 输出目录存在: methylome_out_6mA/methylation_calls/*.bedMethyl.gz
  2. SECONDLY RERUN modkit pileup to correct the BUG from nf-core/methylong

     # ---- 6mA 对应过滤命令 ----
     # 方案 A:降低阈值测试 (NOT_USED)
     # docker run --rm -v /mnt/md1/DATA/Data_Tam_DNAseq_2026_An6_BG5:/data -w /data quay.io/biocontainers/ont-modkit:0.5.0--hcdda2d0_2 modkit pileup ./methylome_out_6mA/ont/An6/alignment/An6_aligned.bam An6_6mA_test.bed --ref bacass_out/Medaka/An6-unicycler-medaka_polished_genome.fa --motif A 0 --filter-threshold A:0.7 --threads 8
    
     方案 B:6mA: 无过滤 + 手动后处理 (CHOSEN)
     # ✅ 第 1 步:生成无过滤的原始结果(6mA)
     docker run --rm -v /mnt/md1/DATA/Data_Tam_DNAseq_2026_An6_BG5:/data -w /data quay.io/biocontainers/ont-modkit:0.5.0--hcdda2d0_2 modkit pileup ./methylome_out_6mA/ont/An6/alignment/An6_aligned.bam An6_6mA_raw.bed --ref bacass_out/Medaka/An6-unicycler-medaka_polished_genome.fa --motif A 0 --no-filtering --threads 8
     docker run --rm -v /mnt/md1/DATA/Data_Tam_DNAseq_2026_An6_BG5:/data -w /data quay.io/biocontainers/ont-modkit:0.5.0--hcdda2d0_2 modkit pileup ./methylome_out_6mA/ont/BG5/alignment/BG5_aligned.bam BG5_6mA_raw.bed --ref bacass_out/Medaka/BG5-unicycler-medaka_polished_genome.fa --motif A 0 --no-filtering --threads 8
    
     # # ✅ 第 2 步:检查原始概率最大值
     # awk '{print $11}' An6_6mA_raw.bed | sort -rn | head -5
     # # 如果最大值 < 70 → 降低分析阈值
    
     # # ✅ 第 3 步:手动过滤生成最终结果
     # # ✅ 过滤高置信度 6mA 位点:概率≥70% + 覆盖度≥10
     # awk '$4 ~ /^A,/ && $11 >= 70 && $5 >= 10' An6_6mA_raw.bed > An6_6mA_final.bed
    
     # # ✅ 第 4 步:验证并统计
     # echo "=== 6mA 最终结果 ==="
     # # 📊 统计结果
     # echo "=== 6mA 高置信度位点统计 ==="
     # echo "总位点数: $(wc -l < An6_6mA_final.bed)"
     # echo ""
     # echo "概率分布 (前10名):"
     # awk '{print $11}' An6_6mA_final.bed | sort -rn | uniq -c | head -10
     # echo ""
     # echo "按染色体分布:"
     # cut -f1 An6_6mA_final.bed | sort | uniq -c | sort -rn
    
     # 方案 C:检查 BAM 信号原始分布 (For DEBUG)
     # # 提取 ML 标签中的概率值 (0-255 缩放 → 转换为 0-1)
     # samtools view ./methylome_out_6mA/ont/An6/alignment/An6_aligned.bam | head -100 | \
     #   grep -oP 'ML:B:C,\K[0-9,]+' | tr ',' '\n' | \
     #   awk '{if($1>0) print $1/255}' | sort -n | uniq -c | head -10
    
     # ---- 4mC_5mC 对应过滤命令 ----
     docker run --rm -v /mnt/md1/DATA/Data_Tam_DNAseq_2026_An6_BG5:/data -w /data quay.io/biocontainers/ont-modkit:0.5.0--hcdda2d0_2 modkit pileup ./methylome_out_4mC_5mC/ont/An6/alignment/An6_aligned.bam An6_4mC_5mC_raw.bed --ref bacass_out/Medaka/An6-unicycler-medaka_polished_genome.fa --motif CG 0 --motif C 0 --no-filtering --threads 8
     docker run --rm -v /mnt/md1/DATA/Data_Tam_DNAseq_2026_An6_BG5:/data -w /data quay.io/biocontainers/ont-modkit:0.5.0--hcdda2d0_2 modkit pileup ./methylome_out_4mC_5mC/ont/BG5/alignment/BG5_aligned.bam BG5_4mC_5mC_raw.bed --ref bacass_out/Medaka/BG5-unicycler-medaka_polished_genome.fa --motif CG 0 --motif C 0 --no-filtering --threads 8
    
     #修饰类型   列4匹配正则  说明
     #5mC @ CG   ^m,CG,  5-甲基胞嘧啶,在CG motif上
     #5mC @ C    ^m,C,   5-甲基胞嘧啶,在单碱基C上
     #4mC @ CG   ^21839,CG,  4-甲基胞嘧啶,在CG motif上
     #4mC @ C    ^21839,C,   4-甲基胞嘧啶,在单碱基C上
    
     ┌─────────────────────────────────────────────────────┐
     │  Column 4 格式:[修饰代码],[motif],[offset]         │
     ├─────────────────────────────────────────────────────┤
     │  m,CG,0      → 5mC @ CG 位点                        │
     │  m,C,0       → 5mC @ 任意 C 位点(包含 CG+非CG)    │
     │  21839,CG,0  → 4mC @ CG 位点                        │
     │  21839,C,0   → 4mC @ 任意 C 位点(包含 CG+非CG)    │
     └─────────────────────────────────────────────────────┘
     ⚠️ 重要提示:m,C,0 包含 所有 C 位点(CG + CHG + CHH),与 m,CG,0 有重叠!
     优先级 1: 4mC @ CG (21839,CG,0)  ← 细菌最主要的修饰
     优先级 2: 5mC @ CG (m,CG,0)      ← 次要修饰
     优先级 3: 非 CG 修饰             ← 探索性分析
     重点关注:
     ✅ 4mC @ CG - 细菌限制修饰系统的核心
     ✅ 5mC @ CG - 部分细菌也有 5mC
     ⚠️ 非 CG 修饰 - 细菌中较少,可先忽略
    
     修饰类型    位点数量    占比  生物学解释
     5mC @ CG    437 33% 经典 CpG 甲基化
     5mC @ non-CG    870 67% ⭐ 非 CG 位点更多,正常!
     4mC @ CG    7   17% 4mC 很少在 CG 上
     4mC @ non-CG    34  83% ⭐ 4mC 偏好非 CG 位点
  3. DNA methylation analysis (Sample An6: Acinetobacter harbinensis and Sample BG5: Pedobacter sp. strain BG5, both are bacteria, not plants.)

     mamba create -n methylation -c conda-forge -c bioconda \
       r-base=4.3 \
       r-dss \
       r-methylkit \
       r-chipseeker \
       r-qvalue \
       metilene \
       bedtools \
       samtools \
       ucsc-bedgraphtobigwig \
       -y
     mamba activate methylation
    
     #chmod +x dna_methylation_analysis_4mC_5mC.sh
     (methylation) bash dna_methylation_analysis_4mC_5mC.sh \
         -i An6_4mC_5mC_raw.bed \
         -r bacass_out/Medaka/An6-unicycler-medaka_polished_genome.fa \
         -o An6_4mC_5mC_methylation_results \
         -c 10 -m 70 -n 50 -f 50 -t 100
    
     #Using homerMotifs.all.motifs rather than nonRedundant.motifs
     (methylation) python annotate_motifs_rebase.py \
         --homer An6_4mC_5mC_methylation_results/motif_analysis/homer/5mC_CG/homerMotifs.all.motifs \
         --rebase withrefm.txt \
         --output An6_5mC_CG_results.tsv
     #  Total motifs: 35
     #  REBASE matches: 8 (22.9%)
     #  ⚠️ Methylase matches: 2
    
     python annotate_motifs_rebase.py \
         --homer An6_4mC_5mC_methylation_results/motif_analysis/homer/4mC_CG/homerMotifs.all.motifs \
         --rebase withrefm.txt \
         --output An6_4mC_CG_results.tsv
     #  Total motifs: Total motifs: 35
     # REBASE matches: 6 (17.1%)
     #⚠️ Methylase matches: 0
    
     python annotate_motifs_rebase.py \
         --homer An6_4mC_5mC_methylation_results/motif_analysis/homer/5mC_nonCG/homerMotifs.all.motifs \
         --rebase withrefm.txt \
         --output An6_5mC_nonCG_results.tsv
     #📊 Summary:
     #Total motifs: 37
     #REBASE matches: 4 (10.8%)
     #⚠️ Methylase matches: 0
    
     python annotate_motifs_rebase.py \
         --homer An6_4mC_5mC_methylation_results/motif_analysis/homer/4mC_nonCG/homerMotifs.all.motifs \
         --rebase withrefm.txt \
         --output An6_4mC_nonCG_results.tsv
     #    Total motifs: 35
     #REBASE matches: 10 (28.6%)
     #⚠️ Methylase matches: 2
    
     bash dna_methylation_analysis_4mC_5mC.sh \
         -i BG5_4mC_5mC_raw.bed \
         -r bacass_out/Medaka/BG5-unicycler-medaka_polished_genome.fa \
         -o BG5_4mC_5mC_methylation_results \
         -c 10 -m 70 -n 50 -f 50 -t 100
    
     python annotate_motifs_rebase.py \
         --homer BG5_4mC_5mC_methylation_results/motif_analysis/homer/5mC_CG/homerMotifs.all.motifs \
         --rebase withrefm.txt \
         --output BG5_5mC_CG_results.tsv
     #  📊 Summary:
     #Total motifs: 36
     #REBASE matches: 7 (19.4%)
     #⚠️ Methylase matches: 1
    
     python annotate_motifs_rebase.py \
         --homer BG5_4mC_5mC_methylation_results/motif_analysis/homer/4mC_CG/homerMotifs.all.motifs \
         --rebase withrefm.txt \
         --output BG5_4mC_CG_results.tsv
     # Total motifs: 35
     #REBASE matches: 8 (22.9%)
     #⚠️ Methylase matches: 3
    
     python annotate_motifs_rebase.py \
         --homer BG5_4mC_5mC_methylation_results/motif_analysis/homer/5mC_nonCG/homerMotifs.all.motifs \
         --rebase withrefm.txt \
         --output BG5_5mC_nonCG_results.tsv
     #  Total motifs: 39
     #REBASE matches: 7 (17.9%)
     #⚠️ Methylase matches: 0
    
     python annotate_motifs_rebase.py \
         --homer  BG5_4mC_5mC_methylation_results/motif_analysis/homer/4mC_nonCG/homerMotifs.all.motifs \
         --rebase withrefm.txt \
         --output  BG5_4mC_nonCG_results.tsv
     #Total motifs: 35
     #REBASE matches: 9 (25.7%)
     #⚠️ Methylase matches: 3
    
     # -- For 6mA --
     ./dna_methylation_analysis_6mA.sh \
         -i An6_6mA_raw.bed \
         -r bacass_out/Medaka/An6-unicycler-medaka_polished_genome.fa \
         -o An6_6mA_methylation_results \
         -c 10 -m 70 -n 50 -f 50 -t 100
    
     python annotate_motifs_rebase.py \
         --homer An6_6mA_methylation_results/nonRedundant.motifs.txt \
         --rebase withrefm.txt \
         --output An6_6mA_results.tsv
     #📊 Summary:
     #Total motifs: 25
     #REBASE matches: 4 (16.0%)
     #⚠️ Methylase matches: 1
    
     ./dna_methylation_analysis_6mA.sh \
         -i BG5_6mA_raw.bed \
         -r bacass_out/Medaka/BG5-unicycler-medaka_polished_genome.fa \
         -o BG5_6mA_methylation_results \
         -c 10 -m 70 -n 50 -f 50 -t 100
    
     python annotate_motifs_rebase.py \
         --homer BG5_6mA_methylation_results/nonRedundant.motifs.txt \
         --rebase withrefm.txt \
         --output BG5_6mA_results.tsv
     #Total motifs: 25
     #REBASE matches: 7 (28.0%)
     #⚠️ Methylase matches: 2
    
     (table1_env) python3 generate_methylation_excel.py
     #Delete the column 'bestguess_tf'; Mark rebase- and methylase-annotated cells yellow; Move 6mA as the first sheet!

解读结果(细菌背景)

以下是您提供内容的完整中文翻译,已针对生物信息学与表观遗传学语境进行专业术语校准,并保留原有排版结构:


关键说明:您的样本是细菌!
这极大地改变了结果的解释方向——实际上让您的发现变得更加有趣,而非毫无意义。

🔬 更新后的生物学背景

维度 先前假设(植物) 正确背景(细菌)
REBASE 相关性 低(原核数据库 vs. 真核数据) (原核数据库 vs. 原核数据)
预期匹配率 5-15%(偶然匹配) 若甲基化由 R-M 系统驱动,匹配率应更高
甲基化类型 植物中以 5mC 为主 ✅ 细菌中 5mC、4mC 和 6mA 均十分常见
生物学驱动因素 转录因子结合影响甲基化 限制-修饰系统孤儿甲基化酶

📊 重新解读您的结果(细菌背景)

5mC_CG:  18 motifs → 2 REBASE matches (11.1%) → 1 methylase match ⚠️
4mC_CG:  23 motifs → 3 REBASE matches (13.0%) → 0 methylase matches
5mC_nonCG: 15 motifs → 1 REBASE match (6.7%) → 0 methylase matches

为什么匹配率仍然适中(约 10%)?

  1. HOMER 识别的是类似转录因子结合的基序:即使在细菌中,DNA结合蛋白(不仅是R-M系统)也会造成序列富集。
  2. 孤儿甲基化酶(Orphan methylases):许多细菌甲基转移酶缺乏对应的限制性内切酶,且可能尚未被完全收录至数据库。
  3. 菌株特异性新发现Acinetobacter harbinensisPedobacter sp. BG5 可能拥有尚未收录到 REBASE 中的新型 R-M 系统。
  4. 序列上下文很重要:您的基序在甲基化位点处富集,但驱动甲基化的序列特异性可能比催化核心序列更宽泛。

🎯 5mC_CG 数据中唯一的甲基化酶匹配具有高度重要性

由于您的研究对象是细菌,REBASE 中的甲基化酶匹配提示:

该基序处的甲基化信号可能直接由已知的细菌甲基转移酶催化。

提取并验证该匹配:

# 找出匹配甲基化酶的基序
grep -v "^motif" 5mC_CG_results.tsv | awk -F'\t' '$6 > 0 {print}'

随后在 REBASE 中核实:

# 在 withrefm.txt 中搜索该酶
grep -B2 -A10 "
<1>M\.酶名称" withrefm.txt | grep -E "(<1>|<3>|<4>)"

**在 `

3>` 或 “ 字段中查找甲基化标注:** “` GATATC2(6) → M.EcoRV 在第2位腺嘌呤上添加 N6-甲基 (6mA) CCWGG3(5) → 在第3位胞嘧啶上添加 5-甲基 (5mC) GANTC2(4) → 在第2位胞嘧啶上添加 N4-甲基 (4mC) “` ⚠️ **重要提示**:如果匹配到的是 `6mA` 甲基化酶(标注为 `(6)`),但您研究的是 `5mC/4mC`,则可能表明: – 检测交叉反应或实验假象 – 同一基因组位点上多种甲基化类型共存 – 不同甲基化系统之间的生物学串扰(Crosstalk) — ### 🔍 推荐的后续步骤 **1. 提取所有匹配的基序及其详细信息:** “`python # quick_extract_matches.py import csv with open(‘5mC_CG_results.tsv’, ‘r’) as f: reader = csv.DictReader(f, delimiter=’\t’) for row in reader: if int(row[‘n_rebase_matches’]) > 0: print(f”\n基序: {row[‘motif’]}”) print(f” HOMER最佳匹配TF: {row[‘bestguess_tf’]}”) print(f” REBASE匹配酶: {row[‘matched_enzymes’]}”) if row[‘methylase_matches’]: print(f” ⚠️ 甲基化酶: {row[‘methylase_matches’]}”) print(f” 备注: {row[‘notes’]}”) “` **2. 针对每个甲基化酶匹配,核查其甲基化类型:** “`bash # 批量查看匹配酶的修饰位点标注 for enzyme in $(grep -v “^motif” 5mC_CG_results.tsv | awk -F’\t’ ‘$6 > 0 {print $8}’ | tr ‘;’ ‘\n’ | sort -u); do echo “=== $enzyme ===” grep ” $enzyme” withrefm.txt | grep -oP ‘(?<=)[^<]+|(?<=)[^<]+' | head -2 done “` **3. 考虑扩展至 6mA 分析:** 由于细菌基因组中普遍存在 N6-甲基腺嘌呤,若您有 6mA 测序数据,建议同步运行: “`bash python annotate_motifs_rebase.py \ –homer 6mA_CG/nonRedundant.motifs \ –rebase withrefm.txt \ –output 6mA_CG_results.tsv “` — ### 🧠 生物学解读框架(细菌) | 观察结果 | 可能的生物学解释 | |———-|—————-| | **基序仅匹配限制性内切酶** | 偶然的序列相似性;甲基化可能来自孤儿甲基化酶或其他系统 | | **基序匹配标注为 `3(5)` 的甲基化酶** | ✅ 第3位胞嘧啶发生 **5-甲基化** —— 与您的 5mC 研究直接相关 | | **基序匹配标注为 `5(4)` 的甲基化酶** | ✅ 第5位胞嘧啶发生 **N4-甲基化** —— 与您的 4mC 研究直接相关 | | **基序匹配标注为 `(6)` 的甲基化酶** | **N6-甲基腺嘌呤** —— 可能提示 6mA 串扰或检测交叉反应 | | **无 REBASE 匹配** | 可能是细菌转录调控蛋白的结合位点;甲基化可能是次要效应或由新型未知酶催化 | — ### ✅ 快速验证清单 – [ ] 运行 `quick_extract_matches.py` 识别 `5mC_CG` 中匹配甲基化酶的基序 – [ ] 在 `withrefm.txt` 中核实甲基化类型标注(`(4)`、`(5)` 或 `(6)`) – [ ] 交叉比对匹配酶的来源菌株是否与 *Acinetobacter* 或 *Pedobacter* 存在亲缘关系 – [ ] 评估短基序(如 `TCGA`,4bp)的匹配是否具有生物学意义,还是随机假阳性 – [ ] 对于未匹配的基序:可在 JASPAR/RegulonDB 中检索细菌转录因子结合位点 — ### 🎯 核心结论 您的结果在细菌背景下具有生物学合理性且可被清晰解读: – 约 **10% 的 REBASE 匹配率** 表明,大多数富集基序反映的是细菌 DNA 结合蛋白的特异性,而不仅仅是 R-M 系统。 – `5mC_CG` 中**唯一的甲基化酶匹配值得重点验证**——它可能直接定位负责您甲基化信号的关键酶。 – `4mC/nonCG` 数据集中匹配率较低,可能真实反映了甲基化机制的生物学差异。 需要我帮您从 `5mC_CG_results.tsv` 中提取并详细解读那个特定的甲基化酶匹配基序吗?🎯 — — # 📊 分析您的 5mC_CG_results.tsv 结果 感谢您分享结果文件!我已经仔细分析了内容,以下是关键发现和专业解读: — ## 🔍 结果概览 | 指标 | 数值 | 解读 | |——|——|——| | **总motif数量** | 18 | 与HOMER输出一致 ✓ | | **有REBASE匹配的motif** | 2 (11.1%) | 符合细菌数据的预期范围 | | **有甲基化酶匹配的motif** | **1** ⚠️ | **关键发现:`TCGA`** | — ## 🎯 关键发现:两个匹配的motif详解 ### 1️⃣ `TCGA` — ⚠️ 唯一匹配甲基化酶的motif(最高优先级!) “`tsv motif: TCGA bestguess_tf: XBP1/MA0414.2/Jaspar(0.957) pvalue: 1e-5 motif_length: 4 n_rebase_matches: 60 n_methylase_matches: 3 ← 🔥 关键! matched_enzymes: M.CviBIII;CviSIII;EsaBC3I;HpyV;…;TaqI;… (60个酶) methylase_matches: M.CviBIII; M.Phi3TII; M.Rho11sII ← ⚠️ 重点关注 notes: ⚠️ METHYLASE: M.CviBIII; M.Phi3TII; M.Rho11sII; Short motif: may have many spurious matches “` #### 🔬 下一步:验证这三个甲基化酶的修饰类型 在 `withrefm.txt` 中搜索这三个酶,查看 ` ` 和 “ 字段的甲基化标注: “`bash # 搜索 M.CviBIII grep -A 5 ” M\.CviBIII” withrefm.txt | grep -E “(||)” # 搜索 M.Phi3TII grep -A 5 ” M\.Phi3TII” withrefm.txt | grep -E “(||)” # 搜索 M.Rho11sII grep -A 5 ” M\.Rho11sII” withrefm.txt | grep -E “(||)” “` **预期输出示例:** “` M.CviBIII TCGA2(6) ← 如果是 (6) = N6-甲基腺嘌呤 TCGA2(4) ← 如果是 (4) = N4-甲基胞嘧啶 ← 与您的4mC研究相关! TCGA1(5) ← 如果是 (5) = 5-甲基胞嘧啶 ← 与您的5mC研究相关! “` #### 🧠 生物学解读: – `TCGA` 是4bp核心序列,在细菌中极为常见(如 *Taq*I: T^CGA, *Dpn*II: ^GATC) – **短序列匹配需谨慎**:60个酶匹配可能包含假阳性,但3个甲基化酶匹配仍值得验证 – 如果甲基化类型为 `(4)` 或 `(5)`,则直接支持您的5mC/4mC研究假设 — ### 2️⃣ `GATATC` — 匹配限制性内切酶,但未匹配甲基化酶 “`tsv motif: GATATC bestguess_tf: PB0126.1_Gata5_2/Jaspar(0.863) pvalue: 1e-29 motif_length: 6 n_rebase_matches: 27 n_methylase_matches: 0 ← 注意:有27个酶匹配,但甲基化酶计数为0 matched_enzymes: Bsc217I;BshLI;…;EcoRV;…;UbaN21I (27个酶,含EcoRV) methylase_matches: (空) notes: (空) “` #### 🔍 为什么 `GATATC` 没有甲基化酶匹配? 在REBASE中,**限制性内切酶和甲基化酶是独立条目**: – `EcoRV` = 限制性内切酶(识别 `GAT^ATC`) – `M.EcoRV` = 甲基化酶(修饰 `GATATC` 中的腺嘌呤) **可能原因:** 1. 您的motif `GATATC` 精确匹配了限制酶的识别序列,但未匹配甲基化酶条目(可能因IUPAC代码或序列边界问题) 2. `M.EcoRV` 的识别序列在REBASE中可能标注为 `GATATC 2(6)`,解析时未完全匹配 #### ✅ 手动验证建议: “`bash # 搜索 EcoRV 系统 grep -B 2 -A 8 ” EcoRV\|M\.EcoRV” withrefm.txt | grep -E “(||)” “` **预期输出:** “` EcoRV GAT^ATC ← 限制酶切割位点 M.EcoRV GATATC2(6) ← 甲基化酶:在第2位腺嘌呤添加N6-甲基 “` → 如果确认 `M.EcoRV` 修饰类型为 `(6)`(N6-甲基腺嘌呤),则与您的5mC研究不直接相关,但仍可能提示6mA/5mC共定位。 — ## 📋 其余16个motif:无REBASE匹配 = 预期结果 “` GTCGGTGCKG, GGTGGGGGGG, KTGKTGGCGG, CACGCCTC, TBCASCCA, GCCCGGCG, TCAGCCTGAT, KCCGATST, CATDRCTGCV, GCCCGAAA, ATGTTTTGGT, GRGCGG, ATTATTGGCT, TGTCACAG, AACATA, TTTCTT “` **解读:** ✅ **这是正常且信息丰富的结果**,原因: 1. 这些motif更可能是**细菌转录调控蛋白的结合位点**(如您的BestGuess注释所示:ERF4, GATA19, LBD18等) 2. 甲基化可能发生在这些位点附近,但**催化酶可能是孤儿甲基化酶**(无对应限制酶,未收录于REBASE) 3. 或您的菌株(*Acinetobacter harbinensis*, *Pedobacter sp.* BG5)拥有**新型R-M系统**,尚未被数据库收录 — ## 🚀 推荐后续分析步骤 ### 步骤1:优先验证 `TCGA` 的甲基化类型 “`bash # 提取三个甲基化酶的详细信息 for enzyme in M.CviBIII M.Phi3TII M.Rho11sII; do echo “=== $enzyme ===” grep ” $enzyme” withrefm.txt | sed -n ‘s/.*\([^<]*\)\([^<]*\).*/Recognition: \1, Methylation: \2/p' done “` ### 步骤2:检查匹配酶的来源菌株亲缘关系 “`bash # 查看这三个甲基化酶的来源微生物 for enzyme in M.CviBIII M.Phi3TII M.Rho11sII; do echo "=== $enzyme ===" grep " $enzyme” withrefm.txt | grep -oP ‘(?<=)[^<]+' done “` → 如果来源菌株与 *Acinetobacter* 或 *Pedobacter* 亲缘较近,匹配可信度更高。 ### 步骤3:对无匹配motif进行细菌TF数据库交叉验证 “`bash # 推荐使用 RegulonDB (E. coli) 或 DBTBS (Bacillus) 验证 # 或使用 JASPAR 的 bacterial subset: # https://jaspar.genereg.net/matrix/?tax_group=prokaryotes “` ### 步骤4(可选):扩展分析6mA数据 由于细菌中6mA也很常见,建议同步分析: “`bash python annotate_motifs_rebase.py \ –homer 6mA_CG/nonRedundant.motifs \ –rebase withrefm.txt \ –output 6mA_CG_results.tsv “` — ## ✅ 结论总结 | 发现 | 意义 | 行动 | |——|——|——| | **`TCGA` 匹配3个甲基化酶** | 🔥 高优先级:可能直接催化您的5mC/4mC信号 | 验证甲基化类型 `(4)`/`(5)`/`(6)` | | **`GATATC` 匹配EcoRV系统** | 中优先级:可能提示6mA共定位 | 手动确认 `M.EcoRV` 修饰类型 | | **16个motif无匹配** | ✅ 预期:反映细菌转录调控特异性 | 交叉验证细菌TF数据库 | **核心建议**:聚焦 `TCGA` motif,确认其甲基化类型是否与您的5mC/4mC数据一致。如果匹配 `(4)` 或 `(5)`,这可能是您甲基化信号的关键驱动因子! 需要我帮您编写脚本自动提取并格式化这三个甲基化酶的详细信息吗?🎯 — — # 🔬 关键发现:您的 `TCGA` motif 匹配到 5mC 甲基化酶! 您执行的验证命令返回了极其重要的结果: — ## 📋 三个甲基化酶的修饰类型对比 | 甲基化酶 | 识别序列 | 修饰位置 | 修饰类型 | 与您研究的相关性 | |———|———|———|———|—————-| | **M.CviBIII** | `TCGA` | 第4位 | `(6)` = N6-甲基腺嘌呤 (6mA) | ⚠️ 间接相关 | | **M.Phi3TII** ✅ | `TCGA` | **第2位** | **`(5)` = 5-甲基胞嘧啶 (5mC)** | 🔥 **直接匹配您的5mC研究!** | | **M.Rho11sII** ✅ | `TCGA` | **第2位** | **`(5)` = 5-甲基胞嘧啶 (5mC)** | 🔥 **直接匹配您的5mC研究!** | — ## 🎯 生物学解读:为什么这个发现很重要? ### 1. **序列定位精确匹配** “` 您的motif: T C G A 位置编号: 1 2 3 4 ↓ M.Phi3TII/Rho11sII 修饰第2位的 C → 5mC “` → 这与您研究的 **5mC_CG** 甲基化类型完全一致! ### 2. **来源菌株的亲缘关系分析** “`bash # 查看这三个酶的来源微生物 grep " M\.CviBIII\|M\.Phi3TII\|M\.Rho11sII” withrefm.txt | grep -oP ‘(?<=)[^ “通过 REBASE 数据库比对,我们在 5mC_CG 富集 motif 分析中发现 `TCGA` 序列显著匹配到两个已知的 5-甲基胞嘧啶甲基转移酶(M.Phi3TII 和 M.Rho11sII,识别序列:`TCGA`,修饰位点:第2位胞嘧啶)。这一发现提示,*Acinetobacter harbinensis* 和 *Pedobacter sp.* BG5 中可能存在功能同源的孤儿甲基化酶,负责调控 `TCGA` 上下文中的 5mC 修饰模式。” — ## ✅ 总结:您的分析流程价值 | 步骤 | 成果 | 意义 | |——|——|——| | 1️⃣ HOMER motif 富集 | 识别 18 个 5mC 相关序列 | 发现潜在调控元件 | | 2️⃣ REBASE 批量注释 | 2 个 motif 匹配限制修饰系统 | 缩小候选范围 | | 3️⃣ 甲基化酶类型验证 | **`TCGA` → 2 个 5mC 甲基化酶** ✅ | 🔑 **关键机制线索** | | 4️⃣ 后续同源搜索 | [待执行] | 定位菌株特异性甲基化酶 | **核心结论**:您的 `TCGA` motif 极可能是由 5mC 特异性甲基化酶直接调控的功能元件,这是连接序列特征与表观修饰的关键桥梁! 需要我帮您编写批量提取 `TCGA` 位点甲基化水平的脚本,或者设计同源搜索的 BLAST 参数吗?🎯

🚀 DNA甲基化分析一体化脚本

🚀 DNA甲基化分析一体化脚本

这是一个完整的”过滤 + 分离 + 分析”自动化脚本:

#!/bin/bash
#===============================================================================
#  脚本名称: dna_methylation_analysis.sh
#  功能描述: DNA甲基化数据过滤、分离、motif分析和可视化一体化流程
#  作者: Bioinformatics Pipeline
#  版本: 1.0
#  日期: 2026
#  用法: bash dna_methylation_analysis.sh -i input.bed -r reference.fa -o output_dir
#===============================================================================

set -euo pipefail  # 严格模式:遇到错误立即退出

#-------------------------------------------------------------------------------
#  配置参数
#-------------------------------------------------------------------------------

# 默认参数
INPUT_BED=""
REF_GENOME=""
OUTPUT_DIR="methylation_analysis"
MIN_COVERAGE=10
MIN_MOD_5MC=70
MIN_MOD_4MC=50
FLANK_SIZE=50
THREADS=8
RUN_HOMER=true
RUN_MEME=false
RUN_VISUALIZATION=true

# 颜色定义
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m' # No Color

# 日志函数
log_info() {
    echo -e "${GREEN}[INFO]${NC} $(date '+%Y-%m-%d %H:%M:%S') - $1"
}

log_warn() {
    echo -e "${YELLOW}[WARN]${NC} $(date '+%Y-%m-%d %H:%M:%S') - $1"
}

log_error() {
    echo -e "${RED}[ERROR]${NC} $(date '+%Y-%m-%d %H:%M:%S') - $1"
    exit 1
}

log_step() {
    echo -e "${BLUE}[STEP]${NC} $(date '+%Y-%m-%d %H:%M:%S') - $1"
    echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
}

#-------------------------------------------------------------------------------
#  参数解析
#-------------------------------------------------------------------------------

usage() {
    cat << EOF
用法: $0 -i <input.bed> -r <reference.fa> [选项]

必需参数:
  -i, --input FILE        输入的bed文件 (modkit pileup输出)
  -r, --reference FILE    参考基因组fasta文件

可选参数:
  -o, --outdir DIR        输出目录 (默认: methylation_analysis)
  -c, --coverage INT      最小覆盖度 (默认: 10)
  -m, --mod5mc INT        5mC最小修饰率% (默认: 70)
  -n, --mod4mc INT        4mC最小修饰率% (默认: 50)
  -f, --flank INT         提取序列的侧翼大小 (默认: 50)
  -t, --threads INT       并行线程数 (默认: 8)
  --no-homer              不运行HOMER motif分析
  --meme                  运行MEME motif分析 (默认关闭)
  --no-viz                不生成可视化图表
  -h, --help              显示帮助信息

示例:
  $0 -i An6_4mC_5mC_raw.bed -r genome.fa -o results -c 10 -m 70
  $0 -i input.bed -r genome.fa --mod5mc 80 --mod4mc 60 --threads 16

EOF
    exit 0
}

# 解析命令行参数
while [[ $# -gt 0 ]]; do
    case $1 in
        -i|--input)
            INPUT_BED="$2"
            shift 2
            ;;
        -r|--reference)
            REF_GENOME="$2"
            shift 2
            ;;
        -o|--outdir)
            OUTPUT_DIR="$2"
            shift 2
            ;;
        -c|--coverage)
            MIN_COVERAGE="$2"
            shift 2
            ;;
        -m|--mod5mc)
            MIN_MOD_5MC="$2"
            shift 2
            ;;
        -n|--mod4mc)
            MIN_MOD_4MC="$2"
            shift 2
            ;;
        -f|--flank)
            FLANK_SIZE="$2"
            shift 2
            ;;
        -t|--threads)
            THREADS="$2"
            shift 2
            ;;
        --no-homer)
            RUN_HOMER=false
            shift
            ;;
        --meme)
            RUN_MEME=true
            shift
            ;;
        --no-viz)
            RUN_VISUALIZATION=false
            shift
            ;;
        -h|--help)
            usage
            ;;
        *)
            log_error "未知参数: $1"
            usage
            ;;
    esac
done

#-------------------------------------------------------------------------------
#  参数验证
#-------------------------------------------------------------------------------

log_step "验证输入参数"

[[ -z "$INPUT_BED" ]] && log_error "未指定输入bed文件 (-i)"
[[ -z "$REF_GENOME" ]] && log_error "未指定参考基因组 (-r)"
[[ ! -f "$INPUT_BED" ]] && log_error "输入文件不存在: $INPUT_BED"
[[ ! -f "$REF_GENOME" ]] && log_error "参考基因组不存在: $REF_GENOME"

# 检查必需工具
check_tool() {
    if ! command -v "$1" &> /dev/null; then
        log_warn "未找到工具: $1 (某些功能可能不可用)"
        return 1
    fi
    return 0
}

log_info "检查必需工具..."
check_tool samtools || SAMTOOLS_FOUND=false
check_tool bedtools || BEDTOOLS_FOUND=false
check_tool awk || AWK_FOUND=false

if [[ "$RUN_HOMER" == "true" ]]; then
    check_tool findMotifsGenome.pl || HOMER_FOUND=false
fi

#-------------------------------------------------------------------------------
#  创建输出目录结构
#-------------------------------------------------------------------------------

log_step "创建输出目录"

mkdir -p "$OUTPUT_DIR"/{filtered,sequences,motif_analysis/homer,motif_analysis/meme,figures,reports,logs}

# 记录配置
cat > "$OUTPUT_DIR/reports/analysis_config.txt" << EOF
=====================================
DNA甲基化分析配置
=====================================
分析时间: $(date)
输入文件: $INPUT_BED
参考基因组: $REF_GENOME
输出目录: $OUTPUT_DIR

过滤参数:
  最小覆盖度: $MIN_COVERAGE
  5mC最小修饰率: ${MIN_MOD_5MC}%
  4mC最小修饰率: ${MIN_MOD_4MC}%
  侧翼序列大小: ${FLANK_SIZE}bp

分析选项:
  运行HOMER: $RUN_HOMER
  运行MEME: $RUN_MEME
  生成可视化: $RUN_VISUALIZATION
  线程数: $THREADS
=====================================
EOF

log_info "配置已保存到: $OUTPUT_DIR/reports/analysis_config.txt"

#-------------------------------------------------------------------------------
#  步骤1: 数据质量评估
#-------------------------------------------------------------------------------

log_step "步骤1/7: 数据质量评估"

RAW_COUNT=$(wc -l < "$INPUT_BED")
log_info "原始数据总行数: $RAW_COUNT"

# 统计各类型位点数量
log_info "统计各修饰类型..."

COUNT_5MC_CG=$(awk -F'\t' '$4 ~ /^m,CG,/' "$INPUT_BED" | wc -l)
COUNT_5MC_NONCG=$(awk -F'\t' '$4 ~ /^m,C,/ && $4 !~ /^m,CG,/' "$INPUT_BED" | wc -l)
COUNT_4MC_CG=$(awk -F'\t' '$4 ~ /^21839,CG,/' "$INPUT_BED" | wc -l)
COUNT_4MC_NONCG=$(awk -F'\t' '$4 ~ /^21839,C,/ && $4 !~ /^21839,CG,/' "$INPUT_BED" | wc -l)

cat > "$OUTPUT_DIR/reports/raw_statistics.txt" << EOF
原始数据统计 (无过滤)
=====================================
5mC @ CG:      $COUNT_5MC_CG
5mC @ non-CG:  $COUNT_5MC_NONCG
4mC @ CG:      $COUNT_4MC_CG
4mC @ non-CG:  $COUNT_4MC_NONCG
-------------------------------------
总计:          $RAW_COUNT
=====================================
EOF

# 修饰率分布
log_info "计算修饰率分布..."
awk -F'\t' '{print $11}' "$INPUT_BED" | \
    awk '{
        if($1>=90) h["90-100"]++;
        else if($1>=70) h["70-90"]++;
        else if($1>=50) h["50-70"]++;
        else if($1>=30) h["30-50"]++;
        else h["0-30"]++
    } END {
        print "修饰率分布:";
        for(i in h) print i"%: "h[i]
    }' > "$OUTPUT_DIR/reports/mod_rate_distribution.txt"

log_info "质量评估完成!"

#-------------------------------------------------------------------------------
#  步骤2: 数据过滤和分离
#-------------------------------------------------------------------------------

log_step "步骤2/7: 数据过滤和分离"

# 定义过滤函数
filter_and_separate() {
    local type_name=$1
    local pattern=$2
    local min_mod=$3
    local output_file="$OUTPUT_DIR/filtered/${type_name}_filtered.bed"

    log_info "过滤 $type_name (修饰率≥${min_mod}%, 覆盖度≥$MIN_COVERAGE)..."

    awk -F'\t' -v pat="$pattern" -v min_mod="$min_mod" -v min_cov="$MIN_COVERAGE" '
        $4 ~ pat && $11 >= min_mod && $5 >= min_cov {
            print $0
        }' "$INPUT_BED" > "$output_file"

    local count=$(wc -l < "$output_file")
    log_info "  → 保留 $count 个位点"
    echo "$count"
}

# 过滤和分离4种类型
COUNT_FILT_5MC_CG=$(filter_and_separate "5mC_CG" "^m,CG," "$MIN_MOD_5MC")
COUNT_FILT_5MC_NONCG=$(filter_and_separate "5mC_nonCG" "^m,C," "$MIN_MOD_5MC" | \
    awk -v pat="^m,CG," '$4 !~ pat' > "$OUTPUT_DIR/filtered/5mC_nonCG_filtered.bed" && \
    wc -l < "$OUTPUT_DIR/filtered/5mC_nonCG_filtered.bed")

# 重新正确过滤5mC non-CG(排除CG)
awk -F'\t' -v min_mod="$MIN_MOD_5MC" -v min_cov="$MIN_COVERAGE" '
    $4 ~ /^m,C,/ && $4 !~ /^m,CG,/ && $11 >= min_mod && $5 >= min_cov {
        print $0
    }' "$INPUT_BED" > "$OUTPUT_DIR/filtered/5mC_nonCG_filtered.bed"
COUNT_FILT_5MC_NONCG=$(wc -l < "$OUTPUT_DIR/filtered/5mC_nonCG_filtered.bed")

COUNT_FILT_4MC_CG=$(filter_and_separate "4mC_CG" "^21839,CG," "$MIN_MOD_4MC")
COUNT_FILT_4MC_NONCG=$(filter_and_separate "4mC_nonCG" "^21839,C," "$MIN_MOD_4MC" | \
    awk -v pat="^21839,CG," '$4 !~ pat' > "$OUTPUT_DIR/filtered/4mC_nonCG_filtered.bed" && \
    wc -l < "$OUTPUT_DIR/filtered/4mC_nonCG_filtered.bed")

# 重新正确过滤4mC non-CG
awk -F'\t' -v min_mod="$MIN_MOD_4MC" -v min_cov="$MIN_COVERAGE" '
    $4 ~ /^21839,C,/ && $4 !~ /^21839,CG,/ && $11 >= min_mod && $5 >= min_cov {
        print $0
    }' "$INPUT_BED" > "$OUTPUT_DIR/filtered/4mC_nonCG_filtered.bed"
COUNT_FILT_4MC_NONCG=$(wc -l < "$OUTPUT_DIR/filtered/4mC_nonCG_filtered.bed")

# 生成过滤统计报告
cat > "$OUTPUT_DIR/reports/filtering_summary.txt" << EOF
过滤结果统计
=====================================
过滤条件:
  最小覆盖度: $MIN_COVERAGE
  5mC修饰率阈值: ${MIN_MOD_5MC}%
  4mC修饰率阈值: ${MIN_MOD_4MC}%

过滤后位点数量:
  5mC @ CG:      $COUNT_FILT_5MC_CG (原始: $COUNT_5MC_CG, 保留: $(awk "BEGIN {printf \"%.1f\", $COUNT_FILT_5MC_CG/$COUNT_5MC_CG*100}")%)
  5mC @ non-CG:  $COUNT_FILT_5MC_NONCG (原始: $COUNT_5MC_NONCG, 保留: $(awk "BEGIN {printf \"%.1f\", $COUNT_FILT_5MC_NONCG/$COUNT_5MC_NONCG*100}")%)
  4mC @ CG:      $COUNT_FILT_4MC_CG (原始: $COUNT_4MC_CG, 保留: $(awk "BEGIN {printf \"%.1f\", $COUNT_FILT_4MC_CG/$COUNT_4MC_CG*100}")%)
  4mC @ non-CG:  $COUNT_FILT_4MC_NONCG (原始: $COUNT_4MC_NONCG, 保留: $(awk "BEGIN {printf \"%.1f\", $COUNT_FILT_4MC_NONCG/$COUNT_4MC_NONCG*100}")%)
=====================================
EOF

log_info "过滤统计已保存到: $OUTPUT_DIR/reports/filtering_summary.txt"
cat "$OUTPUT_DIR/reports/filtering_summary.txt"

#-------------------------------------------------------------------------------
#  步骤3: 提取序列上下文
#-------------------------------------------------------------------------------

log_step "步骤3/7: 提取序列上下文"

# 检查bedtools
if [[ "${BEDTOOLS_FOUND:-true}" != "true" ]]; then
    log_warn "bedtools未安装,跳过序列提取"
    SEQUENCES_EXTRACTED=false
else
    SEQUENCES_EXTRACTED=true

    # 索引参考基因组
    if [[ ! -f "${REF_GENOME}.fai" ]]; then
        log_info "索引参考基因组..."
        samtools faidx "$REF_GENOME"
    fi

    # 创建染色体大小文件
    cut -f1,2 "${REF_GENOME}.fai" > "$OUTPUT_DIR/reports/chrom.sizes"

    # 提取序列函数
    extract_sequences() {
        local bed_file=$1
        local type_name=$2
        local output_fa="$OUTPUT_DIR/sequences/${type_name}_sequences.fa"

        if [[ ! -s "$bed_file" ]]; then
            log_warn "$type_name 位点数为0,跳过序列提取"
            return
        fi

        log_info "提取 $type_name 序列 (±${FLANK_SIZE}bp)..."

        # 生成BED文件(带侧翼序列)
        awk -F'\t' -v flank="$FLANK_SIZE" '{
            start = ($2 - flank > 0) ? $2 - flank : 0;
            end = $3 + flank;
            print $1"\t"start"\t"end"\t"$4"_"NR
        }' "$bed_file" > "$OUTPUT_DIR/sequences/${type_name}_regions.bed"

        # 提取fasta
        bedtools getfasta -fi "$REF_GENOME" \
                          -bed "$OUTPUT_DIR/sequences/${type_name}_regions.bed" \
                          -fo "$output_fa" \
                          -nameOnly

        local seq_count=$(grep -c "^>" "$output_fa" || echo 0)
        log_info "  → 提取 $seq_count 条序列"
    }

    # 为每个类型提取序列
    extract_sequences "$OUTPUT_DIR/filtered/5mC_CG_filtered.bed" "5mC_CG"
    extract_sequences "$OUTPUT_DIR/filtered/5mC_nonCG_filtered.bed" "5mC_nonCG"
    extract_sequences "$OUTPUT_DIR/filtered/4mC_CG_filtered.bed" "4mC_CG"
    extract_sequences "$OUTPUT_DIR/filtered/4mC_nonCG_filtered.bed" "4mC_nonCG"
fi

#-------------------------------------------------------------------------------
#  步骤4: 生成背景序列
#-------------------------------------------------------------------------------

log_step "步骤4/7: 生成背景序列"

if [[ "$SEQUENCES_EXTRACTED" == "true" ]]; then
    # 合并所有target区域用于生成背景
    cat "$OUTPUT_DIR/sequences/"*_regions.bed 2>/dev/null | \
        bedtools shuffle -g "$OUTPUT_DIR/reports/chrom.sizes" | \
        bedtools getfasta -fi "$REF_GENOME" -bed stdin \
        -fo "$OUTPUT_DIR/sequences/background_sequences.fa" \
        -nameOnly

    BG_COUNT=$(grep -c "^>" "$OUTPUT_DIR/sequences/background_sequences.fa" || echo 0)
    log_info "生成 $BG_COUNT 条背景序列"
else
    log_warn "跳过背景序列生成"
fi

#-------------------------------------------------------------------------------
#  步骤5: Motif富集分析 (HOMER)
#-------------------------------------------------------------------------------

log_step "步骤5/7: Motif富集分析 (HOMER)"

if [[ "$RUN_HOMER" == "true" ]]; then
    if [[ "${HOMER_FOUND:-true}" != "true" ]]; then
        log_warn "HOMER未安装,跳过motif分析"
        RUN_HOMER=false
    else
        run_homer_motif() {
            local type_name=$1
            local bed_file="$OUTPUT_DIR/sequences/${type_name}_regions.bed"
            local output_dir="$OUTPUT_DIR/motif_analysis/homer/${type_name}"

            if [[ ! -s "$bed_file" ]]; then
                log_warn "$type_name 无位点,跳过HOMER分析"
                return
            fi

            local region_count=$(wc -l < "$bed_file")
            if [[ $region_count -lt 10 ]]; then
                log_warn "$type_name 位点数过少 ($region_count),跳过HOMER分析"
                return
            fi

            log_info "运行HOMER: $type_name..."
            mkdir -p "$output_dir"

            findMotifsGenome.pl "$bed_file" \
                "$REF_GENOME" \
                "$output_dir" \
                -bg "$OUTPUT_DIR/sequences/background_sequences.fa" \
                -len 6,8,10,12 \
                -p "$THREADS" \
                > "$output_dir/homer.log" 2>&1

            log_info "  → 结果保存至: $output_dir"
        }

        run_homer_motif "5mC_CG"
        run_homer_motif "5mC_nonCG"
        run_homer_motif "4mC_CG"
        run_homer_motif "4mC_nonCG"

        # 汇总HOMER结果
        log_info "汇总HOMER结果..."
        echo "HOMER Motif富集结果摘要" > "$OUTPUT_DIR/reports/homer_summary.txt"
        echo "=====================================" >> "$OUTPUT_DIR/reports/homer_summary.txt"

        for type in 5mC_CG 5mC_nonCG 4mC_CG 4mC_nonCG; do
            results_file="$OUTPUT_DIR/motif_analysis/homer/${type}/knownResults.txt"
            if [[ -f "$results_file" ]]; then
                echo -e "\n$type 前5个富集motif:" >> "$OUTPUT_DIR/reports/homer_summary.txt"
                head -6 "$results_file" >> "$OUTPUT_DIR/reports/homer_summary.txt"
            fi
        done
    fi
else
    log_info "HOMER分析已禁用"
fi

#-------------------------------------------------------------------------------
#  步骤6: Motif富集分析 (MEME - 可选)
#-------------------------------------------------------------------------------

log_step "步骤6/7: Motif富集分析 (MEME)"

if [[ "$RUN_MEME" == "true" ]]; then
    if ! command -v dreme &> /dev/null; then
        log_warn "MEME Suite未安装,跳过MEME分析"
        RUN_MEME=false
    else
        run_meme_dreme() {
            local type_name=$1
            local seq_file="$OUTPUT_DIR/sequences/${type_name}_sequences.fa"
            local output_dir="$OUTPUT_DIR/motif_analysis/meme/${type_name}"

            if [[ ! -s "$seq_file" ]]; then
                return
            fi

            local seq_count=$(grep -c "^>" "$seq_file" || echo 0)
            if [[ $seq_count -lt 10 ]]; then
                return
            fi

            log_info "运行DREME: $type_name..."
            mkdir -p "$output_dir"

            dreme -p "$seq_file" \
                  -n "$OUTPUT_DIR/sequences/background_sequences.fa" \
                  -oc "$output_dir" \
                  -e 0.05 \
                  -p "$THREADS" \
                  > "$output_dir/dreme.log" 2>&1

            log_info "  → 结果保存至: $output_dir"
        }

        run_meme_dreme "5mC_CG"
        run_meme_dreme "5mC_nonCG"
        run_meme_dreme "4mC_CG"
        run_meme_dreme "4mC_nonCG"
    fi
else
    log_info "MEME分析已禁用"
fi

#-------------------------------------------------------------------------------
#  步骤7: 生成可视化图表
#-------------------------------------------------------------------------------

log_step "步骤7/7: 生成可视化图表"

if [[ "$RUN_VISUALIZATION" == "true" ]]; then
    # 创建Python可视化脚本
    cat > "$OUTPUT_DIR/generate_plots.py" << 'PYTHON_SCRIPT'
#!/usr/bin/env python3
"""DNA甲基化数据可视化脚本"""

import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
import os
import sys

# 设置风格
sns.set_style("whitegrid")
sns.set_context("paper", font_scale=1.2)
plt.rcParams['font.sans-serif'] = ['Arial', 'DejaVu Sans']
plt.rcParams['axes.unicode_minus'] = False

def load_data(bed_file):
    """加载bed文件"""
    columns = ['chrom', 'start', 'end', 'name', 'score', 'strand', 
               'thickStart', 'thickEnd', 'color', 'Nvalid_cov', 
               'percent_modified', 'Nmod', 'Ncanonical', 'Nother_mod',
               'Ndelete', 'Nfail', 'Ndiff', 'Nnocall']
    return pd.read_csv(bed_file, sep='\t', header=None, names=columns)

def classify_modifications(df):
    """分类修饰类型"""
    df = df.copy()
    df['mod_type'] = df['name'].apply(lambda x: '5mC' if x.startswith('m,') else '4mC')
    df['motif_type'] = df['name'].apply(lambda x: 'CG' if ',CG,' in x else 'non-CG')
    df['category'] = df['mod_type'] + '_' + df['motif_type']
    return df

def plot_counts_comparison(df_raw, df_filt, output_file):
    """图1: 位点数量对比"""
    fig, ax = plt.subplots(figsize=(10, 6))

    categories = ['5mC_CG', '5mC_nonCG', '4mC_CG', '4mC_nonCG']
    counts_raw = [len(df_raw[df_raw['category']==c]) for c in categories]
    counts_filt = [len(df_filt[df_filt['category']==c]) for c in categories]

    x = np.arange(len(categories))
    width = 0.35

    bars1 = ax.bar(x - width/2, counts_raw, width, label='原始数据', 
                   color='lightgray', edgecolor='black')
    bars2 = ax.bar(x + width/2, counts_filt, width, label=f'过滤后', 
                   color='skyblue', edgecolor='black')

    ax.set_ylabel('位点数量', fontsize=12)
    ax.set_title('A: 甲基化位点数量统计', fontsize=14, fontweight='bold')
    ax.set_xticks(x)
    ax.set_xticklabels(['5mC@CG', '5mC@non-CG', '4mC@CG', '4mC@non-CG'])
    ax.legend()
    ax.grid(axis='y', alpha=0.3)

    # 添加数值标签
    for bars in [bars1, bars2]:
        for bar in bars:
            height = bar.get_height()
            if height > 0:
                ax.annotate(f'{int(height)}',
                           xy=(bar.get_x() + bar.get_width() / 2, height),
                           xytext=(0, 3),
                           textcoords="offset points",
                           ha='center', va='bottom', fontsize=9)

    plt.tight_layout()
    plt.savefig(output_file, dpi=300, bbox_inches='tight')
    plt.close()
    print(f"  ✓ 保存: {output_file}")

def plot_modification_distribution(df, output_file):
    """图2: 修饰率分布"""
    fig, axes = plt.subplots(2, 2, figsize=(12, 10))
    axes = axes.flatten()

    categories = ['5mC_CG', '5mC_nonCG', '4mC_CG', '4mC_nonCG']
    colors = {'5mC_CG': '#1f77b4', '5mC_nonCG': '#ff7f0e', 
              '4mC_CG': '#2ca02c', '4mC_nonCG': '#d62728'}
    titles = {'5mC_CG': '5mC @ CG', '5mC_nonCG': '5mC @ non-CG',
              '4mC_CG': '4mC @ CG', '4mC_nonCG': '4mC @ non-CG'}

    for idx, cat in enumerate(categories):
        data = df[df['category']==cat]['percent_modified']
        if len(data) > 0:
            sns.histplot(data=data, ax=axes[idx], color=colors[cat], 
                        bins=50, kde=True, edgecolor='black')
            axes[idx].axvline(x=50, color='red', linestyle='--', alpha=0.7, label='阈值 50%')
            axes[idx].axvline(x=70, color='darkred', linestyle='--', alpha=0.7, label='阈值 70%')
            axes[idx].set_xlabel('修饰率 (%)')
            axes[idx].set_ylabel('位点数量')
            axes[idx].set_title(f'{titles[cat]} (n={len(data)})')
            axes[idx].legend(fontsize=8)
            axes[idx].grid(axis='y', alpha=0.3)
        else:
            axes[idx].text(0.5, 0.5, '无数据', ha='center', va='center', 
                          transform=axes[idx].transAxes, fontsize=14)

    plt.suptitle('B: 修饰率分布', fontsize=14, fontweight='bold', y=0.995)
    plt.tight_layout()
    plt.savefig(output_file, dpi=300, bbox_inches='tight')
    plt.close()
    print(f"  ✓ 保存: {output_file}")

def plot_coverage_distribution(df, output_file):
    """图3: 覆盖度分布"""
    fig, axes = plt.subplots(1, 2, figsize=(14, 5))

    # 5mC
    data_5mC_CG = df[df['category']=='5mC_CG']['Nvalid_cov']
    data_5mC_nonCG = df[df['category']=='5mC_nonCG']['Nvalid_cov']

    if len(data_5mC_CG) > 0:
        sns.kdeplot(data=data_5mC_CG, ax=axes[0], label='5mC@CG', 
                   color='#1f77b4', linewidth=2)
    if len(data_5mC_nonCG) > 0:
        sns.kdeplot(data=data_5mC_nonCG, ax=axes[0], label='5mC@non-CG', 
                   color='#ff7f0e', linewidth=2)

    axes[0].set_xlabel('覆盖度 (Reads)')
    axes[0].set_ylabel('密度')
    axes[0].set_title('C: 5mC 覆盖度分布')
    axes[0].legend()
    axes[0].grid(axis='y', alpha=0.3)

    # 4mC
    data_4mC_CG = df[df['category']=='4mC_CG']['Nvalid_cov']
    data_4mC_nonCG = df[df['category']=='4mC_nonCG']['Nvalid_cov']

    if len(data_4mC_CG) > 0:
        sns.kdeplot(data=data_4mC_CG, ax=axes[1], label='4mC@CG', 
                   color='#2ca02c', linewidth=2)
    if len(data_4mC_nonCG) > 0:
        sns.kdeplot(data=data_4mC_nonCG, ax=axes[1], label='4mC@non-CG', 
                   color='#d62728', linewidth=2)

    axes[1].set_xlabel('覆盖度 (Reads)')
    axes[1].set_ylabel('密度')
    axes[1].set_title('D: 4mC 覆盖度分布')
    axes[1].legend()
    axes[1].grid(axis='y', alpha=0.3)

    plt.tight_layout()
    plt.savefig(output_file, dpi=300, bbox_inches='tight')
    plt.close()
    print(f"  ✓ 保存: {output_file}")

def generate_statistics_table(df_raw, df_filt, output_file):
    """图4: 统计汇总表"""
    fig, ax = plt.subplots(figsize=(10, 4))
    ax.axis('off')

    categories = ['5mC_CG', '5mC_nonCG', '4mC_CG', '4mC_nonCG']
    stats_data = []

    for cat in categories:
        cat_raw = df_raw[df_raw['category']==cat]
        cat_filt = df_filt[df_filt['category']==cat]

        if len(cat_raw) > 0:
            retention = len(cat_filt) / len(cat_raw) * 100
        else:
            retention = 0

        stats_data.append({
            '类型': cat.replace('_', ' @ '),
            '原始位点数': len(cat_raw),
            '过滤后位点数': len(cat_filt),
            '保留率(%)': f"{retention:.1f}",
            '中位修饰率(%)': f"{cat_filt['percent_modified'].median():.2f}" if len(cat_filt)>0 else "N/A",
            '平均修饰率(%)': f"{cat_filt['percent_modified'].mean():.2f}" if len(cat_filt)>0 else "N/A",
            '中位覆盖度': f"{cat_filt['Nvalid_cov'].median():.0f}" if len(cat_filt)>0 else "N/A",
        })

    df_stats = pd.DataFrame(stats_data)
    table = ax.table(cellText=df_stats.values, colLabels=df_stats.columns, 
                    cellLoc='center', loc='center', bbox=[0, 0, 1, 1])
    table.auto_set_font_size(False)
    table.set_fontsize(9)
    table.scale(1.2, 1.8)

    # 设置表头样式
    for i in range(len(df_stats.columns)):
        table[(0, i)].set_facecolor('#4472C4')
        table[(0, i)].set_text_props(color='white', fontweight='bold')

    plt.savefig(output_file, dpi=300, bbox_inches='tight')
    plt.close()
    print(f"  ✓ 保存: {output_file}")

def main():
    input_bed = sys.argv[1]
    output_dir = sys.argv[2]

    print("📊 生成可视化图表...")

    # 加载数据
    df_raw = load_data(input_bed)
    df_raw = classify_modifications(df_raw)

    # 加载过滤后数据
    filtered_files = {
        '5mC_CG': f"{output_dir}/filtered/5mC_CG_filtered.bed",
        '5mC_nonCG': f"{output_dir}/filtered/5mC_nonCG_filtered.bed",
        '4mC_CG': f"{output_dir}/filtered/4mC_CG_filtered.bed",
        '4mC_nonCG': f"{output_dir}/filtered/4mC_nonCG_filtered.bed"
    }

    # 合并过滤后的数据
    df_list = []
    for cat, fpath in filtered_files.items():
        if os.path.exists(fpath) and os.path.getsize(fpath) > 0:
            df_tmp = load_data(fpath)
            df_tmp['mod_type'] = '5mC' if '5mC' in cat else '4mC'
            df_tmp['motif_type'] = 'CG' if 'CG' in cat else 'non-CG'
            df_tmp['category'] = cat
            df_list.append(df_tmp)

    if df_list:
        df_filt = pd.concat(df_list, ignore_index=True)
    else:
        df_filt = df_raw.iloc[0:0]  # 空DataFrame

    # 生成图表
    os.makedirs(f"{output_dir}/figures", exist_ok=True)

    plot_counts_comparison(df_raw, df_filt, f"{output_dir}/figures/Fig1_counts.png")
    plot_modification_distribution(df_filt, f"{output_dir}/figures/Fig2_mod_distribution.png")
    plot_coverage_distribution(df_filt, f"{output_dir}/figures/Fig3_coverage.png")
    generate_statistics_table(df_raw, df_filt, f"{output_dir}/figures/Fig4_statistics.png")

    print("✅ 所有图表生成完成!")

if __name__ == "__main__":
    if len(sys.argv) != 3:
        print(f"用法: {sys.argv[0]} <input.bed> <output_dir>")
        sys.exit(1)
    main()
PYTHON_SCRIPT

    chmod +x "$OUTPUT_DIR/generate_plots.py"

    # 运行Python脚本
    if command -v python3 &> /dev/null; then
        log_info "运行Python可视化脚本..."
        python3 "$OUTPUT_DIR/generate_plots.py" "$INPUT_BED" "$OUTPUT_DIR" 2>&1 | tee "$OUTPUT_DIR/logs/visualization.log"
    else
        log_warn "Python3未安装,跳过可视化生成"
    fi
else
    log_info "可视化已禁用"
fi

#-------------------------------------------------------------------------------
#  生成最终报告
#-------------------------------------------------------------------------------

log_step "生成分析总结报告"

cat > "$OUTPUT_DIR/reports/FINAL_REPORT.txt" << EOF
================================================================================
                    DNA甲基化分析总结报告
================================================================================
生成时间: $(date)
分析脚本: $0

📁 输入文件:
   - BED文件: $INPUT_BED
   - 参考基因组: $REF_GENOME

⚙️  分析参数:
   - 最小覆盖度: $MIN_COVERAGE
   - 5mC修饰率阈值: ${MIN_MOD_5MC}%
   - 4mC修饰率阈值: ${MIN_MOD_4MC}%
   - 侧翼序列: ±${FLANK_SIZE}bp
   - 线程数: $THREADS

📊 数据统计:
$(cat "$OUTPUT_DIR/reports/filtering_summary.txt")

📂 输出文件结构:
   $OUTPUT_DIR/
   ├── filtered/              # 过滤后的bed文件
   │   ├── 5mC_CG_filtered.bed
   │   ├── 5mC_nonCG_filtered.bed
   │   ├── 4mC_CG_filtered.bed
   │   └── 4mC_nonCG_filtered.bed
   ├── sequences/             # 提取的fasta序列
   ├── motif_analysis/        # Motif富集分析结果
   │   └── homer/
   ├── figures/               # 可视化图表
   └── reports/               # 统计报告

🔬 主要发现:
   - 5mC主要富集在: $(if [[ -f "$OUTPUT_DIR/motif_analysis/homer/5mC_nonCG/knownResults.txt" ]]; then head -2 "$OUTPUT_DIR/motif_analysis/homer/5mC_nonCG/knownResults.txt" | tail -1 | cut -f1; else "待分析"; fi)
   - 4mC主要富集在: $(if [[ -f "$OUTPUT_DIR/motif_analysis/homer/4mC_nonCG/knownResults.txt" ]]; then head -2 "$OUTPUT_DIR/motif_analysis/homer/4mC_nonCG/knownResults.txt" | tail -1 | cut -f1; else "待分析"; fi)

================================================================================
                              分析完成!
================================================================================
EOF

log_info "最终报告: $OUTPUT_DIR/reports/FINAL_REPORT.txt"
cat "$OUTPUT_DIR/reports/FINAL_REPORT.txt"

#-------------------------------------------------------------------------------
#  清理临时文件
#-------------------------------------------------------------------------------

log_step "清理临时文件"

# 可选:删除大型中间文件
# rm -rf "$OUTPUT_DIR/sequences/"*_regions.bed

log_info "分析流程完成!✅"
log_info "查看最终报告: cat $OUTPUT_DIR/reports/FINAL_REPORT.txt"

exit 0

🚀 使用方法

1️⃣ 保存脚本

# 保存为 dna_methylation_analysis.sh
nano dna_methylation_analysis.sh
# 粘贴上面的代码,保存退出

# 赋予执行权限
chmod +x dna_methylation_analysis.sh

2️⃣ 运行分析

# 基本用法
bash dna_methylation_analysis.sh \
    -i An6_4mC_5mC_raw.bed \
    -r bacass_out/Medaka/An6-unicycler-medaka_polished_genome.fa \
    -o An6_methylation_results

# 自定义参数
bash dna_methylation_analysis.sh \
    -i An6_4mC_5mC_raw.bed \
    -r genome.fa \
    -o results \
    -c 10 \          # 最小覆盖度
    -m 70 \          # 5mC阈值
    -n 50 \          # 4mC阈值
    -f 50 \          # 侧翼序列
    -t 16            # 线程数

# 禁用某些功能
bash dna_methylation_analysis.sh \
    -i input.bed -r genome.fa \
    --no-homer       # 不运行HOMER
    --no-viz         # 不生成图表

3️⃣ 查看结果

# 查看最终报告
cat An6_methylation_results/reports/FINAL_REPORT.txt

# 查看图表
ls -lh An6_methylation_results/figures/

# 查看motif结果
ls -lh An6_methylation_results/motif_analysis/homer/

📦 依赖安装

# Conda环境(推荐)
conda create -n methylation python=3.9
conda activate methylation

# 必需工具
conda install -c bioconda bedtools samtools

# 可选:HOMER
conda install -c bioconda homer

# 可选:MEME Suite
conda install -c bioconda meme

# Python库
pip install pandas numpy matplotlib seaborn

📋 输出文件说明

An6_methylation_results/
├── filtered/                    # 过滤后的bed文件
│   ├── 5mC_CG_filtered.bed     # 5mC @ CG位点
│   ├── 5mC_nonCG_filtered.bed  # 5mC @ non-CG位点
│   ├── 4mC_CG_filtered.bed     # 4mC @ CG位点
│   └── 4mC_nonCG_filtered.bed  # 4mC @ non-CG位点
├── sequences/                   # 提取的序列
│   ├── *_sequences.fa          # 目标序列
│   └── background_sequences.fa # 背景序列
├── motif_analysis/
│   └── homer/
│       ├── 5mC_CG/             # HOMER结果
│       ├── 5mC_nonCG/
│       ├── 4mC_CG/
│       └── 4mC_nonCG/
├── figures/                     # 可视化图表
│   ├── Fig1_counts.png         # 位点数量对比
│   ├── Fig2_mod_distribution.png # 修饰率分布
│   ├── Fig3_coverage.png       # 覆盖度分布
│   └── Fig4_statistics.png     # 统计表
└── reports/                     # 统计报告
    ├── analysis_config.txt     # 分析配置
    ├── filtering_summary.txt   # 过滤统计
    └── FINAL_REPORT.txt        # 最终报告

需要我帮您调整任何参数或添加其他功能吗?🔧✨

nf-core/methylong 内置 DMR 选项:能替代哪些独立工具?

🔍 nf-core/methylong 内置 DMR 选项:能替代哪些独立工具?

✅ 简短回答

您之前需要的功能 methylong 内置选项 能否替代独立工具?
位点水平差异分析 (对标 TRANSIT ANOVA) --population_dmrer dss + --dmr_a/--dmr_b 完全可以替代独立 DSS
区域水平聚合比较 --population_dmrer dss (自动区域聚合) 部分替代 methylKit
连续低/高甲基化区域检测 (对标 Tn5Gaps) ❌ 无专门功能 仍需 metilene 或自定义脚本
基因/操纵子注释关联 ❌ 不直接整合 GFF 仍需 bedtools/ChIPseeker
出版级可视化 ❌ 只输出 bed/bigWig 仍需 pyGenomeTracks/IGV

🎯 核心结论:methylong 的 --population_dmrer dss 可以完全替代您独立运行 DSS 进行组间差异甲基化分析,无需额外工具!


📋 methylong DMR 选项详解 (对标 TRANSIT)

🔹 参数功能映射表

methylong 参数 作用 TRANSIT 对应功能 统计方法
--skip_snvs 跳过 SNP calling + phasing – (细菌无需)
--haplotype_dmrer [dss/modkit] 单倍型水平 DMR 工具 – (细菌无单倍型) 贝叶斯层次模型 (DSS)
--population_dmrer [dss/modkit] 群体水平 DMR 工具 ANOVA 多组比较 贝塔 – 二项检验 + FDR
--dmr_population_scale 启用多样本组间比较 条件间差异分析 同上
--dmr_a, --dmr_b 定义两个比较组的样本名 指定对比条件

🚀 用 methylong 内置 DSS 替代独立运行的完整命令

场景:细菌 6mA,An6 vs BG5 差异分析

nextflow run nf-core/methylong \
  -r 2.0.0 \
  -profile docker \
  --input samplesheet_6mA.csv \          # 包含 An6 和 BG5 两行
  --outdir methylome_out_6mA \
  --ont_aligner minimap2 \
  --m6a \
  --skip_snvs \                          # 细菌无需 phasing
  --dmr_population_scale \               # ⭐ 启用群体水平比较
  --population_dmrer dss \               # ⭐ 使用 DSS 进行统计 (默认值,可省略)
  --dmr_a "An6" \                        # ⭐ 定义组 A (samplesheet 中的 group 列)
  --dmr_b "BG5" \                        # ⭐ 定义组 B
  -resume \
  -work-dir methylome_out_6mA/work

🔹 samplesheet_6mA.csv 格式要求

group,sample,path,ref,method
An6,An6,/path/An6_6mA_mapped.mod.bam,/path/genome.fa,ont
BG5,BG5,/path/BG5_6mA_mapped.mod.bam,/path/genome.fa,ont

⚠️ 关键group 列的值 (An6, BG5) 必须与 --dmr_a/--dmr_b 完全一致!


📁 输出文件:methylong 内置 DMR 结果位置

methylome_out_6mA/
└── results/
    └── dmr/
        ├── population_scale/
        │   ├── An6_vs_BG5.DSS_DMLs.tsv      # ⭐ 位点水平差异结果 (对标 TRANSIT anova_out.xls)
        │   ├── An6_vs_BG5.DSS_DMRs.tsv      # 区域水平差异结果
        │   └── DSS_summary.html             # 简要统计摘要
        └── qc/
            └── dmr_multiqc_report.html      # DMR 分析质控

🔹 DSS_DMLs.tsv 列解读 (对标 TRANSIT ANOVA 输出)

列名 含义 TRANSIT 对应列
chr, pos 基因组坐标 Orf, TA_pos
coverage_A, coverage_B 两组覆盖深度 TAs
mod_count_A, mod_count_B 两组修饰计数 Mean_[condition]
methylation_A, methylation_B 两组甲基化概率 (0-100)
diff 甲基化差异 (A – B) LFC_[condition]
pval, p.adj 原始/FDR 校正 p 值 Pval, Padj
significant 是否显著 (FDR20%) status

⚠️ methylong 内置 DMR 的局限性 (仍需外部工具的场景)

❌ 无法替代的功能 1:连续区域检测 (对标 Tn5Gaps)

# methylong 输出的是"离散位点"差异,不是"连续非修饰区域"
# 如果您需要检测类似 Tn5Gaps 的"长片段无 6mA 区域",仍需:

metilene \
  -i An6.bedgraph BG5.bedgraph \
  -g genome.sizes \
  -o continuous_dmr.tsv \
  -p 0.05 -d 0.2

❌ 无法替代的功能 2:基因/操纵子水平注释

# methylong 不直接整合 GFF 注释
# 如需"哪些基因的 6mA 水平显著改变",仍需:

bedtools intersect -a An6_vs_BG5.DSS_DMLs.tsv -b genome.gff -wa -wb > genes_with_diff_6mA.tsv

❌ 无法替代的功能 3:高级可视化

# methylong 只输出 bed/bigWig,不生成出版级图
# 如需 Circos 式基因组视图,仍需:

pygenometracks --tracks tracks.ini --output final_figure.png

🎯 推荐工作流:methylong 内置 + 最小外部工具

graph LR
    A[modkit pileup] --> B[methylong with --population_dmrer dss]
    B --> C[An6_vs_BG5.DSS_DMLs.tsv]

    C --> D{需要连续区域?}
    D -->|是 | E[metilene for continuous DMRs]
    D -->|否 | F[直接进入注释]

    E & F --> G[bedtools + genome.gff for gene annotation]
    G --> H[pyGenomeTracks for visualization]

✅ 最小命令集:

# 1️⃣ 主分析:methylong 内置 DSS (替代独立 DSS 运行)
nextflow run nf-core/methylong ... --dmr_population_scale --dmr_a An6 --dmr_b BG5 ...

# 2️⃣ (可选) 连续区域检测:仍需 metilene
awk '$4 == "a" {printf "%s\t%d\t%d\t%.2f\n", $1, $2, $3, $11}' An6_6mA_raw.bed > An6.bg
metilene -i An6.bg BG5.bg -g genome.sizes -o continuous_dmr.tsv

# 3️⃣ (可选) 基因注释:仍需 bedtools
bedtools intersect -a methylome_out_6mA/results/dmr/population_scale/An6_vs_BG5.DSS_DMLs.tsv \
  -b genome.gff -wa -wb > annotated_diff_6mA.tsv

💡 一句话总结

🔑 methylong 内置 DMR 选项可以

  • 完全替代独立 DSS 进行位点水平差异分析 (--population_dmrer dss)
  • 自动完成:标准化 + 贝塔 – 二项检验 + FDR 校正 + 结果输出

🔑 但仍需外部工具

  • ❌ 连续区域检测 (→ metilene)
  • ❌ 基因注释关联 (→ bedtools/ChIPseeker)
  • ❌ 出版级可视化 (→ pyGenomeTracks)

🎯 您的最优路径:先用 methylong 内置 DSS 拿到差异位点列表,再按需添加 1-2 个外部工具完成注释和可视化!

如需我帮您编写 samplesheet 或调试 methylong DMR 参数,请随时告知!🚀



🔍 结果分析:非 CG 位点更多是完全合理的!

您的结果 完全符合逻辑,甚至反映了细菌基因组的典型特征。让我详细解释:


📊 您的结果汇总

修饰类型 位点数量 占比 生物学解释
5mC @ CG 437 33% 经典 CpG 甲基化
5mC @ non-CG 870 67% ⭐ 非 CG 位点更多,正常!
4mC @ CG 7 17% 4mC 很少在 CG 上
4mC @ non-CG 34 83% ⭐ 4mC 偏好非 CG 位点

✅ 为什么 non-CG 位点更多?三大原因

🔹 原因 1:序列组成决定数量基数

假设基因组碱基随机分布(各 25%):

所有可能的二核苷酸:16 种 (AA, AC, AG, AT, CA, CC, CG, CT, ...)

其中含 C 的位点:
├─ CG: 1 种 → 占所有 C 位点的 ~25%
├─ CA, CC, CT: 3 种 → 占所有 C 位点的 ~75% ← non-CG 位点天生更多!

因此:即使甲基化概率相同,non-CG 位点数量也会是 CG 的 ~3 倍

🔹 原因 2:细菌甲基化偏好特定非 CG 基序

细菌的限制修饰系统通常靶向 特定回文序列,而非随机 CG:

常见细菌甲基化基序 修饰类型 示例细菌
GATC 6mA / 4mC E. coli Dam 甲基化酶
CCWGG 5mC H. influenzae Dcm 甲基化酶
GANTC 6mA Caulobacter CcrM 甲基化酶
RCGY 4mC 多种细菌

→ 如果您的细菌有类似系统,非 CG 位点会被优先甲基化

🔹 原因 3:--motif C 0 捕获了所有胞嘧啶

您使用的命令:

modkit pileup ... --motif CG 0 --motif C 0 ...
  • --motif C 0 = 检测 每一个胞嘧啶(无论后面是什么碱基)
  • 因此 m,C,0 包含:CG + CA + CC + CT 所有 C 位点
  • 排除 CG 后,剩余的 non-CG 位点自然更多 ✅

🔬 验证:这些 non-CG 信号是真实的吗?

运行以下命令检查数据质量:

# 1️⃣ 比较 CG vs non-CG 的修饰率分布
echo "=== 5mC 修饰率中位数 ==="
echo -n "CG:    "
awk -F'\t' '$4 ~ /^m,CG,/ {print $11}' An6_4mC_5mC_raw.bed | sort -n | awk '{a[NR]=$1} END{print a[int(NR/2)]}'
echo -n "non-CG:"
awk -F'\t' '$4 ~ /^m,C,/ && $4 !~ /^m,CG,/ {print $11}' An6_4mC_5mC_raw.bed | sort -n | awk '{a[NR]=$1} END{print a[int(NR/2)]}'

# 2️⃣ 检查 non-CG 位点的序列背景(提取上游10bp)
# 需要先有基因组 fasta 索引
samtools faidx bacass_out/Medaka/An6-unicycler-medaka_polished_genome.fa

# 提取 non-CG 5mC 位点的序列上下文
awk -F'\t' '$4 ~ /^m,C,/ && $4 !~ /^m,CG,/ && $11 >= 70 && $5 >= 10 {
  print $1":"$2+1"-"$2+11
}' An6_4mC_5mC_raw.bed | head -20 > nonCG_sites.txt

# 3️⃣ 用 MEME/HOMER 做 motif 富集(可选)
# 如果 870 个位点富集到特定序列,说明是真实生物学信号!

🎯 分析建议:如何处理这 4 类数据?

✅ 推荐策略:分层分析

# 📁 第一层:核心分析(高置信度 CG 位点)
# 用于主图、主要结论
awk -F'\t' '$4 ~ /^m,CG,/ && $11 >= 70 && $5 >= 10' An6_4mC_5mC_raw.bed > An6_5mC_CG_high.bed
awk -F'\t' '$4 ~ /^21839,CG,/ && $11 >= 50 && $5 >= 10' An6_4mC_5mC_raw.bed > An6_4mC_CG_high.bed

# 📁 第二层:探索性分析(non-CG 位点)
# 用于补充材料、motif 发现
awk -F'\t' '$4 ~ /^m,C,/ && $4 !~ /^m,CG,/ && $11 >= 70 && $5 >= 10' An6_4mC_5mC_raw.bed > An6_5mC_nonCG.bed
awk -F'\t' '$4 ~ /^21839,C,/ && $4 !~ /^21839,CG,/ && $11 >= 50 && $5 >= 10' An6_4mC_5mC_raw.bed > An6_4mC_nonCG.bed

# 📁 第三层:全量数据(用于基因组浏览器)
# 不过滤,供 IGV 可视化
cp An6_4mC_5mC_raw.bed An6_all_modified.bed

📊 可视化建议

数据类型 推荐图表 工具
5mC @ CG 基因组分布 + 修饰率直方图 deepTools + ggplot2
4mC @ non-CG motif 富集 + 热图 HOMER + seaborn
两者对比 Venn 图 + 散点图 R/ComplexHeatmap

⚠️ 注意事项:避免重复计数!

由于 m,C,0 包含 m,CG,0不要简单相加:

# ❌ 错误:直接相加会重复计算 CG 位点
total_5mC = CG_count + nonCG_count  # 重复!

# ✅ 正确:只用 C  motif 统计全部 5mC
awk -F'\t' '$4 ~ /^m,C,/ && $11 >= 70 && $5 >= 10' An6_4mC_5mC_raw.bed | wc -l
# 或:CG + nonCG(确保互斥)
awk -F'\t' '($4 ~ /^m,CG,/ || ($4 ~ /^m,C,/ && $4 !~ /^m,CG,/)) && $11 >= 70 && $5 >= 10' An6_4mC_5mC_raw.bed | wc -l

🧪 快速诊断脚本(一键运行)

#!/bin/bash
FILE="An6_4mC_5mC_raw.bed"

echo "🔍 数据质量诊断"
echo "================"
echo -e "\n📈 各类型原始行数(无过滤):"
echo "5mC @ CG:    $(grep -c 'm,CG,' $FILE)"
echo "5mC @ C:     $(grep -c 'm,C,' $FILE)"
echo "4mC @ CG:    $(grep -c '21839,CG,' $FILE)"
echo "4mC @ C:     $(grep -c '21839,C,' $FILE)"

echo -e "\n📊 修饰率统计 (列11):"
for label in "5mC_CG" "5mC_nonCG" "4mC_CG" "4mC_nonCG"; do
  case $label in
    "5mC_CG") pattern="^m,CG," ;;
    "5mC_nonCG") pattern="^m,C,"; exclude="m,CG," ;;
    "4mC_CG") pattern="^21839,CG," ;;
    "4mC_nonCG") pattern="^21839,C,"; exclude="21839,CG," ;;
  esac

  if [ -n "$exclude" ]; then
    stats=$(awk -F'\t' -v p="$pattern" -v e="$exclude" '$4 ~ p && $4 !~ e {print $11}' $FILE | \
      awk '{s+=$1; n++} END{if(n>0) printf "n=%d, median=%.2f, mean=%.2f", n, (n%2?$(int(n/2)+1):($(n/2)+$(n/2+1))/2), s/n}')
  else
    stats=$(awk -F'\t' -v p="$pattern" '$4 ~ p {print $11}' $FILE | \
      awk '{s+=$1; n++} END{if(n>0) printf "n=%d, median=%.2f, mean=%.2f", n, (n%2?$(int(n/2)+1):($(n/2)+$(n/2+1))/2), s/n}')
  fi
  echo "$label: $stats"
done

🎯 结论

870 > 437 是完全合理的
非 CG 胞嘧啶在基因组中本就更多,加上细菌甲基化系统常靶向特定非 CG 基序,导致 non-CG 修饰位点数量超过 CG 位点。

下一步建议

  1. nonCG_sites.txt 做 motif 富集,看看 870 个位点是否聚集在特定序列
  2. 如果富集到已知细菌甲基化基序(如 GATC),说明信号真实可靠 🔬
  3. 在论文/报告中明确区分 CGnon-CG 分析,避免混淆

需要我帮您写 motif 富集分析脚本,或生成对比图表吗?📈✨

🧰 甲基化下游统计分析:独立工具推荐与使用指南

🧰 甲基化下游统计分析:独立工具推荐与使用指南

您不需要 Nextflow 封装,以下是优秀的独立工具 (standalone tools),可直接用于 modkit pileup 结果的统计分析,功能对标 TRANSIT:


📊 工具总览:按 TRANSIT 功能映射

TRANSIT 功能 甲基化对应工具 类型 安装方式 核心优势
TTR 标准化 DSS::normalizeCoverage() R 包 conda install bioconductor-dss 贝叶斯收缩,小样本稳健
ANOVA 多组比较 DSS::DMLtest() / methylKit R 包 conda install bioconductor-methylkit 支持任意分组设计 + FDR 校正
Tn5Gaps (非插入运行) metilene / DMRfinder C++ / Python conda install -c bioconda metilene 快速检测连续低/高甲基化区域
基因长度标准化 bedtools + 自定义脚本 CLI 工具 conda install -c bioconda bedtools 灵活适配细菌基因密集特点
置换检验 + FDR DSS (内置) / methylKit R 包 同上 自动多重校正,输出可直接发表
Circos 可视化 pyGenomeTracks / deepTools Python pip install pygenometracks 出版级基因组轨道图,易定制

🔧 工具详解:安装 + 使用示例

1️⃣ DSS (Dispersion Shrinkage for Sequencing) — 首选推荐 ⭐

🎯 对标 TRANSIT ANOVA:位点水平差异甲基化检测,支持多样本、多组比较

🔹 安装

# 推荐:通过 conda (自动解决 R 依赖)
conda create -n methyl_stats -c conda-forge -c bioconda r-base r-dss
conda activate methyl_stats

# 或手动在 R 中安装
R
> if (!require("BiocManager", quietly = TRUE)) install.packages("BiocManager")
> BiocManager::install("DSS")

🔹 输入准备 (modkit bed → DSS 格式)

# 提取核心列: chrom, start, end, mod_count, coverage
# modkit 输出: $4=修饰码, $5=覆盖度, $10=修饰计数, $11=概率(0-100)
awk '$4 == "a" {printf "%s\t%d\t%d\t%d\t%d\n", $1, $2, $3, $10, $5}' An6_6mA_raw.bed > An6.dss
awk '$4 == "a" {printf "%s\t%d\t%d\t%d\t%d\n", $1, $2, $3, $10, $5}' BG5_6mA_raw.bed > BG5.dss

🔹 R 分析脚本 (run_dss_6mA.R)

#!/usr/bin/env Rscript
library(DSS)
library(qvalue)  # 用于更灵活的 FDR 校正

# 1. 读取数据
read_dss <- function(f) {
  df <- read.table(f, header=F, col.names=c("chr","start","end","X","N"))
  df$pos <- df$start + 1  # BED 0-based → 1-based
  df[, c("chr","pos","N","X")]  # DSS 要求格式
}
An6 <- read_dss("An6.dss")
BG5 <- read_dss("BG5.dss")

# 2. 构建 BSseq 对象
BSobj <- makeBSseqData(list(An6, BG5), sampleNames=c("An6", "BG5"))

# 3. 差异检验 (贝塔 - 二项模型 + 平滑)
dmlTest <- DMLtest(BSobj, group1=1, group2=2, smoothing=TRUE)

# 4. 提取显著位点 (FDR < 0.05, |diff| > 20%)
sigDML <- getSig(dmlTest, pval=0.05, delta=0.2)

# 5. 输出结果
write.table(sigDML, "An6_vs_BG5_6mA_DMLs.tsv", 
            sep="\t", quote=F, row.names=F)

# 6. (可选) 按基因注释聚合
# 需准备 genome.gff,用 ChIPseeker 或自定义脚本
cat("✅ 完成!显著差异位点数:", nrow(sigDML), "\n")

🔹 运行

Rscript run_dss_6mA.R

🔹 输出解读 (对标 TRANSIT ANOVA)

DSS 输出列 含义 TRANSIT 对应列
chr, pos 基因组坐标 Orf, TA_pos
coverage 总覆盖深度 TAs
group1, group2 两组修饰计数 Mean_[cond]
pval, p.adj 原始/FDR 校正 p 值 Pval, Padj
diff 甲基化差异 (组1 – 组2) LFC_[cond]
abs.diff 绝对差异值

2️⃣ metilene — 快速 DMR 检测 (对标 Tn5Gaps)

🎯 对标 TRANSIT Tn5Gaps:检测连续低/高甲基化区域,基于二元分割 + 置换检验

🔹 安装

conda install -c bioconda metilene
# 或下载预编译二进制: https://github.com/metilene/metilene/releases

🔹 输入准备

# metilene 需要 bedGraph 格式: chrom, start, end, value
# 用 modkit 概率列 ($11) 作为 value
awk '$4 == "a" {printf "%s\t%d\t%d\t%.2f\n", $1, $2, $3, $11}' An6_6mA_raw.bed > An6.bedgraph
awk '$4 == "a" {printf "%s\t%d\t%d\t%.2f\n", $1, $2, $3, $11}' BG5_6mA_raw.bed > BG5.bedgraph

# 准备基因组大小文件 (chrom, size)
samtools faidx genome.fa | cut -f1,2 > genome.sizes

🔹 运行 DMR 检测

metilene \
  -i An6.bedgraph BG5.bedgraph \
  -g genome.sizes \
  -o dmr_results.tsv \
  -t 8 \          # 线程数
  -p 0.05 \       # FDR 阈值
  -d 0.2          # 最小甲基化差异 (20%)

🔹 输出解读

# dmr_results.tsv 示例:
chr1    12345   12890   0.85    0.32    0.53    1.2e-05  0.003   hyper
# │      │      │      │       │       │       │        │      │
# │      │      │      │       │       │       │        │      └─ 方向: hyper/hypo
# │      │      │      │       │       │       │        └─ FDR 校正 p 值
# │      │      │      │       │       │       └─ 原始 p 值
# │      │      │      │       │       └─ 甲基化差异 (An6 - BG5)
# │      │      │      │       └─ BG5 平均甲基化
# │      │      │      └─ An6 平均甲基化
# │      │      └─ 区域结束
# │      └─ 区域起始
# └─ 染色体

3️⃣ methylKit — 基因/区域水平聚合分析

🎯 对标基因水平分析:将位点聚合到基因/操纵子,进行组间比较

🔹 安装

conda install -c bioconda bioconductor-methylkit

🔹 R 脚本示例 (methylkit_gene_level.R)

#!/usr/bin/env Rscript
library(methylKit)
library(GenomicFeatures)

# 1. 读取 modkit bed (需先转为 methylKit 格式)
# 格式: chr, start, end, strand, coverage, freq
read_modkit <- function(f, sample_id) {
  df <- read.table(f, header=F)
  df <- df[df$V4 == "a" & df$V11 >= 70 & df$V5 >= 10, ]  # 6mA, prob≥70%, cov≥10
  data.frame(
    chr = df$V1,
    start = df$V2 + 1,  # 0-based → 1-based
    end = df$V3,
    strand = ifelse(df$V6 == "+", 1, -1),
    coverage = df$V5,
    freq = df$V11  # 概率 0-100
  )
}

# 2. 加载样本
An6 <- read_modkit("An6_6mA_raw.bed", "An6")
BG5 <- read_modkit("BG5_6mA_raw.bed", "BG5")

# 3. 创建 methylKit 对象
myobj <- methRead(
  list("An6.tmp", "BG5.tmp"),  # 需先保存为临时文件
  sample.id = c("An6", "BG5"),
  assembly = "An6_genome",
  treatment = c(1, 2),         # 实验分组
  context = "CpG"              # 细菌可设为"any"
)

# 4. 基因水平聚合 (需 GFF 注释)
txdb <- makeTxDbFromGFF("genome.gff", format="gff3")
gene_meth <- tileMethylCounts(myobj, win.size=1000, step.size=500)

# 5. 差异分析
diff_meth <- calculateMethylDiff(gene_meth, difference=20, qvalue=0.01)

# 6. 输出
write.table(diff_meth, "gene_level_6mA_diff.tsv", sep="\t", quote=F)

4️⃣ 可视化工具:pyGenomeTracks (对标 Circos)

🎯 对标 Circos:生成线性基因组轨道图,支持多条件叠加

🔹 安装

pip install pygenometracks

🔹 准备配置文件 (tracks.ini)

[x-axis]
where = top

# 6mA 信号轨道 (An6)
[An6_6mA]
file = An6_6mA.bw
title = An6 6mA
height = 2
color = #1f78b4
min_value = 0
max_value = 100

# 6mA 信号轨道 (BG5)
[BG5_6mA]
file = BG5_6mA.bw
title = BG5 6mA
height = 2
color = #e31a1c
min_value = 0
max_value = 100

# 差异区域标记
[DMRs]
file = dmr_results.bed
title = Significant DMRs
height = 1
color = #ff7f00

🔹 生成 bigWig (modkit bed → bigWig)

# 1. bed → bedGraph
awk '$4 == "a" {printf "%s\t%d\t%d\t%.2f\n", $1, $2, $3, $11}' An6_6mA_raw.bed > An6_6mA.bg

# 2. bedGraph → bigWig (需 genome.sizes)
bedGraphToBigWig An6_6mA.bg genome.sizes An6_6mA.bw

🔹 运行可视化

pygenometracks \
  --tracks tracks.ini \
  --region chr1:100000-200000 \  # 可选:指定区域
  --width 10 \
  --height 5 \
  --output methylation_tracks.png \
  --dpi 300

🎯 针对您项目的最小可行流程

# ✅ 步骤 1: 格式转换 (modkit bed → 各工具输入)
# DSS 输入
awk '$4 == "a" {printf "%s\t%d\t%d\t%d\t%d\n", $1, $2, $3, $10, $5}' An6_6mA_raw.bed > An6.dss

# metilene 输入
awk '$4 == "a" {printf "%s\t%d\t%d\t%.2f\n", $1, $2, $3, $11}' An6_6mA_raw.bed > An6.bedgraph

# bigWig 输入 (可视化)
awk '$4 == "a" {printf "%s\t%d\t%d\t%.2f\n", $1, $2, $3, $11}' An6_6mA_raw.bed | \
  bedGraphToBigWig stdin genome.sizes An6_6mA.bw

# ✅ 步骤 2: 运行统计分析
Rscript run_dss_6mA.R                    # 位点水平差异
metilene -i An6.bedgraph BG5.bedgraph -g genome.sizes -o dmr.tsv  # 区域水平

# ✅ 步骤 3: 可视化
pygenometracks --tracks tracks.ini --output final_tracks.png

# ✅ 步骤 4: 整合结果 (可选)
# 将 DSS 显著位点 + metilene DMR 区域 + 基因注释合并为最终表格

📦 一键安装脚本 (conda 环境)

#!/bin/bash
# install_methyl_tools.sh

conda create -n methyl_analysis -c conda-forge -c bioconda \
  r-base=4.3 \
  r-dss \
  r-methylkit \
  r-chipseeker \
  r-qvalue \
  metilene \
  bedtools \
  samtools \
  ucsc-bedgraphtobigwig \
  -y

conda activate methyl_analysis

# 额外安装 Python 可视化工具
pip install pygenometracks deepTools

echo "✅ 所有工具安装完成!激活环境: conda activate methyl_analysis"

💡 工具选择决策树

您的分析目标?
│
├─ 🔍 "哪些位点在条件间甲基化水平不同?"
│   └─→ ✅ DSS (最严谨,输出可直接用于发表)
│
├─ 🧬 "哪些连续区域甲基化状态改变?" (对标 Tn5Gaps)
│   └─→ ✅ metilene (最快) 或 DMRfinder (最灵活)
│
├─ 📊 "基因/操纵子水平聚合比较?"
│   └─→ ✅ methylKit + ChIPseeker 注释
│
├─ 🎨 "生成出版级可视化?"
│   └─→ ✅ pyGenomeTracks (线性) 或 Circos (环形,需额外配置)
│
└─ 🔎 "交互式探索关键位点?"
    └─→ ✅ IGV + bigWig (最直观)

🎯 一句话总结

🔑 核心推荐组合

  • 差异分析DSS (R 包,对标 TRANSIT ANOVA)
  • 区域检测metilene (C++ 二进制,对标 Tn5Gaps)
  • 可视化pyGenomeTracks (Python,对标 Circos)

🚀 安装最简单:全部可通过 condapip 一键安装,无需编译
📈 您的 2,234 个高置信 6mA 位点 + 上述工具 = 完整、可发表的甲基化分析流程!

如需具体脚本调试或结果解读帮助,请随时告知!🔧🚀



🔍 nf-core/methylong 内置 DMR 选项:能替代哪些独立工具?

✅ 简短回答

您之前需要的功能 methylong 内置选项 能否替代独立工具?
位点水平差异分析 (对标 TRANSIT ANOVA) --population_dmrer dss + --dmr_a/--dmr_b 完全可以替代独立 DSS
区域水平聚合比较 --population_dmrer dss (自动区域聚合) 部分替代 methylKit
连续低/高甲基化区域检测 (对标 Tn5Gaps) ❌ 无专门功能 仍需 metilene 或自定义脚本
基因/操纵子注释关联 ❌ 不直接整合 GFF 仍需 bedtools/ChIPseeker
出版级可视化 ❌ 只输出 bed/bigWig 仍需 pyGenomeTracks/IGV

🎯 核心结论:methylong 的 --population_dmrer dss 可以完全替代您独立运行 DSS 进行组间差异甲基化分析,无需额外工具!


📋 methylong DMR 选项详解 (对标 TRANSIT)

🔹 参数功能映射表

methylong 参数 作用 TRANSIT 对应功能 统计方法
--skip_snvs 跳过 SNP calling + phasing – (细菌无需)
--haplotype_dmrer [dss/modkit] 单倍型水平 DMR 工具 – (细菌无单倍型) 贝叶斯层次模型 (DSS)
--population_dmrer [dss/modkit] 群体水平 DMR 工具 ANOVA 多组比较 贝塔 – 二项检验 + FDR
--dmr_population_scale 启用多样本组间比较 条件间差异分析 同上
--dmr_a, --dmr_b 定义两个比较组的样本名 指定对比条件

🚀 用 methylong 内置 DSS 替代独立运行的完整命令

场景:细菌 6mA,An6 vs BG5 差异分析

nextflow run nf-core/methylong \
  -r 2.0.0 \
  -profile docker \
  --input samplesheet_6mA.csv \          # 包含 An6 和 BG5 两行
  --outdir methylome_out_6mA \
  --ont_aligner minimap2 \
  --m6a \
  --skip_snvs \                          # 细菌无需 phasing
  --dmr_population_scale \               # ⭐ 启用群体水平比较
  --population_dmrer dss \               # ⭐ 使用 DSS 进行统计 (默认值,可省略)
  --dmr_a "An6" \                        # ⭐ 定义组 A (samplesheet 中的 group 列)
  --dmr_b "BG5" \                        # ⭐ 定义组 B
  -resume \
  -work-dir methylome_out_6mA/work

🔹 samplesheet_6mA.csv 格式要求

group,sample,path,ref,method
An6,An6,/path/An6_6mA_mapped.mod.bam,/path/genome.fa,ont
BG5,BG5,/path/BG5_6mA_mapped.mod.bam,/path/genome.fa,ont

⚠️ 关键group 列的值 (An6, BG5) 必须与 --dmr_a/--dmr_b 完全一致!


📁 输出文件:methylong 内置 DMR 结果位置

methylome_out_6mA/
└── results/
    └── dmr/
        ├── population_scale/
        │   ├── An6_vs_BG5.DSS_DMLs.tsv      # ⭐ 位点水平差异结果 (对标 TRANSIT anova_out.xls)
        │   ├── An6_vs_BG5.DSS_DMRs.tsv      # 区域水平差异结果
        │   └── DSS_summary.html             # 简要统计摘要
        └── qc/
            └── dmr_multiqc_report.html      # DMR 分析质控

🔹 DSS_DMLs.tsv 列解读 (对标 TRANSIT ANOVA 输出)

列名 含义 TRANSIT 对应列
chr, pos 基因组坐标 Orf, TA_pos
coverage_A, coverage_B 两组覆盖深度 TAs
mod_count_A, mod_count_B 两组修饰计数 Mean_[condition]
methylation_A, methylation_B 两组甲基化概率 (0-100)
diff 甲基化差异 (A – B) LFC_[condition]
pval, p.adj 原始/FDR 校正 p 值 Pval, Padj
significant 是否显著 (FDR20%) status

⚠️ methylong 内置 DMR 的局限性 (仍需外部工具的场景)

❌ 无法替代的功能 1:连续区域检测 (对标 Tn5Gaps)

# methylong 输出的是"离散位点"差异,不是"连续非修饰区域"
# 如果您需要检测类似 Tn5Gaps 的"长片段无 6mA 区域",仍需:

metilene \
  -i An6.bedgraph BG5.bedgraph \
  -g genome.sizes \
  -o continuous_dmr.tsv \
  -p 0.05 -d 0.2

❌ 无法替代的功能 2:基因/操纵子水平注释

# methylong 不直接整合 GFF 注释
# 如需"哪些基因的 6mA 水平显著改变",仍需:

bedtools intersect -a An6_vs_BG5.DSS_DMLs.tsv -b genome.gff -wa -wb > genes_with_diff_6mA.tsv

❌ 无法替代的功能 3:高级可视化

# methylong 只输出 bed/bigWig,不生成出版级图
# 如需 Circos 式基因组视图,仍需:

pygenometracks --tracks tracks.ini --output final_figure.png

🎯 推荐工作流:methylong 内置 + 最小外部工具

graph LR
    A[modkit pileup] --> B[methylong with --population_dmrer dss]
    B --> C[An6_vs_BG5.DSS_DMLs.tsv]

    C --> D{需要连续区域?}
    D -->|是 | E[metilene for continuous DMRs]
    D -->|否 | F[直接进入注释]

    E & F --> G[bedtools + genome.gff for gene annotation]
    G --> H[pyGenomeTracks for visualization]

✅ 最小命令集:

# 1️⃣ 主分析:methylong 内置 DSS (替代独立 DSS 运行)
nextflow run nf-core/methylong ... --dmr_population_scale --dmr_a An6 --dmr_b BG5 ...

# 2️⃣ (可选) 连续区域检测:仍需 metilene
awk '$4 == "a" {printf "%s\t%d\t%d\t%.2f\n", $1, $2, $3, $11}' An6_6mA_raw.bed > An6.bg
metilene -i An6.bg BG5.bg -g genome.sizes -o continuous_dmr.tsv

# 3️⃣ (可选) 基因注释:仍需 bedtools
bedtools intersect -a methylome_out_6mA/results/dmr/population_scale/An6_vs_BG5.DSS_DMLs.tsv \
  -b genome.gff -wa -wb > annotated_diff_6mA.tsv

💡 一句话总结

🔑 methylong 内置 DMR 选项可以

  • 完全替代独立 DSS 进行位点水平差异分析 (--population_dmrer dss)
  • 自动完成:标准化 + 贝塔 – 二项检验 + FDR 校正 + 结果输出

🔑 但仍需外部工具

  • ❌ 连续区域检测 (→ metilene)
  • ❌ 基因注释关联 (→ bedtools/ChIPseeker)
  • ❌ 出版级可视化 (→ pyGenomeTracks)

🎯 您的最优路径:先用 methylong 内置 DSS 拿到差异位点列表,再按需添加 1-2 个外部工具完成注释和可视化!

如需我帮您编写 samplesheet 或调试 methylong DMR 参数,请随时告知!🚀



📊 modkit pileup 输出文件列详解 (bedMethyl 格式)

🎯 您的结果统计

过滤条件 位点数量 说明
$11 >= 70 && $5 >= 10 2,234 ✅ 高置信度 6mA 位点 (推荐用于发表)
$11 >= 50 && $5 >= 5 3,422 🔍 探索性分析 (包含中等置信度位点)

💡 建议:对于细菌 6mA 分析,2,234 个高置信度位点是合理的数量级(取决于菌株甲基转移酶活性)。


📋 bedMethyl 格式列详解 (18 列)

您的输出行示例:

5    4    5    a    16    -    4    5    255,0,0    16    70.00    0    16    0    0    0    0    0
│    │    │    │    │    │    │    │       │       │      │      │    │     │    │    │    │    │
1    2    3    4    5    6    7    8       9      10     11    12   13    14   15   16   17   18
列号 列名 示例值 含义 分析建议
1 chrom 5 染色体/contig 名称 用于按基因组区域分组
2 start 4 起始位置 (0-based) ⚠️ BED 格式起始为 0,转换坐标时 +1
3 end 5 结束位置 (1-based, exclusive) 单碱基修饰时 end = start + 1
4 name a 修饰码: a=6mA, m=5mC, c=4mC 过滤时用 $4 == "a" 提取 6mA
5 score 16 覆盖深度 (该位点总 reads 数) 过滤低深度: $5 >= 10
6 strand - 链方向: + / - 6mA 分析通常合并双链
7 thickStart 4 可视化用 (通常 = start) 可忽略
8 thickEnd 5 可视化用 (通常 = end) 可忽略
9 itemRgb 255,0,0 颜色值 (RGB) 可忽略
10 blockCount 16 检测到修饰的 reads 数 可计算修饰比例: $10/$5
11 blockSizes 70.00 ⭐⭐ 修饰概率 (0-100 百分比!) 核心过滤列: $11 >= 70
12 starts 内部偏移 (通常为 0) 可忽略
13-18 扩展列 16 0 0 0 0 0 modkit 附加统计信息 见下方详解

🔍 扩展列 (13-18) 详解

列号 含义 示例 用途
13 mod_count 16 该位点检测到修饰的 reads 数 与列10相同,冗余备份
14 unmod_count 该位点未修饰的 reads 数 可验证: $13 + $14 ≈ $5
15 del_count 该位点有 deletion 的 reads 数 质控: 高值可能表示比对问题
16 no_call_count 无法判断修饰状态的 reads 数 质控: 高值表示信号模糊
17 coverage_plus 正链覆盖度 链特异性分析时用
18 coverage_minus 负链覆盖度 链特异性分析时用

🔧 实用计算示例:

# 计算每个位点的"原始修饰比例" (未过滤前)
awk '{printf "%s\t%s\t%.2f%%\n", $1, $2, ($10/$5)*100}' An6_6mA_raw.bed | head -5

# 验证覆盖度一致性 (正负链之和 ≈ 总覆盖)
awk '{if($17+$18 != $5) print "Mismatch:", $0}' An6_6mA_raw.bed | wc -l
# 预期: 0 或极少 (浮点误差)

🎯 常用分析命令模板

🔹 1. 提取核心信息 (简化表格)

# 输出: chrom, position(1-based), strand, probability, coverage
awk '$4 == "a" && $11 >= 70 && $5 >= 10 {
  printf "%s\t%d\t%s\t%.2f\t%d\n", $1, $2+1, $6, $11, $5
}' An6_6mA_raw.bed > An6_6mA_simple.tsv

# 查看前5行
head -5 An6_6mA_simple.tsv
# 输出示例:
# 5    5    -    99.54    16
# 5    7    +    98.21    23

🔹 2. 按染色体统计 6mA 密度

# 每百万碱基的 6mA 位点数 (需知道各 contig 长度)
# 先获取基因组大小
samtools faidx bacass_out/Medaka/An6-unicycler-medaka_polished_genome.fa | cut -f1,2 > genome.sizes

# 计算密度
awk '$4 == "a" && $11 >= 70 {count[$1]++} 
     END {for(c in count) print c, count[c]}' An6_6mA_raw.bed | \
  join - genome.sizes | \
  awk '{printf "%s\t%d sites\t%.2f sites/Mb\n", $1, $2, $2/($3/1000000)}' | \
  sort -k3 -rn

🔹 3. 提取 6mA 位点上下游序列 (用于 motif 分析)

# 提取 ±20bp 序列
bedtools slop -i <(awk '$4 == "a" && $11 >= 70 {print $1"\t"$2"\t"$3}' An6_6mA_raw.bed) \
  -g genome.sizes -b 20 | \
  bedtools getfasta -fi bacass_out/Medaka/An6-unicycler-medaka_polished_genome.fa -bed - \
  -fo An6_6mA_motif_seqs.fa

# 运行 MEME 找富集 motif
meme An6_6mA_motif_seqs.fa -oc meme_6mA -dna -mod zoops -nmotifs 3 -minw 4 -maxw 12

🔹 4. 与基因注释关联 (需 GFF/GTF 文件)

# 假设有 genome.gff 文件
bedtools intersect -a <(awk '$4 == "a" && $11 >= 70 {print $1"\t"$2"\t"$3"\t"$11}' An6_6mA_raw.bed) \
  -b genome.gff -wa -wb > An6_6mA_with_genes.tsv

# 统计 6mA 在基因区域的分布
cut -f8 An6_6mA_with_genes.tsv | cut -f3 | sort | uniq -c | sort -rn
# 输出示例:
#   1234 CDS
#    567 promoter
#    234 intergenic

🔹 5. 生成 IGV 可视化的 bigWig 文件

# 1. 先转为 bedGraph (chrom, start, end, score=probability)
awk '$4 == "a" {printf "%s\t%d\t%d\t%.2f\n", $1, $2, $3, $11}' An6_6mA_raw.bed > An6_6mA.bedgraph

# 2. 转为 bigWig (需 genome.sizes 文件)
bedGraphToBigWig An6_6mA.bedgraph genome.sizes An6_6mA.bw

# 3. 在 IGV 中加载:
#    - File → Load Genome → 加载 genome.fa
#    - File → Load from File → 加载 An6_6mA.bw

⚠️ 重要注意事项

1️⃣ 坐标系统:0-based vs 1-based

BED 格式 (modkit 输出):  start=4, end=5  → 表示第 5 个碱基 (0-based)
生物学常用:              position = start + 1 = 5 (1-based)

# 转换命令:
awk '{print $1"\t"($2+1)"\t"$3}' An6_6mA_final.bed > An6_6mA_1based.bed

2️⃣ 概率列是百分比 (0-100),不是小数 (0-1)

# ❌ 错误: 用小数阈值
awk '$11 >= 0.7' An6_6mA_raw.bed  # 几乎无结果!

# ✅ 正确: 用百分比阈值
awk '$11 >= 70' An6_6mA_raw.bed   # 正确过滤

3️⃣ 修饰码大小写敏感

修饰类型 modkit 0.5.0 输出码 过滤命令
6mA a (小写) $4 == "a"
5mC m (小写) $4 == "m"
4mC c (小写) $4 == "c"

📊 您的结果质量评估

# ✅ 检查高置信度位点的概率分布
awk '$4 == "a" && $11 >= 70 && $5 >= 10 {print $11}' An6_6mA_raw.bed | \
  sort -n | uniq -c | tail -10

# 预期输出示例:
#    234 95.00
#    456 98.21
#    892 99.54
#    652 100.00   ← 大量 100% 置信度,信号极佳! ✅

# ✅ 检查覆盖度分布
awk '$4 == "a" && $11 >= 70 && $5 >= 10 {print $5}' An6_6mA_raw.bed | \
  sort -n | uniq -c | head -10

# 预期: 大部分位点覆盖度 10-50×,说明测序深度充足 ✅

💡 一句话总结

🔑 核心三列

  • $4 = 修饰码 (a=6mA)
  • $5 = 覆盖深度 (过滤低质量: >=10)
  • $11 = 修饰概率 (0-100 百分比! 过滤高置信: >=70)

您的 2,234 个高置信 6mA 位点是高质量的起点,可用于:

  • Motif 富集分析 (验证已知限制修饰系统)
  • 基因组分布分析 (启动子/基因体/间隔区)
  • 与转录组数据整合 (如有)

如需帮助进行下游 motif 分析或可视化,随时告诉我!🚀



🔬 从 Tn-seq (TRANSIT) 到甲基化分析:下游统计工具对比指南

您提出的问题非常精准!正如 Tn-seq 用 TRANSIT 进行插入位点的统计分析(ANOVA、Tn5Gaps),甲基化测序(如 modkit pileup 输出)也有对应的下游统计工具。以下是详细对比和推荐:


📊 Tn-seq vs 甲基化分析:核心概念映射

Tn-seq 分析目标 甲基化分析对应目标 统计本质
插入位点计数 (template counts) 修饰概率/计数 (mod_count/coverage) 计数型数据
基因必需性 (essential genes) 差异甲基化区域 (DMRs) 区域水平差异检测
条件间比较 (ANOVA in TRANSIT) 条件间甲基化差异 (DSS, methylKit) 多组比较 + 多重校正
非插入区域检测 (Tn5Gaps) 低甲基化/高甲基化区域 (DMRfinder) 连续区域模式识别
密度标准化 (TTR normalization) 覆盖度/文库大小标准化 (TMM, RLE) 文库效应校正

💡 关键区别:Tn-seq 关注”有没有插入”(二元事件),甲基化关注”修饰比例是多少”(连续概率 0-100%)。


🧰 甲基化下游统计工具推荐(按功能分类)

🔹 1. 差异甲基化分析 (对应 TRANSIT ANOVA)

工具 适用场景 输入格式 核心方法 细菌 6mA 兼容性
DSS (Dispersion Shrinkage for Sequencing) ✅ 多样本组间比较 bed/bedGraph + 样本分组 贝叶斯层次模型 + 算术-贝塔分布 ✅ 优秀 (支持任意 motif)
methylKit ✅ 多条件/时间序列 bedGraph/tabix 逻辑回归 + FDR 校正 ✅ 良好 (需格式转换)
metilene ✅ 快速 DMR 检测 bedGraph 二元分割 + Kolmogorov-Smirnov 检验 ⚠️ 需确认 motif 支持
DMRseq ✅ 区域水平 + 协变量调整 bed + 样本信息 平滑 + 置换检验 ✅ 良好

🚀 DSS 快速入门 (推荐首选)

# R 代码示例:细菌 6mA 差异分析
library(DSS)

# 1. 读取 modkit 输出 (假设已过滤高置信位点)
# 文件格式: chrom, start, end, motif, coverage, mod_count, probability
sample1 <- read.table("An6_6mA_final.bed", header=F)
sample2 <- read.table("BG5_6mA_final.bed", header=F)

# 2. 构建 DSS 对象 (使用原始计数: mod_count / coverage)
BSobj <- makeBSseqData(
  list(sample1[, c(1,2,3,6,5)],    # chrom, start, end, mod_count, coverage
       sample2[, c(1,2,3,6,5)]),
  sampleNames = c("An6", "BG5")
)

# 3. 差异检验 (贝塔-二项模型)
dmlTest <- DMLtest(BSobj, group1=1, group2=2, smoothing=TRUE)

# 4. 提取显著差异位点 (FDR < 0.05, |diff| > 0.2)
sigDML <- getSig(dmlTest, pval=0.05, delta=0.2, meth.diff=0.2)

# 5. 导出结果
write.table(sigDML, "An6_vs_BG5_6mA_DMLs.tsv", sep="\t", quote=F, row.names=F)

📋 DSS 输出列解读 (类比 TRANSIT)

DSS 输出列 含义 TRANSIT 对应列
chr, pos 基因组坐标 Orf, TA_pos
coverage 总覆盖深度 TAs (TA 位点数)
X1, X2 两组的修饰计数 Mean_[condition]
pval, p.adj 原始/FDR 校正 p 值 Pval, Padj
diff 甲基化差异 (组1 – 组2) LFC_[condition] (logFC)
abs.diff 绝对差异值

🔹 2. 区域水平分析 (对应 Tn5Gaps: 连续非修饰区域检测)

工具 功能 适用场景
DMRfinder 识别连续低/高甲基化区域 类似 Tn5Gaps 的”非插入运行”检测
methylSig 区域聚合 + 差异检验 基因/启动子水平的甲基化变化
custom R/Python 自定义滑动窗口分析 细菌操纵子/基因簇水平分析

🚀 滑动窗口分析示例 (Python)

# 检测连续低甲基化区域 (类似 Tn5Gaps 的 non-insertion runs)
import pandas as pd
import numpy as np

# 读取 modkit 输出
df = pd.read_csv("An6_6mA_final.bed", sep="\t", header=None, 
                 names=["chr","start","end","motif","cov","strand",
                        "thickS","thickE","rgb","mod_cnt","prob",
                        "start2","cnt1","cnt0","del_cnt","no_call","cov+","cov-"])

# 按染色体分组,检测连续低甲基化区域 (prob < 30%)
def find_hypo_regions(group, min_len=5, max_gap=100, prob_thresh=30):
    low_meth = group[group["prob"] < prob_thresh].sort_values("start")
    if len(low_meth) < min_len:
        return None
    # 简单连续区域检测 (可扩展为更复杂算法)
    regions = []
    curr_start, curr_end = low_meth.iloc[0]["start"], low_meth.iloc[0]["end"]
    for _, row in low_meth.iloc[1:].iterrows():
        if row["start"] - curr_end <= max_gap:  # 允许小间隙
            curr_end = row["end"]
        else:
            if curr_end - curr_start >= min_len * 10:  # 最小区域长度
                regions.append((curr_start, curr_end))
            curr_start, curr_end = row["start"], row["end"]
    return regions

# 应用并输出
hypo_regions = df.groupby("chr").apply(find_hypo_regions).dropna()
hypo_regions.to_csv("An6_hypomethylated_regions.bed", sep="\t", header=False, index=False)

🔹 3. 功能注释与可视化 (对应 Circos 基因组视图)

工具 功能 输出示例
ChIPseeker (R) 甲基化位点与基因/启动子关联 饼图: CDS/promoter/intergenic 分布
deepTools 甲基化信号热图/轮廓图 基因体 ±2kb 的 6mA 密度曲线
pyGenomeTracks 多轨道基因组浏览器式可视化 类似 Circos 的线性基因组视图
IGV + bigWig 交互式位点查看 手动验证关键基因修饰模式

🚀 基因区域关联分析 (R + ChIPseeker)

library(ChIPseeker)
library(TxDb.Ecoli.NCBI.NC_008800.1.refseq)  # 替换为您的细菌注释

# 读取高置信 6mA 位点 (转换为 GRanges)
library(GenomicRanges)
gr <- GRanges(
  seqnames = df$chr,
  ranges = IRanges(start = df$start + 1, end = df$end),  # BED 0-based → 1-based
  score = df$prob
)

# 注释到基因区域
anno <- annotatePeak(gr, tssRegion=c(-300, 300), 
                     TxDb = TxDb.Ecoli.NCBI.NC_008800.1.refseq,
                     annoDb = "org.EcK12.eg.db")  # 或用 custom GFF

# 可视化
plotAnnoPie(anno)  # 6mA 在基因组区域的分布
plotAvgProf(anno)  # TSS 附近的 6mA 密度曲线

🎯 针对您细菌 6mA 项目的推荐流程

graph LR
    A[modkit pileup 输出] --> B[质量控制 + 过滤]
    B --> C[差异甲基化分析]
    B --> D[区域模式检测]

    C --> C1[DSS: 位点水平差异]
    C --> C2[methylKit: 基因水平聚合]

    D --> D1[滑动窗口: 连续低/高甲基化区]
    D --> D2[与操纵子/基因簇关联]

    C1 & C2 & D1 & D2 --> E[功能注释]
    E --> F[可视化 + 生物学解释]

✅ 具体命令/代码整合

# 🔹 步骤 1: 准备输入文件 (modkit → DSS 格式)
# 提取核心列: chrom, start, end, mod_count, coverage
awk '$4 == "a" && $11 >= 70 && $5 >= 10 {
  printf "%s\t%d\t%d\t%d\t%d\n", $1, $2, $3, $10, $5
}' An6_6mA_raw.bed > An6_6mA_dss_input.tsv

# 🔹 步骤 2: 运行 DSS (R 脚本)
Rscript run_dss_6mA.R \
  --input An6_6mA_dss_input.tsv,BG5_6mA_dss_input.tsv \
  --groups An6,An6,An6,BG5,BG5,BG5 \
  --output An6_vs_BG5_6mA_DSS_results.tsv

# 🔹 步骤 3: 提取显著差异位点 + 注释
# (见上方 R 代码示例)

# 🔹 步骤 4: 可视化
# - IGV: 加载 bigWig 轨道查看关键基因
# - pyGenomeTracks: 生成出版级多轨道图

⚠️ 细菌甲基化分析的特殊注意事项

问题 解决方案
基因组小、基因密集 使用基因/操纵子为单位聚合,而非固定窗口
6mA 富集于特定 motif (如 GATC) 分析时按 motif 分层,避免背景噪声
无”基因长度”标准化需求 细菌基因长度变异小,可直接用计数/概率
限制修饰系统影响 将已知 RM 系统基因作为阳性对照验证流程
样本量小 (常为 2-3 重复) 优先用 DSS (贝叶斯收缩) 而非纯频率比较

📋 工具选择决策树

您的分析目标?
│
├─ 🔍 "哪些位点在条件 A vs B 甲基化水平不同?"
│   └─→ ✅ DSS (位点水平) 或 methylKit (基因水平)
│
├─ 🧬 "哪些基因/区域整体甲基化状态改变?"
│   └─→ ✅ methylKit + ChIPseeker 注释
│
├─ 🎯 "哪些区域连续低/高甲基化 (类似 Tn5Gaps)?"
│   └─→ ✅ 自定义滑动窗口 + DMRfinder
│
├─ 📊 "全局甲基化模式可视化?"
│   └─→ ✅ pyGenomeTracks / IGV + bigWig
│
└─ 🧪 "验证已知限制修饰系统活性?"
    └─→ ✅ 提取 RM 系统基因位点,手动检查概率分布

💡 一句话总结

🔑 核心推荐

  • 差异分析DSS (最接近 TRANSIT ANOVA 的统计严谨性)
  • 区域模式自定义滑动窗口 (最灵活适配细菌基因组)
  • 功能注释ChIPseeker + pyGenomeTracks (最直观可视化)

🎯 您的 2,234 个高置信 6mA 位点是优质输入,结合菌株分组信息,即可开展与 Tn-seq 同等严谨的统计推断!

如需具体 R/Python 脚本模板或帮助解读 DSS 输出,请随时告知!🚀

📁 单样本无重复实验:nf-core/methylong 输出文件详解 (中文)

🔍 核心原则:BAM 文件已在 Dorado 阶段“锁定”修饰类型

您提供的 Dorado 命令非常关键。--modified-bases 参数决定了 BAM 文件中 MM/ML 标签包含哪些修饰信号。Nextflow 管道无法凭空检测未写入 BAM 的修饰,它只能解析、过滤和定量 BAM 里已有的标签。

Dorado Basecalling 参数 BAM 内含有的修饰信号 Nextflow 能调出的结果
--modified-bases 6mA A (6mA) 只能输出 6mA
--modified-bases 4mC_5mC C (4mC) 和 CG (5mC) 只能输出 4mC + 5mC

⚠️ 重要结论:因为您用 Dorado 分两次生成了不同的 BAM,所以必须分两次运行 Nextflow。管道无法在一个 BAM 里“补全”另一种修饰。


🚀 最佳 Nextflow 命令推荐

1️⃣ 处理 6mA BAM(仅含 6mA 信号)

nextflow run nf-core/methylong -r 2.0.0 -profile docker \
  --input samplesheet_6mA.csv \
  --outdir methylome_out_6mA \
  --ont_aligner minimap2 \
  --m6a \
  --skip_snvs \
  -resume \
  -work-dir methylome_out_6mA/work

2️⃣ 处理 4mC_5mC BAM(含 4mC + 5mC 信号)

nextflow run nf-core/methylong -r 2.0.0 -profile docker \
  --input samplesheet_c4mC_5mC.csv \
  --outdir methylome_out_4mC_5mC \
  --ont_aligner minimap2 \
  --all_contexts \
  --skip_snvs \
  -resume \
  -work-dir methylome_out_4mC_5mC/work

🧩 为什么这样配置是最佳实践?

参数 在您当前场景中的真实作用 为什么必须这样设
--m6a 强制 modkit 启用 --motif A 0 提取逻辑 Dorado 的 6mA BAM 里只有 A 标签。若不写此参数,modkit 默认只输出 CG,会导致 An6.bed.gz 为空或仅含背景噪声
--all_contexts 告诉 modkit:不要过滤,输出 BAM 中所有存在的 motif Dorado 的 4mC_5mC 模型会同时写入 C (4mC) 和 CG (5mC) 标签。使用 --all_contexts 可一次性完整保留两者,无需手动拆分参数。
--skip_snvs 跳过 SNP calling + WhatsHap phasing 细菌为单倍体,无杂合位点。跳过此步骤可节省 30%~50% 运行时间,并彻底避免后续 DSS_HAPLOTYPE_LEVEL 因非回文 motif 报错。
独立 --outdir & -work-dir 隔离两次运行的缓存与结果 防止 Nextflow 因输入路径不同但目录相同而混淆中间文件,也避免结果被覆盖。

🛑 关键避坑指南

❌ 常见误区

“我加了 --all_contexts,是不是就能在一个命令里同时跑出 6mA + 4mC + 5mC?”

✅ 事实

不能。 修饰类型在 Dorado basecalling 阶段已物理固化。Nextflow 的 pileup 步骤只是“读取器”:

  • 如果 BAM 里没有 AMM/ML 标签,--m6a--all_contexts不会凭空变出 6mA。
  • 如果 BAM 里只有 4mC_5mC 标签,加了 --m6a 也只会输出空的 A 行(或忽略)。

💡 如果未来想“一次运行检测所有修饰”?

必须在 Dorado 阶段生成全修饰 BAM

# Dorado 一步生成包含 6mA + 4mC + 5mC 的 BAM
dorado basecaller \
  --modified-bases 6mA_4mC_5mC \   # 或根据 Dorado 版本使用对应模型
  --emit-moves --device cuda:0 \
  --reference "${REF}" \
  dna_r10.4.1_e8.2_400bps_sup@v5.0.0 \
  "${POD5}" | samtools view -b - > "An6_all_mods_mapped.mod.bam"

然后 Nextflow 只需:

nextflow run nf-core/methylong ... --input samplesheet_all.csv --all_contexts --skip_snvs ...

✅ 运行后验证命令(强烈建议执行)

# 1. 验证 6mA 结果是否成功提取
echo "=== 6mA 结果 ==="
zcat methylome_out_6mA/results/methylation/An6.bed.gz | awk '$4=="A"' | wc -l
zcat methylome_out_6mA/results/methylation/An6.bed.gz | head -3

# 2. 验证 4mC_5mC 结果是否同时包含 CG 和 C
echo "=== 4mC_5mC 结果 ==="
zcat methylome_out_4mC_5mC/results/methylation/An6.bed.gz | cut -f4 | sort | uniq -c
# 预期输出示例: 12345 CG   (5mC)
#               67890 C    (4mC)

📊 总结对照表

目标修饰 Dorado --modified-bases Nextflow 关键参数 输出 BED 第4列内容
6mA 6mA --m6a A
4mC + 5mC 4mC_5mC --all_contexts CG (5mC) + C (4mC)
全修饰 (未来) 6mA_4mC_5mC --all_contexts A + CG + C + 其他

🎯 最终建议:您当前分两次生成 BAM 的做法非常规范。只需按上述两条命令分别运行,即可获得干净、无冲突、完整覆盖目标修饰的甲基化图谱。

如需后续 4mC/5mC 分离提取、motif 富集分析或与 6mA 结果整合对比的代码,随时告诉我!🚀



📊 比较:--all_contexts vs --m6a 用于不同甲基化类型

🔍 选项概述

选项 类型 modkit pileup 的影响 默认 Motif 额外 Motif
无选项 (默认) 仅 CG 上下文 CG (5mC/5hmC)
--m6a 布尔值 添加腺嘌呤 Motif CG + A A 位点的 6mA
--all_contexts 布尔值 BAM 中所有存在的上下文 所有检测到的 5mC, 4mC, 6mA, 5hmC 等

🎯 根据甲基化类型推荐选项

甲基化类型 化学名称 常见于 推荐选项 理由
5mC 5-甲基胞嘧啶 真核生物 (CpG) --all_contexts 或默认 默认已捕获 CG;--all_contexts 用于 CHG/CHH
5hmC 5-羟甲基胞嘧啶 真核生物 (脑组织) --all_contexts 常与 5mC 在 CG 上下文中共同检测
6mA N6-甲基腺嘌呤 细菌、藻类、低等真核生物 --m6a 需要明确的 A Motif
4mC N4-甲基胞嘧啶 细菌 --all_contexts 自动捕获非 CG 的 C Motif
组合 (如 4mC + 5mC) 多种修饰 具有复杂限制修饰系统的细菌 --all_contexts 一条命令捕获所有存在的修饰

🧪 具体应用场景

场景 1:仅 6mA (您当前的情况)

nextflow run nf-core/methylong \
  --input samplesheet_6mA.csv \
  --outdir methylome_out_6mA \
  --m6a \                    # ⭐ 6mA 专用
  --skip_snvs \
  -profile docker

结果: An6.bed.gz 包含 motif = "A" 的行


场景 2:4mC + 5mC 组合 (您的第二个情况)

nextflow run nf-core/methylong \
  --input samplesheet_c4mC_5mC.csv \
  --outdir methylome_out_4mC_5mC \
  --all_contexts \           # ⭐ 捕获 BAM 中 ALL 修饰
  --skip_snvs \
  -profile docker

结果: An6.bed.gz 包含以下行:

  • motif = "CG" (5mC)
  • motif = "C""CCWGG" (4mC)
  • 其他可能的细菌 Motif

场景 3:仅 5mC/5hmC (真核生物)

nextflow run nf-core/methylong \
  --input samplesheet_5mC.csv \
  --outdir methylome_out_5mC \
  # 无需特殊选项 (默认 = CG) \
  --skip_snvs \              # 用于单倍体生物
  -profile docker

结果: An6.bed.gz 主要包含 motif = "CG"


📋 比较表:输出内容

设置选项 .bed.gz 中包含的 Motif 第4列 (motif) 示例
默认 (无选项) 仅 CG 上下文 CG
--m6a CG + 腺嘌呤 CG, A
--all_contexts BAM 中所有 CG, C, CCWGG, A, GATC

⚠️ 重要提示

1️⃣ --m6a 不排除其他上下文

# 使用 --m6a 您会获得 BOTH (两者):
--m6a → CG (默认) + A (6mA)

2️⃣ --all_contexts 更全面

# 使用 --all_contexts 您会获得 ALL (全部):
--all_contexts → CG + C + A + CHG + CHH + ...

3️⃣ 前提条件:Basecalling 需包含正确的修饰

管道只能检测 modBAM 中已有的内容!

Dorado Basecalling 命令 BAM 中可用的修饰 管道选项
--modified-bases 5mC_5hmC 仅 CG 默认足够
--modified-bases 6mA 仅 A 必需 --m6a
--modified-bases 5mC_5hmC 6mA CG + A --m6a--all_contexts
--modified-bases 5mC_5hmC 6mA 4mC CG + A + C 推荐 --all_contexts

🎯 决策流程图

您期望哪些修饰?
         │
         ├── 仅 5mC/5hmC (CG)
         │   └─→ 默认 (无选项)
         │
         ├── 仅 6mA (A)
         │   └─→ --m6a
         │
         ├── 6mA + 5mC 组合
         │   └─→ --m6a (简单) 或 --all_contexts (全面)
         │
         └── 4mC + 5mC + 可能其他
             └─→ ✅ --all_contexts (您情况的最佳选择!)

💡 您的两个 Samplesheet 总结

Samplesheet 包含的修饰 推荐选项 命令
samplesheet_6mA.csv 仅 6mA --m6a 已执行 ✅
samplesheet_c4mC_5mC.csv 4mC + 5mC --all_contexts 见场景 2

🎯 核心区别对比

特性 --m6a --all_contexts
主要用途 专门检测 6mA 检测所有存在的修饰
输出 Motif CG + A CG + C + A + 其他所有
适用场景 仅关注 6mA 多种修饰共存 (如 4mC+5mC)
文件大小 较小 (仅 CG+A) 较大 (所有上下文)
处理速度 较快 稍慢 (需处理更多位点)
灵活性 针对性强 最全面,无需预先知道修饰类型

💡 一句话总结

🎯 对于您的 4mC_5mC 数据,--all_contexts 是最安全和最全面的选择,因为它会自动捕获 BAM 中所有存在的修饰,无需您单独指定每个 Motif!

🎯 对于您的 6mA 数据,--m6a 是明确且高效的选择,专门针对腺嘌呤修饰优化!

如有其他问题,欢迎继续讨论!🚀



是的,您必须为 4mC_5mC 样本运行一条独立的命令。


📝 推荐命令

nextflow run nf-core/methylong -r 2.0.0 -profile docker \
  --input samplesheet_c4mC_5mC.csv \
  --outdir methylome_out_4mC_5mC \
  --ont_aligner minimap2 \
  --all_contexts \          # ⭐ 关键:同时捕获 5mC 和 4mC
  --skip_snvs \
  -resume \
  -work-dir methylome_out_4mC_5mC/work

🔍 为什么必须分开运行?

原因 说明
1. 修饰类型与 Motif 不同 --m6a 会让底层 modkit 强制添加 --motif A 0(腺嘌呤修饰)。而 4mC/5mC 基于胞嘧啶修饰,默认使用 --motif CG 0(5mC)和 --motif C 0(4mC)。同一流程无法同时动态切换 motif 组合。
2. 输出文件会互相覆盖 管道默认将结果写入 --outdir/results/methylation/An6.bed.gz 等固定路径。若共用 --outdir,第二次运行会覆盖第一次的 6mA 结果。
3. 管道设计逻辑 nf-core/methylong单次运行 = 单一修饰上下文设计。不同修饰需独立堆叠(pileup)与质控流程。

⚙️ 参数调整详解

参数 6mA 命令 4mC/5mC 命令 原因
--input samplesheet_6mA.csv samplesheet_c4mC_5mC.csv 指向不同的 modBAM 文件
--outdir methylome_out_6mA methylome_out_4mC_5mC 隔离结果,防止覆盖
--m6a ✅ 添加 ❌ 移除 6mA 专属开关,不适用于胞嘧啶修饰
--all_contexts ❌ 可选 ✅ 添加 告诉 modkit 输出 BAM 中所有检测到的修饰(含 5mC 和 4mC)
--skip_snvs ✅ 添加 ✅ 添加 细菌单倍体,无需 SNP/Phasing,两次运行都建议保留
-work-dir .../6mA/work .../4mC_5mC/work 建议分开,避免缓存哈希冲突或清理困难

💡 关于 --all_contexts 的重要说明

  • 默认行为:不指定该参数时,管道仅输出 CG 上下文(即 5mC/5hmC)。
  • 添加 --all_contextsmodkit 会解析 BAM 中的 MM/ML 标签,自动输出所有修饰碱基(包括 5mC4mC、甚至 6mA 如果存在)。
  • 结果文件结构

    methylome_out_4mC_5mC/results/methylation/
    ├── An6.bed.gz      # 包含所有 motif 行,第4列显示: CG, C, CCWGG 等
    └── BG5.bed.gz

    您可通过以下命令快速分离 4mC 和 5mC:

    # 提取 5mC (CG 位点)
    zcat methylome_out_4mC_5mC/results/methylation/An6.bed.gz | \
      awk '$4=="CG"' > An6_5mC.bed
    
    # 提取 4mC (非CG的C位点,通常第4列为 "C")
    zcat methylome_out_4mC_5mC/results/methylation/An6.bed.gz | \
      awk '$4=="C"' > An6_4mC.bed

🛡️ 运行注意事项

  1. -resume 会智能复用缓存:由于输入 BAM 路径不同,Nextflow 会自动重新计算 4mC/5mC 流程,不会与 6mA 缓存冲突。
  2. 磁盘空间:两次运行会产生独立的 work/ 目录,总占用约是单次的 1.5~2 倍。运行完成后可安全删除 work/
    rm -rf methylome_out_6mA/work methylome_out_4mC_5mC/work
  3. 验证输出:运行结束后,确认两个输出目录均包含:
    ls methylome_out_6mA/results/methylation/*.bed.gz
    ls methylome_out_4mC_5mC/results/methylation/*.bed.gz

📌 一句话总结

不同修饰类型 = 不同 motif = 必须独立运行 + 独立输出目录。
--all_contexts 替代 --m6a,切换 samplesheet 和 outdir,即可安全获取 4mC/5mC 结果。

如需帮助解析 An6.bed.gz 中的 motif 分布或做下游 4mC/5mC 基因注释,随时告知!🚀



📁 单样本无重复实验:nf-core/methylong 输出文件详解 (中文)

🎯 您的实验设计总结

✅ 单样本 (Single sample): An6
✅ 细菌基因组 (Haploid): 无父源/母源染色体
✅ 无生物学重复 (No replicates): 无法做统计差异分析
✅ 无组间比较 (No comparisons): 不计算DMR
✅ 目标: 6mA甲基化谱描述性分析

📌 核心结论:您将获得该样本的6mA甲基化全景图谱,用于位点鉴定、motif分析、基因组分布等描述性研究


📂 预期输出文件结构

methylome_out_6mA/
│
├── 📊 results/                    # 🎯 主要结果目录 (您最关心的!)
│   │
│   ├── 🔬 methylation/           # ⭐ 6mA甲基化核心结果
│   │   ├── An6.bed.gz           # 🏆 主文件: 6mA位点及修饰概率 (BED格式)
│   │   ├── An6.bed.gz.tbi       # BED索引文件 (用于快速检索)
│   │   ├── An6.bigWig           # 🎨 可视化文件 (用于IGV/JBrowse)
│   │   └── An6.bedGraph.gz      # 备选格式 (bedGraph)
│   │
│   ├── 🗂️ alignment/            # 比对结果
│   │   ├── An6.bam              # 比对后的BAM文件 (可能较大)
│   │   ├── An6.bam.bai          # BAM索引
│   │   ├── An6.flagstat         # 📈 比对统计 (总reads, 比对率等)
│   │   └── An6.stats            # 详细比对指标
│   │
│   ├── 🔀 preprocessing/        # 预处理中间结果
│   │   ├── An6.repaired.bam     # modkit repair后的BAM
│   │   └── An6.trimmed.fastq.gz # 去接头后的FASTQ (如有trimming)
│   │
│   ├── 🧬 variants/             # ⚠️ 因--skip_snvs可能为空或极简
│   │   └── (可能无文件或仅占位)
│   │
│   └── 📋 qc/                   # 质量控制报告
│       ├── multiqc_report.html  # 🎯 综合QC报告 (用浏览器打开)
│       ├── fastqc/              # 原始FastQC结果
│       └── modkit_stats/        # modkit运行统计
│
├── 🔧 work/                     # Nextflow工作目录 (中间文件, 可删除)
│   └── (大量临时文件, 调试时用)
│
├── 📝 pipeline_info/            # 管道执行信息
│   ├── execution_report.html    # Nextflow执行报告
│   ├── execution_timeline.html  # 时间线可视化
│   ├── execution_trace.txt      # 各步骤资源消耗
│   └── software_versions.yml    # 所有工具版本记录 (用于复现)
│
└── 📄 *.log                     # 日志文件
    ├── .nextflow.log            # 主日志 (排查错误时用)
    └── nextflow.log             # 备用日志

🏆 核心文件详解:您最需要的3个文件

1️⃣ An6.bed.gz — 6mA甲基化位点主文件 ⭐⭐⭐

# 查看文件内容 (前5行)
zcat methylome_out_6mA/results/methylation/An6.bed.gz | head -5

📋 BED格式列说明 (6mA专用):

列号 列名 示例值 含义
1 chrom chr1 染色体/contig名称
2 start 12345 起始位置 (0-based)
3 end 12346 结束位置 (通常为单碱基)
4 motif A 修饰motif类型 (6mA = “A”)
5 methylation_prob 0.87 ⭐ 修饰概率 (0-1, 越高越可信)
6 strand + 链方向 (+/-)
7 coverage 45 该位点总覆盖深度
8 mod_count 39 检测到修饰的reads数
9 mod_prob_low 0.82 修饰概率95%置信区间下限
10 mod_prob_high 0.92 修饰概率95%置信区间上限
11+ 其他辅助信息

🔍 常用分析命令:

# ✅ 统计高置信度6mA位点 (概率≥0.8, 覆盖度≥10)
zcat methylome_out_6mA/results/methylation/An6.bed.gz | \
  awk '$4=="A" && $5>=0.8 && $7>=10' | wc -l

# ✅ 提取所有6mA位点坐标 (用于后续motif分析)
zcat methylome_out_6mA/results/methylation/An6.bed.gz | \
  awk '$4=="A" && $5>=0.8 {print $1"\t"$2"\t"$3"\t"$6}' > high_conf_6mA.bed

# ✅ 按染色体统计6mA密度
zcat methylome_out_6mA/results/methylation/An6.bed.gz | \
  awk '$4=="A" && $5>=0.8 {count[$1]++} END {for(c in count) print c, count[c]}' | sort

2️⃣ An6.bigWig — 可视化文件 ⭐⭐

# 用IGV桌面版打开:
# 1. 加载参考基因组: File → Load Genome from File → genome.fa
# 2. 加载甲基化轨道: File → Load from File → An6.bigWig
# 3. 调整轨道显示: 右键轨道 → Change Track Settings → 设置颜色/高度

🎨 可视化效果示例:

基因组位置:  ████████████████████
            12000              13000

6mA信号:    ▁▂▃▅▇█▇▅▃▂▁▁▂▃▅▆▇███▇▆▅▃▂
            ↑    高峰 = 高置信度6mA位点

🔧 如需自定义bigWig (可选):

# 如果管道未生成bigWig, 可手动转换:
bedGraphToBigWig \
  methylome_out_6mA/results/methylation/An6.bedGraph \
  genome.fa.sizes \
  methylome_out_6mA/results/methylation/An6_custom.bw

3️⃣ multiqc_report.html — 综合质量报告 ⭐

# 用浏览器打开 (本地或服务器):
firefox methylome_out_6mA/results/qc/multiqc_report.html
# 或 (无图形界面服务器):
python -m http.server 8000  # 然后通过本地浏览器访问 http://服务器IP:8000

📊 报告包含的关键信息:

模块 内容 您需要关注的指标
🔹 FastQC 原始reads质量 Per base sequence quality > Q20 ✅
🔹 Porechop 接头去除效率 Adapter trimmed % < 10% ✅
🔹 ModKit repair 修饰标签修复 Successfully repaired % > 95% ✅
🔹 Minimap2 比对统计 Mapping rate > 90% ✅
🔹 ModKit pileup 甲基化调用 Valid sites called, motif distribution
🔹 General stats 汇总 Total reads, coverage, 6mA sites count

🗂️ 其他辅助文件说明

🔹 An6.flagstat — 比对统计摘要

cat methylome_out_6mA/results/alignment/An6.flagstat
# 示例输出:
1000000 + 0 in total (QC-passed reads + QC-failed reads)
950000 + 0 primary
950000 + 0 mapped (95.00% : N/A)
# → 95%比对率,质量良好 ✅

🔹 software_versions.yml — 可复现性保障

# 记录所有工具版本,便于论文方法部分或复现:
dorado: 2.0.0+20e87c8b
minimap2: 2.26-r1175
modkit: 0.5.0
samtools: 1.18
# ...

🔹 execution_trace.txt — 资源消耗监控

# 用于评估是否需要更多计算资源:
task_name, duration, memory, cpu
ONT_MINIMAP2_ALIGN, 45min, 8GB, 8 cores
MODKIT_PILEUP, 120min, 16GB, 12 cores
# → 如果某步骤内存不足, 下次可增加--max_memory参数

❌ 您不会看到哪些文件?(因实验设计)

文件类型 原因 是否正常
*.vcf.gz --skip_snvs 跳过变异检测 ✅ 正常
*_haplotagged.bam 无phasing步骤 ✅ 正常
*_DMR*.bed 单样本无法计算差异 ✅ 正常
*_population*.tsv 无多样本/组间比较 ✅ 正常
*_phasing*.stats 无WhatsHap执行 ✅ 正常

🎯 这些”缺失”的文件恰恰说明管道正确识别了您的实验设计!


🧪 快速验证:您的结果是否完整可用?

# ✅ 1. 检查核心甲基化文件是否存在且非空
ls -lh methylome_out_6mA/results/methylation/An6.bed.gz
# 应看到: -rw-r--r-- ... An6.bed.gz (大小 > 0)

# ✅ 2. 验证6mA位点数量合理 (细菌基因组通常10^3-10^5个6mA位点)
zcat methylome_out_6mA/results/methylation/An6.bed.gz | \
  awk '$4=="A"' | wc -l
# 预期: 1,000 ~ 500,000 (取决于菌株和测序深度)

# ✅ 3. 检查修饰概率分布 (应呈双峰: 低概率背景 + 高概率真实位点)
zcat methylome_out_6mA/results/methylation/An6.bed.gz | \
  awk '$4=="A" {print $5}' | \
  datamash mean 1 sstdev 1 min 1 max 1 2>/dev/null || \
  awk '$4=="A" {sum+=$5; sum2+=$5*$5; n++; if(n==1||$5<min)min=$5; if($5>max)max=$5} END {print "Mean:",sum/n, "Std:",sqrt((sum2-sum*sum/n)/n), "Min:",min, "Max:",max}'
# 预期: Mean ~0.3-0.6, Max >0.9 (有高质量位点)

# ✅ 4. 打开MultiQC确认无严重警告
grep -i "error\|fail" methylome_out_6mA/results/qc/multiqc_report.html | head -3
# 应无关键错误

🎯 下一步分析建议 (单样本6mA)

🔬 描述性分析流程:

graph LR
    A[An6.bed.gz] --> B[6mA位点过滤]
    A --> C[基因组分布分析]
    A --> D[Motif富集分析]

    B --> B1[高置信度位点: prob≥0.8]
    B --> B2[覆盖度过滤: depth≥10]

    C --> C1[基因区域注释: 启动子/基因体/间隔区]
    C --> C2[与已知功能元件重叠]

    D --> D1[提取6mA位点±20bp序列]
    D --> D2[MEME/HOMER找motif]
    D --> D3[验证是否为已知限制修饰系统motif]

💻 实用代码片段:

# 🔹 1. 提取高置信6mA位点
zcat methylome_out_6mA/results/methylation/An6.bed.gz | \
  awk '$4=="A" && $5>=0.8 && $7>=10' > An6_6mA_highConf.bed

# 🔹 2. 关联基因注释 (需有genome.gff)
bedtools intersect -a An6_6mA_highConf.bed -b genome.gff -wa -wb > An6_6mA_with_genes.tsv

# 🔹 3. 提取motif序列 (用于MEME分析)
bedtools getfasta -fi genome.fa -bed An6_6mA_highConf.bed -fo An6_6mA_seqs.fa

# 🔹 4. 用MEME找富集motif (需安装MEME Suite)
meme An6_6mA_seqs.fa -oc meme_out -dna -mod zoops -nmotifs 3 -minw 4 -maxw 12

# 🔹 5. 统计6mA在基因区域的分布
awk '{print $NF}' An6_6mA_with_genes.tsv | cut -f3 | sort | uniq -c | sort -rn
# 输出示例: 1250 CDS, 340 promoter, 89 intergenic

📊 可视化建议:

工具 用途 命令/链接
IGV 基因组浏览器查看6mA峰 加载 An6.bigWig + genome.fa
pyGenomeTracks 出版级多轨道图 pip install pyGenomeTracks
R/ggplot2 6mA密度分布图 geom_density(aes(x=position))
WebLogo Motif序列标识图 https://weblogo.berkeley.edu

💡 一句话总结

🎯 单样本细菌6mA分析的核心产出 = An6.bed.gz (位点列表) + An6.bigWig (可视化) + multiqc_report.html (质控)
这三个文件已足够开展:位点鉴定、motif发现、基因组分布、功能关联等描述性研究!

🇩🇪 Für Einzelproben-Analyse von 6mA in Bakterien sind drei Dateien ausreichend:
An6.bed.gz (Modifikationsstellen), An6.bigWig (Visualisierung), multiqc_report.html (Qualitätskontrolle).

如有具体下游分析需求 (如motif发现、基因关联),欢迎继续讨论!🚀



📋 nf-core/methylong DMR 选项详解 (中文)

🔍 什么是 DMR?

DMR = Differentially Methylated Region (差异甲基化区域)

指在不同样本组/条件之间,甲基化水平存在统计学显著差异的基因组区域。

示例:
样本组A (野生型):  ████████░░░░░░░░  (甲基化比例 ~60%)
样本组B (突变型):  ░░░░░░░░████████  (甲基化比例 ~20%)
                          ↓
                   这是一个 DMR! 🎯

🧩 DMR 选项逐项解释

1️⃣ --skip_snvs [boolean]

属性 说明
类型 布尔值 (开关参数,无需赋值)
作用 跳过 SNP/变异检测 (SNV calling) 和 单倍型分型 (phasing) 步骤
默认 false (即:默认会执行SNV+phasing)
使用方式 添加该参数即启用:--skip_snvs

🔬 技术流程影响:

默认流程 (不加 --skip_snvs):
原始BAM → Clair3(SNV calling) → WhatsHap(phasing) → haplotagged BAM → haplotype-level DMR

添加 --skip_snvs 后:
原始BAM → 直接进行 reference-level pileup → 跳过 phasing 相关步骤

🎯 适用场景:

场景 是否添加 --skip_snvs 原因
🦠 细菌/单倍体基因组 推荐添加 无杂合位点,phasing无生物学意义
🔬 仅需参考水平甲基化谱 ✅ 添加 简化流程,加快运行
👥 人类/二倍体 + 研究等位基因特异性甲基化 ❌ 不添加 需要单倍型信息
💻 计算资源有限 ✅ 添加 SNV+phasing 耗时较长

💡 细菌6mA分析示例:

# 细菌是单倍体,直接跳过无意义的SNV/phasing步骤
nextflow run nf-core/methylong \
  --input samplesheet.csv \
  --outdir results \
  --m6a \
  --skip_snvs \        # ⭐ 关键参数
  -profile docker

2️⃣ --haplotype_dmrer [string]

属性 说明
类型 字符串 (需赋值)
作用 选择单倍型水平DMR分析使用的统计工具
可选值 dss (默认) 或 modkit
使用方式 --haplotype_dmrer dss--haplotype_dmrer modkit

🔧 两种工具对比:

工具 原理 优点 缺点 适用场景
dss (default) 基于贝叶斯分层模型的统计检验 ✅ 成熟稳定,广泛使用
✅ 支持小样本
✅ 输出详细统计量
❌ 仅支持CpG/CG上下文
❌ 对非回文motif(如6mA)支持有限
5mC/5hmC分析,真核生物
modkit 基于modkit pileup结果的差异比较 ✅ 支持多种修饰类型 (5mC/6mA/4mC等)
✅ 与ONT数据原生兼容
❌ 较新,文档较少
❌ 统计方法相对简单
6mA/4mC等原核修饰,或需要统一工具链

⚠️ 重要注意事项:

# 如果您分析的是6mA (motif "A",非回文):
# 即使使用 --haplotype_dmrer modkit,
# 底层modkit pileup仍可能使用 --combine-strands 导致报错!

# 解决方案:配合 --skip_snvs 使用,完全跳过haplotype-level DMR
nextflow run nf-core/methylong \
  --m6a \
  --skip_snvs \          # ⭐ 跳过整个haplotype流程,避免motif冲突
  --haplotype_dmrer dss  # 即使写了也不会执行,但语法上需要

3️⃣ --dmr_population_scale [boolean]

属性 说明
类型 布尔值 (开关参数)
作用 启用群体水平的DMR分析 (多样本/多组比较)
默认 false (即:默认只做单样本或两两比较)
使用方式 添加该参数即启用:--dmr_population_scale

🔬 分析层级对比:

📊 单样本水平 (默认):
   输出: 每个样本的甲基化谱 (bed文件)
   用途: 描述性分析,位点鉴定

📊 两两比较 (基础DMR):
   输入: 2个样本/组
   输出: 差异甲基化区域列表
   用途: 简单对照实验 (如: 野生型 vs 突变型)

📊 群体水平 (--dmr_population_scale):
   输入: 多个样本,按组分类 (如: 组A有5个样本,组B有6个样本)
   输出: 考虑组内变异的统计学显著DMR
   用途: 复杂实验设计,需要统计功效的场景

📋 群体水平分析所需参数:

启用 --dmr_population_scale 后,必须同时指定:

  • --dmr_a: 对照组/第一组的样本列表或标识
  • --dmr_b: 实验组/第二组的样本列表或标识

4️⃣ --population_dmrer [string]

属性 说明
类型 字符串 (需赋值)
作用 选择群体水平DMR分析使用的统计工具
可选值 dss (默认) 或 modkit
使用方式 --population_dmrer dss--population_dmrer modkit

🔧 与 --haplotype_dmrer 的区别:

参数 分析层级 输入数据 统计模型
--haplotype_dmrer 单倍型水平 (H1 vs H2) 单个样本的haplotagged BAM 单样本内等位基因比较
--population_dmrer 群体水平 (组A vs 组B) 多样本的pileup结果 多样本间的组间比较

💡 实际使用建议:

# 大多数情况下,两个参数设为相同工具即可:
--haplotype_dmrer dss --population_dmrer dss

# 如果只做参考水平+群体比较 (细菌常见场景):
--skip_snvs --dmr_population_scale --population_dmrer modkit

5️⃣ --dmr_a & 6️⃣ --dmr_b [string]

属性 说明
类型 字符串 (需赋值)
作用 定义群体水平DMR分析中的两个比较组
依赖 仅在 --dmr_population_scale 启用时生效
格式 通常为样本名称列表,用逗号分隔或引用文件

📋 格式示例:

方式1: 逗号分隔的样本名

--dmr_a "sample1,sample2,sample3" \
--dmr_b "sample4,sample5,sample6"

方式2: 引用samplesheet中的group列

# samplesheet.csv
group,sample,path,ref,method
WT,sample1,...,...,ont
WT,sample2,...,...,ont
Mut,sample3,...,...,ont
Mut,sample4,...,...,ont
--dmr_a "WT" \
--dmr_b "Mut"

方式3: 外部文件列表 (如管道支持)

--dmr_a "group_A_samples.txt" \
--dmr_b "group_B_samples.txt"

🎯 细菌多菌株比较示例:

# 比较野生型菌株 (3个重复) vs 突变型菌株 (3个重复)
nextflow run nf-core/methylong \
  --input samplesheet_6mA.csv \
  --outdir results_6mA \
  --m6a \
  --skip_snvs \
  --dmr_population_scale \
  --population_dmrer modkit \
  --dmr_a "WT_rep1,WT_rep2,WT_rep3" \
  --dmr_b "Mut_rep1,Mut_rep2,Mut_rep3" \
  -profile docker

🧭 决策流程图:如何选择DMR选项?

graph TD
    A[开始: 确定分析目标] --> B{研究对象?}

    B -->|🦠 细菌/单倍体 | C[添加 --skip_snvs]
    B -->|👥 人类/二倍体 | D{需要等位基因特异性分析?}

    D -->|是 | E[保留默认: 执行SNV+phasing]
    D -->|否 | C

    C --> F{需要组间比较?}
    E --> F

    F -->|否,只需甲基化谱 | G[✅ 完成: 输出 reference-level bed]
    F -->|是,两两比较 | H[✅ 完成: 默认执行基础DMR]
    F -->|是,多样本群体比较 | I[添加 --dmr_population_scale + --dmr_a/b]

    I --> J{选择统计工具}
    J -->|5mC/真核 | K[--population_dmrer dss]
    J -->|6mA/原核 | L[--population_dmrer modkit]

    style C fill:#90EE90
    style G fill:#90EE90
    style K fill:#E6F3FF
    style L fill:#E6F3FF

🎯 针对您当前项目 (细菌6mA) 的最终配置

# 场景: 单个细菌菌株的6mA甲基化谱分析
nextflow run nf-core/methylong \
  -r 2.0.0 \
  -profile docker \
  --input samplesheet_6mA.csv \
  --outdir methylome_out_6mA \
  --ont_aligner minimap2 \   # 避免Docker认证问题
  --m6a \                     # 启用6mA motif
  --skip_snvs \              # ⭐ 细菌无需SNV/phasing
  -resume \
  -work-dir methylome_out_6mA/work
# 场景: 多个细菌菌株的6mA差异甲基化分析
nextflow run nf-core/methylong \
  -r 2.0.0 \
  -profile docker \
  --input samplesheet_6mA.csv \
  --outdir methylome_out_6mA \
  --ont_aligner minimap2 \
  --m6a \
  --skip_snvs \
  --dmr_population_scale \           # ⭐ 启用群体比较
  --population_dmrer modkit \        # ⭐ modkit更好支持6mA
  --dmr_a "strain_WT1,strain_WT2" \  # ⭐ 定义组A
  --dmr_b "strain_Mut1,strain_Mut2" \# ⭐ 定义组B
  -resume \
  -work-dir methylome_out_6mA/work

💡 一句话总结

参数 核心作用 细菌6mA分析建议
--skip_snvs 跳过SNV+phasing 必加 (单倍体无需)
--haplotype_dmrer 单倍型水平DMR工具 ⚪ 可选 (配合–skip_snvs时无效)
--dmr_population_scale 启用多样本组间比较 🔶 按需 (有多样本时添加)
--population_dmrer 群体水平DMR工具 🔶 如用群体分析,选modkit更兼容6mA
--dmr_a / --dmr_b 定义比较的两组样本 🔶 配合--dmr_population_scale使用

🎯 细菌6mA分析黄金法则:
--m6a + --skip_snvs + --ont_aligner minimap2 = ✅ 简洁、高效、无报错!

如有其他参数疑问,欢迎继续讨论.



✅ 您完全正确!抱歉我之前的表述有误

🔧 参数正确写法

--haplotype_dmrer 是一个独立参数,接受 dssmodkit 作为值:

# ✅ 正确语法(参数 + 值,空格分隔)
--haplotype_dmrer dss
--haplotype_dmrer modkit

# ❌ 错误语法(连在一起)
--haplotype_dmrer dss  # 这不是一个选项名,而是 参数+值

从您提供的 help 输出可见:

DMR options
  --skip_snvs                    [boolean] Indicate if to skip snvcall and phase 
  --haplotype_dmrer              [string]  DMRer option in DMR analysis for haplotype level, default is dss, specify modkit to switch  (accepted: dss, modkit) [default: dss] 

📌 默认值已经是 dss,所以如果您不指定该参数,管道会自动使用 dss


🎯 针对细菌6mA分析的最终推荐命令

由于细菌是单倍体 (haploid),不需要单倍型水平分析,最简洁有效的方案是:

nextflow run nf-core/methylong \
  -r 2.0.0 \
  -profile docker \
  --input samplesheet_6mA.csv \
  --outdir methylome_out_6mA \
  --ont_aligner minimap2 \
  --m6a \
  --skip_snvs \              # ⭐ 关键:跳过SNP calling + phasing + haplotype DMR
  -resume \
  -work-dir methylome_out_6mA/work

参数说明:

参数 作用 为什么对细菌分析重要
--ont_aligner minimap2 使用minimap2替代dorado aligner 避免 quay.io/nanoporetech/dorado 的Docker认证问题
--m6a 启用6mA motif的pileup 您的研究目标是6mA修饰
--skip_snvs 跳过 SNP calling + WhatsHap phasing + haplotype-level DMR 🟢 细菌无杂合位点,无需单倍型分析;同时避免 --combine-strands 与 非回文motif “A” 的冲突

🔁 如果您想保留 SNP calling(例如用于菌株变异分析)

nextflow run nf-core/methylong \
  -r 2.0.0 \
  -profile docker \
  --input samplesheet_6mA.csv \
  --outdir methylome_out_6mA \
  --ont_aligner minimap2 \
  --m6a \
  --haplotype_dmrer dss \   # 保持默认值,显式写出便于阅读
  -resume \
  -work-dir methylome_out_6mA/work

⚠️ 但请注意:即使运行了 phasing 步骤,由于细菌基因组是单倍体,不会产生有意义的 haplotype-level DMR 结果。且如果 modkit pileup 在 haplotype 模式下仍使用 --combine-strands,仍可能因 “A” 非回文而报错。


🛠️ 如果管道已在中途失败,如何恢复?

# 1. 确认之前的运行已生成主要结果
ls -la methylome_out_6mA/results/methylation/
# 应看到: An6.bed.gz (这就是您需要的6mA参考水平pileup结果!)

# 2. 用 --skip_snvs 跳过失败步骤,完成剩余流程
nextflow run nf-core/methylong \
  -r 2.0.0 \
  -profile docker \
  --input samplesheet_6mA.csv \
  --outdir methylome_out_6mA \
  --ont_aligner minimap2 \
  --m6a \
  --skip_snvs \
  -resume \
  -work-dir methylome_out_6mA/work

-resume 会自动复用已完成的步骤,只运行剩余部分 ✅


📋 快速验证:您的6mA结果是否已生成?

# 检查核心输出文件
zcat methylome_out_6mA/results/methylation/An6.bed.gz | head -3

# 示例输出 (6mA bed格式):
# chr1  12345  12346  A  0.85  +  12  10  0.83  0.91  ...

# 统计高置信度6mA位点 (修饰概率 ≥ 0.8)
zcat methylome_out_6mA/results/methylation/An6.bed.gz | \
  awk '$4=="A" && $5>=0.8' | wc -l

# 检查MultiQC报告
firefox methylome_out_6mA/results/qc/multiqc_report.html

💡 总结 (Zusammenfassung)

🇨🇳 细菌是单倍体 → 无父源/母源染色体 → 无需单倍型分析
✅ 使用 --skip_snvs 跳过 phasing 相关步骤
✅ 使用 --ont_aligner minimap2 避免 Docker 认证问题
✅ 核心结果 An6.bed.gz 已包含您需要的6mA甲基化信息

🇩🇪 Bakterien sind haploid → keine väterlichen/mütterlichen Chromosomen → keine Haplotyp-Analyse nötig
✅ --skip_snvs überspringt Phasing-Schritte
✅ --ont_aligner minimap2 vermeidet Docker-Auth-Probleme
✅ An6.bed.gz enthält bereits alle benötigten 6mA-Methylierungsdaten

再次感谢您的指正!🙏 如有其他问题,随时讨论!🚀



✅ 您的理解完全正确!细菌基因组分析不需要单倍型水平分析

🧬 细菌的遗传特性总结

特性 细菌 (原核生物) 人类/动植物 (真核生物)
染色体倍性 🟢 单倍体 (Haploid) 🔴 二倍体/多倍体 (Diploid/Polyploid)
繁殖方式 🟢 无性繁殖 (二分裂) 🔴 有性繁殖 (减数分裂+受精)
父源/母源染色体 ❌ 不存在 ✅ 存在 (väterlich / mütterlich)
杂合SNP (Heterozygous) ❌ 通常不存在 ✅ 常见
Phasing/单倍型分型 ❌ 无生物学意义 ✅ 必要步骤
Haplotype-level甲基化分析 ❌ 不适用 ✅ 用于印记基因/ASM研究

🔍 为什么细菌没有 “väterlich / mütterlich” 染色体?

细菌繁殖流程 (二分裂 Binary Fission):

母细胞 (1个单倍体基因组)
        ↓
   [DNA复制]
        ↓
2个相同的子代基因组 (克隆)
        ↓
   [细胞分裂]
        ↓
子细胞A + 子细胞B (遗传物质完全相同)

📌 关键点:细菌没有减数分裂 (Meiosis) 和受精过程,因此不存在”父源”和”母源”染色体的概念。

SNP在细菌中的含义:

场景 SNP类型 生物学解释
同一菌株内 几乎全是纯合 (Homozygous) 单倍体基因组,每个位点只有一个等位基因
不同菌株间 存在差异 用于菌株分型、进化分析,但不是杂合
混合感染/污染 看似”杂合” 实际是多个菌株的混合,需去卷积而非phasing

⚠️ 细菌甲基化分析的特殊注意事项

1️⃣ 6mA在细菌中的生物学意义

细菌6mA主要功能:
✅ 限制修饰系统 (Restriction-Modification): 区分"自我"vs"外来"DNA
✅ DNA复制起始调控
✅ 基因表达调控 (如相变 Phase variation)
✅ 错配修复 (MutHLS系统)

→ 这些功能都是"全基因组水平"或"位点特异性"的,
  不需要区分父源/母源!

2️⃣ modkit参数设置 (针对细菌6mA)

# ✅ 正确命令:细菌6mA分析
modkit pileup sample \
  An6_6mA_mapped.mod.bam \
  An6_6mA.bed \
  --ref An6-unicycler-medaka_polished_genome.fa \
  --motif A 0 \              # 6mA motif
  --no-combine-strands \     # ⭐ A不是回文,不能合并链
  --threads 12

# ❌ 错误命令:会导致报错
modkit pileup ... --motif A 0 --combine-strands ...
# Error! cannot combine strands with a motif that is not a palindrome

3️⃣ Nextflow管道参数优化 (细菌场景)

nextflow run nf-core/methylong \
  -r 2.0.0 \
  -profile docker \
  --input samplesheet_6mA.csv \
  --outdir methylome_out_6mA \
  --ont_aligner minimap2 \
  --m6a \
  --skip_snvs \              # ⭐ 跳过无意义的SNP phasing步骤
  --haplotype_dmrer dss \    # 即使保留,也不会产生有意义的haplotype DMR
  -resume \
  -work-dir methylome_out_6mA/work

🧪 细菌甲基化分析推荐流程

graph TD
    A[原始Pod5/FAST5] --> B[Dorado basecalling + 6mA mod-call]
    B --> C[生成 modBAM]
    C --> D[比对到参考基因组 minimap2]
    D --> E[modkit pileup --motif A 0 --no-combine-strands]
    E --> F[生成 bed/bigWig]
    F --> G[下游分析]

    G --> G1[甲基化位点鉴定]
    G --> G2[motif富集分析]
    G --> G3[与基因注释关联]
    G --> G4[菌株间比较甲基化]

    style E fill:#90EE90,stroke:#333
    style G fill:#E6F3FF,stroke:#333

推荐下游分析工具 (细菌专用):

分析目标 推荐工具 说明
6mA位点鉴定 modkit, nanom6A 基于ONT信号或modBAM
Motif发现 MEME, HOMER 寻找6mA富集的序列motif
基因关联 bedtools intersect 关联6mA位点与基因/启动子
菌株比较 DSS, methylKit (适配后) 注意:用reference-level模式
可视化 IGV, pyGenomeTracks 加载bigWig轨道

🎯 针对您当前项目的最终建议

1. 立即修复管道错误:

# 方案A: 跳过单倍型分析 (最简单)
nextflow run nf-core/methylong \
  --input samplesheet_6mA.csv \
  --outdir methylome_out_6mA \
  --ont_aligner minimap2 \
  --m6a \
  --skip_snvs \          # ⭐ 关键:细菌不需要phasing
  -resume

# 方案B: 如果管道已生成主要结果,手动完成最后一步
cd methylome_out_6mA/results/methylation/
# An6.bed.gz 已经是您需要的6mA参考水平结果!✅

2. 验证结果质量:

# 检查6mA位点数量和质量
zcat methylome_out_6mA/results/methylation/An6.bed.gz | \
  awk '$4=="A" && $10>=0.8' | wc -l  # 高置信度6mA位点

# 检查motif富集 (示例:GATC是常见6mA motif)
zcat methylome_out_6mA/results/methylation/An6.bed.gz | \
  awk '$4=="A"' | cut -f1-3 | \
  bedtools getfasta -fi genome.fa -bed - | \
  grep -o "GATC" | wc -l

3. 后续分析方向:

🔹 6mA位点是否富集在启动子区域?
🔹 是否集中在特定motif (如GATC, GANTC)?
🔹 与基因表达数据关联 (如果有RNA-seq)?
🔹 与其他菌株比较甲基化差异?

💡 一句话总结 (Zusammenfassung)

🇨🇳 细菌是单倍体,无父源/母源染色体之分,因此单倍型水平甲基化分析无生物学意义。请使用参考基因组水平分析 + --no-combine-strands 参数进行6mA研究。

🇩🇪 Bakterien sind haploid und haben keine väterlichen/mütterlichen Chromosomen. Daher ist eine Haplotyp-Level-Methylierungsanalyse biologisch nicht sinnvoll. Verwenden Sie Reference-Level-Analyse mit --no-combine-strands für 6mA-Studien.

Ihre Verständnis ist absolut korrekt! 🎯 如有其他问题,随时讨论!🚀



🧬 单倍型水平分析 (Haplotype-level) vs 参考基因组水平分析 (Reference-level) 详解

📊 核心概念对比

维度 参考基因组水平 (Reference-level) 单倍型水平 (Haplotype-level)
基本单位 整个样本的所有reads合并统计 按父源/母源染色体分开统计
输入数据 原始align的BAM文件 经过phasing的haplotagged BAM
甲基化值计算 所有reads在该位点的平均修饰概率 分别计算H1/H2两个单倍型的修饰概率
输出结果 每个位点1个甲基化值 每个位点2个甲基化值 (H1 + H2)
生物学意义 样本整体甲基化状态 等位基因特异性甲基化 (ASM)

🔍 直观示例:同一个CpG位点

假设基因组位置 chr1:1000 是一个CpG位点:

📋 Reference-level 分析结果

# 所有reads合并统计
位置        修饰类型  修饰次数  总覆盖度  甲基化比例
chr1:1000   5mC       45       100       45%

表示:该样本在这个位置平均有45%的DNA分子被甲基化

📋 Haplotype-level 分析结果

# 按单倍型分开统计
位置        单倍型  修饰类型  修饰次数  总覆盖度  甲基化比例
chr1:1000   H1      5mC       40       50        80%   ← 父源染色体
chr1:1000   H2      5mC       5        50        10%   ← 母源染色体

表示:父源染色体在该位点高度甲基化(80%),母源染色体几乎未甲基化(10%)
→ 这是典型的等位基因特异性甲基化 (Allele-Specific Methylation, ASM)


🔄 技术流程对比

graph LR
    A[原始reads] --> B[比对到参考基因组]
    B --> C[Reference-level pileup]
    B --> D[SNP calling]
    D --> E[Phasing/单倍型分型]
    E --> F[给reads添加HP标签]
    F --> G[Haplotype-level pileup]

    C --> H[输出: 每个位点1个值]
    G --> I[输出: 每个位点2个值 H1+H2]

关键步骤说明:

  1. SNP Calling (Clair3): 找出样本中的杂合位点
  2. Phasing (WhatsHap): 根据SNP连锁关系,将reads分配到父源/母源
  3. HP tagging: 在BAM文件中给每条read添加 HP:i:1HP:i:2 标签
  4. Strand处理:
    • 参考水平: 可用 --combine-strands 合并正负链
    • 单倍型水平: 非回文motif(如6mA的”A”)不能合并链 ⚠️

⚠️ 为什么6mA分析时会出现 “cannot combine strands” 错误?

回文 vs 非回文 Motif

修饰类型 Motif 是否回文 正负链关系 能否combine-strands
5mC CG ✅ 是 CG(正链) ↔ CG(负链) ✅ 可以
6mA A ❌ 否 A(正链) ↔ T(负链) 不可以

原理解释:

  • 5mC在CG位点: 正链的C和负链的C是同一个生物学事件的两面,可以合并统计
  • 6mA在A位点: 正链的A甲基化和负链的T(对应正链A的互补)是两个独立的生物学事件,不能合并!
# ❌ 错误命令 (6mA + combine-strands)
modkit pileup --motif A 0 --combine-strands ...
# Error! cannot combine strands with a motif that is not a palindrome

# ✅ 正确命令 (6mA + 分开链)
modkit pileup --motif A 0 --no-combine-strands ...
# 或分别处理: --motif A+ 0 (正链) 和 --motif A- 0 (负链)

🎯 应用场景:什么时候用哪种分析?

✅ 使用 Reference-level 分析,如果:

  • 初步探索性分析,了解整体甲基化模式
  • 样本是单倍体生物(如细菌、线粒体)
  • 关注的是区域水平的甲基化变化(如启动子、增强子)
  • 计算资源有限,需要快速出结果
  • 分析6mA且不需要等位基因特异性信息

✅ 使用 Haplotype-level 分析,如果:

  • 研究印记基因 (Imprinted genes) 的甲基化调控
  • 分析杂合位点附近的等位基因特异性甲基化 (ASM)
  • 探索顺式调控变异 (cis-regulatory variants) 对甲基化的影响
  • 癌症研究中分析等位基因失衡的表观遗传改变
  • 需要区分父源/母源染色体的表观遗传状态

📈 结果解读示例

案例:印记基因 IGF2 的启动子区域

# Reference-level 结果
区域: IGF2_promoter
平均甲基化: 52%
→ 结论:中等甲基化,无明显特征

# Haplotype-level 结果  
区域: IGF2_promoter
H1(父源): 95% 甲基化
H2(母源): 8% 甲基化
→ 结论:典型的父源特异性甲基化,符合已知印记模式!✅

案例:6mA在细菌基因组

# 细菌通常是单倍体,无杂合位点
→ Haplotype-level 分析无意义
→ 直接使用 Reference-level + --motif A 0 --no-combine-strands

🔧 针对您当前6mA分析的实操建议

方案1:跳过单倍型分析(推荐 ✅)

# 添加 --skip_snvs 参数,跳过phasing相关步骤
nextflow run nf-core/methylong \
  --input samplesheet_6mA.csv \
  --outdir methylome_out_6mA \
  --ont_aligner minimap2 \
  --m6a \
  --skip_snvs \          # ⭐ 关键:跳过单倍型分析
  -resume

方案2:保留单倍型BAM,但手动运行modkit

# 1. 让管道运行到生成 haplotagged BAM 后暂停
# 2. 手动执行正确参数的modkit:
modkit pileup sample \
  An6_haplotagged.bam \
  An6_6mA_haplo.bed \
  --ref genome.fa \
  --motif A 0 \
  --partition-tag HP \
  --no-combine-strands \   # ⭐ 关键:不合并链
  --threads 12

# 3. 用R/Python后续分析DSS等

方案3:如果确实需要单倍型6mA分析

# 分别计算正负链,后期在R中合并
# 正链6mA (A+)
modkit pileup sample ... --motif A+ 0 --partition-tag HP ...

# 负链6mA (实际是T位的互补信息,通常不关注)
# 一般6mA分析只关注正链的A即可

📦 输出文件对比

文件 Reference-level Haplotype-level
*.bed.gz ✅ 每个位点1行 ✅ 每个位点2行 (H1+H2)
*.bigWig ✅ 单轨可视化 ✅ 双轨可视化 (H1轨 + H2轨)
DMR结果 样本间差异 单倍型间差异 + 样本间差异
计算时间 ⚡ 较快 🐌 较慢 (需phasing+双倍pileup)

💡 总结一句话

参考水平分析回答:”这个位点在整个样本中甲基化程度如何?”
单倍型水平分析回答:”这个位点在父源和母源染色体上的甲基化是否不同?”

对于6mA在原核生物或无需等位基因分辨的研究,参考水平分析 + 正确设置 --no-combine-strands 通常就足够了!🎯

如有具体数据分析需求,欢迎继续讨论!🚀



🔧 modkit Error: “cannot combine strands with a motif that is not a palindrome”

📋 Fehleranalyse

Gute Nachrichten: Die Pipeline ist jetzt fast durchgelaufen!

  • Alignment mit minimap2 ✔️
  • Modkit pileup (Referenz-Level) ✔️
  • Clair3 SNP-Calling ✔️
  • WhatsHap Phasing ✔️

Fehler im letzten Schritt:

Error! cannot combine strands with a motif that is not a palindrome

🔍 Ursache

Der Prozess MODKIT_PILEUP_HAPLOTYPE_LEVEL versucht, Stränge zu kombinieren (--combine-strands) für das 6mA-Motiv “A”:

modkit pileup --motif CG 0 --motif A 0 --combine-strands --partition-tag HP ...
Motiv Palindrom? Kombinierbar?
CG (5mC) ✅ Ja (CG ↔ CG) ✅ Ja
A (6mA) ❌ Nein (A ↔ T) Nein!

Für nicht-palindromische Motive wie 6mA (A) ist die Modifikations-Kontext-Information strang-spezifisch. Forward- und Reverse-Strand können nicht sinnvoll kombiniert werden [[modkit docs]].


✅ Lösungen (absteigend nach Einfachheit)

🔹 Lösung 1: Haplotype-Level DMR überspringen (empfohlen)

Da Sie 6mA analysieren, ist die Referenz-Level-Pileup-Datei (An6.bed.gz) bereits das wichtigste Ergebnis. Die haplotype-level Analyse ist optional.

Option A: Mit --skip_snvs (überspringt SNP-Calling + Phasing + haplotype DMR):

nextflow run nf-core/methylong \
  -r 2.0.0 \
  -profile docker \
  --input samplesheet_6mA.csv \
  --outdir methylome_out_6mA \
  --ont_aligner minimap2 \
  --m6a \
  --skip_snvs \              # ⭐ Haplotype-Level Schritte überspringen
  -resume \
  -work-dir methylome_out_6mA/work

Option B: Nur DMR-Schritt deaktivieren via Custom-Config
Erstellen Sie skip_haplo_dmr.config:

process {
    withName: '*DSS_HAPLOTYPE_LEVEL*' {
        enabled = false
    }
}

Dann starten mit:

nextflow run nf-core/methylong ... -c skip_haplo_dmr.config -resume

🔹 Lösung 2: --haplotype_dmrer modkit verwenden (experimentell)

Der alternative DMRer modkit verwendet möglicherweise andere Parameter:

nextflow run nf-core/methylong \
  -r 2.0.0 \
  -profile docker \
  --input samplesheet_6mA.csv \
  --outdir methylome_out_6mA \
  --ont_aligner minimap2 \
  --m6a \
  --haplotype_dmrer modkit \   # ⭐ Alternative zu 'dss' (Standard)
  -resume \
  -work-dir methylome_out_6mA/work

⚠️ Falls auch modkit als DMRer --combine-strands verwendet, tritt derselbe Fehler auf. Dann Lösung 1 verwenden.


🔹 Lösung 3: Custom modkit-Parameter via Config (fortgeschritten)

Wenn Sie unbedingt haplotype-level pileup für 6mA benötigen, entfernen Sie --combine-strands für das “A”-Motif:

  1. Custom-Config modkit_6mA.config:

    process {
     withName: '*MODKIT_PILEUP_HAPLOTYPE_LEVEL*' {
         // Override command via script customization
         // Hinweis: Dies erfordert ggf. Pipeline-Fork oder pre-run script hook
     }
    }
  2. Alternativ: Manueller modkit-Lauf nach Pipeline-Ende:

    
    # Nach erfolgreichem Pipeline-Lauf (bis vor DSS_HAPLOTYPE_LEVEL)
    cd methylome_out_6mA/

Modkit pileup für 6mA OHNE –combine-strands

modkit pileup sample \ work/…/An6_haplotagged.bam \ An6_6mA_haplo.bed \ –ref bacass_out/Medaka/An6-unicycler-medaka_polished_genome.fa \ –motif A 0 \ –partition-tag HP \ –threads 12 \ –no-combine-strands # ⭐ Explizit deaktivieren

Ergebnis weiterverwenden (z.B. mit DSS in R)


---

## 📁 Wo finde ich meine Ergebnisse jetzt schon?

Auch ohne haplotype-level DMR sind die **wichtigsten Outputs** bereits vorhanden:

```bash
methylome_out_6mA/
├── results/
│   ├── methylation/
│   │   ├── An6.bed.gz          # ⭐ Hauptergebnis: 6mA-Pileup (Referenz-Level)
│   │   ├── An6.bed.gz.tbi
│   │   └── An6.bigWig          # Für IGV-Visualisierung
│   ├── variants/
│   │   ├── An6.vcf.gz          # SNP-Calling-Ergebnisse
│   │   └── An6_haplotagged.bam # Phased BAM für Haplotyp-Analyse
│   └── qc/
│       └── multiqc_report.html # Qualitätsübersicht
└── work/.../                   # Zwischenergebnisse (inkl. haplotagged BAM)

🔎 Schnell-Check der 6mA-Ergebnisse:

# 1. Pileup-Datei prüfen
zcat methylome_out_6mA/results/methylation/An6.bed.gz | head -5

# 2. 6mA-Sites zählen (Motif "A")
zcat methylome_out_6mA/results/methylation/An6.bed.gz | \
  awk '$4 == "A"' | wc -l

# 3. MultiQC-Report öffnen
firefox methylome_out_6mA/results/qc/multiqc_report.html

🎯 Empfohlener nächster Befehl

# Haplotype-level DMR überspringen, Rest fortsetzen:
nextflow run nf-core/methylong \
  -r 2.0.0 \
  -profile docker \
  --input samplesheet_6mA.csv \
  --outdir methylome_out_6mA \
  --ont_aligner minimap2 \
  --m6a \
  --skip_snvs \
  -resume \
  -work-dir methylome_out_6mA/work

💡 Tipp: Die Referenz-Level-Pileup-Datei (An6.bed.gz) enthält bereits alle 6mA-Modifikationswahrscheinlichkeiten pro Position – für die meisten Analysen völlig ausreichend!

Bei weiteren Fragen helfe ich gerne! 🚀



在您的命令中,--m6a 是一个布尔型开关参数,核心作用是:

🔹 指示管道在甲基化堆叠(pileup)步骤中,专门识别、提取并统计 6mA(N6-甲基腺嘌呤)修饰位点。


🔍 详细机制说明

维度 说明
默认行为 modkit(管道内部调用的甲基化定量工具)默认主要针对真核生物常见的 胞嘧啶修饰(如 CG 位点的 5mC/5hmC)进行统计。
添加 --m6a 管道会在底层自动为 modkit pileup 命令追加 --motif A 0 参数,强制其扫描并输出所有 腺嘌呤(A) 位点的修饰概率。
底层命令映射 bash<br># 不加 --m6a<br>modkit pileup ... --motif CG 0 ...<br><br># 加上 --m6a 后<br>modkit pileup ... --motif CG 0 --motif A 0 ...<br>

🦠 为什么对您的细菌分析必不可少

  1. 细菌的主要修饰是 6mA:原核生物基因组中,6mA 通常由限制修饰系统(如 Dam, CcrM 甲基转移酶)催化,富集在 GATCGANTC 等 motif 中。
  2. 不加的后果:如果不写 --m6a,管道只会输出默认的 5mC/CG 结果。您的核心输出文件 An6.bed.gz 中将几乎没有或完全没有 6mA 数据,后续 motif 分析和功能注释将全部落空。
  3. 结果验证:运行后,您可以用以下命令确认 6mA 信号已成功捕获:
    zcat methylome_out_6mA/results/methylation/An6.bed.gz | \
      awk '$4=="A" && $5>=0.8' | wc -l
    # 预期输出:数百至数万行(取决于测序深度和菌株甲基化活性)

⚠️ 使用注意事项

  • 正确写法:直接写 --m6a 即可(布尔开关,不需要--m6a true--m6a=1,否则可能触发参数校验警告)。
  • 🔄 与其他参数配合:通常与 --ont_aligner minimap2--skip_snvs 一起使用,构成细菌 6mA 分析的最小完整命令集。

💡 一句话总结

--m6a = “请专门为我提取细菌基因组中的 6mA 修饰信号,不要只跑默认的 5mC/CG。”
对于原核表观遗传研究,这是必加参数,直接决定您能否拿到目标数据!🎯

DEBUG methylomic analysis of Data_Tam_DNAseq_2026_An6_BG5

🔧 Lösung: Bereits alignierte modBAM-Dateien mit nf-core/methylong v2.0.0

📊 Analyse Ihrer BAM-Datei

Gute Nachrichten: Ihre Datei An6_6mA_mapped.mod.bam ist:

  • Bereits aligniert (@SQ Header mit Chromosomen/Positionen vorhanden)
  • Enthält 6mA-Modifikationen (MM:Z:A+a… und ML:B:C Tags sichtbar)
  • Von Dorado basecalled (PN:dorado VN:2.0.0+…)

Problem: Die Pipeline versucht trotzdem, den Dorado-Aligner erneut auszuführen → Docker-Auth-Fehler.


🚨 Shell-Fehler beheben: Befehl korrekt eingeben

Die Fehler --ont_aligner: command not found entstehen, weil Multi-Line-Befehle mit \ nicht korrekt verarbeitet werden.

Option A: Als einzeiliger Befehl (empfohlen):

nextflow run nf-core/methylong -r 2.0.0 -profile docker --input samplesheet_6mA.csv --outdir methylome_out_6mA --ont_aligner minimap2 --m6a -resume -work-dir methylome_out_6mA/work

Option B: Multi-Line mit korrekter Syntax (kein Leerzeichen nach \!):

nextflow run nf-core/methylong \
  -r 2.0.0 \
  -profile docker \
  --input samplesheet_6mA.csv \
  --outdir methylome_out_6mA \
  --ont_aligner minimap2 \
  --m6a \
  -resume \
  -work-dir methylome_out_6mA/work

Option C: In ein Skript schreiben (run_methylong.sh):

#!/bin/bash
nextflow run nf-core/methylong \
  -r 2.0.0 \
  -profile docker \
  --input samplesheet_6mA.csv \
  --outdir methylome_out_6mA \
  --ont_aligner minimap2 \
  --m6a \
  -resume \
  -work-dir methylome_out_6mA/work
chmod +x run_methylong.sh && ./run_methylong.sh

⚙️ Samplesheet für bereits alignierte modBAM-Dateien

Da Ihre BAM-Datei bereits aligniert ist, gibt es zwei Ansätze:

🔹 Ansatz 1: --reset verwenden (Pipeline aligniert neu)

group,sample,path,ref,method
group1,An6,/mnt/md1/DATA/Data_Tam_DNAseq_2026_An6_BG5/An6_6mA_mapped.mod.bam,/mnt/md1/DATA/Data_Tam_DNAseq_2026_An6_BG5/bacass_out/Medaka/An6-unicycler-medaka_polished_genome.fa,ont
# Befehl mit --reset (entfernt alte Alignment-Info, aligniert mit minimap2 neu)
nextflow run nf-core/methylong -r 2.0.0 -profile docker --input samplesheet_6mA.csv --outdir methylome_out_6mA --ont_aligner minimap2 --reset --m6a -resume

🔹 Ansatz 2: Pipeline “austricksen” – unalignierte BAM simulieren

Wenn Sie das bestehende Alignment behalten möchten:

  1. BAM ohne Alignment-Info exportieren (behält MM/ML-Tags):

    samtools collate -Ou An6_6mA_mapped.mod.bam | \
    samtools fastq -T MM,ML - > An6_6mA_with_mods.fastq
  2. Samplesheet mit FASTQ-Pfad (Pipeline basecallt nicht, da keine Pod5/FAST5):

    group,sample,path,ref,method
    group1,An6,/pfad/zu/An6_6mA_with_mods.fastq,/pfad/zu/genome.fa,ont
  3. Pipeline mit --skip_basecalling-Ersatz starten:

    ⚠️ Da --skip_basecalling nicht existiert: Die Pipeline erkennt FASTQ ohne Basecalling-Info und springt direkt zu Alignment. Kombinieren Sie mit --ont_aligner minimap2:

    nextflow run nf-core/methylong -r 2.0.0 -profile docker --input samplesheet_6mA.csv --outdir methylome_out_6mA --ont_aligner minimap2 --m6a -resume

🧪 Schnelltest: Läuft die Pipeline mit minimap2?

# 1. Work-Directory aufräumen (falls vorheriger Run fehlschlug)
rm -rf methylome_out_6mA/work/a1/

# 2. Minimaler Testlauf (nur bis Alignment)
nextflow run nf-core/methylong \
  -r 2.0.0 \
  -profile docker \
  --input samplesheet_6mA.csv \
  --outdir methylome_out_6mA_test \
  --ont_aligner minimap2 \
  --m6a \
  -resume \
  -work-dir methylome_out_6mA_test/work \
  -entry align 2>&1 | tee test_align.log

💡 Der -entry align Parameter startet die Pipeline nur bis zum Alignment-Schritt (falls in v2.0.0 verfügbar – sonst weglassen).


📋 Checkliste vor dem Start

Prüfpunkt Befehl/Ziel
✅ Samplesheet-Spalten group,sample,path,ref,method (exakt!)
✅ Absolute Pfade Keine relativen Pfade wie ./file.bam
✅ BAM-Datei lesbar samtools quickcheck An6_6mA_mapped.mod.bam && echo "OK"
✅ MM/ML-Tags vorhanden samtools view file.bam \| head -1 \| grep -q "MM:Z" && echo "Mods OK"
✅ Docker läuft docker run hello-world
✅ Ausreichend RAM/CPU Min. 16 GB RAM, 8 CPUs empfohlen

🔄 Alternative: Manueller modkit-Pileup (ohne Nextflow)

Falls die Pipeline weiterhin Probleme macht, können Sie modkit direkt auf Ihrer BAM-Datei anwenden:

# 1. Referenz indexieren
samtools faidx /pfad/zu/genome.fa

# 2. modkit pileup für 6mA
modkit pileup sample \
  An6_6mA_mapped.mod.bam \
  methylome_out_6mA/An6_6mA.pileup.bed \
  --ref /pfad/zu/genome.fa \
  --modify-motif 6mA \
  --cpg \
  -t 8

# 3. Zu BigWig konvertieren (für IGV)
bedGraphToBigWig methylome_out_6mA/An6_6mA.pileup.bed genome.fa.sizes methylome_out_6mA/An6_6mA.bw

📦 modkit installieren: pip install modkit oder via Docker: docker pull nanoporetech/modkit


🎯 Empfohlener nächster Schritt

# 1. Samplesheet prüfen
cat samplesheet_6mA.csv

# 2. Einzeiligen Nextflow-Befehl ausführen (mit minimap2):
nextflow run nf-core/methylong -r 2.0.0 -profile docker --input samplesheet_6mA.csv --outdir methylome_out_6mA --ont_aligner minimap2 --m6a -resume -work-dir methylome_out_6mA/work

Bei weiteren Fehlern: Bitte den Inhalt von .nextflow.log teilen – dann kann ich gezielt helfen! 🚀