🚀 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! 🚀

Genomic analysis (Data_Tam_DNAseq_2026_An7_An22_Acinetobacter_sp)

  1. Run nextflow bacass

     conda deactivate
    
     # Downlod k2_standard_08_GB_20251015.tar.gz from https://benlangmead.github.io/aws-indexes/k2#kraken2--bracken
     # Download 20190108_kmerfinder_stable_dirs.tar.gz from https://zenodo.org/records/13447056; 'tar xzf 20190108_kmerfinder_stable_dirs.tar.gz'  #The database does not work!
     # Download the kmerfinder database: https://www.genomicepidemiology.org/services/ --> https://cge.food.dtu.dk/services/KmerFinder/ --> https://cge.food.dtu.dk/services/KmerFinder/etc/kmerfinder_db.tar.gz  #The database works!
    
     # DEBUG: --kmerfinderdb /mnt/nvme1n1p1/REFs/kmerfinder/bacteria/ not working!
    
     nextflow run nf-core/bacass -r 2.6.0 -profile docker --help
    
     # -- Hybrid assembly --
     nextflow run nf-core/bacass -r 2.6.0 -profile docker \
       --input samplesheet_bacass.tsv \
       --outdir bacass_out \
       --assembly_type hybrid \
       --assembler unicycler,dragonflye \
       --kraken2db /mnt/nvme1n1p1/REFs/k2_standard_08_GB_20251015.tar.gz \
       --skip_kmerfinder \
       -resume \
       -work-dir bacass_out/work
    
     # -- Short assembly --
     #Maybe BUG is from '--skip_kmerfinder for -r 2.6.0, using db in 2.5.0'
     nextflow run nf-core/bacass -r 2.5.0 -profile docker \
       --input samplesheet.tsv \
       --outdir bacass_out \
       --assembly_type short \
       --kraken2db /mnt/nvme1n1p1/REFs/k2_standard_08_GB_20251015.tar.gz \
       --kmerfinderdb /mnt/nvme1n1p1/REFs/kmerfinder/bacteria/ \
       -resume \
       -work-dir bacass_out/work
    
     # Using prokka assembly since medaka was not generated!
     jhuang@WS-2290C:~/DATA/Data_Tam_DNAseq_2026_An6_An7_An22_Acinetobacter_sp/bacass_out/Prokka/An7.fna
     jhuang@WS-2290C:~/DATA/Data_Tam_DNAseq_2026_An6_An7_An22_Acinetobacter_sp/bacass_out/Prokka/An22.fna
  2. Species Identification: 快速筛查用 Mash → 精确分类用 GTDB-Tk → 种级验证用 FastANI,三者结合可最大限度提高物种鉴定的准确性和可解释性。

     # 1. 创建环境(推荐 mamba)
     mamba create -n gtdbtk -c conda-forge -c bioconda gtdbtk
     mamba activate gtdbtk
    
     # 2. 下载数据库(仅需首次,约 60GB)
     gtdbtk download --data_dir ./gtdb_data --release 220
    
     wget https://data.gtdb.aau.ecogenomic.org/releases/release232/232.0/auxillary_files/gtdbtk_package/full_package/gtdbtk_r232_data.tar.g
     mamba env config vars set GTDBTK_DATA_PATH="/mnt/nvme4n1p1/gtdb_data/release232"
     # 先退出当前环境,再重新激活
     mamba deactivate
     mamba activate gtdbtk
    
     # 验证环境变量是否加载成功
     echo $GTDBTK_DATA_PATH
     # 应输出:/mnt/nvme4n1p1/gtdb_data/release232
    
     # 3. 运行分类(你提供的命令 + 实用参数)
     gtdbtk classify_wf \
       --genome_dir ./bacass_out/Prokka \
       --out_dir gtdb_out \
       --cpus 64 \
       --extension .fna \
       --prefix mygenome
    
     # 4. 查看结果
     cat gtdb_out/classify/mygenome.bac120.summary.tsv   # 细菌结果
    
     #For An7
     user_genome classification  closest_genome_reference    closest_genome_reference_radius closest_genome_taxonomy closest_genome_ani  closest_genome_af
     An7 d__Bacteria;p__Pseudomonadota;c__Gammaproteobacteria;o__Pseudomonadales;f__Moraxellaceae;g__Acinetobacter;s__Acinetobacter harbinensis  GCF_000816495.1 95  d__Bacteria;p__Pseudomonadota;c__Gammaproteobacteria;o__Pseudomonadales;f__Moraxellaceae;g__Acinetobacter;s__Acinetobacter harbinensis  97.43   0.882
    
     #For An22
     user_genome classification  closest_genome_reference    closest_genome_reference_radius closest_genome_taxonomy closest_genome_ani  closest_genome_af
     An22    d__Bacteria;p__Actinomycetota;c__Actinomycetes;o__Actinomycetales;f__Micrococcaceae;g__Arthrobacter;s__Arthrobacter sp024124825 GCF_029964055.1 95  d__Bacteria;p__Actinomycetota;c__Actinomycetes;o__Actinomycetales;f__Micrococcaceae;g__Arthrobacter;s__Arthrobacter sp024124825 99.23   0.929
    
     other_related_references(genome_id,species_name,radius,ANI,AF)
     GCA_052245515.1, s__Arthrobacter sp052245515, 95.0, 83.71, 0.177;
     GCF_020532825.1, s__Arthrobacter sp020532825, 95.0, 85.21, 0.268;
     GCF_937873245.1, s__Arthrobacter sp937873245, 95.0, 85.74, 0.21;
     GCF_009928425.1, s__Arthrobacter sp009928425, 95.0, 86.58, 0.356;
     GCA_963698285.1, s__Arthrobacter sp963698285, 95.0, 83.14, 0.159;
     GCF_020532805.1, s__Arthrobacter sp020532805, 95.0, 83.75, 0.189;
     GCF_001512305.1, s__Arthrobacter sp001512305, 95.0, 83.7, 0.199;
     GCF_001750145.1, s__Arthrobacter sp001750145, 95.0, 84.97, 0.268;
     GCF_019977335.1, s__Arthrobacter sp019977335, 95.0, 84.61, 0.231;
     GCA_035466775.1, s__Arthrobacter sp035466775, 95.0, 85.13, 0.243;
     GCA_035467435.1, s__Arthrobacter sp035467435, 95.0, 86.43, 0.25;
     GCF_001422645.1, s__Arthrobacter sp001422645, 95.0, 84.35, 0.224;
     GCF_000427315.1, s__Arthrobacter sp000427315, 95.0, 87.23, 0.32;
     GCA_039636775.1, s__Arthrobacter sp039636775, 95.0, 83.78, 0.217;
     GCF_029960645.1, s__Arthrobacter sp029960645, 95.0, 84.79, 0.253;
     GCF_031456935.1, s__Arthrobacter ginsengisoli, 95.0, 84.68, 0.223;
     GCF_052113365.1, s__Arthrobacter sp052113365, 95.0, 84.71, 0.234;
     GCA_036390955.1, s__Arthrobacter sp036390955, 95.0, 86.36, 0.167;
     GCF_030812335.1, s__Arthrobacter oxydans_B, 95.0, 85.33, 0.273;
     GCF_040547365.1, s__Arthrobacter sp040547365, 95.0, 85.47, 0.29;
     GCF_007679325.1, s__Arthrobacter sp007679325, 95.0, 84.42, 0.219;
     GCF_040547025.1, s__Arthrobacter sp040547025, 95.0, 85.41, 0.318;
     GCF_030433895.1, s__Arthrobacter sp030433895, 95.0, 84.8, 0.252;
     GCF_050157025.1, s__Arthrobacter sp050157025, 95.0, 82.71, 0.153;
     GCF_040547005.1, s__Arthrobacter sp040547005, 95.0, 83.22, 0.151;
     GCA_034376805.1, s__Arthrobacter sp034376805, 95.0, 85.48, 0.304;
     GCA_028370155.1, s__Arthrobacter sp028370155, 95.0, 84.56, 0.235
  3. Antimicrobial resistance gene profiling and Resistome and Virulence Profiling with Abricate and RGI (Reisistance Gene Identifier)

     conda activate /home/jhuang/miniconda3/envs/bengal3_ac3
     abricate --list
    
     conda deactivate
    
     ENV_NAME=/home/jhuang/miniconda3/envs/bengal3_ac3 \
     ASM=bacass_out/Prokka/An22.fna \
     SAMPLE=An22 \
     OUTDIR=resistome_virulence_An22 \
     MINID=70 MINCOV=50 \
     THREADS=32 \
     ~/Scripts/run_abricate_resistome_virulome_one_per_gene.sh
    
     #ABRicate thresholds: MINID=80 MINCOV=60
     Database        Hit_lines       File
     MEGARes 0       resistome_virulence_An7/raw/An7.megares.tab
     CARD    0       resistome_virulence_An7/raw/An7.card.tab
     ResFinder       0       resistome_virulence_An7/raw/An7.resfinder.tab
     VFDB    0       resistome_virulence_An7/raw/An7.vfdb.tab
    
     #ABRicate thresholds: MINID=70 MINCOV=50
     Database        Hit_lines       File
     MEGARes 5       resistome_virulence_An7/raw/An7.megares.tab
     CARD    5       resistome_virulence_An7/raw/An7.card.tab
     ResFinder       0       resistome_virulence_An7/raw/An7.resfinder.tab
     VFDB    3       resistome_virulence_An7/raw/An7.vfdb.tab
    
     Database        Hit_lines       File
     MEGARes 2       resistome_virulence_An22/raw/An22.megares.tab
     CARD    1       resistome_virulence_An22/raw/An22.card.tab
     ResFinder       0       resistome_virulence_An22/raw/An22.resfinder.tab
     VFDB    2       resistome_virulence_An22/raw/An22.vfdb.tab
    
     conda activate /home/jhuang/miniconda3/envs/bengal3_ac3
     #NEED_TO_ADAPT: OUTDIR = Path("resistome_virulence_An7")
     #NEED_TO_ADAPT: SAMPLE = "An7"
     python ~/Scripts/merge_amr_sources_by_gene.py
    
     python ~/Scripts/export_resistome_virulence_to_excel_py36.py \
       --workdir resistome_virulence_An22 \
       --sample An22 \
       --out Resistome_Virulence_An22.xlsx
     # Delete the column 'COVERAGE_MAP' in all 'Raw_*' sheets
  4. Report

Dear XXXX,

Please find below a summary of genomic analyses for samples An7 and An22.

1. Species Identification

Sample An7: Acinetobacter harbinensis ✅ Confirmed

Parameter Value Interpretation
Closest Reference GCF_000816495.1 Type strain of A. harbinensis
ANI 97.43% ✅ Well above 95% species threshold
AF (Alignment Fraction) 0.882 ✅ 88.2% of genome aligns; ANI estimate is robust
Final Taxonomy d__Bacteria;p__Pseudomonadota;c__Gammaproteobacteria;o__Pseudomonadales;f__Moraxellaceae;g__Acinetobacter;s__Acinetobacter harbinensis Consistent with genomic expectations

🟢 Conclusion: An7 is confidently assigned to Acinetobacter harbinensis.


Sample An22: Arthrobacter sp. strain An22 🟡 Potential Novel Species

Parameter Value Interpretation
Closest Reference GCF_029964055.1 (Arthrobacter sp024124825) 🟡 Unclassified candidate species
ANI 99.23% ✅ Highly similar to unclassified reference
AF (Alignment Fraction) 0.929 ✅ Reliable ANI estimate
Final Taxonomy d__Bacteria;p__Actinomycetota;c__Actinomycetes;o__Actinomycetales;f__Micrococcaceae;g__Arthrobacter;s__Arthrobacter sp024124825 Clear genus assignment; species-level novelty

Comparison with Named Arthrobacter Species:

Reference Species ANI (%) AF Same Species?
A. ginsengisoli (GCF_031456935.1) 84.68 0.223 ❌ ANI < 95%
A. oxydans B (GCF_030812335.1) 85.33 0.273 ❌ ANI < 95%
A. sp000427315 (GCF_000427315.1) 87.23 0.320 ❌ (highest among named/unclassified)
A. sp035467435 (GCA_035467435.1) 86.43 0.250
A. sp036390955 (GCA_036390955.1) 86.36 0.167
A. sp009928425 (GCF_009928425.1) 86.58 0.356
A. sp040547365 (GCF_040547365.1) 85.47 0.290
A. sp040547025 (GCF_040547025.1) 85.41 0.318
A. sp034376805 (GCA_034376805.1) 85.48 0.304
A. sp020532825 (GCF_020532825.1) 85.21 0.268
A. sp035466775 (GCA_035466775.1) 85.13 0.243
A. sp052113365 (GCF_052113365.1) 84.71 0.234
A. sp029960645 (GCF_029960645.1) 84.79 0.253
A. sp019977335 (GCF_019977335.1) 84.61 0.231
A. sp030433895 (GCF_030433895.1) 84.80 0.252
A. sp028370155 (GCA_028370155.1) 84.56 0.235
A. sp001750145 (GCF_001750145.1) 84.97 0.268
A. sp001422645 (GCF_001422645.1) 84.35 0.224
A. sp039636775 (GCA_039636775.1) 83.78 0.217
A. sp020532805 (GCF_020532805.1) 83.75 0.189
A. sp052245515 (GCA_052245515.1) 83.71 0.177
A. sp001512305 (GCF_001512305.1) 83.70 0.199
A. sp040547005 (GCF_040547005.1) 83.22 0.151
A. sp963698285 (GCA_963698285.1) 83.14 0.159
A. sp050157025 (GCF_050157025.1) 82.71 0.153
A. sp937873245 (GCF_937873245.1) 85.74 0.210

🟡 Conclusion: An22 shows >99% ANI to an unclassified Arthrobacter reference genome (GCF_029964055.1) but <86% ANI to all named Arthrobacter species (including A. ginsengisoli and A. oxydans). This supports An22 representing a candidate novel species, tentatively labeled Arthrobacter sp. strain An22.


2. AMR Genes Summary

An7 (A. harbinensis): 6 genes detected (CARD/MEGARes consensus)

  • adeIJK (RND efflux pump complex) → multidrug resistance (carbapenems, cephalosporins, fluoroquinolones, macrolides, tetracyclines, etc.)
  • abeM (MATE efflux pump) → fluoroquinolones, disinfecting agents & antiseptics
  • LpsB → intrinsic resistance to colistin and other peptide antibiotics
  • MEXT → RND efflux regulator (multi-compound & biocide resistance)

An22 (Arthrobacter sp. strain An22): 3 genes detected

  • rpoB mutants (CARD) → rifamycin resistance (mutations in rifampicin-binding pocket)
  • MTRAD (MEGARes) → multi-drug RND efflux regulator
  • PARY (MEGARes) → aminocoumarin-resistant DNA topoisomerase (aminocoumarin resistance)

📝 Note: Efflux regulators (MEXT, MTRAD) and intrinsic/target-modification genes are frequently observed in environmental Arthrobacter/Acinetobacter isolates. Phenotypic AST validation is recommended if clinical or biotechnological applications are planned.


3. Virulence Factors (VFDB)

Sample Hits Key Genes Implication
An7 3 htpB (Hsp60), katA (catalase), pilT (twitching motility) Stress survival, oxidative defense, adhesion/biofilm formation
An22 2 icl (isocitrate lyase), ideR (iron-dependent regulator) Metabolic adaptation (glyoxylate shunt), iron homeostasis & potential persistence

4. Methylome Data

“Could you please clarify if the datasets include methylome data?”

Yes – Datasets include POD5 files (Oxford Nanopore) containing raw signal data for base modification detection. Methylome analysis is in progress.


5. Attachments

  • Resistome_Virulence_An7.xlsx – Detailed AMR/virulence tables for A. harbinensis An7
  • Resistome_Virulence_An22.xlsx – Detailed AMR/virulence tables for Arthrobacter sp. strain An22

Each file includes CARD/MEGARes/ResFinder annotations and VFDB virulence factors (%ID, coverage, genomic coordinates, and strand orientation).

Please let me know if you need further breakdowns or phenotypic correlation analysis.

Best, YYYY

Genomic analysis (Data_Tam_DNAseq_2026_An6_BG5)

  1. cat longreads

