From 4e19fbdb8afb6f0451ddc040f1575cbe5e00fc76 Mon Sep 17 00:00:00 2001 From: Matiq Date: Sun, 6 Sep 2026 18:47:00 +0300 Subject: [PATCH] replace TSV with CSV for variant outputs --- README.md | 5 +++-- ffpe_damage_v2.py | 21 +++++++++++---------- 2 files changed, 14 insertions(+), 12 deletions(-) diff --git a/README.md b/README.md index d1f4a13..2af70a3 100644 --- a/README.md +++ b/README.md @@ -72,14 +72,15 @@ python3 -m venv --system-site-packages .venv | `strand_damage_profile_3prime.csv` | то же по 3′-концу | | `end_enrichment.csv` | C>T/G>A % в первых/последних 1,3,5,10,20 основаниях, по R1/R2 | | `candidate_CtoT.bed`, `candidate_GtoA.bed` | позиции для IGV; имя = `ref>alt;depth;alt;VAF` | -| `candidate_variants.tsv` | контекст каждой позиции: VAF, средняя позиция в read, strand bias, BQ, раскладка R1/R2 | +| `candidate_variants.csv` | контекст каждой позиции: VAF, средняя позиция в read, strand bias, BQ, раскладка R1/R2 | +| `clean_variants.csv` / `ffpe_suspect_variants.csv` | разделение на чистые и подозрительные | | `CtoT_R1.png` … `GtoA_R2_3prime.png` | графики частоты по позиции в read (5′ и 3′) | ### Как читать результат - **Классическая FFPE-сигнатура**: пик `C>T` у 5′-конца R1 и `G>A` у 3′-конца R2 — две цепи одного и того же дезаминирования цитозина. Проверяйте профили R1/R2 и по strand. - Если C>T/G>A повышены равномерно по всей длине read (без пика у концов) — это не классическое end-associated повреждение, а другой артефакт/ошибки. -- **Отличить настоящий вариант от дезаминирования** (`candidate_variants.tsv`): настоящий вариант имеет ожидаемый VAF, распределён по read (средняя позиция ~ середина), встречается на обеих цепях (strand bias не значим) и не привязан к концам. Дезаминирование концентрируется у концов read и на одной цепи. +- **Отличить настоящий вариант от дезаминирования** (`candidate_variants.csv`): настоящий вариант имеет ожидаемый VAF, распределён по read (средняя позиция ~ середина), встречается на обеих цепях (strand bias не значим) и не привязан к концам. Дезаминирование концентрируется у концов read и на одной цепи. ## 2. Классификация относительно контролей diff --git a/ffpe_damage_v2.py b/ffpe_damage_v2.py index 11cf99d..61415b9 100644 --- a/ffpe_damage_v2.py +++ b/ffpe_damage_v2.py @@ -33,7 +33,8 @@ Outputs (in --outdir): strand_damage_profile_3prime.csv (3' profile) end_enrichment.csv candidate_CtoT.bed / candidate_GtoA.bed (IGV tracks) - candidate_variants.tsv (per-position context) + candidate_variants.csv (per-position context) + clean_variants.csv / ffpe_suspect_variants.csv CtoT_R1.png CtoT_R2.png GtoA_R1.png GtoA_R2.png (5' plots) CtoT_R1_3prime.png ... GtoA_R2_3prime.png (3' plots) """ @@ -616,15 +617,15 @@ def write_beds_and_variants(d, args): df["is_ffpe_suspect"] = [x[0] for x in flags] df["ffpe_reason"] = [x[1] for x in flags] - df.to_csv(os.path.join(args.outdir, "candidate_variants.tsv"), - index=False, sep="\t") + df.to_csv(os.path.join(args.outdir, "candidate_variants.csv"), + index=False) clean = df[~df["is_ffpe_suspect"]] damaged = df[df["is_ffpe_suspect"]] - clean.to_csv(os.path.join(args.outdir, "clean_variants.tsv"), - index=False, sep="\t") - damaged.to_csv(os.path.join(args.outdir, "ffpe_suspect_variants.tsv"), - index=False, sep="\t") + clean.to_csv(os.path.join(args.outdir, "clean_variants.csv"), + index=False) + damaged.to_csv(os.path.join(args.outdir, "ffpe_suspect_variants.csv"), + index=False) for name, subset, fname in [ ("clean", clean, "candidate_CtoT_clean.bed"), @@ -647,8 +648,8 @@ def write_beds_and_variants(d, args): f.writelines(clean_ga) return df else: - open(os.path.join(args.outdir, "clean_variants.tsv"), "w").close() - open(os.path.join(args.outdir, "ffpe_suspect_variants.tsv"), "w").close() + open(os.path.join(args.outdir, "clean_variants.csv"), "w").close() + open(os.path.join(args.outdir, "ffpe_suspect_variants.csv"), "w").close() return pd.DataFrame() @@ -886,7 +887,7 @@ def main(): n_flag = int(flagged_df["is_ffpe_suspect"].sum()) n_clean = len(flagged_df) - n_flag print(f"variants flagged FFPE : {n_flag} / {len(flagged_df)} " - f"-> ffpe_suspect_variants.tsv / clean_variants.tsv") + f"-> ffpe_suspect_variants.csv / clean_variants.csv") if __name__ == "__main__":