diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml new file mode 100644 index 0000000..abfab9c --- /dev/null +++ b/.github/workflows/tests.yml @@ -0,0 +1,28 @@ +name: Tests + +on: + pull_request: + branches: [main] + push: + branches: [main] + +jobs: + test: + name: pytest + runs-on: ubuntu-latest + steps: + - name: Check out source + uses: actions/checkout@v4 + + - name: Set up Python + uses: actions/setup-python@v5 + with: + python-version: "3.11" + + - name: Install package and pytest + run: | + python -m pip install --upgrade pip + pip install -e . pytest + + - name: Run tests + run: pytest tests/ -v diff --git a/DEVELOPMENT.md b/DEVELOPMENT.md index 2949043..47a1b1f 100644 --- a/DEVELOPMENT.md +++ b/DEVELOPMENT.md @@ -187,7 +187,24 @@ pytest tests/ per-command parallel/sequential/fallback logic) across all three compression types. `tests/test_validate.py` covers index integrity (size/mtime/hash header fields, `mafutils validate`'s three-way verdict, and `--verify-hash` -on `fetch`/`stats`/`gc`). +on `fetch`/`stats`/`gc`). `tests/test_stats.py` checks `mafutils stats`'s +computed `overall.tsv`/`species.tsv` values against numbers hand-derived +directly from `tests/example.maf`'s raw content (not just "doesn't crash"), +including a regression guard that the sequential (`-p 1`, no +`ProcessPoolExecutor`) and real multi-worker (`-p 2`+) paths produce +identical output. + +`tests/test_real_data.py` runs `stats`/`gc`/`fetch` against +`tests/real-excerpt.maf` -- 8 real, complete alignment blocks extracted +read-only from gwct's actual ~42GB production MAF +(`data/hamsters/uncompressed/...`), not hand-crafted. Unlike +`example.maf`-based tests (which verify exact hand-computed values), +these check plausibility/robustness on genuinely real data -- real +species-naming conventions, real gap patterns, real block-size +distribution -- since a hand-crafted fixture wouldn't think to include +whatever real data actually looks like. This is deliberately still a +tiny, committed fixture, not the real dataset itself: `data/hamsters/` +stays untouched and out of git (see the `.gitignore` `data/` entry). ## Releasing to PyPI diff --git a/README.md b/README.md index 633f7c4..6e925c5 100644 --- a/README.md +++ b/README.md @@ -177,6 +177,7 @@ Options: | `--fasta-dedupe` | FASTA duplicate handling: `none` or `most-seq` | | `--processes`, `-p` | Number of worker processes (see Compression above — plain gzip always runs single-process) | | `--mode`, `-m` | Fetch mode: `block` or `scaffold` | +| `--scaffold-subdirs` | Group output files into subfolders named by reference scaffold (`//`) instead of one flat directory | | `--verbose` | Emit warning lines from each completed batch | | `--profile` | Log internal timing breakdowns | | `--verify-hash` | Verify the index's stored content hash against the MAF file (see Index Integrity above) | diff --git a/mafutils/fetch.py b/mafutils/fetch.py index ee56499..a15ce78 100644 --- a/mafutils/fetch.py +++ b/mafutils/fetch.py @@ -90,6 +90,7 @@ WORKER_INDEX = None WORKER_OUTPUT = None WORKER_SINGLE_OUTPUT = None +WORKER_SCAFFOLD_SUBDIRS = None WORKER_AS_FASTA = None WORKER_FASTA_HEADER = None WORKER_EXPECTED_SPECIES = None @@ -174,6 +175,7 @@ def initBatchWorker( verbose, profile, prefetched_cache=None, + scaffold_subdirs=False, ): global WORKER_HEADER global WORKER_MAF_FILE @@ -181,6 +183,7 @@ def initBatchWorker( global WORKER_INDEX global WORKER_OUTPUT global WORKER_SINGLE_OUTPUT + global WORKER_SCAFFOLD_SUBDIRS global WORKER_AS_FASTA global WORKER_FASTA_HEADER global WORKER_EXPECTED_SPECIES @@ -196,6 +199,7 @@ def initBatchWorker( WORKER_INDEX = index WORKER_OUTPUT = output WORKER_SINGLE_OUTPUT = single_output + WORKER_SCAFFOLD_SUBDIRS = scaffold_subdirs WORKER_AS_FASTA = as_fasta WORKER_FASTA_HEADER = fasta_header WORKER_EXPECTED_SPECIES = expected_species @@ -714,6 +718,20 @@ def trimMafBlock(block_text, bed_start, bed_end, BATCHLOG, verbose=False, warnin ############################################################################# +def buildOutputPath(output_dir, scaffold, out_basename, ext, scaffold_subdirs): + """ + Shared per-output-file path builder for block mode (fetchByRegion) and + scaffold mode (fetchByScaffold/fetchScaffoldsSequential). The scaffold + subdirectory itself is never created here -- callers must pre-create + every needed one upfront (see run_fetch) before any of these paths are + actually opened for writing. + """ + if scaffold_subdirs: + return os.path.join(output_dir, scaffold, out_basename + ext) + return os.path.join(output_dir, out_basename + ext) + +############################################################################# + def fetchByRegion( region, header, @@ -729,6 +747,7 @@ def fetchByRegion( verbose=False, warning_state=None, profile_state=None, + scaffold_subdirs=False, ): """ Worker function to process a single BED region: @@ -760,7 +779,7 @@ def fetchByRegion( fill_cache = {} # For fasta output, hold sequences per species - output_filename = os.path.join(output, out_basename + (".fa" if as_fasta else ".maf")) + output_filename = buildOutputPath(output, scaffold, out_basename, ".fa" if as_fasta else ".maf", scaffold_subdirs) out_stream = None if single_output: @@ -997,6 +1016,7 @@ def fetchByBatch( verbose=WORKER_VERBOSE, warning_state=warning_state, profile_state=profile_state, + scaffold_subdirs=WORKER_SCAFFOLD_SUBDIRS, ) batch_results[result_idx] = region_result if not WORKER_SINGLE_OUTPUT: @@ -1027,13 +1047,13 @@ def fetchByBatch( ############################################################################# -def fetchByScaffold(scaffold, start_end, maf_file, maf_header, maf_compression, out_dir, LOG): +def fetchByScaffold(scaffold, start_end, maf_file, maf_header, maf_compression, out_dir, LOG, scaffold_subdirs=False): """ Worker function to extract one scaffold from the MAF file. start_end is a tuple (start_byte, end_byte). """ start, end = start_end - output_path = os.path.join(out_dir, f"{scaffold}.maf") + output_path = buildOutputPath(out_dir, scaffold, scaffold, ".maf", scaffold_subdirs) try: with COMMON.openMaf(maf_file, maf_compression, "rb") as mfp, open(output_path, "wb") as outfp: @@ -1047,7 +1067,7 @@ def fetchByScaffold(scaffold, start_end, maf_file, maf_header, maf_compression, return f"{output_path}: Wrote {scaffold}"; -def fetchScaffoldsSequential(ordered_scaffolds, index, maf_file, maf_header, maf_compression, out_dir, LOG): +def fetchScaffoldsSequential(ordered_scaffolds, index, maf_file, maf_header, maf_compression, out_dir, LOG, scaffold_subdirs=False): """ Extracts multiple scaffolds using a single open MAF handle, in the given (ascending file-offset) order. Used for gzip input: reusing one handle @@ -1058,7 +1078,7 @@ def fetchScaffoldsSequential(ordered_scaffolds, index, maf_file, maf_header, maf with COMMON.openMaf(maf_file, maf_compression, "rb") as mfp: for scaffold in ordered_scaffolds: start, end = index[scaffold] - output_path = os.path.join(out_dir, f"{scaffold}.maf") + output_path = buildOutputPath(out_dir, scaffold, scaffold, ".maf", scaffold_subdirs) try: LOG.info(f">>> Scaffold {scaffold}"); data = COMMON.readMafBlockBytes(mfp, maf_compression, start, end) @@ -1101,6 +1121,13 @@ def run_fetch(args, cmdline="mafutils fetch"): LOG.error(f"Invalid mode: '{args.mode}'. Must be 'block' or 'scaffold'.") sys.exit(1) # Validate mode + + if args.scaffold_subdirs and args.single_output: + LOG.error("--scaffold-subdirs cannot be used with --single-output.") + sys.exit(1) + # --single-output collects blocks into one combined file and never uses + # per-region output_basename/output_filename at all, so it doesn't + # compose with grouping per-region files into scaffold subfolders. # if args.max_no_overlap_regions < -1: # LOG.error("--max-no-overlap-regions must be >= -1.") # sys.exit(1) @@ -1171,6 +1198,12 @@ def run_fetch(args, cmdline="mafutils fetch"): sys.exit(1) LOG.info(f"Extracting {len(scaffold_set)} scaffolds from scaffold index: {scaffold_set}"); + if args.scaffold_subdirs: + # Pre-create upfront in the main process, same rationale as + # block mode below -- avoids any per-worker/cross-process race. + for scaffold in scaffold_set: + os.makedirs(os.path.join(args.output, scaffold), exist_ok=True) + # Process scaffolds in ascending file-offset order; for gzip this is # what lets a single reused handle avoid ever seeking backward. ordered_scaffolds = sorted(scaffold_set, key=lambda s: index[s][0]) @@ -1182,7 +1215,7 @@ def run_fetch(args, cmdline="mafutils fetch"): "gzip-compressed files; --processes will be ignored. (Use a bgzip-compressed MAF " "for real parallel speedup on compressed input.)" ) - for result in fetchScaffoldsSequential(ordered_scaffolds, index, args.maf_file, maf_header, maf_compression, args.output, LOG): + for result in fetchScaffoldsSequential(ordered_scaffolds, index, args.maf_file, maf_header, maf_compression, args.output, LOG, scaffold_subdirs=args.scaffold_subdirs): LOG.info(result) else: # Extract from MAF using the region index for matching scaffolds @@ -1198,7 +1231,8 @@ def run_fetch(args, cmdline="mafutils fetch"): maf_header, maf_compression, args.output, - LOG + LOG, + args.scaffold_subdirs, )) for future in futures: result = future.result() @@ -1273,6 +1307,15 @@ def run_fetch(args, cmdline="mafutils fetch"): else: # basename_mode == "coords": region["output_basename"] = f"{scaffold}-{start}-{end}" + if args.scaffold_subdirs: + # Pre-create every needed scaffold subdirectory upfront, in the main + # process, mirroring the single os.makedirs(args.output, ...) above -- + # block-mode writes happen inside ProcessPoolExecutor workers, and + # nothing per-worker creates directories today, so doing this here + # avoids needing any cross-process race handling at write time. + for scaffold in {region["scaffold"] for region in regions}: + os.makedirs(os.path.join(args.output, scaffold), exist_ok=True) + info_outfile = os.path.join(args.output, "maf_fetch_summary.tsv") # if args.fasta_header and not args.fasta: @@ -1303,6 +1346,7 @@ def run_fetch(args, cmdline="mafutils fetch"): args.verbose, args.profile, prefetch_cache, + args.scaffold_subdirs, ), ) as executor, open(info_outfile, "w") as info_out: summary_headers = ["scaffold", "start", "end", "basename", "n.overlapping.blocks", "block.lengths", "interblock.distances", "n.sequences"] @@ -1462,6 +1506,7 @@ def fetch_command( fasta_dedupe: Annotated[FastaDedupeMode, typer.Option("--fasta-dedupe", help="When outputting FASTA, collapse duplicate species per block; 'most-seq' keeps the copy with most non-gap bases.")] = FastaDedupeMode.none, processes: Annotated[int, typer.Option("--processes", "-p", help="Number of parallel processes to use (default: 1)")] = 1, mode: Annotated[FetchMode, typer.Option("--mode", "-m", help="Mode: 'block' to trim by regions, 'scaffold' to extract whole scaffolds (default: block)")] = FetchMode.block, + scaffold_subdirs: Annotated[bool, typer.Option("--scaffold-subdirs", help="Group output files into subfolders named by reference scaffold (//) instead of one flat directory.")] = False, single_output: Annotated[bool, typer.Option("--single-output", hidden=True)] = False, verbose: Annotated[bool, typer.Option("--verbose", help="Print every warning line after each batch completes.")] = False, profile: Annotated[bool, typer.Option("--profile", help="Log aggregate timing breakdowns for internal fetch steps.")] = False, @@ -1480,6 +1525,7 @@ def fetch_command( fasta_dedupe=fasta_dedupe.value, processes=processes, mode=mode.value, + scaffold_subdirs=scaffold_subdirs, single_output=single_output, verbose=verbose, profile=profile, diff --git a/tests/real-excerpt.maf b/tests/real-excerpt.maf new file mode 100644 index 0000000..2f8b4a3 --- /dev/null +++ b/tests/real-excerpt.maf @@ -0,0 +1,131 @@ +##maf version=1 + +a +s Mus_musculus.CM000994.3 125888838 82 + 195154279 TCC-ATCTACTCAAACCTAATTCTTTACGATTCACTGAAGAAATCCCCTCCAGGAAGAAATCCTGATC-TTTGATTCTTCTTTC +s Phodopus_campbelli.chr12 18452278 5 - 32442325 T----------------------------------------------------------------------------TCCA--- +s Phodopus_sungorus_new.chr12 17334137 5 - 31225933 T----------------------------------------------------------------------------TCCA--- +s Phodopus_roborovskii.JAEOAF010000031.1 16485673 8 + 29770300 T----------------------------------------------------------------------------TACATCT +s Cricetus_cricetus.OZ199631.1 140166140 8 - 205530201 T----------------------------------------------------------------------------TTTTTTT +s Dicrostonyx_torquatus.JAQHUG010000071.1 6038229 4 - 8539717 A----------------------------------------------------------------------------TTT---- +s Arvicola_amphibius.NC_052058.2 72668393 4 - 166747489 A----------------------------------------------------------------------------CTT---- +s Microtus_pennsylvanicus.CM073176.1 20976023 4 + 113485825 A----------------------------------------------------------------------------cct---- +s Microtus_arvalis.JAHRII010002323.1 111060626 4 + 200229077 A----------------------------------------------------------------------------CTT---- +s Neotoma_floridana.CM113793.1 27921528 83 - 95303938 TCC-ATCTTCTCAAACCTAATACTTCAAGATTCACCTAAGAAATCACCTCCAGGAAGAAACCCTGATTACTTAATTCCTTTTTC +s Onychomys_torridus.LR877198.1 72220278 83 + 93020901 CCC-ACCTACTCAAACCTAATTCTTCAAGATTCATCTAAGAAATTATCTCTAGGAAGAAACTCTGATTACTTAATTCCTTTTTC +s Peromyscus_californicus.VALE03000237.1 12778336 84 + 80346014 TCCCATCTACTCAAACCTAATTCTTCAAGATTCACCTAAGAAATTACCTCCAGGAAGAAACCCTGATTACTTAATTCCTTTTTC +s Peromyscus_maniculatus_North.CM113205.1 35699024 84 + 104458120 TCCCATCTACTCAAACCTAATTCTTCAAGATTCACCTAAGAAATTACCTCCAGGAAGAAACCCTGATTACTTAATTCCTTTTTC + + +a +s Mus_musculus.CM000994.3 125888920 187 + 195154279 TTGGGAATCAAGTTGAGTGCTCAGTTTCAGTAGATACAGACAACCC-CCA---CC---C----AGCC--TTGTACTCAATATTCCATAATTGTGTCATATTTGTACTGTGTTTGGGATCTATTGT-----------CTTCCTA-GGACAATCGGAAGGGACAAAAGAAGGTAATAGCAACAAGGTCACCATCAGC----------T-CTCAGATCTCAGAGGA +s Phodopus_campbelli.chr12 18452286 180 - 32442325 TAAAGGA-------------------CCAGTGGTCACAGACAATCCTCCC---CC---CCAACACCCTTTTTTAGTCAATAGTCCATAA-------ACCTGTGTTCTATTCTTGGAATCCAATGGGAAATATCATACTTCCT-GGGACAACCAGAACTGGAAGAGGAGGATAATAGCAATG---TCACC------ATCAGCA-AAATCTTAAGTGCTGCGGGA +s Phodopus_sungorus_new.chr12 17334145 152 - 31225933 TAAAGGA-------------------CCAGTGGTCACAGACAATCCTCCA---CC---CCAACAGCCTTTTTTAGTCAATAGTCCATAA-------ACCTGTGTCCTATTCTTGGAATCCAATGTGAAATATCATACTTC-T-GGGACAACCAGAACTGGAAGAGTTGGATAATAGCAATG---TCACC---------------------------------- +s Phodopus_roborovskii.JAEOAF010000031.1 16485768 182 + 29770300 TAAAGGA-------------------CCAGTGTTAACAGACAATCCTTTC---CTCCACCAACAGCC--TTTTAGTCAATATCCCATAA-------ACATTTGCCCTATACTTGGAATCCAATGTGAAAAATCATACTCCCT-GGAACAACCAGAGCAGGCAGAGTTGGATAATAGCAATG---TCACC------ATCAGCAGAAAACTTAAGTGCTGTGGGA +s Cricetus_cricetus.OZ199631.1 140166148 180 - 205530201 TAAAGGA-------------------TCAGTGATCACAGACAATCC-CCATGCCT---CCAGTAGCC--TTTTAGTCAATATTCCATAA-------GCATTCATCCTGTAGTTGGAATCCAATATGAAATATCATACTTCCT--GGACAACCAGAATGGGCAGAGTAGGATAATAGTAACA---TCACC------ACCAGCAGAAAACTTAAGTGTTATGGGA +s Neotoma_floridana.CM113793.1 27921611 174 - 95303938 TTAAGGA-------------------TCAGTGGTTCCAGACAATCCCCCA---CA---C----AGCC--TT-TAGTCAATATTCCATAA-------ACATTTGTCCTGTACTTGGAATCCAATATGAAATATCATACTTCCTG-GGATGACCAGAATGGTCAGAGGAAGATAATAGCAACA---TCACCATCAGC------AGAAAACTTAAGTGTTATGGGA +s Onychomys_torridus.LR877198.1 72220361 175 + 93020901 TTAAGGA-------------------TCAGTGGTCACAGACAATCCTCCA---CA---C----AGCCT-TT-TAGCCAATATCCCATAA-------ACATTTGTCCTGTACTGGGAACCTAATATGAAATATCATACTTCCTG-GGACAACCAGAATGGTCAGAGGAAGATAATAGCAGCA---TCACCATCAGC------AGAAAACTTAAAAGTTATGGGA +s Peromyscus_californicus.VALE03000237.1 12778420 175 + 80346014 TTAAGGA-------------------TCAGTGGTCACAGACAATCCTCCA---CA---C----AGCCT-TT-TAGCCAATATTCCATAA-------ACATTTGTCCTGTACTTGGAATCTAATATGAAATATCATCCTTCCTG-GGACAACCAGAATGGTCAGAGGAAGATAACAGCCACA---TCACCATCAGC------AGAAAACTTAAATGTTATGGGA +s Peromyscus_maniculatus_North.CM113205.1 35699108 175 + 104458120 TTAAGCA-------------------TCAGTGGTCACAGACAATCCTCCA---CA---C----AGCCT-TT-TAGCCAATATTCCATAA-------ACATTTGTCCTGTACTTGGAATCTAATATGAAATATCATCCTTCCTG-GGACAACCAGAATGGTCAGAGGAAGATAACAGCCACA---TCACCATCAGC------AGAAAACTTAAATGTTATGGGA + + +a +s Mus_musculus.CM000994.3 125889107 10 + 195154279 G---------------------GGGCATCTG +s Phodopus_campbelli.chr12 18452505 18 - 32442325 TT-------------TTGCAATGAtcatctc +s Phodopus_sungorus_new.chr12 17334315 18 - 31225933 TT-------------TTGCAATGATCATCTC +s Phodopus_roborovskii.JAEOAF010000031.1 16485989 18 + 29770300 TT-------------CTGCAATGATCATCTT +s Cricetus_cricetus.OZ199631.1 140166328 31 - 205530201 TTCTAGAAGAGGGGCTTGTAATGATCATCTG +s Neotoma_floridana.CM113793.1 27921822 18 - 95303938 TT-------------TTGCAATGATCATCTC +s Onychomys_torridus.LR877198.1 72220576 18 + 93020901 TT-------------TTGCAATGAACATCTC +s Peromyscus_californicus.VALE03000237.1 12778635 18 + 80346014 TT-------------TTGCAATGATCATCTC +s Peromyscus_maniculatus_North.CM113205.1 35699323 18 + 104458120 TT-------------TTGCAATGACCATCTC + + +a +s Mus_musculus.CM000994.3 125889117 440 + 195154279 CATGTCTGACAAAGCACTTGCT---TG---ACACAGGACAATAAAATTCTGTCATGAACTATCATGAAGT-ATGTGACAGGATGACAAAGCATGGGTGAAAAGGAAGTTG---TGTCACATTTGGGTGGCACTT-ATATGCTTCTGGTAATGATGGTGGC----------TCTT--TAAAGTTTCTTATGACTTCTTTGTAACTAGCGAGTAAGCTCTGTGGGCA--------TTGCAGGCTATCACCTTCCTCTTCATAACAGCACTGA-AGTTCATGTCtgtgaggctcaatctctgttgtcaaccagatggcattaagtctgtccatgaaaacagacctctgggg----------atgtctgtgatagaggttaggctatttaaagttgaaagacccaccctaa-tctgagtggtaccagttcatgggctggggttctag-act---gaaagaaagagagaaaggaagctgagccctagcctta +s Phodopus_campbelli.chr12 18452900 426 - 32442325 CA----------TGTACTTTCT---T----AC--AGGACAATAAAATCCTAGCATGGGCTATCATGAAGTTATGTGACAAGACGGTAAGGCATGGATGGAAAGGAGCCCATGTC---ATGTTCAGG-GGCACTT-ACATGCTGCTGGCA---------GTGATCGTTGAGTCTTTATAAAGTTTCTTGTGTTTTCTCTGTAACTAGCCTGTAAGCTCTGTGGGCAGGGATGCATTGCATGCTGTCCCCTCCCTACTCCAAACAGCACTAA-GCTTCATGTCTGTACGGCTTAATCGTGACTGTCAACCAGATGGGACAAAGTCTGTCTATGAAAACAA--------------------ATGTCTGTGAGGGATATCAGGCtaactgaggttggaagacccactctaaAtctgagtggcaccaatctatgggcttgtgagct-gGaat---aagcaaggagaa---agtaagctgagccccagcattc +s Phodopus_sungorus_new.chr12 17334333 426 - 31225933 CA----------AGTACTTACT---T----AC--AGGACAATAAAATCCTAGCATGGGCTATCATGAAGTTATGTGACATGACGATAAGGCATGGATGGAAAGGAGCCCATGTC---ATGTTCAGG-GGCACTT-ACATGCTGCTGGCA---------GTGATCGTTGAGTCTTTATAAAGTTTCTTGTGTTTTCTCTGTAACTAGCCTGTAAGCTCTGTGGGCAGAGATGCATTGCATGCTGTCCCCTTCCTACTCCAAACAGCACCAA-GCTTCATGTCTGTACGGCTTAATCGTGACTGTCAACCAGATGGGACAAAGTCTGTCTATGAAAACAA--------------------ATGTCTGTGAGGGACATCAGGCTAACTGAGGTTTGAAGACACACTCTAAATTTGAGTGGCACCAATCTATGGGCttgtgagct-gGaat---aagcaaggagaa---agtgagctgagccccagcattc +s Phodopus_roborovskii.JAEOAF010000031.1 16486007 437 + 29770300 CA----------AGTACTTACTTGAT----AC--AGGACAATAAAATCCTAGCATAGGCTATCATGAAGTTATGTGACAAGATGATAAAGCATGGGTGGAAAGGAG-CCATGTC---ATGTTCAGG-GGCATTT-ACATGCTGTTGGCA---------GTGATCGTTGAGTCTTTATAACGTTTCCTGTGTTTTCTCTGTAACTAGCCTGTAAGCTCTGTGGGCAGGAATCCATTGCATGCTGTCTCCTTCCTACTCCCAACAGCACCAA-GCTTCATGTCtgtaaggcttcatcgtgactgtcaaccagatggaataaagtctgtctatgaaaacaa----------ATATCTGGGGatgtctgtgagggacatcgggctaactgaggttggaagacccactctaaAtctaagtgacaccaatct-tgggcttgtgagct-gGaat---aaacaaggagaa---agtgagctgagccccagcattc +s Cricetus_cricetus.OZ199631.1 140166359 437 - 205530201 CA----------AGTACTTACT---T-GACAC--AGGACAATAAAATCCTAGCATGGACTATCATCCAGTTATGTGACAAGATGATAAGGTATGGGTGGAAAGGAACCCAAGTC---ATTTTCGGG-GACACTTAACATGCTATTGGTA---------GTGATTG-TGAGTCTT--TAAAGTTTCTCATGCCTTCTCTGTAACTAGCCTGTAAGCTCTGTGGGCAGGACTGCATTGCATGCTGTCTCCCTCCTACTCCTAACAGCACCAA-GCTTCCTGTCtgtgaggcttaatcatgactgtcaaccagacgggataaagtctgcctatgaaaacaa----------ATGTCTGGGCatgtctgtgagggacatcatgctaattgaggttggaaggcccaccctaaAtctgagtgacaccaatccatgtgctggtgtgct-gGaat---gaacaaagagga---agtgagctgagatccagcattc +s Cricetulus_griseus.NC_048598.1 130954973 1 - 193770019 ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------c +s Dicrostonyx_torquatus.JAQHUG010000071.1 6038233 79 - 8539717 -----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------CTCTAAGCCTGAGTTAcaccaatccatgggctggtgtgct-aGaat---gaa---acaggagaaagtgagctgagctccagcattc +s Arvicola_amphibius.NC_052058.2 72668397 79 - 166747489 -----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ctctaaAcccgagttacaccaatccatgggctggtgtgct-gGaat---gag---aaaggagaaagtgagctgagccccagcagtc +s Microtus_pennsylvanicus.CM073176.1 20976027 78 + 113485825 -----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ccctaaAcctgagttacaccaatccatgagttggtgtgct-gGaat---gag---aa-ggagaaagtgagctgagccccagcatgc +s Microtus_arvalis.JAHRII010002323.1 111060630 76 + 200229077 -----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ctctaaAcctgagttacatcaatccatggactg---tgcc-gAaat---gag---aaaggagaaagtgagctgagccccagcatgc +s Neotoma_floridana.CM113793.1 27921840 432 - 95303938 CA----------AGCACTTACT---T----ACATAGGACAATCAAATCCTATCATGGACTATCATGAAGTTATATGACAAGATGATAAGGCATGGATGGAAAAGAGTCTGCATC---ATATTTTGG-GGCACTC-ACATGCTGCTGGTA---------GC----------TCTT--TAAATTTTCTTGTGTCTTCTCTGTAACTAGCCTGTAAGCTCTGTGGGCAGGACTGCATTGCATGCTGTCTCCTTCCTATTCCCAATAGCACCAA-GCTTCATGTCtgtgaggcttaatcttgactgtcatccagatgagataaagtctgtctgtgaaaacaaacgtctgggg----------atgcctgtgagggagatcaggctaatggaggatgggagacccgccctaaAtctgaagggcaccaatccatgggctgctctgct-gGaatATAgagaaaaaaccagaaagtgagctgagtcccagcattc +s Onychomys_torridus.LR877198.1 72220594 423 + 93020901 CA----------AGTACTTACT---T-G--ACATAGGACAATAAAATCCTATCATGGACTATCATGAAGTTATGTGACAAGATGATAAGGCATGGGTGGAAAGGAGT--G---T---ATATTTTGG-GGCCCT--AAATGCTGCTGGTA---------GC----------TCTT--TAAATTTCCTTGTGTCTTCTCTGTAACTAGCCTGTAAGCTCTGTCCTCAGGGCTGCCCTGCGTGCTGTCTCCTTCCTGCTCTCAAGGGCACCAA-GCTTCAGGTCtgtgaggcttaatcttgactgtcaacaagaagggataaagtctgtctatgcaaacaaacatctgggg----------atggctgtgagggagatcaggctaatggaggttggaggacctgccctaaAtctgagtggcaccattctatgggctggtgagct-gGaat---gaacaaaaaa-aggaagggagctgagccccagcattc +s Peromyscus_californicus.VALE03000237.1 12778653 427 + 80346014 CA----------AGTACTTACT---T-G--ACATAGGACAATAAAATCTTGTCATGGACTATCATGAAGTTATATGACAAGATGATAAGGCATGGATAGAAAGGAGTCTG---T---ATATTTTGG-GGCCCTT-ATATGCTGCTGGTA---------GC----------TCTT--TAAATTTCCT-GTGTCTTCTCTATAACTCGCCTGTAAGCTCTGTGGGCAGGCCTACATTACGTGCTGTCTCCTTCCTGCTCCCAAAAGCACCAAAGCTTCATGTCTGtgaggcttaatcttgactgtcaaccagaagggataaagtctgtctatgaaaacaaatgtctgagg----------atgtctgtgagggagatcaggctaatggaggttggaaggcctgccctaaAtctgagcggcaccattccatgggctggtgagct-gGaat---aaacaaaaaggagaaagtgagctgggtcccagtattc +s Peromyscus_maniculatus_North.CM113205.1 35699341 427 + 104458120 CA----------AGTACTTACT---T-G--ACATAGGACAATAAAATCCTATCATGGACTATCATGAAGTTATGTGACAAGGTGATAAGGCATGGATGGAAAGGAGTCTG---T---ATGTTTTGG-GGCCCTT-ACATGCTGCTGGTA---------GC----------TCTT--TCAATTTCCTTGTGTCTTCTCTGTCACTCGCCTGGAAGCTCTGTGAGCAGGGCTGCATTACGTGCTGTCTCCTTCCTGCTCCCCAAAGCACCGAACCTTCATGTCtgtgaggcttaatcttgactgtcaaccagaagggataaagtccgtctatgaaaacaaatgtctgagg----------atgtctgagagggagatcaggctaatggaggttggaaggcctgccctacAtctaagcggcaccactccatgggctggtgagct-g-aat---gaacaaaaaggagaaagtgagctgagtcccagtattc + + +a +s Mus_musculus.CM000994.3 125889557 280 + 195154279 gtt-ctgcctgcttcctgactgtggatgccaagtgaccagctgtctctcatgctggctgccatgccttcttcaggatgaactgtgtccctccagac--atgtgagt---------------------gcaaaac------------accctccctccctccct-ccctccctccctctcccttccttctttaggatgcttttcttag---c--ttttgttacagtattcagaaaagtgacAATTCATAGAGAGTCTTCAACAGGTCCTCACCAAGCA-----CTTATGGAATCATAGCAGGC------------T-AA-A-----------TG----GGCTAAAAATCCTCCTCCT +s Rattus_norvegicus.CM070403.1 39970935 170 + 109350286 -----------------------------------------------------------------------------------------------------------------------------------------------------ctcccttcctctttAttttccctccc---cccttcttcccttaggttgctttccttag---cCAttttgtcacagtaaccagaaaagtgacAACTCAC--AGAGTCTCCAACAGATCCTCACCAAGCG-----CCCATGGAATCACAGCAGGCAGAGGAGTCACTT-AA-A-----------AG----GGCTAAAAATCC------- +s Phodopus_campbelli.chr12 18453724 270 - 32442325 acaGctccctgcttcctggctgcggatggcatgtgaccagcttcctcctgttcttgctgccatgccctcctcatgatggactgtattcctttggaaCTctg--agtAAAGCAACAACCACAACAACAacaacaa------------g--c-----------------------------TCTTTGTCCTTTAAGTTGCTGA--GTCA-GCA--CTTTGTCCCTGTACTCAGAAAAGGGACA-TTCATAGTGAGTCTCCTTCGGGTCCTCACCAGGCA-----CACA--GGATTGTGGCGGGCAGGGGATTCACTT-AG-CT----------CC----TCCT-----CCG------- +s Phodopus_sungorus_new.chr12 17335144 282 - 31225933 acaGctccctgcttcctggctgcggatggcatgtgaccagcttcctcctgttcttgctgccatgccctcctcatgatggactgtatccctttggaaCTctg--agtAAAGCAACAACAACAACAACAacaacaaCAACAACAACAAg--c-----------------------------tctttgtcccttaagttgctta--gtCA-GTA--CTTTGTCACTGTACTCAGAAAAGGGACA-TTCATAGTGAGTCTCCTTCGGGTCCTCACCAGGCA-----CACA--GGATTGTGGCGGGCAGAGGATTCACTT-AA-CT----------CC----TCCT-----CCG------- +s Phodopus_roborovskii.JAEOAF010000031.1 16486444 261 + 29770300 attGctctctgcttcctggctgtggatggcccgtgaccagcttcc-cccattcttgctgccgtgtcctcctcctgatggactctatcactttggaa--ctg--agtAAAACAACAA-------CAAA-----aa------------g--c-----------------------------tctttgttccttaagttgcttt--gtca-GTa--ttttgtcactgtactcagaaaAGGGGCAGTTCATAGTGAGTCTCCTTCAGGTCCTCATCAGGTCCTCATCACA--GAATTGTGGCAGGTAGAGGATTCACTT-AA-AT----------CC----TCCT-----CCT------- +s Cricetus_cricetus.OZ199631.1 140166796 266 - 205530201 attGctctctgcttcctgattgtggatgccatgtgaccacctgcctcctattcttgctgctatgcctttcccatgatggactgtatccttttggaa--ctgtgatgT---AAAAAACA--AAGCAAAacaaaac------------a--c-----------------------------acttggtttcttaagttgcttt--gtga-GTa--gtttgtcactgtaatcagaaaagGGAGAGTTCATAGTGAGTCTCCGACAGGTCCTCACCAAGCA-----CACA--GAGCGGGGGCAGGGAGAGGATTCACTT-AA-AA----------CC----TCCT-----CCT------- +s Cricetulus_griseus.NC_048598.1 130954974 265 - 193770019 attGctctctgcttcctgactgtggatgccatgtgaccacctgcctcctattcttgctgccatgcctttcccatgatggactgtatccctttggaa--ctgtgaggTAAAAAC----A--AAACAAAacaaaac------------a--c-----------------------------actttgtttcttaagttgcatt--gtga-GTa--ttttgttactgtaatcagaaaagGGACAGTTCATAGTGAGTCTCCGACAGGTCCTCACCAAGCA-----CACA--GAGTGGTGGCAGGTAGAGGATTCACTT-AA-AA----------CC----TCCT-----CCT------- +s Dicrostonyx_torquatus.JAQHUG010000071.1 6038312 259 - 8539717 actGctctctgcttcctgactgtgg-tgccatgtgactagccagctcctactcttgctgctgtgccttccccatgacaaactgtgtccctctggaa--ctgtgagtTCAAAAACAG-------GAAAggaaaaa------------a--a-----------------------------ccttccctccttaaggttcttt--gccaGGTa--ttttgtcatggtagtcagaaaagtgacaattcATGGCAAGTCTCCATCAGGTCCTCACCAAGCA-----CACACGGAACTGTGACCGGT------------------AGAGGACATGC-C----TCCT-----TTT------- +s Arvicola_amphibius.NC_052058.2 72668476 265 - 166747489 actGctctctgcttcctgactgtgggtgccaagtgactagccagctcctactcttgctgtcatgccttccccatgacagactatatccccctaaga--ctgtgagtTCAAAAA----A--AAGAAAAggaaaaa------------a--c-----------------------------ccttccctccttaaggtccttt--gccaGGTa--ttttgtcatggtagtcagaaaagtgacAACTCATGGTGAGTCTCAATCAGGTCCTCACCAAGCA-----CACACAGAATCGTGGCAGGA------------------AGAGGATTCGC-TTAAGTCCT-----TTT------- +s Microtus_pennsylvanicus.CM073176.1 20976105 241 + 113485825 actGctctctgcttcctgactgtgggtgccatgtgaccagccagctcctactcttgctgtcatgccttccccatgacagacgatttccccctagaa--ctgtgagtTCAAAAAGAG-------AAATggaaaaa------------a--c-----------------------------ccttccctccttaaggtcgttt--gccaGGTa--ttttgtcacggcagttagaaaagtgacAGTTGATGGCAAGTCTCCATCAGGTCCTCACCAAGCA-----CACACAGAATTGTGGCAGGC------------------------------------------------------ +s Microtus_arvalis.JAHRII010002323.1 111060706 260 + 200229077 actGctctctgcttcctgactgttggtgccatgtgaccagccagctcctactcttgctgctgtgctttccccatgacaaactgtgtccccctagga--ctgtgagtTCAAAAAAAG-------AAAAgaaaaaa------------a--c-----------------------------ccttgcctccttaaggtccttt--gccaGGTa--ttttgtcacggtagttagaaaAGTGACAGTTCATGGCAAGTCTCCATCAGGTCCTCACCAAGCA-----CACACAGAATTGTGACTGGT------------------AGAGGATATGC-C----TCCT-----CTT------- +s Neotoma_floridana.CM113793.1 27922272 255 - 95303938 attGctctctgcttcctgactgcagatgccgtgtgaccagct----------------gccacgccttccccatgatggactctatccctctggaa--ctgtgagtTCAAAAACAACA--AACAAACaaacaaa------------g--c-----------------------------ccttccttccttaagctgcctctgtcag-GTa--ctttacgactgtaaccagagaagTGATGGTTCATGGGGAGTCTCCA--AGGTTGTCCCCAAGCA-----CATACAGAATTGTGGCATGCAGTAGATTCACTTAAA-T-----------TC----TCCT-----CCT------- +s Onychomys_torridus.LR877198.1 72221017 244 + 93020901 attActctctgcttcctgactgtggaggccatgtgaccagctgcctcctactctttcagccatgccttccccatgatggactgcattcctgtggaa--ttg--agtCCCAAAACAGCA--AACAAACaaa---g---------------t-----------------------------ccttccttccttaagctgccttcatcag----------gtcactgtaaccagaaaagtgacGGTTCATGGGGAGTC---------------ACAAGCA-----CACATAGAATCATGGCAGGCAGAGGATTCACTT-AA-T-----------CC----TCCT-----CCT------- +s Peromyscus_californicus.VALE03000237.1 12779080 263 + 80346014 attActctctgcttcctgactgtggaggccatgggaccagctgcctcctgctctttcagccacgccctcctcatgatggactgtgtccctgtggaa--ctgtgagtTCAAAAACAACA--AACAGACaaaccaa---------------t-----------------------------ccttccttccttaagctgccttcgtcag----------gtcactgtaaccagaaGAGTGATGATTCATGGGGAGTCTCCA--AGGTCGTCCCCAAGCA-----CACACAGAATCATGGCAGGCAGAGGGTTCACTT-AAAT-----------CC----TCCT-----CCT------- +s Peromyscus_maniculatus_North.CM113205.1 35699768 259 + 104458120 attActctctgctacctgactgtggaggccacgtgaccagctgcctcctcctctttcggccacgccttccccatgatggattggatccctgtggaa--ctgtgagtCCACAAACAACA--AAGAAACaaacaaa---------------g--------------------------------tccttccttaagcggcctttgtcag----------gtcactgtcaccagaagagtGCTGATTCATGGGGAGTCTCCA--AGGTCGTCCCCAAGCA-----CACACAGAATCATGGCAGGCAGAGGATTCACTT-AA-A-----------CC----TCCT-----CCT------- + + +a +s Mus_musculus.CM000994.3 125889837 333 + 195154279 ACCCACATTTCCTTTCCTAAAGTGTATTCAGGTCAGCAATGAAAGTTCTCCAAAGGCAACTGCCTGGGGACAGAAAGACAGCAATGCACATGGATCCTCAGGATGCCACTGCAAACACAGGACCACCCTTTACTTGCATGTGGACCTGAGGAACCTTTGTAATTAATCACCCCTTAAGCTGAATGACTGATGTAGGAAACGCTAGACAGGGGTGAGAGCCTCAGGCCAGTCAGTTAATCACATCA-AGAAGAAATGGAGATAAATTCATCTTACCC-ACTTAGCAATTACCTCATTCACACTTGCCAAT-AAAAGAAACTAATTGTTCTGCCCTTT +s Rattus_norvegicus.CM070403.1 39971105 325 + 109350286 ACACACATTCCCTTTCCTTGTATGTGTTCAGGTCAGCAATGAAAGTTCTCCAAAGGCAATCACACAGGGACAGAAGGACAGCATGCC-CATGAGTCCTCAGGATGCCACCGCAAAGAAAGGATCCGCCTTTACTTGCATGTG-------GGATTCTTTATAATTAATCATACCTTATGGTAAATGACTGATGTAGCAAATTCTAGACAGGGGTGAGAGCCTCAGGCTACTCAGTTAATCACATCA-TGAAGAAATGGAGATAAATTCATCTTACCC-AGTTACCAATTACCTCTTTCACAGTTGCCAAT-AAAAGAAACTAATCGTTCTGCCCTTT +s Phodopus_campbelli.chr12 18453994 318 - 32442325 GC-CATGTTTCCTTTTCTTGAGTGTCTTCAGGTTAGTAATGAAAGCCCTGCAAAGACAATTACACCGGGACAGGAGGACAGAATACC-CGTGAATCCTCAGGATGCCCGGGCAAACATAGGGCCTCCTGTCACTTGCATGTGGGCCAAAGAAGCATTTGTAATTAATTGTACTTGATGGTGAATGACTAATGTAGCGAACTCTAGACAGGGGTGAGAGCTTCAGGCCAGC--------------AATGAAGCAATGGAGATAAATTCATCTTACTC-AGTTACCAATTACCTCTTTCATACTTGGCAAT-AAAATAAACTGATTGTTATGCCCTTT +s Phodopus_sungorus_new.chr12 17335426 318 - 31225933 GC-CGTGTTTCCTTTTCTTGAGTGTCTTCAGGTTAGCAATGAAAGCCCTGCAAAGACAATTACACCAGGACAGGAGGACAGAATACC-CGTGAATCCTCAGGATGCCCGGGCAAACATAGGGCCTCCTGTCACTTGCATGTGGGCCAAAGAAGCATTTGTAATTAATTGTACTTGATGGTGAATGACTAATGTAGCGAACTCTAGACAGGGGTGAGAACTTCAGGCCAGC--------------AATGAAGCAATGGAAATAAATTCATCTTACTC-AGTTACCAATTACCTCTTTCATACTTGGCAAT-AAAATAAACTGATTGTTATGCCCTTT +s Phodopus_roborovskii.JAEOAF010000031.1 16486705 319 + 29770300 GCACGTGTTTCCTTTTCTTGAGTGTCTTCAGGTTAGCAATGAAAGTCCTGCAAAGGCAATTACACCGGGACAGGAGGACAGAATACC-CGTGAATCCTCAGGATGCCTGGACAAACAAAGGGCCTCCCTTTACTTGCATGTGGGCCTAAGAAGCATTTGTAATTAATTGTACTTGATGGTGAATGACTAATGTAGCGAACTCTAGACAGGGGTGAGAGCTTTAGGCCAGC--------------AATGAAGCAATGGAGACAAATTCATCTTACTC-AGTTACCAATTACCTCTTTCATACTTGGCAAT-AAAATAAACTGATTGTTGTGCCCTTT +s Cricetus_cricetus.OZ199631.1 140167062 318 - 205530201 GTGCATGTTTCCTTTTCTTGTGTGCCTTCAGGTTAGCAATGAAAGTCCTGCAAAGGCAATTACA-CAGGACAGAAGGACAGAATACC-CACAAATCCTCAGGATGACAGTGCAAACAAATGGCCTCCCTTTACTTACATGTGGGCCTAAGAAGCATTTGTAATTAATTGCACTTGATGGTGAATGACTAATGTAGCAAACTCTAGACAGGGGTGAGAGCTTCAGGCCATC--------------AGTGAAGCAATGGAGATAAATTCATCTTACCC-AGTTACCAATTACCTCTTTCATACTTGGCAAT-AAAATAAACTGATTGTTCTGCCCTTT +s Cricetulus_griseus.NC_048598.1 130955239 319 - 193770019 GTGCATGTTTCCTTTTCTTGTGTGCCTTCAGGTTAGCAATGAAAGTCCCGAAAAGGCAATTACACAGGGACAGAAGGACAGAATACC-CACGAATCCTCAGGATGACAGTGCAAACAAATGGCCTCCCTTTACTTACATGTGGGCCTAAGAAGCATTTGTAATTAATTGCACTTGATGGTGAATGACTAATGTAGCAAACTCTAGACAGGGGTGAGAGCTTCAGGCCATC--------------AATGAAGCAATGGAGATAAATTCATCTTACCC-AGTTACCAATTACCTCTTTCATACTTGGCAAT-AAAATAAACTAATTGTTCTGCCCTTT +s Dicrostonyx_torquatus.JAQHUG010000071.1 6038571 314 - 8539717 GCACACATTTCCTTTCCTTGTGTGTCTTCAGGTT--------------------GGCAGTTACATAGGGACAGAAGGACAGCATAAC-CAAGAATCCTCAGGATAACACTGCAATCAAAGGGCCTCTCTTTATTTGTATGTGGGCCTAAGAAGCATTTGTAATTAATCACACCTGATGGCAAATGACTGATGTAGGAAACTCTAGGCAGGGGTGAGAGCTTCAGGCTAGCCAGTTAATCACAGCAATGAAGAAACAGAGATAAATTCATCTTACCC-AGTTACCAATCACCCCTCTCACACTTGGCGATAAAAAGGAACTGATTGTTCTGCCTGTT +s Arvicola_amphibius.NC_052058.2 72668744 313 - 166747489 ACACACATTTCTTCTCCTTGTGAGTCTTCAGGCT--------------------GGCAGTTACATAGGGACAGAAGGACAGCAGACC-CAAGAATCCTCAGGATACCACTGCTATCAAAGGGCCTCTCGTTGTTTGCATGTGGGCCTAAGAAGCATTTGTAATTAATCACACCTGATGGCAAATGACTGATGTAGCAAACTCTTGGCAGGGGTGAGAGCTTCAGGCCAGCCGGTTAATCACAGCAATGAAGAAACGGAGATGAATTCATCTTACCC-AGTTACCAATCACCTCGTTCACACTTGCCGAT-AAAAGAAACTGATTGTTCTGCCCTTT +s Microtus_pennsylvanicus.CM073176.1 20976356 287 + 113485825 --------------------TGAGTCTTCAGGTT--------------------GGCAGTTACATAGGGACAG-AGGACAGCAGACC-CAAGAATCCTCAGGATAG------GATCAAAGGGCCTCTCGTTATTTGCATGTGGGCCTAAGAAGCATTTGTAATTAATCACACCCCATGGCAAATGACTGATGTAGCAAACTCTAGGCAGGGGGGAGAGCTTCAGGCCAGCCAGTTAATCACAGCAATGAAGAAACAGAGATAAATTCATCTTACCCCAGTTACCAATCACCTCTTTCACACTTGGCAAT-AAAAGGAACTGATTGTTCTGCCTGTT +s Microtus_arvalis.JAHRII010002323.1 111060966 306 + 200229077 GCACACATTTCCTTTCCTTGTGAGTCTTCAGGTT--------------------GGCAGTTACATAGGGACAG-AGGACAGCAGACC-CAAGAATCCTCAGGATTG------GATCAAAGGGCCTCCCTTCATTTGCATGTGGGCCGAAGAAGCATTTGTAATTTATCACACCCAATGGCAAATGACTGATGTAGCAAACTCTAGGCAGGGGTGAGAGCTTCAGGTCAGCCAGTTAATCACAGCAATGAAGAAACGGAGATGAATTCATCTTACCC-AGGTACCAATCACCTCTTTCACACTTGGCAAT-AAAAGGAATTGATTGTTCTGcccatt +s Neotoma_floridana.CM113793.1 27922527 333 - 95303938 GCACACGCTGCCTTTTCTTGTGTGTCTTCACATCAGCAATGAAAGTCCTCCACAGGCAAATACATAGGGACAGAAGGACAGCATACT-CATGCATCCTTAGGATGCCAGTGCAATCTAAAGGCCCCCCTTTACCTGCAGGTGTACCTAAGAAGCATTTGCAATTAATCGCACCTGATGGTGAGTGACTGATGTAGCAAACTCTCGACAGGGGTGAGAGCTTCAGGCCGGGCAGTTAATCATGGCAATGAAGAAATGGAGATAAATTTATCTTACCC-AGTAACCAATTGCCTCTTTCACATTTGGCAAT-AAAAGAAACTGATTGCTCTGCCCTTT +s Onychomys_torridus.LR877198.1 72221261 332 + 93020901 GCACCTGTTGCCTTTTCTTGTGTGTCTCCAAGTCAGCAATGGACGTCCCCTACAGGTAATTACACAGGGACAGAGGAACAGCACAGC-CACACGACCTCAAGATGCCAGTACAAACTAAAGGCCTC-CTTGCCCTGCATATGTGCCTAAGAAGCATTTGTAATTAATCGCACCTGATGGTGAGTGACTGATGTAGCAAACTCTAGACAGGGGTgagagcttcaggccagccagttaatcacagcaAtgaagaaatggagacaaattcATCTTATCC-AGTTACCAATGGTGTCTTTCACACTTGGCAAT-AAAAGAAACTGATTGCTCTGCCCTTT +s Peromyscus_californicus.VALE03000237.1 12779343 332 + 80346014 ACACATGCTGCCTTTTCTTGTGTGTCTTCAAGTCAGCAATGAAAGTCCCCCACAGGCAATTGCACAGGGACAAAAGGACAGCGCAGC-CATGCATCCTCAAGATGCCGGTGCAAACTAAAGGCCTC-CTTTTCCTGCTTGTGTGCCTAAGAAGCATTTGTAATTAACCGCACCTGATGGTGAGTGACGGATGTAGCAAACTCCAGACAGGGGTGAGAGCTTCCGGCCAGCCagttaatcacagcaAtgaagaaatggagacaaattcaTCTTATCC-GGTTAGCAATGGCCTCTTTCACACTCGGCAAT-AAAAGCAACTGATTGCTCTGCCCTTT +s Peromyscus_maniculatus_North.CM113205.1 35700027 332 + 104458120 GTACACGCTGCCTTTTCTTGTGTGTCTTCAAGTCAGCAATGAAAATCCTCCACAGGCAATTGCACAGGGACAGAAGGACAGCGTAGC-CATGTATCCTCAAGATGCCGGTGCAAACTAAAGGCCTC-CTTTCCCTGCATGTGTGCCTAAGAAGCATTTGTAATTAACCACACCTGATGGTGAGTGACGGCTGGAGCCAACTCCAGACAGGGGTGAGAGCTTCCAGCCAGCCAGTTAATCACAGCAATGAAGAAATGGAGACAAATTCATCTTATCC-GGTTACCAATGGCTTCTTTCACACTCGGCCAT-AAAAGCAACTGATTGCTCTGCCCTTT + + +a +s Mus_musculus.CM000994.3 125890170 1154 + 195154279 ATCTTTTTAATATGAAAGTGATTTAAGACAACTGTAAAGCCAAGTTTTTTTTTTTTaaatgggctagggatgcagctctgtggtagagcactggcccagcaagcatgaggtcttgt-tttattctacagg-at----cacacatacacagaCCACACTCCCACAGCACACATAAGGCACACA-----------GTAGATCCACTGTAGACAACACATGGT------------------------GTGTACACAACAGATGAGCAGCAGGCACACAACAGATGTATACAACATAG-------------CACAGAAACAATGAATAAATGTAATAGACATATACATAACATGAacacaacacacata--tac-cattcacaccg-cacacactc-aagacattcattgtacacacaatatacacaacagataca--TATAACA--G--ATATTCAAC--AGAT--ATATAAC-ATACAATAAGTGTAGCACACACAAACAAAA---TTAGAAAAACACTCATATAAAAATTAC-----------------------ATAAATAAAACAAAATTACATATATAAAACAAAAACTA--CTGTGTACTCATATGTAAAG-ATCAAA-----AGCAAAGCACAAAGTCACTAGAAGAACTGTGACGTTTTAAAAATTAACTCAGGAATAGGGAAGCTTTTGGTTCAAAACAACTGGTGTTTGACCATTATAAAAATAAAACGTATACAAGCATGAACTTCCCATGTG-ATATCATAAGCAAATGGAGGTCCCTGCACGAAAAATGAAGG-AGGGGA-AATCCTCCCTAACTCTGAAGAGATTCTGGAAACCATGATGACACAGACTAACAAGACGAGTGAAAACTCAGTCAC------CAGCAGAAGGTTCACAGG--GAGGAATACAG-CCATCTCTGTGTACACATTTGAGGGTGG-TTCCAGAGATGA-----CTACATCGTCAGGACTCTGA-CCACTAAATCCTTTACTCCATTGATTGCCACATCACTGAAATAGATTATCAGGAAGTGGGAAAACTGAGGAAAAAGGGAGAAGATTGAAGGCAGTTGGTCAGCAGGT-A-GG-G-CGCACGCCCAAGGGCAATATCTTGCCCTTTCCTGTTGTGGCTCCTCTCTGCTCCATGCCTACCAAGATATGAGCT----CCTCTATTTG-----------TCTCCTCcatggactgaatcccctgaaaccaa-gagcaaagtcaatccattctccct-------------taagttgttcccattgg---------cta-tttc--gttacagGT--A +s Rattus_norvegicus.CM070403.1 39971430 1107 + 109350286 ATCTTTTTAATATGAAAGTGATTTAAGACAATTGCAAAGCCAAGTTTTTTTTTT---AATAggctagggaggcaactttgtggtagagcactcacccagcaagcatgagcccttgtGtttattctacagg-at----caca-atacacagatTACA--TCCACAGCATGCATAATGCACACA-----------ATAGATCCACTATAGACAACACACGAT------------------------GTATACATAACACCCATACCACAGATACACAACAGATGTATACAACATAGTTAACACAGAAACAGCAA----------------------------ACATAACATTCACACGAC--------------------------------------ACATTCAATATACACTCAACATACACAAAAGACACT--CATAACC--G--ATACAGAAC--AGAT--GTATAAC-ACACAACACTTGTAACAAACAC--ACAAAA---TT---AAAACACTCATACAA-AATTATTATTCTCACACAACACACAGCATATACACAAAACACA--TG--TCTGTAAGGCAAAAACTA--CTTTGCATTCCTATAAAAAG-ATAAAA-----TCCAAGGCACAAAGATTCTAGAAGAACTGTTAAGTTTTAAAAACTAACTCAGGAATAGGGCAAAGTTTGGTCTGAAACAGTTGGTGTTTGACCATGATAAAAATAAAACATGTACACGCATGAACTTCCTATGTG-ATGTCATAGGCAAATGGAGGTCCCTCTATGATACATGAAGG-AGGGGA-AACCCTTCCTGACTCTGAAGAGTTTATAGAAACTGTGATGACACAGACTAACAAGGCAAATGAAAACTCAGAGAC------CAAAAG-ATGTTCACAGA--GAGGAATACAG-CTACCTCTGTGTATATATTTGAGGGCGG-TTCTTGAGATGA-----C-ACATCATCAGGACTCTGA-CCACT-----CTTTACTCCATTGATGGACTCAGCACTGAAATAGATTATCAGGAAGTGGGGCCACTCGGGAAGATGGGAGCAGATTGAAGGTAACTGGTCAGCAGGT-A-AG-G-GGCACGCCCAACGGCAATATTTTGCCCTTTCCTGTTACGGCTCCACTCTGCTTCCTGCCTACCAAGATATGCgct----gctctatctg-----------tctcctccatgggctgaaacccctgaaaccat-gagcaaagtaaatctgttctccct-------------taagttgttcccattgg---------cta-tttt--gttacagGT--A +s Phodopus_campbelli.chr12 18454312 1133 - 32442325 ATCTTTTTAATATGAAAGTGATTTAAGACAActgca--------------------------------g------cccagtggtagagcatttacccagcGAGTATGAGGCCGTAGGTTTATTCTACAGT-AT----CACACATACACAGGAAACACACCCAC---------AA--CACACATAAGACATGCAATAGACATACTGCAGACAACATGTGAC------------------------ATGTACACAACA-----------ATCATACAACAGATATACACAACATAGACAACAC-AAAGCAGTAGAAACAACAGACGTACATACCAGACATATatgtaacatgcacacaacaca----CAtaa-cattcacacaa-cacatacta-gagaaatATAATACACATAGAACATATACAACAGA--CACATATAATA--G--ATACAGAAC--AGAT--ATATAAC-ACACAACACTTGCAACAGACAC--ACACAAAACCC---AAAACA----TACAATAATCACAGCTCTCATACAATATATAGCACACATAAAATACACA--TACATACCCAG--GAAAAATTA--CTTTGTATTTATATATAAAG-ATAAAA-----CCTAAAGCACAAAGATACTAGGAGAATTATGGAACTTTATAAATTAATTTGCGAATAGAAGAGAGTTTGGTCAGAAGTAATCGATGTTTGACCATTATAAAAATAAAACATACACAAACAAGAACTTCTCATGTA-AAGTCATAGGCAAATGGAAACCCCTGTATGGCAAATGAAGG-AGGGAATAACCCTCCCTGACTGTGAAGAATTTATTGAAACTCTGATGACAAAGACTAACAAGGC-AGTGCAA--------ACAGTCACCAGCAGAAGGTTCATAGACACAGGCACGCAGGCCACGTCTGTGTGCACCTGTGAGGGAGG-TTCCAGCGATGA-----CGACATC-TCAGGACTC-GAGCCAGTGGAAGGTTTACTCTACTGACTGACTCAGCATTGGAACAGATTACTGGGAAGTGACAGAACTGGAGATAATGGAACCAGATTGGAGGTAGCTGGTC-GGGGGT-A-AG-GGGACATGCCTACGGGCAGTATCTTG----------TTAGGGTTCCACTCTCCTTCCTGCTAACCATGATATGAGCT----GCTCTATCTGCCAGACCCTCACCTCCTTCATGGTCTGAAACCTCTAAAACCAT-GAGCAAAGTAAATACATTCTCCTTTAAGTTGTTCACAT-------------TAG---------CTA-TTTTT-GTCACAGGTGCA +s Phodopus_sungorus_new.chr12 17335744 1130 - 31225933 ATCTTTTTAATATGAAAGTGATTTAAGACAactgca--------------------------------g------ctcagtggtagagcatttacccagcaagtatgaggccgtagGtttattctacagt-at----cacacatacacaggaaacacacccac---------aa--cacacaTAAGACATGCAatagacatactgcagacaacatgtgac------------------------atgtacacaaca-----------ggcatacaacagatatacacaacatagACAACAC-AGAGCaatagaaacaacagacatacataccagacatatatgtaacatgcacacaacaca------taa-cattcacacaa-cacatacta-GAGACATATAATACACACAGAACATATACAACAGA--CA--TATAATA--G--ATACAGAAC--AGGT--ATATAAC-ACACAACACTTGCAACAGACAC--ACACAAAACCC---AAAACA----TACAATAATTACAGCTCTCATACAATATATAGCACACATAAGATACACA--CACATACCCAG--GAAAAATTA--CTTTGTATTTATGTATAAAG-ATAAAA-----CCTAAAGCACAAAGACACTAGGAGAATTATGGAACTTTATAAATTAATTTGCGAATAGAGGAGAATTTGGTCAGAAGTAATCGATGTTTGACCATTATAAAAATAAAACATACACAAACAAGAACTTTACATGTA-AAGTCATAGGCAAATGGAAACCCCTGCATGACAAATGAAGG-AGGGAATAACCCTCCCTGACTGTGAAGAATTTATTGAAACTCTGATGACAAAGACTAACAAGGC-AGTGCAA--------ACAGTCACCAGCAGAAGGTTCATAGACACAGGCACGCAGGCCACGTCTGTGTGCACCTGTGAGGGAGG-TTCCAGAGATGA-----CGACATC-TCAGGACTC-GAGCCAGTGGAAGGTTTACTCTACTGACTGACTCAGCATTGGAACAGATTACTGGGAAGTGACAGAACTGGAGATAATGGAACCAGATTGGAGGTAGCTGGTC-GGGGGT-A-AG-GGGACATGCCTACGGGCAGCATCTTG----------TTAGGGTTCCACTCTCCTTCCTGCTAACCATGATATGAGCT----GCTCTATCTGCCAGACCCTCACCTCCATCatggtctgaaacctctgaaaccat-gagcaaagtaaatacattctccttTAAGTTGTTCACAt-------------tag---------ctt-ttttTTGTCACAGGTGCA +s Phodopus_roborovskii.JAEOAF010000031.1 16487024 1036 + 29770300 ATCTTCTTAATATGAAAGTGATTTAAGACAACTGCAAAGGCAATT-----------------GTTGAG------------------------------------ATGAGGCCGTGTGTTTATTCTACAAT-AT----catacatacacaggaaacacatccac---------aacacacacaCAAGATATGCAatagacacactgtagacaacatgtgac------------------------atgtagacaata-----------ggcatacaacagatatacacagcatagATAACAC-AAAGCaacagaaataacaga-atacataccagatatacatgtaacatgcacacaacaca----CAtaa-cattcacctaa-cacatacta-gagacatataatatacacacaacatatacagcaga--c----ataata--g--atacagaac--agat--atataac-actca-------------acac--acacaaAACcc---aaaaca----tacaataatcaaAGCTCTCCTACATTATACAGCATacataagatacaca--tacatacccaG--GAAAAATTA--CTTTGCATTTATATATAAAG-ATAAAA-----CCTAAAGCACAGAGATAGTAGGAGAATTGTGAAACTTTATAAATTAATTTGTGAATAGAGGAGAGTTTGGTCAGAAACAATTGATGTTTGACCATCATAAAAATAAAACATACACAAACATGAACTCCACATGTA-ATGTCACAGGCAAATGGAAAGCCCTGTATGACAAATGAAGG-AGGGAATAAGCCTCCCTGACTGTGAAGAACTTATTGAAACTGTGATGACAAAGAATAATAAGGCAAGTGGAAACCCAATGACAGTCACCAGCAGAAGGTTCATAGACATAGGCATACAGGCCACATGTGTGTGCAT-----------------------------------------------------------------------CTGGCTGACTCAGCATTGGAATATATTGCTGGGAAGTTGGAGAAGTGGAGATAACGGGACCAGATTGGACGTAGCTGGTCAGGGGGT-A-AG-GGGACATGCCTAAAGGCAGTGTCTTG----------TTAGGGTGCCACTCCCCTTTCTGCTAACCATGATATGAGCT----GCTCTATCTGCCAGACCCTCACctccttcatggtctgaaacctctgaaaccat-gagcaaagtaaatagtctctcctt-------------t-------------tag---------cta-ttttT-gtcaCCAGTGCA +s Cricetus_cricetus.OZ199631.1 140167380 1129 - 205530201 ATCTTTTTAATATGAAAGTGATTTAAgccaactgcaaagccagct-----------------gctgggggtacagctcagtggtagagcacttgtccagcaagcatgaggcagtgtAtttattctacaat-at----ctcacacacacagaaaacacacccac---------aagacatgca-----------atagacacattgttgacaatacatgac------------------------atgtacacaata-----------ggcatataacagttatacacgacatagATAACAC-AAAGCaacagaaactacagacctacataccagacatatatgtaacatgcatacaacacacacaCAcaa-cattcacacaaCcacatatga-gagacttataatatacacagaacatatacagcagacaca--tataata--g--atacagaac--agat--atgtaaa-atgcaacacttgcaacagacac--acaagAAACCA---AAAACA----TACAATAACCACAGCTCTCATACAATATACAGAATACATATAATGTATG--TACATACACAG--CAAAAA-TA--CTTTGCATTTATGTATAAAG-ATAAAA-----TCTAAAGCACAAAGATACTAGGAGAATTATGAAACTTTATCAATTCATTTGGGAAAAGAAGAGATTTTAGTCAGAATTAATTGATGTTTGGCCATTACAAAAATAAAACATACACAAACATGAACTCCACCTGTA-ATGTCATGGGCAAATG--------------ACAAATGAAGG-AGGAAA-ACCCCTCCTTGACTCTGAAGAGCTTATGGAAACCGTGATGACAAAGACTAACAAGGAAAGTGAAAACTCAGTGATAGTCACCAGCAGAAGGTTCATAGACATAGCGATACAGGCCACCTCTGTGTGCACCTATGAAGGTGG-TTCCAGAGTTGA-----TGACATCATCAGGACTCTGAGCCAGTAAAAGGTTTACTCTATGGATTGACTCAACACTGGAATAGATTACCAGGAAGTGAGAGAACTGGGGATGATGGAACCAGATTGGAGGTAGTTGGTCAGGAGGT-A-GG-GTGGCATGCCTAGGGGTAATATCT---------------------------CCTTCCTGTCTACCATGATATGAGCT----GCTCTATCTGATAGACCCTTGcctccatcatggtctgaaacctctgtaaccat-gagcaaagaaaatactttctccct-------------taagtttttcacattag---------ctg-ttttT-gtcacaggtGCa +s Cricetulus_griseus.NC_048598.1 130955558 1135 - 193770019 ATCTTTTTAATATGAAAGTGATTTAAGCCAACTGCAAAGCCAACT-----------------gctgggggtacagctctgtggtagagcacttgcccagaaagcatgaggcagtgtAtttattctacaat-atCACAcacacacacacagaaaacacacccac---------aagacatgca-----------atagatacattgttgacaatacatgac------------------------atgtacacaata-----------ggcatataacagttatacacaacatagATAACAC-AAAGCaacagaaactacagacctacataccagacatatatgtaacatgcatacaacacacacaCGtaa-cattcacacaa-cacatatga-gagacttataatatacacagaccatatacaacagacaca--tataata--gATatacagaac--agat--atataaa-acgcaacacttgcaacagacac--acaaaaAACca---aaaaca----tacaataatcacAGCTCTCATACAATATACAGAGTacatataatgtata--tacatacatag--CAAAAATTA--CTTTGCATTTATATATAAAG-ATAAAA-----CCTAAAGCACAAAGATACTAGGAGAGTTATGAAACTTTATAAATTAATTTGGGAAAAGAAGAGATTTTAGTCAGAAATAATTGATGTTTGACCATTACAAAAATAAAACATACACAAACATGAACTCCACTTGTA-ATGTCATAGGCAAATG--------------ACAAATGGAGG-AGGAAA-ACCCCTCCCTGACTCTGAAGAGCTTATGGAAACTGTGATGACAAAGACTAACAAGGAAAGTGAAAACTCAGTGACAGTTACCAGCAGAAGGTTCATAGACATAGGCATACAGGCCACCTCTGTGTGTACCTATGAAGGCGG-TTCCAGAGATGA-----TGACATCATCAGGACTCTGAGCCAGTAAAAGGTTTACTCTATCGATTGACTCAACACTGGAATAGATTACCAGGAAGTGAGAGAACTGGGGATGATGGAACCAGATTGGAGGTAGTTGGTCAGGAGGC-A-GG-GTGGCATGCCTAGGGGTAATATCT---------------------------CCTTCCTGCCTACCATGATATGAGCT----GCTCTAGCTGATAGACCCTTGCCTCCatcatggtctgaaacctctgtaaccat-gagcaaagaaaatactttctcctt-------------taagtttttcacattag---------ctg-ttttT-gtcacagGTGCA +s Dicrostonyx_torquatus.JAQHUG010000071.1 6038885 1118 - 8539717 ATCTTTTTAATATGAAAGTGATTTACGGCAACTGCAAAACCAGCT-----------------GC-ggggatgcagctcagaggtagagcacttgctcagtgagcatgaggctttctGtttattctacaat-at----cacacataaacagacaacacacccgc---------agcacataca-----------atagagacattatggacaatacatgac------------------------at-----------------------------------atacacaacatagATAACACAAAAAGaacagaaaaaacagacatacataacaga-atatatgtaacatacacacaacacatacaCAtaa-catttacacaa-cacatacga-gagacatataatatacacagaacatatacaacagatgca--tataata--g--atatacaac--aaat--atgtaac-atacatcacttgcaacagacat--aaataaAACtc---aaagcacttacacaataatcatAGCTCTCATACAATATATAGCATacatataagacaca--tgtatacacag--caaatatta--ctttgtattcatatataaat-ataaaa-----cctaaagcacaaaggcacaaggagaattatgaaactttataaattaacttgGGAATAGAGAAGATTTTGGTCAGGAATAATTGATGTTTGGCCATTATAAAAATTAAACAAACACAAACATAAACTCCACATGTGGACATCATAGGCAGATGGAAATCCCTGCATG-CAAATGAAGG-AGGGA----CCCTACTTGACTCTGAAGAGCTTATGCAAACTGTGATGACAAAGACTAACAAGGCAAGTGAGAACTCAGTGACAGTTACCAGCAGAAGGCTCACAGATACAGGCATACAGGCCACCTCCGTGTGCATCTGTGAGGGTGG-TTCCAGAGACGA-----TGGCACCATCAGGACCCTGAGCCAGTAAAAGGTTTACTCCACTGATCGACTCAAGATTAGAACAGATTACCAGTGAGTTTGAGAACTGGGGAAGATGGGACCAGATTGGAAACAGTGGTTCAGGGCAT-G-GC-GGGGCATGCCTAGGGGCAAAATCTGA----------TCAGGGCTCCACTCTGTTTCCTGCCTACCA-GATATGAgct----gctctatc--TT-----CCAGcctccttcatggact---------gaaaccat-gagcaaagtaaattctttctccct-------------cgagtttttcacagtgg---------ctg-tttt--gtcacagggGCa +s Arvicola_amphibius.NC_052058.2 72669057 1139 - 166747489 ATCTTTTT-ATATGAACGTGATCGAGGAGAACTGCAAAACCAACG-----------------GC-ggggatgctgctcagaggtagagcacttgctcagtgagcatgaggccttgtGtttattctacaat-at----cacacataaacagacagcgcacccac---------agcacatgca-----------atagacacactgtggacaatacatgacATATATACAACAGGCACAACACAGat-----------------------------------atatacaacatagATAGCACAAAAACaacagaaaccacagacatacataacaga-atgtatgtaacatacacacaacacacaca--taa-cattcatacaa-cacatacaa-gacacatataacatacacagaacatatacaacagatgca--tattata--g--acataca----agat--atataac-atacattacttg-aacagacat--acacaaAATtc---aaaa-acccatacaataatcatAGCTCTCATATAATATACAGCATgcatataacacaca--tgtatacacag--caaaaatta--ctttgtattcatatataaatAaaAAAA-----CCTAAAGCACAAAGTCACTAGGAGAATTATGAAGCTTTATAAATTAACTTGGGAATAAGGGAGATTTTGGTCAGGAATAATTGATGTTTGACCATTACAGAAATTAAACATACACAAACATAAACTCCACGTGTGGATATCATAGGCAGATGGAAATCCCTGTATGACAAATGAAGG-AGGGA----CCCTCCTTGACTCTGAAGAGCTTATGCAAACTGTGATGACAAAGACCAACAAGGCAAGTGAGAACTCAgtgacAGTCACcagcagaaggctcacagaCAcacgcatacagGccacctctgtgtgcacctgtgagGGTGG-TTCCAGAGATGA-----TGGCATCATCAGGACCCGGAGCCAGTAAAAGGGTTACTCCAATGATCGACTCAAGATTAGAACAGATTACCAGGAAGTTTGAGAA-CAGGGAAGATGGGACCAGATTGGAGATAGTGGTTCAGGGGGTGG-GGGGGGGCATGCCTAGGGGCAAAATCTGG----------TCAGGGCTTCGCTCTGCTTCCTGCCTACCA-GATATGAACT----GCTCTATC--CT-----CCAGCCTCCTTCATGGACT---------GAAACCATGGAGCAAAGTAAATTCTTTCTCTCG-------------CGAGCTTTTCACAGTGG---------CTG-TTTT--GTCACGAGTGCa +s Microtus_pennsylvanicus.CM073176.1 20976643 1100 + 113485825 ATCTTTTTAATATGAAAGTGATCTAGGATAACTGCAAAACCAGCT-----------------gc-ggggatgcagctcagaggtagagcacttgctcagcgagcatgaggccttgtGtttattctacaat-at----cacacataaacagacaacacacccac---------agtgcataca-----------acat-caca-tgtggacaatacatgac------------------------at-----------------------------------atacacaacacagATAACACAAAAACaacagaaacaacagacatacatagcgga-atatatgtaacatacacacaacacacaca--taa-cattca------------------cacatgtaatatacacagaacatatacaacatatgca--tatgata--g--atatacaacATatat--atataat-atatatcacttgcaacagacat--acataaAACtc---aaagcacttgtacaataatcatAGCTCTCATACAATATATAGCACacatataacagaca--tgtatacacaG--CAAAAATTA--CTTTGTGTTCATATATAAAT-ATAATA-----CCTAAAACACAAAGGCACTTGGAGAATTAGGAAGCCTTATAAATTAACTTGGGAATAGGGGAGATTTTGGTCAGGAATAATTGATGTTTGACCATTATAAAAATTAAAGATACACAAACATAAACTCTACATGTGCATATCATAGGCAAGTAGAAATCCCTGAATGACAAATGAAGG-AGGGA----CCCTCCTTGA--CTGAAGAGTTTATGCAAACTGTGATGACAAAGACTAAAAAGGCAAGTGAGAACTCAGTGACAGTCACCAGCAGAAGGCTCACAGACACAGGCATACAGGTCACCTCTGTGTGCACCTGGGAGGGTGG-TTCCAGAGACGA-----TGGCATCATCAGGACCCAGAGCCAGTAAAGGGGTTACTCCACTAATCGACTCAAGATTAGAACAGATTACCAGGAAGTTTGAGAACCAGGGAAGATGGGACCAGATTGGAGACAGTGGTTCAGGGGGT-A-GGAGGGGCAAGCCTAGGGGAAAAATCTGG----------TCAGGAATTCActctgcttcctacctatca-gatgtgaact----gctctatc--CT-----CCAGcctccttcatggact---------gaaaccat-gagctaagtaaattctttctccct-------------cgagtttttcacagtgg---------ctg-tttt--atcacaAGTGCA +s Microtus_arvalis.JAHRII010002323.1 111061327 1117 + 200229077 atctttttaatatgaaagtgatctaggataactgcaaaaccagct-----------------gc-agggatgcagctcagaggtagagcatttgctcagtgagcttgaggccttgtGtttattctacaat-at----tacacataaacagacaacatacccac---------agtacataca-----------acat-caca-tgtggacaatacatgac------------------------at-----------------------------------atacacaacatagATAACACAAAAACaacagaaacaacagacatacataacaga-atatatgtaacatatacacaacacacata--taa-cattcacacaa-cacatacaa-gagacatataatatacacagaacatatacaacagatgca--tatgata--g--atatacaacATatatGTatataac-atatatcacttgcaacagacat--acataaAACtc---aaagcacttatacaataatcatAGCTCTCATACAATATATAGCACacatataacagaca--tgtaTACACAG--CAAAAATTA--CTTTGTGTTCATATATAAAT-AAA-TA-----CCTAAAACACAAAGGCACTAGGAGAATTATGAAGCCTTATAAATTAACTTGGGAATAGGGGAGATTTTGGTCAGGAATAATTGATGtttgaccattataaaaattaaagatacacaaacataaactCCACATGTGCTTATCATAGGGAAATGGAAATCCCTGTATGACAAATGAATG-AGGGA----CCCTCCTTGA--CTGAAGAGTTTATGCAAACTGTGATGACAAAGACTAAAAAGGCAAGTGAGAACTCAGTGACAGTCACCAGCAGAAGGCTCACAGACACAGGCATACAGGTCACCTCTGTGTGCACCTGTGAGGGTGG-TTCCAGAGACGA-----TGGCATCATCAGGACCCGGAGCCAGTAAAAGGGTTACTCCACTGATCGACTCAAGATTAGAACAGATTACCAGGAAGTTTGAGAACCAGGGAAGATGGGACCAGATTGGAGACAGTGGTTCAGGGGGT-A-GGAGGGGCATGCCTAGGGGAAAAATCTGG----------TCAGGGATTCActctgcttcctacctatca-gatgtgaact----gctctatc--CT-----CCAGcctccttcatggact---------gaaaccat-gagcaaagtaaattctttctccct-------------cgagtttttcacagtgg---------ctg-tttt--atcacaAGTGCA +s Neotoma_floridana.CM113793.1 27922860 1142 - 95303938 ATCTTTTTAATATGAAAGTGATTTAAGACAACTGCAAAgctagct-----------------gctggggatgcagctcagtggtagagcacttgcctggcaagcatgaggccttgtGtttattccacaat-at----cacatatacacagacaacacacccacagcatacacaagac-----------------------------------------------------------------------acacaaaa-----------ggcatacaacagatatacataacatagATAACACAAAAACaacag-aaaaacagacatacataacagacatatatgtaacatgcacacaacacacaca--taa-catttacacaa-cacatacta-aagacatataatatacacagaacatctacaacaaacata--taat--a--g--atacacaac--agat--atatcac-atacaacacttgcaacagacac--atacaaAACtc---aaaacactcatacaacaatcacAGCTCTTACACAACATACAGCATacacataatataca--tgcacacacag--caaaaatta--ctttacattcatatgtacag-ataaaa-----ctcaaagtacaaagacacTAGGAGAATTATGAAGCTTTATAAATTAACATGGGAATAGGGGAGATTTTGGTCAGAGTTAATTGATGTTTGACCATTATAAAAATAAAACATCCACAAACATTAACTCCACATGAGGGTGTCATAGGCAAGTGGAAATCCCTGTATGACAAATGAAGATGGGAAA-CCCCCTCCCTGACTCTGAAGAGTTTACGGAAACTGTAATGACAGAGACTAACAAGGCAAGTGAAAACTCTGTGACAGTCACCAGCAGAAGGTTCACAGACACAGGCACACAGGCCACCTCTGTGTGCACCTGTGAGGGTGG-TTCCAGAGATGA-----AGACATCATCAGGACTCTGAGCCAGCAAAAGGTTTACACCACTGATTGACTCAT---TGGAATAGATTACCAGGAAGTGGGAGAGCTGGGGAGGATGGGATCAGATTGGAGGTAGTTCGTCAGGGGTTGAGGG-GGGGCACACCTAGAGGCACTATCTTG----------TTAGAGTTCCGctctccttcctgcctaccatgatgtgagct----gctctatctaCCTGATCCTTGcctccttcatggactcaaacctctgaaaccat-gagcaaagtaaatactttctccct-------------taagtttttcacattggCTATTTTGTcta-tttt--gtcacaggtGCa +s Onychomys_torridus.LR877198.1 72221593 1147 + 93020901 ATCTTTTTAATATGAAAGTGAttgaagacaacctcaaagctagat-----------------gctggggatgcagctcagtggtagagcacttgcccagcaagcctgaggccttatGtttattcttcaac-at----cacacatacacagataacacacccatagcatacataagacacata-----------atagacatattgtagacaacacatg--ACATGT----------------------acacaaca-----------ggcatacaacagttaaacacaacatagATACCAC-AAAACaactgaaataacagacatacataacagacatatatgtaacatgcacacaactcatgca--taa-cattcacacaa-cacacactaGaagacaaataatatacacagaacatacacaacaaacaca--tata--a--t--ata---------------------Aacacaacacctgcaacagacac--atacaaAACtc---aaa-cactcatacaacaatcacAGCTCTTATACAACATACAGCATacacataatataca--tgcatacacag--CAAAAATTA--CTTTGCATTCATATATAAAG-ATAAAATAAAACCCCAGGTACAAAGACACTAGGAGAATTATGAAGCTTTATATATTAACTTGGGAATAGGGGAGATTTTGGTCAAAGTTAATTGATGTTTGATCACTAGAAAAATGAAACATACACAAACATGAACTCCACAATAGGATGTCACAGACAAGTGGAAATCC-AGTGTGACAAAAGAAGA-AGGAAA-ACCCCTCCCTGACTCTGAAGAGTTTATGGAAACTGTAATGTCAAA-ACTGACAAGGCAAGTGAAAACTCTGTGACCGTCACCAGCAGAAGGTTCACAGACACAGGCCTAGAGGCCACCT--GTGTGCACCTGTGAGG--GG-TTCCAGAGATAA-----TGACATCATCAGGACTCTGAGCCAGTAACGAGTTTACTCCACTGATTGACTCAC---TGGAACAGATTACCAGGAAGTGGGAGAACTGGGCAAGATGGGACCAGATTGGAGGT-------CAGGGAGC-AGGG-GGAGCATGCCTACCAGCAATATCTTG----------TTAGGGTTCTGctctccttcctgcctatcatgatatgagctAGCTgctctagctaACTGACCCTCAcctccttcatggactcagacctctgaaactat-gagcaaattaaatactttctccct-------------tgaggttttcacagtgg---------cca-tctt--atcacaggcGCa +s Peromyscus_californicus.VALE03000237.1 12779675 1153 + 80346014 ATCTTTTTAATATGAAAATgatttaagacacccgcaaagctagct-----------------gctggggacgcagcccagtggtagagcacttgcccagcaagcacgaggccttgtGtttcttctacagtTat----cacacatacacagacaacacacccacagcatacataagacatgcg-----------atagacacattgtagacaacacatg--GCATGT----------------------acacagca-----------ggcatacaacagacatacacaacatagATACCACAGAAACaacagaaataacaga-------------catatatgtaacatgcacacaacacacaca--taa-cattcacacaa-cacatacta-gagatatataatatacacagaacatatacaacaaataca--tgta--aTAg--aaacacaac--agat--atataacAacacaacatttgcaacagacac--acaaaaAACtc---aaaacactcatacaacaatcacAGCTCTTACTCAACATACAGCATacacataatataca--tgcatacacag--GAAAAAATA--CTTCGCATTCATATATAAAG-ATAAAA-----CCCAAAGTACAAAGACACTGGGAGAATTATGAAGCTTGATACATTAACCTGGGAACAGGCGAGATTTCGGTCAGAGATAACTGATGTTTGAACATTATAAAAATGAAACATGCACAAACGTGAACTCCACATGAGGATGTCACAGGCAAGTGGAAATCCCAGTATGACAGAAGAAGA-AGGAAA-ACCCCTCCCTGACTCTGAAGAGTATATGGAAACTGTAATGACAAAGACTAACAAGGCAAGTGAAAACTCTGTGAACGTCATCAGCAG---GTTCACAGACACAGGCATCCAGGCCACCT--GTGAGCACCTGGGAGG--GGGTTCCAGAGATGA-----CGACATCATGAGGACTCTGAGCCAGTAACAGCTTTACTCCACTGATTGACTCAG---TGGAACAGAGTACCAGGAATTGGGAGAACTGGGCAAGATGGAACCAGATTGGAGGTAGTTGGTCAGGGGGC-AGAG-GGGA-ATGTCTACTGGCAATATCTTG----------TTAGGGTTCTGctctccttcctgcctatcatgatatgagct----gctctatctaCATGACCCTCAcctccttcacggactcaaacctctgaaactat-gagcaaattaaatactttcttcct-------------taaggttttcacattgg---------ctaCtttt--atcacaggtGCa +s Peromyscus_maniculatus_North.CM113205.1 35700359 1160 + 104458120 ATCTTTTTAATATGAAAGTGATTTAAGACACCCGCAAAGCTCGCt-----------------gctggggatgcagctcagtggtagagcacttgcccagcaagcacgaggccttgtGtttcttctacaatGat----cacacatacacagacaacacactcacagcatacataagacacgcg-----------atagacacattgtagacaacacatg--ACATGT----------------------acagagga-----------ggcatacaacagacatacacaacatagATACCACAAAAACaacagaaataacagagatatgtaacagacatatatgtaacatgcacacaacacacaca--taaAtattcacacaa-cacatacta-gaaatatataatatacacagaaca---------aacaca--taca--aTAg--aaacacaac--agat--atataacAacacaacatttgcaacagacac--ataaaaAACtc---aaaacactcatacaacaatcacAGCTCTTACACAACATACAGCATacacataatataca--tgcatacacCG--AAAAAAAAAACCTTCGCATTCATGTATAAAG-ATAAAA-----CCCAAAGTACAAAGACACTGGGAGAATTATGAAGCTTTATACATTAACTTGGGAATAGGGGAGATTTTGGTCAGAGTTAACTGATGTTTGACCATTATAAAAATGAAACATGCACAAACATGAACTCCACATGAGGATGTCATAGGCAAGTGGAAATCCCCGTGTGAGAAAAGAAGA-AGGAAA-ACCCCTCCCTGACTCTGAAGAGTTTGTGGAAACTGTAATGACAAAGACTAACAAGGTGAGTGAAAACTCTGTGACCGTCACCAGCAG---GCTCACAGACACAGGCATCCAGGCCACCT--GTGTGCACCTGTGGGG--GG-TTCCAGAGATGACGACATGACATCATCAGGACTCTGCGCCAGTAAC-AGGTTACTCCACTGATTGACTCAG---TGGAACAGGGTACCAGGAAGTGAGAGAACTGGGCAAGATGGGACCAGACTGGAGGTAGTTGGTCACGGGGC-AGGG-GGGGCGTGGCTATTGGCAATATCTTG----------TTAGGGTTCCGCTCTCCTTCCAGCCTAGCAT---ATGAGCT----GCTCTATCtaCTGGACTCTCAcctccttcatggactcaaacctctgaaaccat-gagcaaattaaatactttcttccc-------------taaggttttcacattgg---------ctg-tttt--atcacaggtGCa + + +a +s Mus_musculus.CM000994.3 125891324 34 + 195154279 CACAGTCACCAAGTACTTCATGGTCTTGGATGAG +s Rattus_norvegicus.CM070403.1 39972568 30 + 109350286 CAAAATCACCAAG----TAATGGTCTTGGATAAA +s Phodopus_campbelli.chr12 18455457 34 - 32442325 CACAATAACCAAGTTCTGAATggtcctggatgac +s Phodopus_sungorus_new.chr12 17336886 34 - 31225933 CACAATAACCAAGTTCTGAATGgtcctggatgac +s Phodopus_roborovskii.JAEOAF010000031.1 16488072 34 + 29770300 CACAATGACCAAGTTCTGAATGGTCCTGGATGAC +s Cricetus_cricetus.OZ199631.1 140168521 34 - 205530201 CACAATCACCAAGTTCTTAATGATCCTGGATGAT +s Cricetulus_griseus.NC_048598.1 130956705 34 - 193770019 CACAATCACCAAGTTCTTAATGATCCTGGATGAT +s Dicrostonyx_torquatus.JAQHUG010000071.1 6040015 34 - 8539717 CACAAACATCAAGTTCTTAATGATcctgggtgac +s Arvicola_amphibius.NC_052058.2 72670208 31 - 166747489 cacaatca-caagttcttagtga-tccgggtga- +s Microtus_pennsylvanicus.CM073176.1 20977755 34 + 113485825 CACAACCATCAAGTTCTTAATGATTCTGGATGac +s Microtus_arvalis.JAHRII010002323.1 111062456 34 + 200229077 CACAACCATCAAGTTCTTAATGATTCTGGATGAC +s Neotoma_floridana.CM113793.1 27924014 34 - 95303938 CACAATCACCAAATTCTTAATggtcctggatgac +s Onychomys_torridus.LR877198.1 72222752 28 + 93020901 CACAATCACCAAGTTCTTAATGGTCCTG------ +s Peromyscus_californicus.VALE03000237.1 12780840 34 + 80346014 cacaatcaccaagttcttaatggtcctggatgac +s Peromyscus_maniculatus_North.CM113205.1 35701531 34 + 104458120 cacaatcaccaagttcttcatggtcctgggtgac + + diff --git a/tests/real-excerpt.maf.block.idx b/tests/real-excerpt.maf.block.idx new file mode 100644 index 0000000..1fd879a --- /dev/null +++ b/tests/real-excerpt.maf.block.idx @@ -0,0 +1,9 @@ +# mafutils-index format=2 maf=real-excerpt.maf compression=none size=47241 mtime=1784644433.0 hash=md5:7146e0c45ac589e8998a3fe232ca5ad7 +CM000994.3 125888838 82 84 135 13 17 1874 +CM000994.3 125888920 187 223 275 9 1874 4416 +CM000994.3 125889107 10 31 82 9 4416 5221 +CM000994.3 125889117 440 487 539 14 5221 12879 +CM000994.3 125889557 280 356 408 15 12879 19122 +CM000994.3 125889837 333 336 388 15 19122 25065 +CM000994.3 125890170 1154 1324 1377 15 25065 45843 +CM000994.3 125891324 34 34 85 15 45843 47241 diff --git a/tests/real-excerpt.maf.scaffold.idx b/tests/real-excerpt.maf.scaffold.idx new file mode 100644 index 0000000..dcdb6a9 --- /dev/null +++ b/tests/real-excerpt.maf.scaffold.idx @@ -0,0 +1,2 @@ +# mafutils-index format=2 maf=real-excerpt.maf compression=none size=47241 mtime=1784644433.0 hash=md5:7146e0c45ac589e8998a3fe232ca5ad7 +CM000994.3 17 47241 diff --git a/tests/test_fetch.py b/tests/test_fetch.py index 700dc77..8000cd1 100644 --- a/tests/test_fetch.py +++ b/tests/test_fetch.py @@ -118,3 +118,64 @@ def test_maf_fetch_fasta_region(chrom, start, end, region_id, tmp_path): expected = expected.rstrip('\n') assert got == expected, f"FASTA output for region {region_id} does not match expected" + + +def test_scaffold_subdirs_groups_output_by_scaffold(tmp_path): + """ + --scaffold-subdirs groups per-region output files into + //.maf instead of a flat /. Runs + with -p 2 (real multi-worker ProcessPoolExecutor dispatch, matching how + block-mode writes actually happen) across regions spanning multiple + scaffolds, including two scaffolds (chr1, chr4) with multiple regions + each, to confirm they land in the same subdirectory without any + cross-worker race (directories are pre-created upfront, see fetch.py). + """ + out_dir = str(tmp_path) + cmd = [ + sys.executable, "-m", "mafutils", "fetch", + MAF_FILE, BED_FILE, + "--index", INDEX_FILE, + "-b", "id", + "-o", out_dir, + "--scaffold-subdirs", + "-p", "2", + ] + result = subprocess.run(cmd, check=False, cwd=REPO_ROOT, capture_output=True, text=True) + assert result.returncode == 0, f"Unexpected non-zero exit: {result.stderr}" + + # chr1 has 3 regions with real output (06-noalign has no overlap, so no + # file); chr4 has 2; chr2/chr3/chrX have 1 each. chrZ (09-missingchrom) + # never gets that far (unknown scaffold errors before any writes). + assert sorted(os.listdir(os.path.join(out_dir, "chr1"))) == [ + "01-singleblock-gap.maf", + "02-truncatedblock.maf", + "03-crossblocks-missing.maf", + ] + assert os.listdir(os.path.join(out_dir, "chr2")) == ["04-singleblock.maf"] + assert os.listdir(os.path.join(out_dir, "chr3")) == ["05-crossblocks.maf"] + assert os.listdir(os.path.join(out_dir, "chrX")) == ["07-negstrand.maf"] + assert sorted(os.listdir(os.path.join(out_dir, "chr4"))) == [ + "08-span-multiple-gaps.maf", + "10-crossblocks-missing-species.maf", + ] + + # Content should be identical to the flat-layout output for the same region. + with open(os.path.join(out_dir, "chr2", "04-singleblock.maf")) as fp: + got = fp.read().rstrip("\n") + with open(os.path.join(EXPECTED_MAF_DIR, "04-singleblock.maf")) as fp: + expected = fp.read().rstrip("\n") + assert got == expected + + +def test_scaffold_subdirs_rejected_with_single_output(tmp_path): + cmd = [ + sys.executable, "-m", "mafutils", "fetch", + MAF_FILE, BED_FILE, + "--index", INDEX_FILE, + "--scaffold-subdirs", + "--single-output", + "-o", os.path.join(str(tmp_path), "out.maf"), + ] + result = subprocess.run(cmd, check=False, cwd=REPO_ROOT, capture_output=True, text=True) + assert result.returncode != 0 + assert "--scaffold-subdirs cannot be used with --single-output" in result.stderr diff --git a/tests/test_real_data.py b/tests/test_real_data.py new file mode 100644 index 0000000..1231c88 --- /dev/null +++ b/tests/test_real_data.py @@ -0,0 +1,115 @@ +import csv +import os +import subprocess +import sys + +TEST_DIR = os.path.dirname(__file__) +REPO_ROOT = os.path.abspath(os.path.join(TEST_DIR, "..")) + +MAF_FILE = os.path.join(TEST_DIR, "real-excerpt.maf") +INDEX_FILE = os.path.join(TEST_DIR, "real-excerpt.maf.block.idx") + +# 8 real, complete alignment blocks, extracted read-only from gwct's real +# ~42GB production MAF (data/hamsters/uncompressed/...), a couple GB in to +# skip past the initial all-N region. Unlike example.maf (hand-crafted, used +# to independently verify exact output values in test_stats.py/test_gc.py), +# this fixture exists to catch real-world-data surprises a hand-crafted +# fixture wouldn't think to include (real species-naming conventions, real +# gap patterns, real block-size distribution) -- so these tests check +# plausibility/robustness/"does it run cleanly on real data", not exact +# hand-computed values. +EXPECTED_SPECIES = { + "Phodopus_sungorus_new", + "Phodopus_campbelli", + "Phodopus_roborovskii", + "Cricetulus_griseus", + "Cricetus_cricetus", + "Dicrostonyx_torquatus", + "Peromyscus_maniculatus_North", + "Microtus_arvalis", + "Microtus_pennsylvanicus", + "Arvicola_amphibius", + "Neotoma_floridana", + "Mus_musculus", + "Rattus_norvegicus", + "Peromyscus_californicus", + "Onychomys_torridus", +} + +# All 8 blocks are on the same real reference scaffold/coordinate range. +REAL_SCAFFOLD = "CM000994.3" +REAL_START = 125888838 +REAL_END = 125891358 # last block's start (125891324) + size (34) + + +def run(cmd_args): + cmd = [sys.executable, "-m", "mafutils"] + cmd_args + return subprocess.run(cmd, check=False, cwd=REPO_ROOT, capture_output=True, text=True) + + +def read_overall(path): + with open(path, "r", encoding="utf-8") as fp: + lines = fp.readlines()[1:] + return dict(line.rstrip("\n").split("\t") for line in lines) + + +def test_stats_runs_cleanly_on_real_data(tmp_path): + out_prefix = os.path.join(str(tmp_path), "out") + result = run(["stats", MAF_FILE, INDEX_FILE, "-o", out_prefix]) + assert result.returncode == 0, result.stderr + + overall = read_overall(out_prefix + ".overall.tsv") + assert int(overall["total_blocks"]) == 8 + assert int(overall["total_species"]) == 15 + assert int(overall["total_parse_errors"]) == 0 + assert int(overall["blocks_with_zero_parsed_seq_lines_but_index_nonzero"]) == 0 + + +def test_stats_species_list_matches_known_species(tmp_path): + out_prefix = os.path.join(str(tmp_path), "out") + result = run(["stats", MAF_FILE, INDEX_FILE, "-o", out_prefix]) + assert result.returncode == 0, result.stderr + + with open(out_prefix + ".species.tsv", "r", encoding="utf-8") as fp: + reader = csv.DictReader(fp, delimiter="\t") + got_species = {row["species"] for row in reader} + assert got_species == EXPECTED_SPECIES + + +def test_gc_runs_cleanly_and_plausibly_on_real_data(tmp_path): + out_prefix = os.path.join(str(tmp_path), "out") + result = run(["gc", MAF_FILE, INDEX_FILE, "-o", out_prefix]) + assert result.returncode == 0, result.stderr + + with open(out_prefix + ".gc.csv", "r", encoding="utf-8") as fp: + reader = csv.DictReader(fp) + gc_values = {row["species"]: float(row["gc"]) for row in reader} + + assert gc_values.keys() == EXPECTED_SPECIES + for species, gc in gc_values.items(): + # Real rodent genomic GC content clusters tightly around 0.40-0.45 in + # this fixture; 0.30-0.55 gives real margin without being so loose it + # would miss a genuine encoding/parsing bug (e.g. counting gaps as GC). + assert 0.30 <= gc <= 0.55, f"{species}: implausible GC content {gc}" + + +def test_fetch_runs_cleanly_on_real_data(tmp_path): + bed_path = os.path.join(str(tmp_path), "region.bed") + with open(bed_path, "w", encoding="utf-8") as fp: + fp.write(f"{REAL_SCAFFOLD}\t{REAL_START}\t{REAL_END}\tregion1\n") + + out_dir = str(tmp_path) + result = run([ + "fetch", MAF_FILE, bed_path, + "--index", INDEX_FILE, + "-b", "id", + "-o", out_dir, + ]) + assert result.returncode == 0, result.stderr + + output_file = os.path.join(out_dir, "region1.maf") + assert os.path.isfile(output_file), "Expected fetch output file was not created" + with open(output_file, "r", encoding="utf-8") as fp: + content = fp.read() + assert content.count("\na") + content.startswith("a") >= 1, "Expected at least one alignment block in fetch output" + assert "Mus_musculus" in content diff --git a/tests/test_stats.py b/tests/test_stats.py new file mode 100644 index 0000000..4d8bbc1 --- /dev/null +++ b/tests/test_stats.py @@ -0,0 +1,143 @@ +import csv +import os +import subprocess +import sys + +import pytest + +TEST_DIR = os.path.dirname(__file__) +REPO_ROOT = os.path.abspath(os.path.join(TEST_DIR, "..")) + +MAF_FILE = os.path.join(TEST_DIR, "example.maf") +INDEX_FILE = os.path.join(TEST_DIR, "example.maf.block.idx") + +# Hand-verified directly against tests/example.maf's raw content (10 blocks; +# human present in all 10, chimp in 8 [blocks 1,2,3,4,5,6,8,10], gorilla in 2 +# [blocks 7,9]). Every block has exactly 2 taxa, so parsimony-informative +# sites (requiring >=2 states each seen >=2 times) are structurally +# impossible; variable sites occur only in block 3 (6 columns) and block 4 +# (1 column), the only two blocks where both taxa have different non-gap +# bases in the same column. +EXPECTED_OVERALL = { + "total_blocks": 10, + "total_species": 3, + "total_alignment_columns": 61, + "total_sequence_lines": 20, + "all_gap_sites": 0, + "variable_sites": 7, + "invariant_sites": 54, + "parsimony_informative_sites": 0, + "total_parse_errors": 0, + "blocks_with_zero_parsed_seq_lines_but_index_nonzero": 0, +} + +# blocks_present / gaps_total / nongaps_total per species, hand-counted +# directly from each block's raw sequence strings. +EXPECTED_SPECIES_RAW = { + "human": {"blocks_present": 10, "gaps_total": 3, "nongaps_total": 58}, + "chimp": {"blocks_present": 8, "gaps_total": 11, "nongaps_total": 41}, + "gorilla": {"blocks_present": 2, "gaps_total": 1, "nongaps_total": 8}, +} + + +def run_stats(args): + cmd = [sys.executable, "-m", "mafutils", "stats"] + args + result = subprocess.run(cmd, check=False, cwd=REPO_ROOT, capture_output=True, text=True) + assert result.returncode == 0, f"stats failed (exit {result.returncode}):\n{result.stderr}" + return result + + +def read_overall(path): + with open(path, "r", encoding="utf-8") as fp: + lines = fp.readlines()[1:] + return dict(line.rstrip("\n").split("\t") for line in lines) + + +def read_species(path): + with open(path, "r", encoding="utf-8") as fp: + reader = csv.DictReader(fp, delimiter="\t") + return {row["species"]: row for row in reader} + + +def assert_overall_matches(overall): + for key, expected in EXPECTED_OVERALL.items(): + assert int(overall[key]) == expected, f"{key}: expected {expected}, got {overall[key]}" + + +def assert_species_matches(species): + assert species.keys() == EXPECTED_SPECIES_RAW.keys() + for sp, expected in EXPECTED_SPECIES_RAW.items(): + row = species[sp] + assert int(row["blocks_present"]) == expected["blocks_present"], sp + assert int(row["gaps_total"]) == expected["gaps_total"], sp + assert int(row["nongaps_total"]) == expected["nongaps_total"], sp + + # Derived ratios computed from the hand-verified raw counts above, + # not hardcoded floats -- still an independent check of the formula + # application, without risking manual 8-decimal arithmetic errors. + blocks_present = expected["blocks_present"] + blocks_missing = 10 - blocks_present + total_cells = expected["gaps_total"] + expected["nongaps_total"] + assert int(row["blocks_missing"]) == blocks_missing, sp + assert float(row["presence_fraction"]) == pytest.approx(blocks_present / 10, abs=1e-6), sp + assert float(row["gap_fraction_cells"]) == pytest.approx(expected["gaps_total"] / total_cells, abs=1e-6), sp + assert float(row["avg_gaps_per_present_block"]) == pytest.approx( + expected["gaps_total"] / blocks_present, abs=1e-6 + ), sp + + +def test_overall_stats_match_hand_verified_values(tmp_path): + out_prefix = os.path.join(str(tmp_path), "out") + run_stats([MAF_FILE, INDEX_FILE, "-o", out_prefix]) + assert_overall_matches(read_overall(out_prefix + ".overall.tsv")) + + +def test_species_stats_match_hand_verified_values(tmp_path): + out_prefix = os.path.join(str(tmp_path), "out") + run_stats([MAF_FILE, INDEX_FILE, "-o", out_prefix]) + assert_species_matches(read_species(out_prefix + ".species.tsv")) + + +def test_no_block_table_omits_block_file(tmp_path): + out_prefix = os.path.join(str(tmp_path), "out") + run_stats([MAF_FILE, INDEX_FILE, "-o", out_prefix, "--no-block-table"]) + assert not os.path.exists(out_prefix + ".block.tsv") + + +def test_block_table_present_by_default(tmp_path): + out_prefix = os.path.join(str(tmp_path), "out") + run_stats([MAF_FILE, INDEX_FILE, "-o", out_prefix]) + assert os.path.isfile(out_prefix + ".block.tsv") + + +def test_sequential_and_parallel_paths_produce_identical_output(tmp_path): + """ + Regression guard for the processes=1 ProcessPoolExecutor-skip fix: the + direct in-process call (-p 1) and the real multi-worker pool path + (-p 2, forced into multiple chunks via a small --chunk-size) must + produce identical overall/species output, not just "doesn't crash". + """ + seq_prefix = os.path.join(str(tmp_path), "seq") + par_prefix = os.path.join(str(tmp_path), "par") + run_stats([MAF_FILE, INDEX_FILE, "-o", seq_prefix, "-p", "1"]) + run_stats([MAF_FILE, INDEX_FILE, "-o", par_prefix, "-p", "2", "--chunk-size", "3"]) + + assert read_overall(seq_prefix + ".overall.tsv") == read_overall(par_prefix + ".overall.tsv") + assert read_species(seq_prefix + ".species.tsv") == read_species(par_prefix + ".species.tsv") + + +def test_expected_species_file_reports_missing_species(tmp_path): + species_file = os.path.join(str(tmp_path), "species.txt") + with open(species_file, "w", encoding="utf-8") as fp: + fp.write("human\nchimp\ngorilla\norangutan\n") + + out_prefix = os.path.join(str(tmp_path), "out") + run_stats([MAF_FILE, INDEX_FILE, "-o", out_prefix, "--expected-species-file", species_file]) + + overall = read_overall(out_prefix + ".overall.tsv") + assert int(overall["total_species"]) == 4 # 3 observed + 1 expected-but-absent + + species = read_species(out_prefix + ".species.tsv") + assert "orangutan" in species + assert int(species["orangutan"]["blocks_present"]) == 0 + assert int(species["orangutan"]["blocks_missing"]) == 10