./cat_longreads.sh

  1. Run unicycler

     conda activate /home/jhuang/miniconda3/envs/trycycler
    
     unicycler -1 /mnt/md1/DATA/Data_Tam_DNAseq_2026_An6_BG5/X101SC26036392-Z01-J002/clean_data/An6/An6_L1_1.clean.rd.fq.gz -2 /mnt/md1/DATA/Data_Tam_DNAseq_2026_An6_BG5/X101SC26036392-Z01-J002/clean_data/An6/An6_L1_2.clean.rd.fq.gz -l /mnt/md1/DATA/Data_Tam_DNAseq_2026_An6_BG5/X101SC26036392-Z01-J003/Release-X101SC26036392-Z01-J003-20260513_01/Data-X101SC26036392-Z01-J003/An6/2157_4C_PBK79106_7ec05c46/merged_An6_longreads.fastq.gz --mode normal -t 100 -o An6_unicycler_normal
    
     unicycler -1 /mnt/md1/DATA/Data_Tam_DNAseq_2026_An6_BG5/X101SC26036392-Z01-J002/clean_data/BG5/BG5_L1_1.clean.rd.fq.gz -2 /mnt/md1/DATA/Data_Tam_DNAseq_2026_An6_BG5/X101SC26036392-Z01-J002/clean_data/BG5/BG5_L1_2.clean.rd.fq.gz -l /mnt/md1/DATA/Data_Tam_DNAseq_2026_An6_BG5/X101SC26036392-Z01-J003/Release-X101SC26036392-Z01-J003-20260513_01/Data-X101SC26036392-Z01-J003/BG5/2157_4C_PBK79106_7ec05c46/merged_BG5_longreads.fastq.gz --mode normal -t 100 -o BG5_unicycler_normal
    
     unicycler -1 /mnt/md1/DATA/Data_Tam_DNAseq_2026_An6_BG5/X101SC26036392-Z01-J002/clean_data/An6/An6_L1_1.clean.rd.fq.gz -2 /mnt/md1/DATA/Data_Tam_DNAseq_2026_An6_BG5/X101SC26036392-Z01-J002/clean_data/An6/An6_L1_2.clean.rd.fq.gz -l /mnt/md1/DATA/Data_Tam_DNAseq_2026_An6_BG5/X101SC26036392-Z01-J003/Release-X101SC26036392-Z01-J003-20260513_01/Data-X101SC26036392-Z01-J003/An6/2157_4C_PBK79106_7ec05c46/merged_An6_longreads.fastq.gz --mode conservative -t 100 -o An6_unicycler_conservative
    
     unicycler -1 /mnt/md1/DATA/Data_Tam_DNAseq_2026_An6_BG5/X101SC26036392-Z01-J002/clean_data/BG5/BG5_L1_1.clean.rd.fq.gz -2 /mnt/md1/DATA/Data_Tam_DNAseq_2026_An6_BG5/X101SC26036392-Z01-J002/clean_data/BG5/BG5_L1_2.clean.rd.fq.gz -l /mnt/md1/DATA/Data_Tam_DNAseq_2026_An6_BG5/X101SC26036392-Z01-J003/Release-X101SC26036392-Z01-J003-20260513_01/Data-X101SC26036392-Z01-J003/BG5/2157_4C_PBK79106_7ec05c46/merged_BG5_longreads.fastq.gz --mode conservative -t 100 -o BG5_unicycler_conservative
    
     unicycler -1 /mnt/md1/DATA/Data_Tam_DNAseq_2026_An6_BG5/X101SC26036392-Z01-J002/clean_data/An6/An6_L1_1.clean.rd.fq.gz -2 /mnt/md1/DATA/Data_Tam_DNAseq_2026_An6_BG5/X101SC26036392-Z01-J002/clean_data/An6/An6_L1_2.clean.rd.fq.gz -l /mnt/md1/DATA/Data_Tam_DNAseq_2026_An6_BG5/X101SC26036392-Z01-J003/Release-X101SC26036392-Z01-J003-20260513_01/Data-X101SC26036392-Z01-J003/An6/2157_4C_PBK79106_7ec05c46/merged_An6_longreads.fastq.gz --mode bold -t 100 -o An6_unicycler_bold
    
     unicycler -1 /mnt/md1/DATA/Data_Tam_DNAseq_2026_An6_BG5/X101SC26036392-Z01-J002/clean_data/BG5/BG5_L1_1.clean.rd.fq.gz -2 /mnt/md1/DATA/Data_Tam_DNAseq_2026_An6_BG5/X101SC26036392-Z01-J002/clean_data/BG5/BG5_L1_2.clean.rd.fq.gz -l /mnt/md1/DATA/Data_Tam_DNAseq_2026_An6_BG5/X101SC26036392-Z01-J003/Release-X101SC26036392-Z01-J003-20260513_01/Data-X101SC26036392-Z01-J003/BG5/2157_4C_PBK79106_7ec05c46/merged_BG5_longreads.fastq.gz --mode bold -t 100 -o BG5_unicycler_bold
  2. Run nextflow bacass

     conda deactivate
    
     # Downlod k2_standard_08_GB_20251015.tar.gz from https://benlangmead.github.io/aws-indexes/k2#kraken2--bracken
     # Download 20190108_kmerfinder_stable_dirs.tar.gz from https://zenodo.org/records/13447056; 'tar xzf 20190108_kmerfinder_stable_dirs.tar.gz'  #The database does not work!
     # Download the kmerfinder database: https://www.genomicepidemiology.org/services/ --> https://cge.food.dtu.dk/services/KmerFinder/ --> https://cge.food.dtu.dk/services/KmerFinder/etc/kmerfinder_db.tar.gz  #The database works!
    
     # DEBUG: --kmerfinderdb /mnt/nvme1n1p1/REFs/kmerfinder/bacteria/ not working!
    
     nextflow run nf-core/bacass -r 2.6.0 -profile docker --help
     nextflow run nf-core/bacass -r 2.6.0 -profile docker \
       --input samplesheet_bacass.tsv \
       --outdir bacass_out \
       --assembly_type hybrid \
       --assembler unicycler,dragonflye \
       --kraken2db /mnt/nvme1n1p1/REFs/k2_standard_08_GB_20251015.tar.gz \
       --skip_kmerfinder \
       -resume \
       -work-dir bacass_out/work
    
     #We can skip kmerfinder since kraken2 do similar function:
     功能,KmerFinder,Kraken2,您的需求
     物种鉴定,✅ 基于 k-mer 频率,✅ 基于 k-mer 分类,二者选一即可
     污染筛查,✅ 可检测外源序列,✅ 可检测外源序列,✅ 有 Kraken2 足够
     数据库大小,~32 GB,~8 GB,Kraken2 更轻量
     运行速度,较慢,较快,Kraken2 更快
     细菌特异性,✅ 针对细菌优化,✅ 支持细菌,二者均可
    
     # Using Polished genomes for downstream analyses
     jhuang@WS-2290C:~/DATA/Data_Tam_DNAseq_2026_An6_BG5/bacass_out/Medaka$ grep ">" An6-unicycler-medaka_polished_genome.fa
     jhuang@WS-2290C:~/DATA/Data_Tam_DNAseq_2026_An6_BG5/bacass_out/Medaka$ grep ">" BG5-unicycler-medaka_polished_genome.fa
  3. Species Identification: 快速筛查用 Mash → 精确分类用 GTDB-Tk → 种级验证用 FastANI,三者结合可最大限度提高物种鉴定的准确性和可解释性。

