Skip to content

[OC-832] Fix dropped sample/mapping rows on merge; tighten mergesqlite checks - #420

Open
cvaske wants to merge 2 commits into
masterfrom
cv/OC-832-mergesqlite-bug
Open

[OC-832] Fix dropped sample/mapping rows on merge; tighten mergesqlite checks#420
cvaske wants to merge 2 commits into
masterfrom
cv/OC-832-mergesqlite-bug

Conversation

@cvaske

@cvaske cvaske commented Aug 19, 2026

Copy link
Copy Markdown
Contributor

Overview

Improve mergesqlite such that we can use it as part of parallelization of OpenCravat (e.g. in nextflow pipelines). This fixes bugs in the current variant/sample mapping, performs additional sample name checks, and provides ways to map sample names to the FILENAME__SAMPLE format that multi-file oc run commands use.

Changes

  • fix mergesqlite() dropping sample and mapping rows for any variant that already exists in the merged output (uid_dic was never populated for the skip-duplicate-variant case, so later sample/mapping inserts for that uid were silently skipped)
  • extend the pre-merge consistency check beyond variant/gene_header column names to also cover sample_header/mapping_header columns and (name, version) pairs for variant_annotator/gene_annotator across all input dbs; error out naming the mismatch before doing any merge work
  • recompute "Number of unique input variants" and "Result modified at" in the merged db's info table instead of leaving db 1's stale values
  • detect colliding sample_id values across input dbs and error out by default
  • add an opt-in path:label argument suffix to rename a file's sample_ids to label__sample_id to resolve a collision
  • add tests/test_mergesqlite.py covering all of the above

Tests

  • unit tests with pytest tests/test_mergesqlite.py -v
  • manual checks from the code block below (make sure VCFs have tabs)
printf '##fileformat=VCFv4.2\n#CHROM\tPOS\tID\tREF\tALT\tQUAL\tFILTER\tINFO\tFORMAT\tSAMPLE_A\nchr1\t10100\t.\tC\tT\t.\t.\t.\tGT\t0/1\nchr1\t12000\t.\tA\tT\t.\t.\t.\tGT\t1/1\nchr1\t30000\t.\tT\tC\t.\t.\t.\tGT\t0/1\n' > job1.vcf
printf '##fileformat=VCFv4.2\n#CHROM\tPOS\tID\tREF\tALT\tQUAL\tFILTER\tINFO\tFORMAT\tSAMPLE_B\nchr1\t10100\t.\tC\tT\t.\t.\t.\tGT\t1/1\nchr1\t12000\t.\tA\tT\t.\t.\t.\tGT\t0/1\nchr1\t42000\t.\tC\tT\t.\t.\t.\tGT\t0/1\n' > job2.vcf

oc module install-base --user-email-opt-out
oc module install cancer_hotspots -y

oc run job1.vcf -d job1_out -n job1 -l hg38 -a cancer_hotspots
oc run job2.vcf -d job2_out -n job2 -l hg38 -a cancer_hotspots

oc util mergesqlite job1_out/job1.sqlite job2_out/job2.sqlite -o merged.sqlite

oc util showsqliteinfo merged.sqlite

cvaske added 2 commits August 19, 2026 13:11
…e checks

- fix mergesqlite() dropping sample and mapping rows for any variant that
  already exists in the merged output (uid_dic was never populated for
  the skip-duplicate-variant case, so later sample/mapping inserts for
  that uid were silently skipped)
- extend the pre-merge consistency check beyond variant/gene_header
  column names to also cover sample_header/mapping_header columns and
  (name, version) pairs for variant_annotator/gene_annotator across all
  input dbs; error out naming the mismatch before doing any merge work
- recompute "Number of unique input variants" and "Result modified at"
  in the merged db's info table instead of leaving db 1's stale values
- detect colliding sample_id values across input dbs and error out by
  default
- add an opt-in `path:label` argument suffix to rename a file's
  sample_ids to `label__sample_id` to resolve a collision
- add tests/test_mergesqlite.py covering all of the above
Four correctness bugs in mergesqlite() could silently drop, duplicate,
or misattribute merged sample/mapping rows:

- new_uid running counter was clobbered by the Sample/Mapping blocks
  reusing it as a scratch variable, causing duplicate base__uid values
  and misattributed sample rows when merging 3+ dbs.
- variant_id() concatenated chrom+pos+ref+alt with no delimiter, so
  distinct variants (e.g. chr=1/pos=234 vs chr=12/pos=34) could collide
  and get silently merged onto the wrong variant. Now delimited with ':'.
- fileno_dic only recorded entries for newly-seen input filepaths,
  raising KeyError when a later db repeated an earlier db's input path;
  now maps repeated filepaths onto their existing fileno.
- labels was a dict keyed by dbpath, so passing the same physical file
  twice with different :label suffixes silently dropped the first
  label; now a list parallel to dbpaths.
- mergesqlite_check_info()'s column consistency check now also checks
  order of columns, which matehes the merging logic used later on.

Added regression tests for all five, each confirmed to fail against
the prior behavior before the fix.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant