countmut 0.2.2__tar.gz → 0.2.3__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {countmut-0.2.2/countmut.egg-info → countmut-0.2.3}/PKG-INFO +1 -1
- {countmut-0.2.2 → countmut-0.2.3}/backend/countmut_core.c +25 -145
- {countmut-0.2.2 → countmut-0.2.3}/backend/countmut_core.h +4 -6
- {countmut-0.2.2 → countmut-0.2.3}/backend/countmut_core_main.c +6 -0
- {countmut-0.2.2 → countmut-0.2.3}/backend/countmut_expr.c +22 -1
- countmut-0.2.3/countmut/_core/countmut_core +0 -0
- {countmut-0.2.2 → countmut-0.2.3/countmut.egg-info}/PKG-INFO +1 -1
- {countmut-0.2.2 → countmut-0.2.3}/pyproject.toml +1 -1
- countmut-0.2.2/countmut/_core/countmut_core +0 -0
- {countmut-0.2.2 → countmut-0.2.3}/LICENSE +0 -0
- {countmut-0.2.2 → countmut-0.2.3}/MANIFEST.in +0 -0
- {countmut-0.2.2 → countmut-0.2.3}/README.md +0 -0
- {countmut-0.2.2 → countmut-0.2.3}/backend/Makefile +0 -0
- {countmut-0.2.2 → countmut-0.2.3}/backend/bedidx.c +0 -0
- {countmut-0.2.2 → countmut-0.2.3}/backend/bgzf.c +0 -0
- {countmut-0.2.2 → countmut-0.2.3}/backend/bgzf.h +0 -0
- {countmut-0.2.2 → countmut-0.2.3}/backend/countmut_expr.h +0 -0
- {countmut-0.2.2 → countmut-0.2.3}/backend/faidx.c +0 -0
- {countmut-0.2.2 → countmut-0.2.3}/backend/faidx.h +0 -0
- {countmut-0.2.2 → countmut-0.2.3}/backend/hts.c +0 -0
- {countmut-0.2.2 → countmut-0.2.3}/backend/hts.h +0 -0
- {countmut-0.2.2 → countmut-0.2.3}/backend/ketopt.h +0 -0
- {countmut-0.2.2 → countmut-0.2.3}/backend/khash.h +0 -0
- {countmut-0.2.2 → countmut-0.2.3}/backend/kseq.h +0 -0
- {countmut-0.2.2 → countmut-0.2.3}/backend/ksort.h +0 -0
- {countmut-0.2.2 → countmut-0.2.3}/backend/kstdint.h +0 -0
- {countmut-0.2.2 → countmut-0.2.3}/backend/kstring.h +0 -0
- {countmut-0.2.2 → countmut-0.2.3}/backend/razf.c +0 -0
- {countmut-0.2.2 → countmut-0.2.3}/backend/razf.h +0 -0
- {countmut-0.2.2 → countmut-0.2.3}/backend/sam.c +0 -0
- {countmut-0.2.2 → countmut-0.2.3}/backend/sam.h +0 -0
- {countmut-0.2.2 → countmut-0.2.3}/countmut/__init__.py +0 -0
- {countmut-0.2.2 → countmut-0.2.3}/countmut/backend.py +0 -0
- {countmut-0.2.2 → countmut-0.2.3}/countmut/bam_tags.py +0 -0
- {countmut-0.2.2 → countmut-0.2.3}/countmut/cli.py +0 -0
- {countmut-0.2.2 → countmut-0.2.3}/countmut/core.py +0 -0
- {countmut-0.2.2 → countmut-0.2.3}/countmut/model.py +0 -0
- {countmut-0.2.2 → countmut-0.2.3}/countmut/utils.py +0 -0
- {countmut-0.2.2 → countmut-0.2.3}/countmut.egg-info/SOURCES.txt +0 -0
- {countmut-0.2.2 → countmut-0.2.3}/countmut.egg-info/dependency_links.txt +0 -0
- {countmut-0.2.2 → countmut-0.2.3}/countmut.egg-info/entry_points.txt +0 -0
- {countmut-0.2.2 → countmut-0.2.3}/countmut.egg-info/requires.txt +0 -0
- {countmut-0.2.2 → countmut-0.2.3}/countmut.egg-info/top_level.txt +0 -0
- {countmut-0.2.2 → countmut-0.2.3}/setup.cfg +0 -0
- {countmut-0.2.2 → countmut-0.2.3}/tests/test_cli.py +0 -0
- {countmut-0.2.2 → countmut-0.2.3}/tests/test_core.py +0 -0
- {countmut-0.2.2 → countmut-0.2.3}/tests/test_correctness.py +0 -0
- {countmut-0.2.2 → countmut-0.2.3}/tests/test_router.py +0 -0
- {countmut-0.2.2 → countmut-0.2.3}/tests/test_unified.py +0 -0
- {countmut-0.2.2 → countmut-0.2.3}/tests/test_utils.py +0 -0
|
@@ -331,12 +331,7 @@ static void write_header(FILE *fp, const cm_config *cfg) {
|
|
|
331
331
|
}
|
|
332
332
|
return;
|
|
333
333
|
}
|
|
334
|
-
if (cfg->out ==
|
|
335
|
-
fputs("chrom\tpos\tstrand\tmotif\tu0\tu1\tu2\tm0\tm1\tm2", fp);
|
|
336
|
-
if (cfg->save_rest) fputs("\to0\to1\to2", fp);
|
|
337
|
-
fputs("\tmutation_rate", fp);
|
|
338
|
-
fputc('\n', fp);
|
|
339
|
-
} else if (cfg->out == CM_OUT_COMPOSITION) {
|
|
334
|
+
if (cfg->out == CM_OUT_COMPOSITION) {
|
|
340
335
|
if (cfg->strandless) fputs("chrom\tpos\tref\tdepth\ta\tc\tg\tt\tn", fp);
|
|
341
336
|
else fputs("chrom\tpos\tstrand\tref\tdepth\ta\tc\tg\tt\tn", fp);
|
|
342
337
|
if (cfg->count_indels) fputs("\tins\tdel\tref_skip\tfail", fp);
|
|
@@ -372,14 +367,21 @@ static void emit_site(worker_t *w, const cm_config *cfg, bam_hdr_t *hdr, FILE *f
|
|
|
372
367
|
w->motif_buf[mlen] = 0;
|
|
373
368
|
motif = w->motif_buf;
|
|
374
369
|
}
|
|
375
|
-
/*
|
|
370
|
+
/* No ref/mut targets in the template path (unified counter): the
|
|
376
371
|
* derived u/m/o fields stay off for template rows. */
|
|
377
|
-
int refi =
|
|
378
|
-
int muti = cfg->mut_base ? base_to_index((char)cfg->mut_base) : -1;
|
|
372
|
+
int refi = -1, muti = -1;
|
|
379
373
|
/* Per-strand rows: counts are this strand only, per category slot. */
|
|
380
374
|
for (int s = 0; s < 2; ++s) {
|
|
381
375
|
if (s == 0 && !emit_plus) continue;
|
|
382
376
|
if (s == 1 && !emit_minus) continue;
|
|
377
|
+
/* target_base: emit only the strand whose reference base (on that
|
|
378
|
+
* strand) equals the target. For m6A (target A) this keeps the
|
|
379
|
+
* '+' strand A-site (genomic ref A) and the '-' strand A-site
|
|
380
|
+
* (genomic ref T), dropping the spurious complement-strand rows. */
|
|
381
|
+
if (cfg->target_base >= 0) {
|
|
382
|
+
char sref = (s == 0) ? ref_ch : rc_nt(ref_ch);
|
|
383
|
+
if (base_to_index((char)sref) != cfg->target_base) continue;
|
|
384
|
+
}
|
|
383
385
|
int sdepth = site->ins[s] + site->del[s] + site->refskip[s] + site->fail[s];
|
|
384
386
|
for (int c = 0; c < CM_CAT_MAX; ++c)
|
|
385
387
|
for (int b = 0; b < 5; ++b) sdepth += site->cnt[s][c][b];
|
|
@@ -398,42 +400,7 @@ static void emit_site(worker_t *w, const cm_config *cfg, bam_hdr_t *hdr, FILE *f
|
|
|
398
400
|
}
|
|
399
401
|
return;
|
|
400
402
|
}
|
|
401
|
-
if (cfg->out ==
|
|
402
|
-
int refi = base_to_index((char)cfg->ref_base), muti = base_to_index((char)cfg->mut_base);
|
|
403
|
-
int mlen = cfg->pad * 2 + 1;
|
|
404
|
-
int motif_ready = 0; /* build the reference-forward window once */
|
|
405
|
-
for (int s = 0; s < 2; ++s) {
|
|
406
|
-
if (s == 0 && !emit_plus) continue;
|
|
407
|
-
if (s == 1 && !emit_minus) continue;
|
|
408
|
-
int u0 = site->cnt[s][0][refi], m0 = site->cnt[s][0][muti];
|
|
409
|
-
int u1 = site->cnt[s][1][refi], m1 = site->cnt[s][1][muti];
|
|
410
|
-
int u2 = site->cnt[s][2][refi], m2 = site->cnt[s][2][muti];
|
|
411
|
-
int ut = u0 + u1 + u2, mt = m0 + m1 + m2; /* total unconverted / converted */
|
|
412
|
-
int o0 = site->cnt[s][0][0]+site->cnt[s][0][1]+site->cnt[s][0][2]+site->cnt[s][0][3]+site->cnt[s][0][4]-u0-m0;
|
|
413
|
-
int o1 = site->cnt[s][1][0]+site->cnt[s][1][1]+site->cnt[s][1][2]+site->cnt[s][1][3]+site->cnt[s][1][4]-u1-m1;
|
|
414
|
-
int o2 = site->cnt[s][2][0]+site->cnt[s][2][1]+site->cnt[s][2][2]+site->cnt[s][2][3]+site->cnt[s][2][4]-u2-m2;
|
|
415
|
-
if (u1 + m1 + u2 + m2 <= 0) continue;
|
|
416
|
-
if (!motif_ready) {
|
|
417
|
-
/* Reference-forward window for BOTH strands (bases are counted
|
|
418
|
-
* reference-forward), built at most once per site. */
|
|
419
|
-
for (int k2 = (int)pos - cfg->pad; k2 < (int)pos + cfg->pad + 1; ++k2) {
|
|
420
|
-
w->motif_buf[k2 - ((int)pos - cfg->pad)] =
|
|
421
|
-
(k2 < 0 || k2 >= w->chr_len) ? 'N'
|
|
422
|
-
: (char)toupper((unsigned char)w->chr_seq[k2]);
|
|
423
|
-
}
|
|
424
|
-
w->motif_buf[mlen] = 0;
|
|
425
|
-
motif_ready = 1;
|
|
426
|
-
}
|
|
427
|
-
fprintf(fp, "%s\t%d\t%c\t%s\t%d\t%d\t%d\t%d\t%d\t%d",
|
|
428
|
-
hdr->target_name[tid], (int)pos + 1, s ? '-' : '+', w->motif_buf,
|
|
429
|
-
u0, u1, u2, m0, m1, m2);
|
|
430
|
-
if (cfg->save_rest) fprintf(fp, "\t%d\t%d\t%d", o0, o1, o2);
|
|
431
|
-
fprintf(fp, "\t%.4f",
|
|
432
|
-
(ut + mt) ? (double)mt / (double)(ut + mt)
|
|
433
|
-
: strtod("nan", (char **)NULL));
|
|
434
|
-
fputc('\n', fp);
|
|
435
|
-
}
|
|
436
|
-
} else if (cfg->out == CM_OUT_COMPOSITION) {
|
|
403
|
+
if (cfg->out == CM_OUT_COMPOSITION) {
|
|
437
404
|
if (!cfg->strandless) {
|
|
438
405
|
for (int s = 0; s < 2; ++s) {
|
|
439
406
|
if (s == 0 && !emit_plus) continue;
|
|
@@ -521,8 +488,7 @@ static int expr_pile_apply(cm_expr *x, const cm_config *cfg, worker_t *w,
|
|
|
521
488
|
w->motif_buf[mlen] = 0;
|
|
522
489
|
motif = w->motif_buf;
|
|
523
490
|
}
|
|
524
|
-
int refi =
|
|
525
|
-
int muti = cfg->mut_base ? base_to_index((char)cfg->mut_base) : -1;
|
|
491
|
+
int refi = -1, muti = -1; /* no ref/mut targets in the unified counter */
|
|
526
492
|
return cm_expr_pile(x, chrom, pos, ref_ch, motif, cnt, ins, del, rs, fl,
|
|
527
493
|
refi, muti);
|
|
528
494
|
}
|
|
@@ -565,9 +531,6 @@ static void count_interval(worker_t *w, const cm_config *cfg, bam_hdr_t *hdr, FI
|
|
|
565
531
|
if (n == 0) continue;
|
|
566
532
|
const char ref_ch = w->chr_seq[pos]; /* pre-uppercased */
|
|
567
533
|
|
|
568
|
-
if (cfg->out == CM_OUT_CONVERSION && cfg->ref_base && ref_ch != cfg->ref_base)
|
|
569
|
-
continue;
|
|
570
|
-
|
|
571
534
|
if (n > w->sel_cap) {
|
|
572
535
|
w->sel = (int *)realloc(w->sel, n * sizeof(int));
|
|
573
536
|
w->mapq_a = (int *)realloc(w->mapq_a, n * sizeof(int));
|
|
@@ -634,16 +597,11 @@ static void count_interval(worker_t *w, const cm_config *cfg, bam_hdr_t *hdr, FI
|
|
|
634
597
|
* CIGAR order (left->right); complement the base into the
|
|
635
598
|
* reference frame (parity with countmut 0.0.x + pysam pairs). */
|
|
636
599
|
if (s == 1 && base_i < 4) base_i = 3 - base_i;
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
* the selection loop for every kept candidate. */
|
|
643
|
-
int cat = w->g_a[i];
|
|
644
|
-
if (cat < 0) cat = 0; /* defensive */
|
|
645
|
-
site.cnt[s][cat][base_i]++;
|
|
646
|
-
}
|
|
600
|
+
/* router-assigned category slot (0..CM_CAT_MAX-1); g_a set in
|
|
601
|
+
* the selection loop for every kept candidate. */
|
|
602
|
+
int cat = w->g_a[i];
|
|
603
|
+
if (cat < 0) cat = 0; /* defensive */
|
|
604
|
+
site.cnt[s][cat][base_i]++;
|
|
647
605
|
}
|
|
648
606
|
|
|
649
607
|
/* ---------- emit ---------- */
|
|
@@ -753,40 +711,6 @@ static int cmp_site_ord(const void *a, const void *b) {
|
|
|
753
711
|
* jumps straight to the (sorted) target positions. Both funnel into
|
|
754
712
|
* rw_add_base(), so dedup/quality decisions are byte-identical. */
|
|
755
713
|
|
|
756
|
-
static uint32_t cigar_ref_len(const bam1_t *b) {
|
|
757
|
-
const uint32_t *cig = bam_get_cigar(b);
|
|
758
|
-
uint32_t r = 0;
|
|
759
|
-
for (int i = 0; i < b->core.n_cigar; ++i) {
|
|
760
|
-
int op = (int)bam_cigar_op_p(&cig[i]);
|
|
761
|
-
if (op == 0 || op == 2 || op == 3 || op == 7 || op == 8)
|
|
762
|
-
r += (uint32_t)bam_cigar_oplen_p(&cig[i]);
|
|
763
|
-
}
|
|
764
|
-
return r;
|
|
765
|
-
}
|
|
766
|
-
static int cigar_has_indels(const bam1_t *b) {
|
|
767
|
-
const uint32_t *cig = bam_get_cigar(b);
|
|
768
|
-
for (int i = 0; i < b->core.n_cigar; ++i) {
|
|
769
|
-
int op = (int)bam_cigar_op_p(&cig[i]);
|
|
770
|
-
if (op == 1 || op == 2 || op == 3) return 1;
|
|
771
|
-
}
|
|
772
|
-
return 0;
|
|
773
|
-
}
|
|
774
|
-
static uint32_t cigar_leading_softclips(const bam1_t *b) {
|
|
775
|
-
const uint32_t *cig = bam_get_cigar(b);
|
|
776
|
-
uint32_t sc = 0;
|
|
777
|
-
for (int i = 0; i < b->core.n_cigar; ++i) {
|
|
778
|
-
int op = (int)bam_cigar_op_p(&cig[i]);
|
|
779
|
-
if (op == 4) sc += (uint32_t)bam_cigar_oplen_p(&cig[i]);
|
|
780
|
-
else break; /* soft-clips only at the 5' end before the first M */
|
|
781
|
-
}
|
|
782
|
-
return sc;
|
|
783
|
-
}
|
|
784
|
-
static int tgt_lower_bound(const int *a, int n, int v) {
|
|
785
|
-
int lo = 0, hi = n;
|
|
786
|
-
while (lo < hi) { int mid = (lo + hi) >> 1; if (a[mid] < v) lo = mid + 1; else hi = mid; }
|
|
787
|
-
return lo;
|
|
788
|
-
}
|
|
789
|
-
|
|
790
714
|
/* Add one matched base to the (pos,qname) dedup table. Applies the mutation
|
|
791
715
|
* target gate (skipped when `already_target`), trim (is_internal), the -e
|
|
792
716
|
* filter and the (mapq,read1,qual) preference. When `direct` is set the base
|
|
@@ -801,9 +725,6 @@ static rw_w *rw_add_base(worker_t *w, const cm_config *cfg, bam_hdr_t *hdr, int
|
|
|
801
725
|
khash_t(posq) *h, rw_w *wins, int *wins_cap, int *wins_n) {
|
|
802
726
|
uint32_t qlen = b->core.l_qseq;
|
|
803
727
|
if (qpos >= qlen) return wins;
|
|
804
|
-
if (!already_target && cfg->out == CM_OUT_CONVERSION && cfg->ref_base) {
|
|
805
|
-
if (ref_pos >= w->chr_len || w->chr_seq[ref_pos] != cfg->ref_base) return wins;
|
|
806
|
-
}
|
|
807
728
|
if (s == 0) {
|
|
808
729
|
if ((int)qpos < cfg->trim_fragment_start || (int)qlen - (int)qpos <= cfg->trim_fragment_end) return wins;
|
|
809
730
|
} else {
|
|
@@ -831,8 +752,7 @@ static rw_w *rw_add_base(worker_t *w, const cm_config *cfg, bam_hdr_t *hdr, int
|
|
|
831
752
|
if (s == 1 && base_i < 4) base_i = 3 - base_i;
|
|
832
753
|
int qual = (int)bam_get_qual(b)[qpos];
|
|
833
754
|
if (direct) {
|
|
834
|
-
int cat =
|
|
835
|
-
? ((qual >= cfg->min_baseq) ? 2 : 0) : rslot;
|
|
755
|
+
int cat = rslot;
|
|
836
756
|
sm_get(sm, ref_pos)->cnt[s][cat][base_i]++;
|
|
837
757
|
return wins;
|
|
838
758
|
}
|
|
@@ -868,15 +788,6 @@ static void count_interval_readwalk(worker_t *w, const cm_config *cfg, bam_hdr_t
|
|
|
868
788
|
|
|
869
789
|
if (w->last_tid != tid) load_chr_seq(w, hdr, tid);
|
|
870
790
|
|
|
871
|
-
/* sorted target positions (mutation mode) for the indel-free fast path */
|
|
872
|
-
int *tgt = NULL; int tgt_n = 0;
|
|
873
|
-
if (cfg->out == CM_OUT_CONVERSION && cfg->ref_base && end > beg) {
|
|
874
|
-
tgt = (int *)malloc((size_t)(end - beg) * sizeof(int));
|
|
875
|
-
for (int p = beg; p < end && p < w->chr_len; ++p)
|
|
876
|
-
if (w->chr_seq[p] == (char)cfg->ref_base)
|
|
877
|
-
tgt[tgt_n++] = p;
|
|
878
|
-
}
|
|
879
|
-
|
|
880
791
|
khash_t(posq) *h = kh_init(posq);
|
|
881
792
|
khash_t(qn2id) *qnids = kh_init(qn2id);
|
|
882
793
|
int qname_n = 0;
|
|
@@ -899,14 +810,8 @@ static void count_interval_readwalk(worker_t *w, const cm_config *cfg, bam_hdr_t
|
|
|
899
810
|
if (rcur < end && rcur + len > beg) {
|
|
900
811
|
int64_t lo = rcur > beg ? rcur : beg;
|
|
901
812
|
int64_t hi = rcur + len < end ? rcur + len : end;
|
|
902
|
-
|
|
903
|
-
|
|
904
|
-
if ((int)p < w->chr_len && w->chr_seq[p] == cfg->ref_base)
|
|
905
|
-
sm_get(&sm, p)->fail[s]++;
|
|
906
|
-
} else {
|
|
907
|
-
for (int64_t p = lo; p < hi; ++p)
|
|
908
|
-
sm_get(&sm, p)->fail[s]++;
|
|
909
|
-
}
|
|
813
|
+
for (int64_t p = lo; p < hi; ++p)
|
|
814
|
+
sm_get(&sm, p)->fail[s]++;
|
|
910
815
|
}
|
|
911
816
|
rcur += len;
|
|
912
817
|
}
|
|
@@ -969,22 +874,7 @@ static void count_interval_readwalk(worker_t *w, const cm_config *cfg, bam_hdr_t
|
|
|
969
874
|
/* direct(ref_pos,qpos) = counts straight into the site (no dedup hash) */
|
|
970
875
|
#define RW_DIRECT(_qpos) ((ovl == 0) || (ovl == 1 && ((int)(_qpos) < olo || (int)(_qpos) >= ohi)))
|
|
971
876
|
|
|
972
|
-
|
|
973
|
-
/* fast path: indel-free read -> jump straight to target positions */
|
|
974
|
-
int64_t r_start = b->core.pos;
|
|
975
|
-
uint32_t sc = cigar_leading_softclips(b);
|
|
976
|
-
int64_t r_end = r_start + (int64_t)cigar_ref_len(b);
|
|
977
|
-
int64_t lo = r_start > beg ? r_start : beg;
|
|
978
|
-
int64_t hi = r_end < end ? r_end : end;
|
|
979
|
-
for (int ti = tgt_lower_bound(tgt, tgt_n, (int)lo); ti < tgt_n; ++ti) {
|
|
980
|
-
int64_t ref_pos = tgt[ti];
|
|
981
|
-
if (ref_pos >= hi) break;
|
|
982
|
-
uint32_t qpos = (uint32_t)((ref_pos - r_start) + sc);
|
|
983
|
-
wins = rw_add_base(w, cfg, hdr, tid, b, s, ref_pos, qpos,
|
|
984
|
-
qid, 1, RW_DIRECT(qpos), &sm,
|
|
985
|
-
h, wins, &wins_cap, &wins_n);
|
|
986
|
-
}
|
|
987
|
-
} else {
|
|
877
|
+
{
|
|
988
878
|
uint32_t qcur = 0;
|
|
989
879
|
int64_t rcur = b->core.pos;
|
|
990
880
|
for (int i = 0; i < b->core.n_cigar; ++i) {
|
|
@@ -1008,15 +898,8 @@ static void count_interval_readwalk(worker_t *w, const cm_config *cfg, bam_hdr_t
|
|
|
1008
898
|
if (rcur < end && rcur + len > beg) {
|
|
1009
899
|
int64_t lo2 = rcur > beg ? rcur : beg;
|
|
1010
900
|
int64_t hi2 = rcur + len < end ? rcur + len : end;
|
|
1011
|
-
|
|
1012
|
-
|
|
1013
|
-
if ((int)p < w->chr_len && w->chr_seq[p] == cfg->ref_base) {
|
|
1014
|
-
if (is_del) sm_get(&sm, p)->del[s]++; else sm_get(&sm, p)->refskip[s]++;
|
|
1015
|
-
}
|
|
1016
|
-
} else {
|
|
1017
|
-
for (int64_t p = lo2; p < hi2; ++p)
|
|
1018
|
-
if (is_del) sm_get(&sm, p)->del[s]++; else sm_get(&sm, p)->refskip[s]++;
|
|
1019
|
-
}
|
|
901
|
+
for (int64_t p = lo2; p < hi2; ++p)
|
|
902
|
+
if (is_del) sm_get(&sm, p)->del[s]++; else sm_get(&sm, p)->refskip[s]++;
|
|
1020
903
|
}
|
|
1021
904
|
rcur += len;
|
|
1022
905
|
break;
|
|
@@ -1032,8 +915,7 @@ static void count_interval_readwalk(worker_t *w, const cm_config *cfg, bam_hdr_t
|
|
|
1032
915
|
if (!kh_exist(h, k)) continue;
|
|
1033
916
|
int64_t pos = kh_key(h, k).pos;
|
|
1034
917
|
const rw_w *win = &wins[kh_val(h, k)];
|
|
1035
|
-
int cat =
|
|
1036
|
-
? ((win->qual >= cfg->min_baseq) ? 2 : 0) : win->slot;
|
|
918
|
+
int cat = win->slot;
|
|
1037
919
|
site_t *st = sm_get(&sm, pos);
|
|
1038
920
|
st->cnt[win->strand][cat][win->base]++;
|
|
1039
921
|
}
|
|
@@ -1048,7 +930,6 @@ static void count_interval_readwalk(worker_t *w, const cm_config *cfg, bam_hdr_t
|
|
|
1048
930
|
int64_t pos = ord[i].pos;
|
|
1049
931
|
if (pos < 0 || pos >= w->chr_len) continue;
|
|
1050
932
|
char ref_ch = w->chr_seq[pos]; /* pre-uppercased */
|
|
1051
|
-
if (cfg->out == CM_OUT_CONVERSION && cfg->ref_base && ref_ch != cfg->ref_base) continue;
|
|
1052
933
|
if (w->inc_bed && !bed_overlap(w->inc_bed, hdr->target_name[tid], (int)pos, (int)pos + 1)) continue;
|
|
1053
934
|
if (w->exc_bed && bed_overlap(w->exc_bed, hdr->target_name[tid], (int)pos, (int)pos + 1)) continue;
|
|
1054
935
|
/* -p site filter */
|
|
@@ -1066,7 +947,6 @@ static void count_interval_readwalk(worker_t *w, const cm_config *cfg, bam_hdr_t
|
|
|
1066
947
|
kh_destroy(posq, h);
|
|
1067
948
|
free(wins);
|
|
1068
949
|
free(ord);
|
|
1069
|
-
free(tgt);
|
|
1070
950
|
sm_free(&sm);
|
|
1071
951
|
bam_destroy1(b);
|
|
1072
952
|
if (aux.itr) bam_itr_destroy(aux.itr);
|
|
@@ -42,7 +42,6 @@ typedef struct {
|
|
|
42
42
|
#define CM_STRAND_FORWARD 1
|
|
43
43
|
#define CM_STRAND_REVERSE 2
|
|
44
44
|
|
|
45
|
-
#define CM_OUT_CONVERSION 0 /* legacy/unused: u/m conversion view (dead) */
|
|
46
45
|
#define CM_OUT_COMPOSITION 1 /* output format: per-base composition (default) */
|
|
47
46
|
#define CM_OUT_ALLELE 2 /* output format: ref/alt / VCF */
|
|
48
47
|
|
|
@@ -50,12 +49,11 @@ typedef struct {
|
|
|
50
49
|
int32_t out; /* CM_OUT_* (output format) */
|
|
51
50
|
int32_t engine; /* CM_ENGINE_* */
|
|
52
51
|
int32_t vcf; /* allele output: emit VCF */
|
|
53
|
-
int
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
52
|
+
int target_base; /* strand-aware reference base to emit (-1 = no filter).
|
|
53
|
+
When set, only the strand whose reference base
|
|
54
|
+
equals this base is emitted (m6A A-site on either
|
|
55
|
+
strand). */
|
|
57
56
|
int pad; /* {motif} reference window: 2*pad+1 bases (--motif-pad) */
|
|
58
|
-
int save_rest; /* legacy/unused */
|
|
59
57
|
const char *output_expr; /* -o output-row template (overrides the built-in format) */
|
|
60
58
|
const char *fmt_header; /* header line for a custom output template ("" = none) */
|
|
61
59
|
int min_mapq;
|
|
@@ -168,6 +168,7 @@ int main(int argc, char **argv) {
|
|
|
168
168
|
{"pile-expr", required_argument, 0, 2003},
|
|
169
169
|
{"output-expr", required_argument, 0, 2004},
|
|
170
170
|
{"fmt-header", required_argument, 0, 2005},
|
|
171
|
+
{"target-base", required_argument, 0, 2006},
|
|
171
172
|
{"verbose", no_argument, 0, 'V'},
|
|
172
173
|
{"help", no_argument, 0, 'h'},
|
|
173
174
|
{0, 0, 0, 0},
|
|
@@ -180,6 +181,11 @@ int main(int argc, char **argv) {
|
|
|
180
181
|
case 2003: cfg.pile_expr = optarg; break;
|
|
181
182
|
case 2004: cfg.output_expr = optarg; break;
|
|
182
183
|
case 2005: cfg.fmt_header = optarg; break;
|
|
184
|
+
case 2006: {
|
|
185
|
+
char tb = (char)toupper((unsigned char)optarg[0]);
|
|
186
|
+
cfg.target_base = (tb == 'A') ? 0 : (tb == 'C') ? 1 : (tb == 'G') ? 2 : (tb == 'T') ? 3 : -1;
|
|
187
|
+
break;
|
|
188
|
+
}
|
|
183
189
|
case 'V': cfg.verbose = 1; break;
|
|
184
190
|
case 'f': fa = optarg; break;
|
|
185
191
|
case 'o': out = optarg; break;
|
|
@@ -473,7 +473,7 @@ static int compile_chunk(lua_State *L, const char *expr, const char *what,
|
|
|
473
473
|
if (need_qpos) *need_qpos = has_token(src, "qpos") || has_token(src, "QPOS");
|
|
474
474
|
if (need_bq) *need_bq = has_token(src, "bq") || has_token(src, "BQ") || has_token(src, "baseq");
|
|
475
475
|
if (need_base) *need_base = has_token(src, "base");
|
|
476
|
-
if (need_ref) *need_ref = has_token(src, "ref");
|
|
476
|
+
if (need_ref) *need_ref = has_token(src, "ref") || has_token(src, "base") || has_token(src, "BASE");
|
|
477
477
|
if (need_dist) *need_dist = has_token(src, "dist5") || has_token(src, "dist3")
|
|
478
478
|
|| has_token(src, "DIST5") || has_token(src, "DIST3")
|
|
479
479
|
|| has_token(src, "distance_from_5prime")
|
|
@@ -897,11 +897,32 @@ static void pile_set_all(lua_State *L, cm_expr *x, const char *chrom, int64_t po
|
|
|
897
897
|
char refstr[2] = { ref_ch ? ref_ch : 'N', 0 };
|
|
898
898
|
const char *mot = motif ? motif : "";
|
|
899
899
|
|
|
900
|
+
/* Strand-aware m6A reference base. For the site-level (-p) namespace the
|
|
901
|
+
* site is a potential A-site if the genomic reference is A (the '+'
|
|
902
|
+
* strand A-site) or T (the '-' strand A-site). For a per-strand row
|
|
903
|
+
* (strand_s == 0/1) `base` is the reference base ON THAT STRAND, so a
|
|
904
|
+
* filter `base == 'A'` keeps A-sites on both strands automatically. */
|
|
905
|
+
char basestr[2] = { 'N', 0 };
|
|
906
|
+
if (strand_s == 0) { /* '+' strand: reference base = genomic */
|
|
907
|
+
basestr[0] = ref_ch ? ref_ch : 'N';
|
|
908
|
+
} else if (strand_s == 1) { /* '-' strand: reference base = complement */
|
|
909
|
+
static const char comp[256] = { ['A']='T', ['T']='A', ['C']='G', ['G']='C' };
|
|
910
|
+
basestr[0] = ref_ch ? comp[(unsigned char)ref_ch] : 'N';
|
|
911
|
+
if (basestr[0] == 0) basestr[0] = 'N';
|
|
912
|
+
} else { /* site-level: A-site on either strand */
|
|
913
|
+
if (ref_ch == 'A' || ref_ch == 'T')
|
|
914
|
+
basestr[0] = 'A';
|
|
915
|
+
else if (ref_ch)
|
|
916
|
+
basestr[0] = ref_ch;
|
|
917
|
+
}
|
|
918
|
+
|
|
900
919
|
p_int(x, "pos", (lua_Integer)pos);
|
|
901
920
|
p_int(x, "POS", (lua_Integer)pos);
|
|
902
921
|
p_str(x, "ref", refstr);
|
|
903
922
|
p_str(x, "ref_base", refstr);
|
|
904
923
|
p_str(x, "REF", refstr);
|
|
924
|
+
p_str(x, "base", basestr);
|
|
925
|
+
p_str(x, "BASE", basestr);
|
|
905
926
|
p_int(x, "depth", depth);
|
|
906
927
|
p_int(x, "DEPTH", depth);
|
|
907
928
|
p_str(x, "chrom", chrom ? chrom : "");
|
|
Binary file
|
|
Binary file
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|