🔬 主流物种鉴定工具对比

工具 适用对象 核心原理 优势 局限性
GTDB-Tk(CHOSEN) [[12]] 细菌/古菌 基于120+个单拷贝标记基因的系统发育分析 分类标准客观(基于GTDB数据库),分辨率高,适合新物种发现 仅支持原核生物,计算量较大
Mash / Mash Screen [[35]] 所有生物 MinHash算法快速估算基因组距离(ANI近似) 速度极快(秒级),可筛查污染,支持参考库自定义 分辨率依赖参考库完整性,对远缘物种区分有限
Kraken2 [[25]] 所有生物 k-mer + LCA(最低共同祖先)分类 速度快,支持自定义数据库,可处理混合样本 内存需求高(标准库~30GB),假阳性需置信度过滤
FastANI [[36]] 细菌/古菌 全基因组平均核苷酸一致性(ANI)计算 金标准方法,95-96% ANI ≈ 同种,结果可解释性强 需两两比对,大规模筛查较慢
NCBI BLAST+ 16S/全基因组 [[2]] 所有生物 序列相似性比对 数据库最全,结果直观,适合初步筛查 16S分辨率有限(种内难区分),全基因组BLAST慢
    # 1. 创建环境(推荐 mamba)
    mamba create -n gtdbtk -c conda-forge -c bioconda gtdbtk
    mamba activate gtdbtk

    # 2. 下载数据库(仅需首次,约 60GB)
    gtdbtk download --data_dir ./gtdb_data --release 220

    wget https://data.gtdb.aau.ecogenomic.org/releases/release232/232.0/auxillary_files/gtdbtk_package/full_package/gtdbtk_r232_data.tar.g
    mamba env config vars set GTDBTK_DATA_PATH="/mnt/nvme4n1p1/gtdb_data/release232"
    # 先退出当前环境,再重新激活
    mamba deactivate
    mamba activate gtdbtk

    # 验证环境变量是否加载成功
    echo $GTDBTK_DATA_PATH
    # 应输出:/mnt/nvme4n1p1/gtdb_data/release232

    # 3. 运行分类(你提供的命令 + 实用参数)
    gtdbtk classify_wf \
      --genome_dir ./bacass_out/Medaka \
      --out_dir gtdb_out \
      --cpus 64 \
      --extension .fa \
      --prefix mygenome

    # 4. 查看结果
    cat gtdb_out/classify/mygenome.bac120.summary.tsv   # 细菌结果

        #For An6:
        #closest_genome_reference   closest_genome_reference_radius closest_genome_taxonomy closest_genome_ani  closest_genome_af
        #GCF_000816495.1    95  d__Bacteria;p__Pseudomonadota;c__Gammaproteobacteria;o__Pseudomonadales;f__Moraxellaceae;g__Acinetobacter;s__Acinetobacter harbinensis  97.41   0.892

        #For BG5:
        #closest_genome_reference   closest_genome_reference_radius closest_genome_taxonomy closest_genome_ani  closest_genome_af
        #GCF_040547305.1    95  d__Bacteria;p__Bacteroidota;c__Bacteroidia;o__Sphingobacteriales;f__Sphingobacteriaceae;g__Pedobacter;s__Pedobacter sp040547305 98.45   0.894
        #other_related_references(genome_id,species_name,radius,ANI,AF)
        #GCF_040822065.1, s__Pedobacter sp040822065, 95.0, 89.17, 0.499;
        #GCF_014200595.1, s__Pedobacter cryoconitis_C, 95.0, 89.48, 0.577;
        #GCF_003259615.1, s__Pedobacter cryoconitis, 95.0, 89.22, 0.556;
        #GCF_040026395.1, s__Pedobacter lusitanus, 95.0, 83.93, 0.167;
        #GCA_014302835.1, s__Pedobacter sp014302835, 95.0, 84.24, 0.161;
        #GCF_014200605.1, s__Pedobacter cryoconitis_B, 95.0, 84.47, 0.194;
        #GCF_001590605.1, s__Pedobacter cryoconitis_A, 95.0, 91.97, 0.663
  1. Using https://www.bv-brc.org/app/ComprehensiveGenomeAnalysis to annotate the genome using scaffolded results from bacass. ComprehensiveGenomeAnalysis provides comprehensive overview of the data.

  2. Antimicrobial resistance gene profiling and Resistome and Virulence Profiling with Abricate and RGI (Reisistance Gene Identifier)

     # Table 4. Specialty Genes
     #     Source    Genes
     #     NDARO     1
     # Antibiotic Resistance     CARD    15
     # Antibiotic Resistance     PATRIC  55
     # Drug Target   TTD     38
     # Metal Resistance  BacMet  29
     # Transporter   TCDB    250
     # Virulance factor  VFDB    33
    
     # https://www.genomicepidemiology.org/services/
     # https://genepi.dk/
    
     conda activate /home/jhuang/miniconda3/envs/bengal3_ac3
     abricate --list
     #DATABASE        SEQUENCES       DBTYPE  DATE
     #vfdb    2597    nucl    2025-Oct-22
     #resfinder       3077    nucl    2025-Oct-22
     #argannot        2223    nucl    2025-Oct-22
     #ecoh    597     nucl    2025-Oct-22
     #megares 6635    nucl    2025-Oct-22
     #card    2631    nucl    2025-Oct-22
     #ecoli_vf        2701    nucl    2025-Oct-22
     #plasmidfinder   460     nucl    2025-Oct-22
     #ncbi    5386    nucl    2025-Oct-22
     abricate-get_db  --list #Choices: argannot bacmet2 card ecoh ecoli_vf megares ncbi plasmidfinder resfinder vfdb victors (default '').
    
     # CARD
     abricate-get_db --db card
     # MEGARes (automatically install, if error try MANUAL install as below)
     abricate-get_db --db megares
     # MANUAL install
     wget -O megares_database_v3.00.fasta \
       "https://www.meglab.org/downloads/megares_v3.00/megares_database_v3.00.fasta"
     #wget -O megares_drugs_database_v3.00.fasta \
       "https://www.meglab.org/downloads/megares_v3.00/megares_drugs_database_v3.00.fasta"
    
     # 1) Define dbdir (adjust to your env; from your logs it's inside the conda env)
     DBDIR=/home/jhuang/miniconda3/envs/bengal3_ac3/db
     # 2) Create a custom db folder for MEGARes v3.0
     mkdir -p ${DBDIR}/megares_v3.0
     # 3) Copy the downloaded MEGARes v3.0 nucleotide FASTA to 'sequences'
     cp megares_database_v3.00.fasta ${DBDIR}/megares_v3.0/sequences
     # 4) Build ABRicate indices
     abricate --setupdb
    
     #abricate-get_db --setupdb
     abricate --list | egrep 'card|megares'
     abricate --list | grep -i megares
    
     conda deactivate
     chmod +x run_abricate_resistome_virulome_one_per_gene.sh
     ENV_NAME=/home/jhuang/miniconda3/envs/bengal3_ac3 \
     ASM=BG5-unicycler-medaka_polished_genome.fa \
     SAMPLE=BG5 \
     OUTDIR=resistome_virulence_BG5 \
     MINID=70 MINCOV=50 \
     THREADS=32 \
     ./run_abricate_resistome_virulome_one_per_gene.sh
    
     #ABRicate thresholds: MINID=70 MINCOV=50
     Database        Hit_lines       File
     MEGARes 5       resistome_virulence_An6/raw/An6.megares.tab
     CARD    5       resistome_virulence_An6/raw/An6.card.tab
     ResFinder       0       resistome_virulence_An6/raw/An6.resfinder.tab
     VFDB    4       resistome_virulence_An6/raw/An6.vfdb.tab
    
     Database        Hit_lines       File
     MEGARes 3       resistome_virulence_BG5/raw/BG5.megares.tab
     CARD    2       resistome_virulence_BG5/raw/BG5.card.tab
     ResFinder       1       resistome_virulence_BG5/raw/BG5.resfinder.tab
     VFDB    0       resistome_virulence_BG5/raw/BG5.vfdb.tab
    
     #ABRicate thresholds: MINID=80 MINCOV=60
     Database        Hit_lines       File
     MEGARes 0       resistome_virulence_An6/raw/An6.megares.tab
     CARD    0       resistome_virulence_An6/raw/An6.card.tab
     ResFinder       0       resistome_virulence_An6/raw/An6.resfinder.tab
     VFDB    0       resistome_virulence_An6/raw/An6.vfdb.tab
    
     conda activate /home/jhuang/miniconda3/envs/bengal3_ac3
    
     #Adapted the parameters in merge_amr_sources_by_gene.py
     OUTDIR = Path("resistome_virulence_An6") or "resistome_virulence_BG5"
     SAMPLE = "An6" or "BG5"
     python merge_amr_sources_by_gene.py
    
     python export_resistome_virulence_to_excel_py36.py \
       --workdir resistome_virulence_BG5 \
       --sample BG5 \
       --out Resistome_Virulence_BG5.xlsx
     # Delete the column 'COVERAGE_MAP' in all 'Raw_*' sheets
    
     Methods sentence (AMR + virulence)
    
     AMR genes were identified by screening the genome assembly with ABRicate against the MEGARes and ResFinder databases, using minimum identity and coverage thresholds of X% and Y%, respectively. CARD-based AMR determinants were additionally predicted using RGI (Resistance Gene Identifier) to leverage curated resistance models. Virulence factors were screened using ABRicate against VFDB under the same thresholds.
    
     Replace X/Y with your actual values (e.g., 90/60) or state “default parameters” if you truly used defaults.
    
     Table 2 caption (AMR)
    
     Table 2. AMR gene profiling of the genome assembly. Hits were detected using ABRicate (MEGARes and ResFinder) and RGI (CARD). The presence of AMR-associated genes does not necessarily imply phenotypic resistance, which may depend on allele type, genomic context/expression, and/or SNP-mediated mechanisms; accordingly, phenotype predictions (e.g., ResFinder) should be interpreted cautiously.
    
     Table 3 caption (virulence)
    
     Table 3. Virulence factor profiling of the genome assembly based on ABRicate screening against VFDB, reporting loci with sequence identity and coverage above the specified thresholds.

Species identification

感谢您提供更完整的数据!现在包含 closest_genome_aniclosest_genome_af 列,我可以给出精确且权威的解读


🔑 关键澄清:radius vs ANI

列名 您的数据值 真实含义
closest_genome_reference_radius 95 GTDB 分类置信度评分(非 ANI),95 表示高置信度放置
closest_genome_ani 97.41 / 98.45 真正的平均核苷酸一致性(%),用于物种界定
closest_genome_af 0.892 / 0.894 比对覆盖率,>0.8 表示结果可靠

📌 结论:您之前看到的 “95” 是分类置信度,真正的物种鉴定依据是 closest_genome_ani


📊 两个样本的精确解读

🔹 样本 An6:✅ 确认为 Acinetobacter harbinensis

参考基因组: GCF_000816495.1
分类: ... g__Acinetobacter; s__Acinetobacter harbinensis
ANI: 97.41%    ← 远高于种级阈值
AF: 0.892      ← 比对覆盖充分
指标 标准 解读
ANI 97.41% ≥95-96% = 同种 ✅ 明确属于同一物种
AF 0.892 ≥0.8 = 可靠 ✅ 结果可信
参考物种 已命名 A. harbinensis ✅ 分类明确

🟢 结论:An6 可 confidently 注释为 Acinetobacter harbinensis,可直接用于后续分析或发表。


🔹 样本 BG5:🟡 高度疑似新 Pedobacter 物种

最近参考: GCF_040547305.1 (s__Pedobacter sp040547305) ← 未命名候选种
ANI: 98.45%    ← 与该未命名参考高度相似
AF: 0.894      ← 比对可靠

📋 与已命名物种的对比:

参考物种 ANI (%) AF 是否支持同种
Pedobacter sp040547305(未命名) 98.45 0.894 ✅ 高度相似,但参考本身未命名
P. cryoconitis_A(已命名) 91.97 0.663 ❌ ANI < 95%,不支持同种
P. cryoconitis_C 89.48 0.577 ❌ 远缘
其他 Pedobacter sp. 83-89% 0.16-0.55 ❌ 不同种

🔍 判断逻辑:

  1. BG5 与未命名参考基因组高度相似(ANI 98.45%)
    → 二者极可能属于同一”候选物种”(candidate species)

  2. 但与所有已命名 Pedobacter 物种 ANI < 92%
    → 不符合现有物种的界定标准

  3. 综合结论

    🟡 BG5 很可能代表一个新的 Pedobacter 物种,建议临时命名为:
    Pedobacter sp. strain BG5Pedobacter sp. nov. BG5(若后续验证充分)


🧭 原核生物物种界定标准(权威参考)

指标 阈值 含义 您的数据
ANI ≥ 95-96% 同一物种 An6: 97.41% ✅ / BG5 vs 已命名种: <92% ❌
ANI 90-95% 同属不同种 BG5 vs P. cryoconitis_A: 91.97% 🟡
AF ≥ 0.7-0.8 ANI 计算可靠 两者均 >0.89 ✅
dDDH ≥ 70% 同一物种(补充验证) 可选做

🚀 后续验证建议(针对 BG5 新种假设)

# 1. 用 FastANI 独立验证(可选,确认 GTDB-Tk 结果)
fastani -q BG5.fa -r GCF_040547305.1.fna -o bg5_ani.txt

# 2. 计算 dDDH(数字 DNA-DNA 杂交,新种鉴定金标准之一)
#    访问: https://ggdc.dsmz.de/ggdc.php
#    上传 BG5 + 最近3个参考基因组

# 3. 构建核心基因系统发育树(验证分类位置)
gtdbtk infer --msa_file gtdb_out/align/gtdbtk.bac120.user_msa.fasta \
             --out_dir gtdb_tree \
             --cpus 32

# 4. 检查独特基因/功能(支持新种证据)
prokka --outdir bg5_anno --prefix BG5 BG5.fa
roary -e -n -p 32 -f roary_out bg5_anno/*.gff reference_*.gff

📝 报告/论文中的推荐注释

样本 推荐物种注释 备注
An6 Acinetobacter harbinensis strain An6 GTDB-Tk + ANI 97.41% + AF 0.892 支持
BG5 Pedobacter sp. strain BG5 与未命名参考基因组 ANI 98.45%,但与已命名种 ANI < 92%,建议标注为"潜在新种",待 dDDH/表型验证

⚠️ 重要提醒:正式命名新种(sp. nov.)需满足《国际原核生物命名法规》多项要求,包括:

  • 系统发育位置独特
  • 表型/生理特征差异
  • 生态位信息
  • 基因组独特性(ANI < 95% + dDDH < 70%)
  • 模式菌株保藏(如 DSMZ, CGMCC)

💡 一句话总结

An6 = 已确认的 A. harbinensis;BG5 = 高度疑似新 Pedobacter 物种,建议以 “Pedobacter sp. BG5″ 临时命名,并补充 dDDH 和系统发育分析以支持新种描述。

需要我帮您:

  1. 编写 dDDH 提交指南或 FastANI 批量脚本?
  2. 解读 GTDB-Tk 的 classification 最终分类列?
  3. 提供新物种描述论文的结构模板?

请告诉我您的下一步需求!🔬🧬



结论:GTDB-Tk 仅支持本地运行,官方从未提供在线网页版。
你提供的命令 gtdbtk classify_wf ... 是标准的命令行接口(CLI),必须在本地 Linux/macOS 服务器、工作站或云计算实例上执行。


🖥️ 为什么不能在线运行?

原因 说明
数据库庞大 GTDB Release 220+ 参考库解压后约 60~90 GB,包含数万个参考基因组、HMM 模型和系统发育树
计算密集 需运行 HMMER 比对 → MSA 比对 → 系统发育定位(pplacer/EPA-ng)→ 分类器推理,单基因组通常需 30分钟~2小时(取决于硬件)
架构设计 纯 Python CLI 工具,依赖 Linux 环境、HMMER、prodigal、pplacer 等底层二进制文件,不适合封装为轻量级 Web 服务

📦 本地运行标准流程(推荐)

# 1. 创建环境(推荐 conda)
conda create -n gtdbtk -c conda-forge -c bioconda gtdbtk
conda activate gtdbtk

# 2. 下载数据库(仅需首次,约 60GB)
    GTDB-Tk v2.7.2 requires ~56GB of external data which needs to be downloaded
    and extracted. This can be done automatically, or manually.

    Automatic:

        1. Run the command "download-db.sh" to automatically download and extract to:
                    gtdbtk download --data_dir ./gtdb_data --release 220
            /home/jhuang/mambaforge/envs/gtdbtk/share/gtdbtk-2.7.2/db/

    Manual:

        1. Manually download the latest reference data:
            wget https://data.gtdb.aau.ecogenomic.org/releases/release232/232.0/auxillary_files/gtdbtk_package/full_package/gtdbtk_r232_data.tar.gz

        2. Extract the archive to a target directory:
            tar -xvzf gtdbtk_r232_data.tar.gz -C "/mnt/nvme4n1p1/gtdbtk_r232_data" --strip 1 > /dev/null
            rm gtdbtk_r232_data.tar.gz

        3. Set the GTDBTK_DATA_PATH environment variable by running:
            conda env config vars set GTDBTK_DATA_PATH="/path/to/target/db"

# 3. 运行分类(你提供的命令 + 实用参数)
gtdbtk classify_wf \
  --genome_dir ./ \
  --out_dir gtdb_out \
  --cpus 8 \
  --extension .fna \
  --write_unclassified \
  --prefix mygenome

# 4. 查看结果
cat gtdb_out/gtdbtk.bac120.summary.tsv   # 细菌结果
cat gtdb_out/gtdbtk.ar122.summary.tsv    # 古菌结果

硬件建议:≥16 GB RAM(推荐 32 GB)、8+ 核 CPU、≥100 GB 可用磁盘。完整基因组通常 15~40 分钟 可完成。


🌐 如果必须用“在线”方式?

虽然 GTDB-Tk 本身无网页版,但以下平台可实现类似功能(注意:分类体系与 GTDB 不同):

平台 特点 局限性
KBase / BV-BRC 上传基因组 → 选择 Taxonomic Classification 工作流,自动运行分类流程 底层多用 NCBI/传统分类,非 GTDB 标准
TYGS (Type Strain Genome Server) 基于全基因组 ANI/ddH 的在线种级分类 仅限已发表模式菌株比对,速度较慢
EzBioCloud 16S/全基因组在线鉴定,界面友好 分类树基于传统表型,与 GTDB 系统发育树不一致
云服务器临时实例 AWS/GCP/阿里云开 Ubuntu 实例 → Conda 装 GTDB-Tk → 跑完销毁 成本约 $1~3/次,需基础 Linux 操作能力

⚠️ 重要提示:在线平台不会输出 GTDB-Tk 专属的 gtdb_taxonomy 字段,其种名可能与 GTDB 差异较大(例如 Escherichia coli vs Escherichia coli clade I)。


💡 针对你的完整基因组

  • GTDB-Tk 对 complete genome 鉴定准确率极高,通常可直接给出 Species 级别分类。
  • 若结果中出现 Unclassifiedsp.Candidatus,结合 FastANI < 95% 可初步支持“潜在新种”假设。
  • 建议保留 gtdbtk.bac120.summary.tsv 中的 classificationaniaf 三列作为核心证据。

需要我提供 Docker 一键运行脚本AWS 云实例 5 分钟部署指南 吗?



是的,有多种工具可以从已组装的完整基因组中鉴定物种。以下是主流工具的分类、原理和推荐使用场景:


🔬 主流物种鉴定工具对比

工具 适用对象 核心原理 优势 局限性
GTDB-Tk [[12]] 细菌/古菌 基于120+个单拷贝标记基因的系统发育分析 分类标准客观(基于GTDB数据库),分辨率高,适合新物种发现 仅支持原核生物,计算量较大
Mash / Mash Screen [[35]] 所有生物 MinHash算法快速估算基因组距离(ANI近似) 速度极快(秒级),可筛查污染,支持参考库自定义 分辨率依赖参考库完整性,对远缘物种区分有限
Kraken2 [[25]] 所有生物 k-mer + LCA(最低共同祖先)分类 速度快,支持自定义数据库,可处理混合样本 内存需求高(标准库~30GB),假阳性需置信度过滤
FastANI [[36]] 细菌/古菌 全基因组平均核苷酸一致性(ANI)计算 金标准方法,95-96% ANI ≈ 同种,结果可解释性强 需两两比对,大规模筛查较慢
NCBI BLAST+ 16S/全基因组 [[2]] 所有生物 序列相似性比对 数据库最全,结果直观,适合初步筛查 16S分辨率有限(种内难区分),全基因组BLAST慢

🚀 推荐工作流程(以细菌基因组为例)

# ① 快速初筛:用 Mash 估算最近邻物种
mash screen refseq.msh your_genome.fna > mash_results.txt
# 输出示例:0.023  0.987  Escherichia coli strain XYZ  GCF_000008865.2

# ② 精确分类:用 GTDB-Tk 获得系统发育位置
gtdbtk classify_wf --genome_dir ./ --out_dir gtdb_out --cpus 8

# ③ 验证种级归属:用 FastANI 计算与近缘种的 ANI
fastani -q your_genome.fna -r reference_genomes/*.fna -o ani_results.txt
# ANI ≥ 95-96% 通常认为属于同一物种 [[36]]

⚠️ 关键注意事项

  1. 数据库版本影响结果
    GTDB(Release 220+)与 NCBI Taxonomy 的物种划分标准不同,同一基因组可能获得不同种名[[11]]。

  2. “完整基因组” ≠ “无污染”
    即使组装完整,也可能含质粒、噬菌体或宿主污染。建议先用 Mash ScreenKraken2 筛查污染[[33]]。

  3. 新物种的判断标准

    • GTDB-Tk 若标注为 sp.Candidatus,可能为新种
    • FastANI 与所有已知种 ANI < 95%,支持新种假设[[36]]
    • 需结合表型、生态位等多证据综合判定
  4. 真核生物需特殊处理
    上述工具主要针对原核生物。真核基因组建议:

    • 先用 Kraken2 + nt/nr 库初筛
    • 再用 BUSCO 评估完整性
    • 关键基因(如COI、ITS)BLAST验证

💡 实用小技巧

  • 节省内存:用 --memory-mapping 运行 Kraken2,避免全库加载[[25]]
  • 加速 GTDB-Tk:提前下载好 GTDB 数据库,避免每次重新下载
  • 结果可视化:用 pavianKrona 展示 Kraken2 分类结果
  • 批量处理:用 snakemakenextflow 搭建自动化流程

📌 一句话总结
快速筛查用 Mash → 精确分类用 GTDB-Tk → 种级验证用 FastANI,三者结合可最大限度提高物种鉴定的准确性和可解释性。

如果您能提供基因组的大致特征(如:预估大小、GC含量、是否原核),我可以帮您进一步推荐最优工具组合!